Exemplo n.º 1
0
        private void GenerateSpriteSequenceTargets(StaticTextureSource source)
        {
            if (!source.HasVariants)
            {
                throw new ArgumentException(string.Format("SpriteSequence {0} cannot be dynamically mapped without at least one source rectangle.", source.SpriteSequence));
            }

            int i = _level.SpriteSequences.ToList().FindIndex(s => s.SpriteID == (int)source.SpriteSequence);

            if (i == -1)
            {
                return;
            }

            TRSpriteSequence sequence = _level.SpriteSequences[i];

            StaticMapping[source] = new List <StaticTextureTarget>();

            // An assumption is made here that each variant in the source will have the same number
            // of rectangles. We only want to define targets for the number of source rectangles, rather
            // than the total number of sprites.
            int numTargets = source.VariantMap[source.Variants[0]].Count;

            for (int j = 0; j < numTargets; j++)
            {
                TRSpriteTexture sprite = _level.SpriteTextures[sequence.Offset + j];
                StaticMapping[source].Add(new StaticTextureTarget
                {
                    Segment = j,
                    Tile    = sprite.Atlas,
                    X       = sprite.X,
                    Y       = sprite.Y
                });
            }
        }
Exemplo n.º 2
0
        public Dictionary <TexturedTile, List <TexturedTileSegment> > GetSpriteSegments(TR2Entities entity)
        {
            Dictionary <TexturedTile, List <TexturedTileSegment> > segmentMap = new Dictionary <TexturedTile, List <TexturedTileSegment> >();
            int i = Level.SpriteSequences.ToList().FindIndex(s => s.SpriteID == (int)entity);

            if (i != -1)
            {
                TRSpriteSequence sequence = Level.SpriteSequences[i];
                List <int>       indices  = new List <int>();
                for (int j = 0; j < sequence.NegativeLength * -1; j++)
                {
                    indices.Add(sequence.Offset + j);
                }

                foreach (TexturedTile tile in _tiles)
                {
                    List <TexturedTileSegment> segments = tile.GetSpriteTextureIndexSegments(indices);
                    if (segments.Count > 0)
                    {
                        segmentMap[tile] = segments;
                    }
                }
            }

            return(segmentMap);
        }
Exemplo n.º 3
0
        private void ApplyFlamePatch()
        {
            // TextureDeduplicator will have removed the extra flame blasts present in DA and Lair (Flamethrower and Dragon).
            // We need to ensure that if these models are present in any level, that the sprite sequences for the blasts point
            // to the same as the grenade blast instead.

            List <TR2Entities> flameEnemies = new List <TR2Entities>
            {
                TR2Entities.FlamethrowerGoon, TR2Entities.DragonExplosionEmitter_N
            };

            if
            (
                Definitions.ToList().FindIndex(d => flameEnemies.Contains(d.Entity)) != -1 ||
                Level.Models.ToList().FindIndex(m => flameEnemies.Contains((TR2Entities)m.ID)) != -1
            )
            {
                List <TRSpriteSequence> sequences = Level.SpriteSequences.ToList();
                int blastSequence   = sequences.FindIndex(s => s.SpriteID == (int)TR2Entities.FireBlast_S_H);
                int grenadeSequence = sequences.FindIndex(s => s.SpriteID == (int)TR2Entities.Explosion_S_H);

                if (grenadeSequence != -1)
                {
                    if (blastSequence == -1)
                    {
                        TRSpriteSequence grenadeBlast = sequences[grenadeSequence];
                        sequences.Add(new TRSpriteSequence
                        {
                            SpriteID       = (int)TR2Entities.FireBlast_S_H,
                            NegativeLength = grenadeBlast.NegativeLength,
                            Offset         = grenadeBlast.Offset
                        });

                        Level.SpriteSequences = sequences.ToArray();
                        Level.NumSpriteSequences++;
                    }
                    else
                    {
                        Level.SpriteSequences[blastSequence].Offset = sequences[grenadeSequence].Offset;
                    }
                }
            }
        }
Exemplo n.º 4
0
        private void MergeSpriteTextures()
        {
            List <TRSpriteTexture>  levelSpriteTextures  = Level.SpriteTextures.ToList();
            List <TRSpriteSequence> levelSpriteSequences = Level.SpriteSequences.ToList();

            foreach (TRModelDefinition definition in Definitions)
            {
                if (!_importSegments.ContainsKey(definition) || definition.SpriteSequences.Count == 0)
                {
                    continue;
                }

                foreach (TR2Entities spriteEntity in definition.SpriteSequences.Keys)
                {
                    TRSpriteSequence sequence = definition.SpriteSequences[spriteEntity];
                    sequence.Offset = -1;
                    levelSpriteSequences.Add(sequence);

                    foreach (int bitmapIndex in definition.SpriteTextures[spriteEntity].Keys)
                    {
                        List <IndexedTRSpriteTexture> textures = definition.SpriteTextures[spriteEntity][bitmapIndex];

                        for (int i = 0; i < textures.Count; i++)
                        {
                            if (sequence.Offset == -1)
                            {
                                // mark the position of the first sprite only
                                sequence.Offset = (short)levelSpriteTextures.Count;
                            }
                            levelSpriteTextures.Add(textures[i].Texture);
                        }
                    }
                }
            }

            Level.SpriteTextures    = levelSpriteTextures.ToArray();
            Level.NumSpriteTextures = (uint)levelSpriteTextures.Count;

            Level.SpriteSequences    = levelSpriteSequences.ToArray();
            Level.NumSpriteSequences = (uint)levelSpriteSequences.Count;
        }
Exemplo n.º 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;
                }
            }
        }
Exemplo n.º 6
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);
                                }
                            }
                        }
                    }
                }
            }
        }