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 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()); }