public static packSprites ( IList |
||
sourceSprites | IList |
|
outputSprites | ICollection |
|
isCompressed | bool | |
context | ContentProcessorContext | |
return | PixelBitmapContent |
public static PixelBitmapContent<Color> packSprites( IList<BitmapContent> sourceSprites, ICollection<Rectangle> outputSprites, bool isCompressed, ContentProcessorContext context )
{
if( sourceSprites.Count == 0 )
throw new InvalidContentException( "There are no sprites to pack" );
// Build up a list of all the sprites needing to be arranged.
var sprites = new List<ArrangedSprite>();
for( var i = 0; i < sourceSprites.Count; i++ )
{
var sprite = new ArrangedSprite();
// Include a single pixel padding around each sprite, to avoid filtering problems if the sprite is scaled or rotated.
sprite.width = sourceSprites[i].Width + 2;
sprite.height = sourceSprites[i].Height + 2;
sprite.index = i;
sprites.Add( sprite );
}
// Sort so the largest sprites get arranged first.
sprites.Sort( compareSpriteSizes );
// Work out how big the output bitmap should be.
var outputWidth = guessOutputWidth( sprites );
var outputHeight = 0;
var totalSpriteSize = 0;
// Choose positions for each sprite, one at a time.
for( var i = 0; i < sprites.Count; i++ )
{
positionSprite( sprites, i, outputWidth );
outputHeight = Math.Max( outputHeight, sprites[i].y + sprites[i].height );
totalSpriteSize += sprites[i].width * sprites[i].height;
}
// DXT compression requires texture sizes to be a multiple of 4
if( isCompressed )
outputHeight = (outputHeight + 3) & ~3;
// sort the sprites back into index order.
sprites.Sort( compareSpriteIndices );
context.Logger.LogImportantMessage(
"\nPacked {0} sprites into a {1}x{2} sheet, {3}% efficiency",
sprites.Count, outputWidth, outputHeight,
totalSpriteSize * 100 / outputWidth / outputHeight );
return copySpritesToOutput( sprites, sourceSprites, outputSprites, outputWidth, outputHeight );
}
/// <summary> /// Converts an array of sprite filenames into a texture atlas object. /// </summary> public override TextureAtlasContent Process(string[] input, ContentProcessorContext context) { logger = context.Logger; var textureAtlas = new TextureAtlasContent { animationFPS = (int)animationFPS }; var sourceSprites = new List <BitmapContent>(); var imagePaths = new List <string>(); // first, we need to sort through and figure out which passed in paths are images and which are folders foreach (var inputPath in input) { // first, the easy one. if it isnt a directory its an image so just add it if (!Directory.Exists(inputPath)) { if (isValidImageFile(inputPath)) { imagePaths.Add(inputPath); } continue; } // we have a directory. we need to recursively add all images in all subfolders processDirectory(inputPath, imagePaths, textureAtlas); } // Loop over each input sprite filename foreach (var inputFilename in imagePaths) { // Store the name of this sprite. var spriteName = getSpriteNameFromFilename(inputFilename, input); textureAtlas.spriteNames.Add(spriteName, sourceSprites.Count); context.Logger.LogMessage("Adding texture: {0}", spriteName); // Load the sprite texture into memory. var textureReference = new ExternalReference <TextureContent>(inputFilename); var texture = context.BuildAndLoadAsset <TextureContent, TextureContent>(textureReference, "TextureProcessor"); if (inputFilename.Contains(".9")) { logger.LogMessage("\tprocessing nine patch texture"); textureAtlas.nineSliceSplits[spriteName] = processNinePatchTexture(texture); } sourceSprites.Add(texture.Faces[0][0]); } // Pack all the sprites into a single large texture. var packedSprites = TextureAtlasPacker.packSprites(sourceSprites, textureAtlas.spriteRectangles, compressTexture, context); textureAtlas.texture.Mipmaps.Add(packedSprites); if (compressTexture) { textureAtlas.texture.ConvertBitmapType(typeof(Dxt5BitmapContent)); } return(textureAtlas); }