public bool Import(TR2CombinedLevel level, TextureLevelMapping mapping) { // Ensure any changes already made are committed to the level mapping.CommitGraphics(); using (TexturePacker packer = new TexturePacker(level.Data)) { List <TRObjectTexture> textures = level.Data.ObjectTextures.ToList(); foreach (StaticTextureSource source in mapping.LandmarkMapping.Keys) { if (textures.Count == _maxTextures) { break; } if (!source.HasVariants) { continue; } List <Rectangle> segments = source.VariantMap[source.Variants[0]]; foreach (int segmentIndex in mapping.LandmarkMapping[source].Keys) { foreach (LandmarkTextureTarget target in mapping.LandmarkMapping[source][segmentIndex]) { IndexedTRObjectTexture texture = CreateTexture(segments[segmentIndex]); target.MappedTextureIndex = textures.Count; textures.Add(texture.Texture); Bitmap image; if (target.BackgroundIndex != -1) { IndexedTRObjectTexture indexedTexture = new IndexedTRObjectTexture { Index = target.BackgroundIndex, Texture = level.Data.ObjectTextures[target.BackgroundIndex] }; BitmapGraphics tile = GetTile(level.Data, indexedTexture.Atlas); BitmapGraphics clip = new BitmapGraphics(tile.Extract(indexedTexture.Bounds)); clip.Overlay(source.Bitmap); image = clip.Bitmap; } else { image = source.Bitmap; } packer.AddRectangle(new TexturedTileSegment(texture, image)); } } } try { packer.Pack(true); // Perform the room data remapping foreach (StaticTextureSource source in mapping.LandmarkMapping.Keys) { if (!source.HasVariants) { continue; } foreach (int segmentIndex in mapping.LandmarkMapping[source].Keys) { foreach (LandmarkTextureTarget target in mapping.LandmarkMapping[source][segmentIndex]) { if (target.MappedTextureIndex == -1) { // There wasn't enough space for this continue; } TR2Room room = level.Data.Rooms[target.RoomNumber]; foreach (int rectIndex in target.RectangleIndices) { room.RoomData.Rectangles[rectIndex].Texture = (ushort)target.MappedTextureIndex; } } } } level.Data.ObjectTextures = textures.ToArray(); level.Data.NumObjectTextures = (uint)textures.Count; return(true); } catch (PackingException) { return(false); } } }
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); } } } } } } }