public override void Export() { List <TexturedTileSegment> allSegments = new List <TexturedTileSegment>(); using (TexturePacker levelPacker = new TexturePacker(Level, TextureClassifier)) { Dictionary <TexturedTile, List <TexturedTileSegment> > textureSegments = levelPacker.GetModelSegments(Definition.Entity); TRTextureDeduplicator deduplicator = new TRTextureDeduplicator { SegmentMap = textureSegments, UpdateGraphics = false }; deduplicator.Deduplicate(); Definition.ObjectTextures = new Dictionary <int, List <IndexedTRObjectTexture> >(); Definition.SpriteSequences = new Dictionary <TR2Entities, TRSpriteSequence>(); Definition.SpriteTextures = new Dictionary <TR2Entities, Dictionary <int, List <IndexedTRSpriteTexture> > >(); int bitmapIndex = 0; foreach (List <TexturedTileSegment> segments in textureSegments.Values) { for (int i = 0; i < segments.Count; i++) { TexturedTileSegment segment = segments[i]; if (!deduplicator.ShouldIgnoreSegment(Definition.Entity, segment)) { allSegments.Add(segment); Definition.ObjectTextures[bitmapIndex++] = new List <IndexedTRObjectTexture>(segment.Textures.Cast <IndexedTRObjectTexture>().ToArray()); } } } if (_entitySpriteDependencies.ContainsKey(Definition.Entity)) { foreach (TR2Entities spriteEntity in _entitySpriteDependencies[Definition.Entity]) { TRSpriteSequence sequence = Level.SpriteSequences.ToList().Find(s => s.SpriteID == (int)spriteEntity); if (sequence != null) { Definition.SpriteSequences[spriteEntity] = sequence; } Dictionary <TexturedTile, List <TexturedTileSegment> > spriteSegments = levelPacker.GetSpriteSegments(spriteEntity); Definition.SpriteTextures[spriteEntity] = new Dictionary <int, List <IndexedTRSpriteTexture> >(); foreach (List <TexturedTileSegment> segments in spriteSegments.Values) { for (int i = 0; i < segments.Count; i++) { TexturedTileSegment segment = segments[i]; allSegments.Add(segment); Definition.SpriteTextures[spriteEntity][bitmapIndex++] = new List <IndexedTRSpriteTexture>(segment.Textures.Cast <IndexedTRSpriteTexture>().ToArray()); } } } } if (allSegments.Count > 0) { using (TexturePacker segmentPacker = new TexturePacker()) { segmentPacker.AddRectangles(allSegments); segmentPacker.Options = new PackingOptions { FillMode = PackingFillMode.Horizontal, OrderMode = PackingOrderMode.Area, Order = PackingOrder.Descending, GroupMode = PackingGroupMode.Squares }; segmentPacker.TileWidth = _defaultBitmapWidth; segmentPacker.TileHeight = _defaultBitmapHeight; segmentPacker.MaximumTiles = 1; segmentPacker.Pack(); if (segmentPacker.OrphanedRectangles.Count > 0) { throw new PackingException(string.Format("Failed to export textures for {0}.", Definition.Entity)); } Definition.ObjectTextureCost = segmentPacker.TotalUsedSpace; TexturedTile tile = segmentPacker.Tiles[0]; List <Rectangle> rects = new List <Rectangle>(); foreach (TexturedTileSegment segment in allSegments) { rects.Add(segment.MappedBounds); } Definition.TextureSegments = rects.ToArray(); Rectangle region = tile.GetOccupiedRegion(); Definition.Bitmap = tile.BitmapGraphics.Extract(region); if (ExportIndividualSegments) { string dir = Path.Combine(SegmentsFolder, Definition.Alias.ToString()); if (Directory.Exists(dir)) { Directory.Delete(dir, true); } Directory.CreateDirectory(dir); foreach (TexturedTileSegment segment in allSegments) { segment.Bitmap.Save(Path.Combine(dir, segment.FirstTextureIndex + ".png"), ImageFormat.Png); } } } } else { Definition.ObjectTextureCost = 0; } } }
private void Pack() { using (TexturePacker packer = new TexturePacker(Level)) { List <TR2Entities> removals = new List <TR2Entities>(); if (ClearUnusedSprites) { removals.Add(TR2Entities.Map_M_U); } if (EntitiesToRemove != null) { removals.AddRange(EntitiesToRemove); } packer.RemoveModelSegments(removals, TextureRemap); ApplyFlamePatch(); if (ClearUnusedSprites) { RemoveUnusedSprites(packer); } List <TexturedTileSegment> allSegments = new List <TexturedTileSegment>(); foreach (List <TexturedTileSegment> segmentList in _importSegments.Values) { // We only add unique segments, so if another segment already exists, // remap the definition's segment to that one. Example of when this is // needed is importing the dragon as DragonBack duplicates a lot of // DragonFront, so this will greatly reduce the import cost. for (int i = 0; i < segmentList.Count; i++) { TexturedTileSegment segment = segmentList[i]; int j = FindMatchingSegment(allSegments, segment); if (j == -1) { allSegments.Add(segment); } else { TexturedTileSegment otherSegment = allSegments[j]; segmentList[i] = allSegments[j]; foreach (IndexedTRObjectTexture texture in segment.Textures) { if (!otherSegment.IsObjectTextureFor(texture.Index)) { otherSegment.AddTexture(texture); } } } } } packer.AddRectangles(allSegments); packer.Pack(true); if (packer.OrphanedRectangles.Count > 0) { List <string> entityNames = new List <string>(); foreach (TRModelDefinition def in Definitions) { entityNames.Add(def.Entity.ToString()); } throw new PackingException(string.Format ( "Failed to pack {0} rectangles for model types [{1}].", packer.OrphanedRectangles.Count, string.Join(", ", entityNames) )); } } }