private Image <Rgba32>[] GetFrames(Image <Rgba32> source, int frameWidth, int frameHeight) { int framesInWidth = source.Width / frameWidth; int framesInHeight = source.Height / frameHeight; if (framesInWidth * framesInHeight == 0) { // string a = "b"; } //List<Image<Rgba32>> result = new List<Image<Rgba32>>(); Image <Rgba32>[] result = new Image <Rgba32> [framesInHeight * framesInWidth]; int counter = 0; for (int x = 0; x < framesInWidth; x++) { for (int y = 0; y < framesInHeight; y++) { var newBitmap = new Image <Rgba32>(frameWidth, frameHeight); TextureUtils.CopyRegionIntoImage( source, new System.Drawing.Rectangle(x * frameWidth, y * frameHeight, frameWidth, frameHeight), ref newBitmap, new System.Drawing.Rectangle(0, 0, frameWidth, frameHeight)); result[counter++] = newBitmap; //result.Add(newBitmap); } } return(result.ToArray()); }
private int Process(ref Image <Rgba32> target, KeyValuePair <ResourceLocation, Image <Rgba32> >[] data, ref int xi, ref int yi, ref int xOffset, ref int yRemaining, int total, int processed, IDictionary <ResourceLocation, TextureInfo> locations, IProgressReceiver progressReceiver, bool animated) { int done = processed; var count = 0; foreach (var bm in data.OrderByDescending(x => x.Value.Height)) { var key = bm.Key; count++; // double percentage = 100D * ((double)processed / (double)total); progressReceiver.UpdateProgress(processed, total, null, key.ToString()); var sourceRegion = new System.Drawing.Rectangle(0, 0, bm.Value.Width, bm.Value.Height); var targetRegion = new System.Drawing.Rectangle(xi, yi, bm.Value.Width, bm.Value.Height); TextureUtils.CopyRegionIntoImage(bm.Value, sourceRegion, ref target, targetRegion); if (!locations.ContainsKey(key)) { locations.Add(key, new TextureInfo(new Vector2(target.Width, target.Height), new Vector2(xi, yi), bm.Value.Width / 16, bm.Value.Height / 16, animated, true)); } if (bm.Value.Height > TextureHeight) { xOffset = xi; yRemaining = bm.Value.Height; } xi += bm.Value.Width; if (count == target.Width / TextureWidth) { yi += TextureHeight; xi = 0; yRemaining -= TextureHeight; count = 0; } done++; } return(done); }
private int Process(ref Bitmap bmp, KeyValuePair <string, Bitmap>[] data, ref int xi, ref int yi, ref int xOffset, ref int yRemaining, int total, int processed, IDictionary <string, TextureInfo> locations, IProgressReceiver progressReceiver) { int done = processed; var count = 0; foreach (var bm in data.OrderByDescending(x => x.Value.Height)) { string key = bm.Key; count++; double percentage = 100D * ((double)processed / (double)total); progressReceiver.UpdateProgress((int)percentage, "Stitching textures...", key); var sourceRegion = new System.Drawing.Rectangle(0, 0, bm.Value.Width, bm.Value.Height); var targetRegion = new System.Drawing.Rectangle(xi, yi, bm.Value.Width, bm.Value.Height); TextureUtils.CopyRegionIntoImage(bm.Value, sourceRegion, ref bmp, targetRegion); if (!locations.ContainsKey(key)) { locations.Add(key, new TextureInfo(new Vector2(xi, yi), bm.Value.Width, bm.Value.Height)); } if (bm.Value.Height > TextureHeight) { xOffset = xi; yRemaining = bm.Value.Height; } xi += bm.Value.Width; if (count == AtlasWidth / TextureWidth) { yi += TextureHeight; xi = 0; yRemaining -= TextureHeight; count = 0; } done++; } return(done); }
private Image <Rgba32>[] GetFrames(Image <Rgba32> source) { int ix = source.Width / TextureWidth; int iy = source.Height / TextureHeight; List <Image <Rgba32> > result = new List <Image <Rgba32> >(); for (int x = 0; x < ix; x++) { for (int y = 0; y < iy; y++) { var newBitmap = new Image <Rgba32>(TextureWidth, TextureHeight); TextureUtils.CopyRegionIntoImage(source, new System.Drawing.Rectangle(x * TextureWidth, y * TextureHeight, TextureWidth, TextureHeight), ref newBitmap, new System.Drawing.Rectangle(0, 0, TextureWidth, TextureHeight)); result.Add(newBitmap); } } return(result.ToArray()); }
private Bitmap[] GetFrames(Bitmap source) { int ix = source.Width / TextureWidth; int iy = source.Height / TextureHeight; List <Bitmap> result = new List <Bitmap>(); for (int x = 0; x < ix; x++) { for (int y = 0; y < iy; y++) { Bitmap newBitmap = new Bitmap(TextureWidth, TextureHeight); TextureUtils.CopyRegionIntoImage(source, new System.Drawing.Rectangle(x, y, TextureWidth, TextureHeight), ref newBitmap, new System.Drawing.Rectangle(0, 0, TextureWidth, TextureHeight)); result.Add(newBitmap); } } return(result.ToArray()); }
private PooledTexture2D[] ProcessFrames(GraphicsDevice device, IProgressReceiver progressReceiver, IDictionary <ResourceLocation, ImageEntry> blockTextures) { Dictionary <ResourceLocation, Image <Rgba32>[]> blockFrames = new Dictionary <ResourceLocation, Image <Rgba32>[]>(); foreach (var other in blockTextures.Where( x => x.Value.Image.Height != x.Value.Image.Width)) { if (!blockFrames.TryGetValue(other.Key, out _)) { blockFrames.Add(other.Key, GetFrames(other.Value, TextureWidth, TextureHeight)); } } var animatedFrameInfo = new Dictionary <ResourceLocation, TextureInfo>(); GenerateAtlasInternal( blockFrames.Select(x => new KeyValuePair <ResourceLocation, Image <Rgba32> >(x.Key, x.Value[0])).ToArray(), progressReceiver, animatedFrameInfo, true, out var animatedFrame); AnimatedAtlasSize = new Vector2(animatedFrame.Width, animatedFrame.Height); _animatedAtlasLocations = animatedFrameInfo; var frameCount = blockFrames.Max(x => x.Value.Length); while (frameCount % 2 != 0) { frameCount++; } var frames = new Image <Rgba32> [frameCount]; frames[0] = animatedFrame; for (int i = 1; i < frames.Length; i++) { // double percentage = 100D * ((double) i / (double) frames.Length); progressReceiver.UpdateProgress(i, frames.Length, $"Animating frame {i + 1} / {frames.Length}..."); var target = (i > 0 ? frames[i - 1] : animatedFrame).CloneAs <Rgba32>(); //new Bitmap(animatedFrame); // System.Drawing.Rectangle destination; foreach (var animated in blockFrames) { progressReceiver.UpdateProgress(i, frames.Length, null, animated.Key.ToString()); if (animatedFrameInfo.TryGetValue(animated.Key, out var textureInfo)) { //((i % 3 == 0 ? i - 1 : i) / 6) var destination = new System.Drawing.Rectangle( (int)textureInfo.Position.X, (int)textureInfo.Position.Y, textureInfo.Width * 16, textureInfo.Height * 16); var sourceRegion = new System.Drawing.Rectangle(0, 0, textureInfo.Width * 16, textureInfo.Height * 16); var index = i % animated.Value.Length; var indexOffset = 0; bool shouldInterpolate = false; float interpolationValue = 0.5f; if (blockTextures.TryGetValue(animated.Key, out var imageEntry) && imageEntry.Meta != null) { var meta = imageEntry.Meta; if (meta.Animation != null) { if (meta.Animation.Interpolate) { int extraFrames = (frames.Length - animated.Value.Length); var interpolationFrames = (int)Math.Floor( ((double)extraFrames / (double)animated.Value.Length)); var remainder = i % interpolationFrames; if (remainder != 0) { shouldInterpolate = true; interpolationValue = (1f / interpolationFrames) * remainder; indexOffset = -remainder; // index -= remainder; } } if (meta.Animation.Frames != null) { var entry = meta.Animation.Frames[(i + indexOffset) % meta.Animation.Frames.Length]; if (entry.Integer.HasValue) { index = (int)entry.Integer.Value; } else if (entry.FrameClass != null) { index = (int)entry.FrameClass.Index; } } else { index = (i + indexOffset) % animated.Value.Length; } } } //TextureUtils.ClearRegion(ref target, destination); if (shouldInterpolate) { TextureUtils.CopyRegionIntoImage( ((i + indexOffset >= 0) ? frames[(i + indexOffset) % frames.Length] : animatedFrame), destination, ref target, destination, clear: true); } var texture = animated.Value[index]; TextureUtils.CopyRegionIntoImage( texture, sourceRegion, ref target, destination, shouldInterpolate, interpolationValue, clear: !shouldInterpolate); } } frames[i] = target; } return(frames.Select( (x, index) => { var a = GetMipMappedTexture2D(device, x); //totalSize += a.MemoryUsage; return a; }).ToArray()); }
public void GenerateAtlas(GraphicsDevice device, KeyValuePair <string, Image <Rgba32> >[] bitmaps, IReadOnlyDictionary <string, TextureMeta> meta, IProgressReceiver progressReceiver) { Stopwatch sw = Stopwatch.StartNew(); Log.Info($"Generating texture atlas out of {bitmaps.Length} bitmaps..."); long totalSize = 0; Image <Rgba32> no; using (MemoryStream ms = new MemoryStream(ResourceManager.ReadResource("Alex.Resources.no.png"))) { no = Image.Load <Rgba32>(ms); } // Dictionary<string, Bitmap[]> animatedFrames = new Dictionary<string, Bitmap[]>(); foreach (var bmp in bitmaps) { if (meta.TryGetValue(bmp.Key, out var textureMeta)) { if (textureMeta.Animation == null || textureMeta.Animation == default) { continue; } // Bitmap[] bmpFrames = GetFrames(bmp.Value); // animatedFrames.Add(bmp.Key, bmpFrames); } } var regular = new[] { new KeyValuePair <string, Image <Rgba32> >("no_texture", no), }.Concat(bitmaps.Where(x => x.Value.Height == TextureHeight && x.Value.Width == TextureWidth)).ToArray(); var others = bitmaps.Where(x => x.Value.Height != TextureHeight || x.Value.Width != TextureWidth).ToList(); Image <Rgba32>[] waterFrames = new Image <Rgba32> [0]; Image <Rgba32>[] lavaFrames = new Image <Rgba32> [0]; Image <Rgba32>[] waterFlowFrames = new Image <Rgba32> [0]; Image <Rgba32>[] lavaFlowFrames = new Image <Rgba32> [0]; Image <Rgba32>[] fireFrames = new Image <Rgba32> [0]; Image <Rgba32>[] fireFrames2 = new Image <Rgba32> [0]; Image <Rgba32>[] portalFrames = new Image <Rgba32> [0]; Image <Rgba32>[] seagrassFrames = new Image <Rgba32> [0]; foreach (var other in others.ToArray()) { if (other.Key.Contains("water") && other.Key.Contains("still")) { waterFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("water") && other.Key.Contains("flow")) { waterFlowFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("lava") && other.Key.Contains("still")) { lavaFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("lava") && other.Key.Contains("flow")) { lavaFlowFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("fire_0")) { fireFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("fire_1")) { fireFrames2 = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("nether_portal")) { portalFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("seagrass")) { seagrassFrames = GetFrames(other.Value); others.Remove(other); } //seagrass } Dictionary <string, TextureInfo> stillFrameInfo = new Dictionary <string, TextureInfo>(); GenerateAtlasInternal(regular, others.ToArray(), progressReceiver, stillFrameInfo, out var stillAtlas); _stillFrame = TextureUtils.BitmapToTexture2D(device, stillAtlas, out var size); //stillAtlas.Save(Path.Combine(DebugPath, "atlas.png")); totalSize += size; _atlasLocations = stillFrameInfo; Dictionary <string, Image <Rgba32> > animated = new Dictionary <string, Image <Rgba32> >(); if (waterFrames.Length > 0) { animated.Add("block/water_still", waterFrames[0]); } if (waterFlowFrames.Length > 0) { animated.Add("block/water_flow", waterFlowFrames[0]); } if (lavaFrames.Length > 0) { animated.Add("block/lava_still", lavaFrames[0]); } if (lavaFlowFrames.Length > 0) { animated.Add("block/lava_flow", lavaFlowFrames[0]); } if (fireFrames.Length > 0) { animated.Add("block/fire_0", fireFrames[0]); } if (fireFrames2.Length > 0) { animated.Add("block/fire_1", fireFrames2[0]); } if (portalFrames.Length > 0) { animated.Add("block/nether_portal", portalFrames[0]); } if (seagrassFrames.Length > 0) { animated.Add("block/seagrass", seagrassFrames[0]); } var animatedFrameInfo = new Dictionary <string, TextureInfo>(); GenerateAtlasInternal(animated.ToArray(), new KeyValuePair <string, Image <Rgba32> > [0], progressReceiver, animatedFrameInfo, out Image <Rgba32> animatedFrame); AnimatedAtlasSize = new Vector2(animatedFrame.Width, animatedFrame.Height); TextureInfo waterLocation, waterFlowLocation, lavaLocation, lavaFlowLocation, fireLocation, fireLocation2, portalLocation, seagrassLocation; animatedFrameInfo.TryGetValue("block/water_still", out waterLocation); animatedFrameInfo.TryGetValue("block/water_flow", out waterFlowLocation); animatedFrameInfo.TryGetValue("block/lava_still", out lavaLocation); animatedFrameInfo.TryGetValue("block/lava_flow", out lavaFlowLocation); animatedFrameInfo.TryGetValue("block/fire_0", out fireLocation); animatedFrameInfo.TryGetValue("block/fire_1", out fireLocation2); animatedFrameInfo.TryGetValue("block/nether_portal", out portalLocation); animatedFrameInfo.TryGetValue("block/seagrass", out seagrassLocation); //var waterLocation = new Vector3(); // var baseBitmap = new Bitmap(stillAtlas.Width, stillAtlas.Height); var frameCount = Math.Max(Math.Max(Math.Max(waterFrames.Length, Math.Max(waterFlowFrames.Length, Math.Max(lavaFrames.Length, Math.Max(lavaFlowFrames.Length, fireFrames.Length)))), portalFrames.Length), seagrassFrames.Length); while (frameCount % 2 != 0) { frameCount++; } var frames = new Texture2D[frameCount]; for (int i = 0; i < frames.Length; i++) { var target = animatedFrame.CloneAs <Rgba32>(); //new Bitmap(animatedFrame); var r = new System.Drawing.Rectangle(0, 0, TextureWidth, TextureHeight); var destination = new System.Drawing.Rectangle((int)waterLocation.Position.X, (int)waterLocation.Position.Y, TextureWidth, TextureHeight); if (waterFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(waterFrames[((i % 3 == 0 ? i - 1 : i) / 6) % waterFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)waterFlowLocation.Position.X, (int)waterFlowLocation.Position.Y, TextureWidth, TextureHeight); if (waterFlowFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(waterFlowFrames[i % waterFlowFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)lavaLocation.Position.X, (int)lavaLocation.Position.Y, TextureWidth, TextureHeight); if (lavaFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(lavaFrames[i % lavaFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)lavaFlowLocation.Position.X, (int)lavaFlowLocation.Position.Y, TextureWidth, TextureHeight); if (lavaFlowFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(lavaFlowFrames[i % lavaFlowFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)fireLocation.Position.X, (int)fireLocation.Position.Y, TextureWidth, TextureHeight); if (fireFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(fireFrames[i % fireFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)fireLocation2.Position.X, (int)fireLocation2.Position.Y, TextureWidth, TextureHeight); if (fireFrames2.Length > 0) { TextureUtils.CopyRegionIntoImage(fireFrames2[i % fireFrames2.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)portalLocation.Position.X, (int)portalLocation.Position.Y, TextureWidth, TextureHeight); if (portalFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(portalFrames[i % portalFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)seagrassLocation.Position.X, (int)seagrassLocation.Position.Y, TextureWidth, TextureHeight); if (seagrassFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(seagrassFrames[i % seagrassFrames.Length], r, ref target, destination); } frames[i] = TextureUtils.BitmapToTexture2D(device, target, out var s); totalSize += s; // target.Save(Path.Combine(DebugFramePath, $"frame{i}.png")); } _animatedAtlasLocations = animatedFrameInfo; AtlasSize = new Vector2(stillAtlas.Width, stillAtlas.Height); _frames = frames; sw.Stop(); Log.Info($"TextureAtlas generated in {sw.ElapsedMilliseconds}ms! ({PlayingState.GetBytesReadable(totalSize, 2)})"); }
private void GenerateAtlas(GraphicsDevice device, IDictionary <ResourceLocation, ImageEntry> blockTextures, IProgressReceiver progressReceiver) { Stopwatch sw = Stopwatch.StartNew(); Log.Info($"Generating texture atlas out of {(blockTextures.Count)} bitmaps..."); long totalSize = 0; Image <Rgba32> no; using (MemoryStream ms = new MemoryStream(ResourceManager.ReadResource("Alex.Resources.no.png"))) { no = Image.Load <Rgba32>(ms); } Dictionary <ResourceLocation, TextureInfo> stillFrameInfo = new Dictionary <ResourceLocation, TextureInfo>(); GenerateAtlasInternal( new[] { new KeyValuePair <ResourceLocation, Image <Rgba32> >("no_texture", no), }.Concat( blockTextures .Where(x => x.Value.Image.Height == TextureHeight && x.Value.Image.Width == TextureWidth).Select( x => new KeyValuePair <ResourceLocation, Image <Rgba32> >(x.Key, x.Value.Image))).ToArray(), progressReceiver, stillFrameInfo, false, out var stillAtlas); AtlasSize = new Vector2(stillAtlas.Width, stillAtlas.Height); // totalSize += size; _atlasLocations = stillFrameInfo; Dictionary <ResourceLocation, Image <Rgba32>[]> blockFrames = new Dictionary <ResourceLocation, Image <Rgba32>[]>(); foreach (var other in blockTextures.Where( x => x.Value.Image.Height != x.Value.Image.Width)) { if (!blockFrames.TryGetValue(other.Key, out _)) { blockFrames.Add(other.Key, GetFrames(other.Value.Image, TextureWidth, TextureHeight)); } } var animatedFrameInfo = new Dictionary <ResourceLocation, TextureInfo>(); GenerateAtlasInternal( blockFrames.Select(x => new KeyValuePair <ResourceLocation, Image <Rgba32> >(x.Key, x.Value[0])).ToArray(), progressReceiver, animatedFrameInfo, true, out Image <Rgba32> animatedFrame); AnimatedAtlasSize = new Vector2(animatedFrame.Width, animatedFrame.Height); _animatedAtlasLocations = animatedFrameInfo; var frameCount = blockFrames.Max(x => x.Value.Length); while (frameCount % 2 != 0) { frameCount++; } var frames = new Image <Rgba32> [frameCount]; frames[0] = animatedFrame; for (int i = 1; i < frames.Length; i++) { double percentage = 100D * ((double)i / (double)frames.Length); progressReceiver.UpdateProgress((int)percentage, $"Animating frame {i + 1} / {frames.Length}..."); var target = (i > 0 ? frames[i - 1] : animatedFrame).CloneAs <Rgba32>(); //new Bitmap(animatedFrame); // System.Drawing.Rectangle destination; foreach (var animated in blockFrames) { progressReceiver.UpdateProgress((int)percentage, null, animated.Key.ToString()); if (animatedFrameInfo.TryGetValue(animated.Key, out var textureInfo)) { //((i % 3 == 0 ? i - 1 : i) / 6) var destination = new System.Drawing.Rectangle( (int)textureInfo.Position.X, (int)textureInfo.Position.Y, textureInfo.Width, textureInfo.Height); var sourceRegion = new System.Drawing.Rectangle(0, 0, textureInfo.Width, textureInfo.Height); var index = i % animated.Value.Length; var indexOffset = 0; bool shouldInterpolate = false; float interpolationValue = 0.5f; if (blockTextures.TryGetValue(animated.Key, out var imageEntry) && imageEntry.Meta != null) { var meta = imageEntry.Meta; if (meta.Animation != null) { if (meta.Animation.Interpolate) { int extraFrames = (frames.Length - animated.Value.Length); var interpolationFrames = (int)Math.Floor(((double)extraFrames / (double)animated.Value.Length)); var remainder = i % interpolationFrames; if (remainder != 0) { shouldInterpolate = true; interpolationValue = (1f / interpolationFrames) * remainder; indexOffset = -remainder; // index -= remainder; } } if (meta.Animation.Frames != null) { var entry = meta.Animation.Frames[(i + indexOffset) % meta.Animation.Frames.Length]; if (entry.Integer.HasValue) { index = (int)entry.Integer.Value; } else if (entry.FrameClass != null) { index = (int)entry.FrameClass.Index; } } else { index = (i + indexOffset) % animated.Value.Length; } } } //TextureUtils.ClearRegion(ref target, destination); if (shouldInterpolate) { TextureUtils.CopyRegionIntoImage( ((i + indexOffset >= 0) ? frames[(i + indexOffset) % frames.Length] : animatedFrame), destination, ref target, destination, clear: true); } var texture = animated.Value[index]; TextureUtils.CopyRegionIntoImage(texture, sourceRegion, ref target, destination, shouldInterpolate, interpolationValue, clear: !shouldInterpolate); } } frames[i] = target; } _frames = frames.Select( x => { var a = TextureUtils.BitmapToTexture2D(device, x, out var s); totalSize += s; return(a); }).ToArray(); _stillFrame = TextureUtils.BitmapToTexture2D(device, stillAtlas, out var size); totalSize += size; sw.Stop(); Log.Info( $"TextureAtlas's generated in {sw.ElapsedMilliseconds}ms! ({PlayingState.GetBytesReadable(totalSize, 2)})"); /* * PngEncoder encoder = new PngEncoder(); * * stillAtlas.Save("atlas.png", encoder); * * if (!Directory.Exists("frames")) * Directory.CreateDirectory("frames"); * * for (var index = 0; index < frames.Length; index++) * { * var frame = frames[index]; * * frame.Save(Path.Combine("frames", $"frame-{index}.png"), encoder); * }*/ }
private void GenerateAtlas(GraphicsDevice device, IDictionary <ResourceLocation, Image <Rgba32>[]> blockFrames, IDictionary <ResourceLocation, Image <Rgba32> > blockTextures, IProgressReceiver progressReceiver) { Stopwatch sw = Stopwatch.StartNew(); Log.Info($"Generating texture atlas out of {(blockFrames.Count + blockTextures.Count)} bitmaps..."); long totalSize = 0; Image <Rgba32> no; using (MemoryStream ms = new MemoryStream(ResourceManager.ReadResource("Alex.Resources.no.png"))) { no = Image.Load <Rgba32>(ms); } var regularTextures = new[] { new KeyValuePair <ResourceLocation, Image <Rgba32> >("no_texture", no), }.Concat(blockTextures.Where(x => x.Value.Height == TextureHeight && x.Value.Width == TextureWidth)).ToArray(); var oddSizedTextures = blockTextures.Where(x => x.Value.Height != TextureHeight || x.Value.Width != TextureWidth).ToArray(); for (var index = 0; index < oddSizedTextures.Length; index++) { var other = oddSizedTextures[index]; if (blockFrames.TryGetValue(other.Key, out var values)) { oddSizedTextures[index] = new KeyValuePair <ResourceLocation, Image <Rgba32> >(other.Key, values[0]); } } Dictionary <ResourceLocation, TextureInfo> stillFrameInfo = new Dictionary <ResourceLocation, TextureInfo>(); GenerateAtlasInternal(regularTextures, oddSizedTextures, progressReceiver, stillFrameInfo, false, out var stillAtlas); _stillFrame = TextureUtils.BitmapToTexture2D(device, stillAtlas, out var size); AtlasSize = new Vector2(stillAtlas.Width, stillAtlas.Height); totalSize += size; _atlasLocations = stillFrameInfo; var animatedFrameInfo = new Dictionary <ResourceLocation, TextureInfo>(); GenerateAtlasInternal(blockFrames.Select(x => new KeyValuePair <ResourceLocation, Image <Rgba32> >(x.Key, x.Value[0])).ToArray(), new KeyValuePair <ResourceLocation, Image <Rgba32> > [0], progressReceiver, animatedFrameInfo, true, out Image <Rgba32> animatedFrame); AnimatedAtlasSize = new Vector2(animatedFrame.Width, animatedFrame.Height); _animatedAtlasLocations = animatedFrameInfo; var frameCount = blockFrames.Max(x => x.Value.Length); while (frameCount % 2 != 0) { frameCount++; } var frames = new Texture2D[frameCount]; for (int i = 0; i < frames.Length; i++) { double percentage = 100D * ((double)i / (double)frames.Length); progressReceiver.UpdateProgress((int)percentage, $"Animating frame {i}..."); var target = animatedFrame.CloneAs <Rgba32>(); //new Bitmap(animatedFrame); // System.Drawing.Rectangle destination; foreach (var animated in blockFrames) { progressReceiver.UpdateProgress((int)percentage, null, animated.Key.ToString()); if (animatedFrameInfo.TryGetValue(animated.Key, out var textureInfo)) { //((i % 3 == 0 ? i - 1 : i) / 6) var destination = new System.Drawing.Rectangle( (int)textureInfo.Position.X, (int)textureInfo.Position.Y, textureInfo.Width, textureInfo.Height); TextureUtils.CopyRegionIntoImage( animated.Value[i % animated.Value.Length], new System.Drawing.Rectangle(0, 0, textureInfo.Width, textureInfo.Height), ref target, destination); } } frames[i] = TextureUtils.BitmapToTexture2D(device, target, out var s); totalSize += s; } _frames = frames; sw.Stop(); Log.Info($"TextureAtlas generated in {sw.ElapsedMilliseconds}ms! ({PlayingState.GetBytesReadable(totalSize, 2)})"); }
public void GenerateAtlas(KeyValuePair <string, Bitmap>[] bitmaps, IProgressReceiver progressReceiver) { Log.Info($"Generating texture atlas out of {bitmaps.Length} bitmaps..."); long totalSize = 0; Bitmap no; using (MemoryStream ms = new MemoryStream(ResourceManager.ReadResource("Alex.Resources.no.png"))) { no = new Bitmap(ms); } var regular = new[] { new KeyValuePair <string, Bitmap>("no_texture", no), }.Concat(bitmaps.Where(x => x.Value.Height == TextureHeight && x.Value.Width == TextureWidth)).ToArray(); var others = bitmaps.Where(x => x.Value.Height != TextureHeight || x.Value.Width != TextureWidth).ToList(); Bitmap[] waterFrames = new Bitmap[0]; Bitmap[] lavaFrames = new Bitmap[0]; Bitmap[] waterFlowFrames = new Bitmap[0]; Bitmap[] lavaFlowFrames = new Bitmap[0]; foreach (var other in others.ToArray()) { if (other.Key.Contains("water") && other.Key.Contains("still")) { waterFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("water") && other.Key.Contains("flow")) { waterFlowFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("lava") && other.Key.Contains("still")) { lavaFrames = GetFrames(other.Value); others.Remove(other); } else if (other.Key.Contains("lava") && other.Key.Contains("flow")) { lavaFlowFrames = GetFrames(other.Value); others.Remove(other); } } Dictionary <string, TextureInfo> stillFrameInfo = new Dictionary <string, TextureInfo>(); GenerateAtlasInternal(regular, others.ToArray(), progressReceiver, stillFrameInfo, out Bitmap stillAtlas); _stillFrame = TextureUtils.BitmapToTexture2D(Graphics, stillAtlas, out var size); totalSize += size; _atlasLocations = stillFrameInfo; Dictionary <string, Bitmap> animated = new Dictionary <string, Bitmap>(); if (waterFrames.Length > 0) { // total++; animated.Add("block/water_still", waterFrames[0]); // regular = regular.Append(new KeyValuePair<string, Bitmap>("block/water_still", waterFrames[0])).ToArray(); } if (waterFlowFrames.Length > 0) { // total++; animated.Add("block/water_flow", waterFlowFrames[0]); // regular = regular.Append(new KeyValuePair<string, Bitmap>("block/water_flow", waterFlowFrames[0])).ToArray(); } if (lavaFrames.Length > 0) { animated.Add("block/lava_still", lavaFrames[0]); // total++; // regular = regular.Append(new KeyValuePair<string, Bitmap>("block/lava_still", lavaFrames[0])).ToArray(); } if (lavaFlowFrames.Length > 0) { animated.Add("block/lava_flow", lavaFlowFrames[0]); // total++; // regular = regular.Append(new KeyValuePair<string, Bitmap>("block/lava_flow", lavaFlowFrames[0])).ToArray(); } var animatedFrameInfo = new Dictionary <string, TextureInfo>(); GenerateAtlasInternal(animated.ToArray(), new KeyValuePair <string, Bitmap> [0], progressReceiver, animatedFrameInfo, out Bitmap animatedFrame); TextureInfo waterLocation, waterFlowLocation, lavaLocation, lavaFlowLocation; animatedFrameInfo.TryGetValue("block/water_still", out waterLocation); animatedFrameInfo.TryGetValue("block/water_flow", out waterFlowLocation); animatedFrameInfo.TryGetValue("block/lava_still", out lavaLocation); animatedFrameInfo.TryGetValue("block/lava_flow", out lavaFlowLocation); //var waterLocation = new Vector3(); // var baseBitmap = new Bitmap(stillAtlas.Width, stillAtlas.Height); var frames = new Texture2D[Math.Max(waterFrames.Length, waterFlowFrames.Length)]; for (int i = 0; i < frames.Length; i++) { var target = new Bitmap(animatedFrame); var r = new System.Drawing.Rectangle(0, 0, TextureWidth, TextureHeight); var destination = new System.Drawing.Rectangle((int)waterLocation.Position.X, (int)waterLocation.Position.Y, TextureWidth, TextureHeight); if (waterFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(waterFrames[((i % 3 == 0 ? i - 1 : i) / 6) % waterFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)waterFlowLocation.Position.X, (int)waterFlowLocation.Position.Y, TextureWidth, TextureHeight); if (waterFlowFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(waterFlowFrames[i % waterFlowFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)lavaLocation.Position.X, (int)lavaLocation.Position.Y, TextureWidth, TextureHeight); if (lavaFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(lavaFrames[i % lavaFrames.Length], r, ref target, destination); } destination = new System.Drawing.Rectangle((int)lavaFlowLocation.Position.X, (int)lavaFlowLocation.Position.Y, TextureWidth, TextureHeight); if (lavaFlowFrames.Length > 0) { TextureUtils.CopyRegionIntoImage(lavaFlowFrames[i % lavaFlowFrames.Length], r, ref target, destination); } frames[i] = TextureUtils.BitmapToTexture2D(Graphics, target, out var s); totalSize += s; } _animatedAtlasLocations = animatedFrameInfo; AtlasSize = new Vector2(stillAtlas.Width, stillAtlas.Height); _frames = frames; Log.Info($"TextureAtlas generated! ({PlayingState.GetBytesReadable(totalSize, 2)})"); }