Exemple #1
0
        private void TidySegment(TexturedTileSegment segment, Dictionary <int, int> reindexMap)
        {
            for (int i = segment.Textures.Count - 1; i > 0; i--) //ignore the first = the largest
            {
                AbstractIndexedTRTexture texture          = segment.Textures[i];
                AbstractIndexedTRTexture candidateTexture = null;
                for (int j = 0; j < segment.Textures.Count; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    AbstractIndexedTRTexture texture2 = segment.Textures[j];
                    if (texture.Equals(texture2))
                    {
                        candidateTexture = texture2;
                        break;
                    }
                }

                if (candidateTexture != null)
                {
                    reindexMap[texture.Index] = candidateTexture.Index;
                    texture.Invalidate();
                    segment.Textures.RemoveAt(i);
                }
            }
        }
Exemple #2
0
        private List <int> GetSpriteTextureList(TexturedTileSegment segment)
        {
            List <int> indices = new List <int>();

            foreach (AbstractIndexedTRTexture texture in segment.Textures)
            {
                if (texture is IndexedTRSpriteTexture)
                {
                    indices.Add(texture.Index);
                }
            }
            return(indices);
        }
Exemple #3
0
 private int FindMatchingSegment(List <TexturedTileSegment> segments, TexturedTileSegment segment)
 {
     for (int i = 0; i < segments.Count; i++)
     {
         TexturedTileSegment otherSegment = segments[i];
         if
         (
             otherSegment.FirstTextureIndex == segment.FirstTextureIndex &&
             otherSegment.FirstClassification == segment.FirstClassification
         )
         {
             return(i);
         }
     }
     return(-1);
 }
Exemple #4
0
        public bool ShouldIgnoreSegment(TR2Entities entity, TexturedTileSegment segment)
        {
            if (IgnoreEntityTextures.ContainsKey(entity))
            {
                if (IgnoreEntityTextures[entity].Count == 0)
                {
                    return(true);
                }

                foreach (int textureIndex in IgnoreEntityTextures[entity])
                {
                    if (segment.IsObjectTextureFor(textureIndex))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemple #5
0
        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;
                }
            }
        }
Exemple #6
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)
                                               ));
                }
            }
        }
Exemple #7
0
        private void CollateSegments()
        {
            // Rebuild the segment list. We assume the list of IndexedTRObjectTextures has been
            // ordered by area descending to preserve the "master" texture for each segment.
            _importSegments = new Dictionary <TRModelDefinition, List <TexturedTileSegment> >();

            // Track existing sprite sequences to avoid duplication
            List <TRSpriteSequence> spriteSequences = Level.SpriteSequences.ToList();

            foreach (TRModelDefinition definition in Definitions)
            {
                if (!definition.HasGraphics || definition.IsDependencyOnly)
                {
                    continue;
                }

                _importSegments[definition] = new List <TexturedTileSegment>();
                using (BitmapGraphics bg = new BitmapGraphics(definition.Bitmap))
                {
                    foreach (int segmentIndex in definition.ObjectTextures.Keys)
                    {
                        Bitmap segmentClip          = bg.Extract(definition.TextureSegments[segmentIndex]);
                        TexturedTileSegment segment = null;
                        foreach (IndexedTRObjectTexture texture in definition.ObjectTextures[segmentIndex])
                        {
                            if (segment == null)
                            {
                                _importSegments[definition].Add(segment = new TexturedTileSegment(texture, segmentClip));
                            }
                            else
                            {
                                segment.AddTexture(texture);
                            }
                        }
                    }

                    List <TR2Entities> spriteEntities = new List <TR2Entities>(definition.SpriteSequences.Keys);
                    foreach (TR2Entities spriteEntity in spriteEntities)
                    {
                        TRSpriteSequence existingSequence = spriteSequences.Find(s => s.SpriteID == (int)spriteEntity);
                        if (existingSequence != null)
                        {
                            definition.SpriteSequences.Remove(spriteEntity);
                            continue;
                        }
                        else
                        {
                            // Add it to the tracking list in case we are importing 2 or more models
                            // that share a sequence e.g. Dragon/Flamethrower and Flame_S_H
                            spriteSequences.Add(new TRSpriteSequence {
                                SpriteID = (int)spriteEntity
                            });
                        }

                        // The sequence will be merged later when we know the sprite texture offsets.
                        // For now, add the segments we need for packing.
                        Dictionary <int, List <IndexedTRSpriteTexture> > spriteTextures = definition.SpriteTextures[spriteEntity];
                        foreach (int segmentIndex in spriteTextures.Keys)
                        {
                            Bitmap segmentClip          = bg.Extract(definition.TextureSegments[segmentIndex]);
                            TexturedTileSegment segment = null;
                            foreach (IndexedTRSpriteTexture texture in spriteTextures[segmentIndex])
                            {
                                if (segment == null)
                                {
                                    _importSegments[definition].Add(segment = new TexturedTileSegment(texture, segmentClip));
                                }
                                else
                                {
                                    segment.AddTexture(texture);
                                }
                            }
                        }
                    }
                }
            }
        }