diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-03-03 20:22:30 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-03-03 20:22:30 -0500 |
commit | 043508ed4264a3024b281665bfbf6e073c029fdf (patch) | |
tree | 6474892938f4263642f4b30b726a83720418a6cc /src/StardewModdingAPI/Framework/ContentEventHelper.cs | |
parent | 5d32b9802942e70c2d51d0edc376d92ac35b1032 (diff) | |
download | SMAPI-043508ed4264a3024b281665bfbf6e073c029fdf.tar.gz SMAPI-043508ed4264a3024b281665bfbf6e073c029fdf.tar.bz2 SMAPI-043508ed4264a3024b281665bfbf6e073c029fdf.zip |
add texture patching to content events (#173)
Diffstat (limited to 'src/StardewModdingAPI/Framework/ContentEventHelper.cs')
-rw-r--r-- | src/StardewModdingAPI/Framework/ContentEventHelper.cs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/StardewModdingAPI/Framework/ContentEventHelper.cs b/src/StardewModdingAPI/Framework/ContentEventHelper.cs index a58efe32..ebd04692 100644 --- a/src/StardewModdingAPI/Framework/ContentEventHelper.cs +++ b/src/StardewModdingAPI/Framework/ContentEventHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace StardewModdingAPI.Framework @@ -85,6 +86,56 @@ namespace StardewModdingAPI.Framework data[key] = value(data[key]); } + /// <summary>Overwrite part of the image.</summary> + /// <param name="source">The image to patch into the content.</param> + /// <param name="sourceArea">The part of the <paramref name="source"/> to copy (or <c>null</c> to take the whole texture). This must be within the bounds of the <paramref name="source"/> texture.</param> + /// <param name="targetArea">The part of the content to patch (or <c>null</c> to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet.</param> + /// <param name="patchMode">Indicates how an image should be patched.</param> + /// <exception cref="ArgumentNullException">One of the arguments is null.</exception> + /// <exception cref="ArgumentOutOfRangeException">The <paramref name="targetArea"/> is outside the bounds of the spritesheet.</exception> + /// <exception cref="InvalidOperationException">The content being read isn't an image.</exception> + public void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace) + { + // get texture + Texture2D target = this.GetData<Texture2D>(); + + // get areas + sourceArea = sourceArea ?? new Rectangle(0, 0, source.Width, source.Height); + targetArea = targetArea ?? new Rectangle(0, 0, Math.Min(sourceArea.Value.Width, target.Width), Math.Min(sourceArea.Value.Height, target.Height)); + + // validate + if (source == null) + throw new ArgumentNullException(nameof(source), "Can't patch from a null source texture."); + if (sourceArea.Value.X < 0 || sourceArea.Value.Y < 0 || sourceArea.Value.Right > source.Width || sourceArea.Value.Bottom > source.Height) + throw new ArgumentOutOfRangeException(nameof(sourceArea), "The source area is outside the bounds of the source texture."); + if (targetArea.Value.X < 0 || targetArea.Value.Y < 0 || targetArea.Value.Right > target.Width || targetArea.Value.Bottom > target.Height) + throw new ArgumentOutOfRangeException(nameof(targetArea), "The target area is outside the bounds of the target texture."); + if (sourceArea.Value.Width != targetArea.Value.Width || sourceArea.Value.Height != targetArea.Value.Height) + throw new InvalidOperationException("The source and target areas must be the same size."); + + // get source data + int pixelCount = sourceArea.Value.Width * sourceArea.Value.Height; + Color[] sourceData = new Color[pixelCount]; + source.GetData(0, sourceArea, sourceData, 0, pixelCount); + + // merge data in overlay mode + if (patchMode == PatchMode.Overlay) + { + Color[] newData = new Color[targetArea.Value.Width * targetArea.Value.Height]; + target.GetData(0, targetArea, newData, 0, newData.Length); + for (int i = 0; i < sourceData.Length; i++) + { + Color pixel = sourceData[i]; + if (pixel.A != 0) // not transparent + newData[i] = pixel; + } + sourceData = newData; + } + + // patch target texture + target.SetData(0, targetArea, sourceData, 0, pixelCount); + } + /// <summary>Replace the entire content value with the given value. This is generally not recommended, since it may break compatibility with other mods or different versions of the game.</summary> /// <param name="value">The new content value.</param> /// <exception cref="ArgumentNullException">The <paramref name="value"/> is null.</exception> |