/// <summary> /// Creates and Saves texture atlas image from images in GroupAsset /// </summary> /// <param name="commandContext">The command context</param> /// <param name="spriteToPackedSprite">A map associating the packed sprite info to the original sprite</param> /// <returns>Status of building</returns> private ResultStatus CreateAtlasTextures(ICommandContext commandContext, out Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite) { var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService); spriteToPackedSprite = new Dictionary <SpriteInfo, PackedSpriteInfo>(); // Pack textures using (var texTool = new TextureTool()) { var textureElements = new List <AtlasTextureElement>(); // Input textures var imageDictionary = new Dictionary <string, Image>(); var imageInfoDictionary = new Dictionary <string, SpriteInfo>(); var sprites = Parameters.SheetAsset.Sprites; var packingParameters = Parameters.SheetAsset.Packing; bool isSRgb = Parameters.SheetAsset.IsSRGBTexture(Parameters.ColorSpace); for (var i = 0; i < sprites.Count; ++i) { var sprite = sprites[i]; if (sprite.TextureRegion.Height == 0 || sprite.TextureRegion.Width == 0 || sprite.Source == null) { continue; } // Lazy load input texture and cache in the dictionary for the later use Image texture; if (!imageDictionary.ContainsKey(sprite.Source)) { texture = LoadImage(texTool, new UFile(sprite.Source), isSRgb); imageDictionary[sprite.Source] = texture; } else { texture = imageDictionary[sprite.Source]; } var key = Url + "_" + i; var sourceRectangle = new RotableRectangle(sprite.TextureRegion, sprite.Orientation == ImageOrientation.Rotated90); textureElements.Add(new AtlasTextureElement(key, texture, sourceRectangle, packingParameters.BorderSize, sprite.BorderModeU, sprite.BorderModeV, sprite.BorderColor)); imageInfoDictionary[key] = sprite; } // find the maximum texture size supported var maximumSize = TextureHelper.FindMaximumTextureSize(new TextureHelper.ImportParameters(Parameters), new Size2(int.MaxValue / 2, int.MaxValue / 2)); // Initialize packing configuration from GroupAsset var texturePacker = new TexturePacker { Algorithm = packingParameters.PackingAlgorithm, AllowMultipack = packingParameters.AllowMultipacking, MaxWidth = maximumSize.Width, MaxHeight = maximumSize.Height, AllowRotation = packingParameters.AllowRotations, }; var canPackAllTextures = texturePacker.PackTextures(textureElements); if (!canPackAllTextures) { commandContext.Logger.Error("Failed to pack all textures"); return(ResultStatus.Failed); } // Create and save every generated texture atlas for (var textureAtlasIndex = 0; textureAtlasIndex < texturePacker.AtlasTextureLayouts.Count; ++textureAtlasIndex) { var atlasLayout = texturePacker.AtlasTextureLayouts[textureAtlasIndex]; ResultStatus resultStatus; using (var atlasImage = AtlasTextureFactory.CreateTextureAtlas(atlasLayout, isSRgb)) using (var texImage = texTool.Load(atlasImage, isSRgb)) { var outputUrl = SpriteSheetAsset.BuildTextureAtlasUrl(Url, textureAtlasIndex); var convertParameters = new TextureHelper.ImportParameters(Parameters) { OutputUrl = outputUrl }; resultStatus = TextureHelper.ShouldUseDataContainer(Parameters.SheetAsset.IsStreamable && Parameters.SheetAsset.Type != SpriteSheetType.UI, texImage.Dimension)? TextureHelper.ImportStreamableTextureImage(assetManager, texTool, texImage, convertParameters, CancellationToken, commandContext) : TextureHelper.ImportTextureImage(assetManager, texTool, texImage, convertParameters, CancellationToken, commandContext.Logger); } foreach (var texture in atlasLayout.Textures) { spriteToPackedSprite.Add(imageInfoDictionary[texture.Name], new PackedSpriteInfo(texture.DestinationRegion, textureAtlasIndex, packingParameters.BorderSize)); } if (resultStatus != ResultStatus.Successful) { // Dispose used textures foreach (var image in imageDictionary.Values) { image.Dispose(); } return(resultStatus); } } // Dispose used textures foreach (var image in imageDictionary.Values) { image.Dispose(); } } return(ResultStatus.Successful); }
public PackedSpriteInfo(RotableRectangle packedRectangle, int atlasTextureIndex, float borderSize) { this.packedRectangle = packedRectangle; this.borderSize = borderSize; AtlasTextureIndex = atlasTextureIndex; }
/// <summary> /// Creates and Saves texture atlas image from images in GroupAsset /// </summary> /// <param name="logger">Status Logger</param> /// <param name="spriteToPackedSprite">A map associating the packed sprite info to the original sprite</param> /// <returns>Status of building</returns> private ResultStatus CreateAtlasTextures(Logger logger, out Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite) { spriteToPackedSprite = new Dictionary <SpriteInfo, PackedSpriteInfo>(); // Pack textures using (var texTool = new TextureTool()) { var textureElements = new List <AtlasTextureElement>(); // Input textures var imageDictionary = new Dictionary <string, Image>(); var imageInfoDictionary = new Dictionary <string, SpriteInfo>(); var sprites = AssetParameters.SheetAsset.Sprites; var packingParameters = AssetParameters.SheetAsset.Packing; for (var i = 0; i < sprites.Count; ++i) { var sprite = sprites[i]; if (sprite.TextureRegion.Height == 0 || sprite.TextureRegion.Width == 0 || sprite.Source == null) { continue; } // Lazy load input texture and cache in the dictionary for the later use Image texture; if (!imageDictionary.ContainsKey(sprite.Source)) { texture = LoadImage(texTool, new UFile(sprite.Source), AssetParameters.SheetAsset.SRgb); imageDictionary[sprite.Source] = texture; } else { texture = imageDictionary[sprite.Source]; } var key = Url + "_" + i; var sourceRectangle = new RotableRectangle(sprite.TextureRegion, sprite.Orientation == ImageOrientation.Rotated90); textureElements.Add(new AtlasTextureElement(key, texture, sourceRectangle, packingParameters.BorderSize, sprite.BorderModeU, sprite.BorderModeV, sprite.BorderColor)); imageInfoDictionary[key] = sprite; } // Initialize packing configuration from GroupAsset var texturePacker = new TexturePacker { Algorithm = packingParameters.PackingAlgorithm, AllowMultipack = packingParameters.AllowMultipacking, MaxHeight = packingParameters.AtlasMaximumSize.Y, MaxWidth = packingParameters.AtlasMaximumSize.X, AllowRotation = packingParameters.AllowRotations, }; var canPackAllTextures = texturePacker.PackTextures(textureElements); if (!canPackAllTextures) { logger.Error("Failed to pack all textures"); return(ResultStatus.Failed); } // Create and save every generated texture atlas for (var textureAtlasIndex = 0; textureAtlasIndex < texturePacker.AtlasTextureLayouts.Count; ++textureAtlasIndex) { var atlasLayout = texturePacker.AtlasTextureLayouts[textureAtlasIndex]; ResultStatus resultStatus; using (var atlasImage = AtlasTextureFactory.CreateTextureAtlas(atlasLayout)) using (var texImage = texTool.Load(atlasImage)) { var outputUrl = SpriteSheetAsset.BuildTextureAtlasUrl(Url, textureAtlasIndex); var convertParameters = new TextureHelper.ImportParameters(AssetParameters) { OutputUrl = outputUrl }; resultStatus = TextureHelper.ImportTextureImage(texTool, texImage, convertParameters, CancellationToken, logger); } foreach (var texture in atlasLayout.Textures) { spriteToPackedSprite.Add(imageInfoDictionary[texture.Name], new PackedSpriteInfo(texture.DestinationRegion, textureAtlasIndex, packingParameters.BorderSize)); } if (resultStatus != ResultStatus.Successful) { // Dispose used textures foreach (var image in imageDictionary.Values) { image.Dispose(); } return(resultStatus); } } // Dispose used textures foreach (var image in imageDictionary.Values) { image.Dispose(); } } return(ResultStatus.Successful); }