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 CutHair(TR2CombinedLevel level) { // Every level has a 64x64 transparent gunflare texture so rather than // importing something else, we'll just try to find that texture and // point Lara's braid to it, so making it invisible. TRMesh[] gunflareMeshes = TR2LevelUtilities.GetModelMeshes(level.Data, TR2Entities.Gunflare_H); if (gunflareMeshes == null) { return; } ISet <int> textureIndices = new HashSet <int>(); foreach (TRMesh mesh in gunflareMeshes) { foreach (TRFace4 r in mesh.TexturedRectangles) { textureIndices.Add(r.Texture); } foreach (TRFace3 t in mesh.TexturedTriangles) { textureIndices.Add(t.Texture); } } IndexedTRObjectTexture transparentTexture = null; foreach (int index in textureIndices) { transparentTexture = new IndexedTRObjectTexture { Index = index, Texture = level.Data.ObjectTextures[index] }; Rectangle rect = transparentTexture.Bounds; if (rect.Width == 64 && rect.Height == 64) { break; } else { transparentTexture = null; } } // Did we find it? if (transparentTexture == null) { return; } // Erase the braid foreach (TRMesh mesh in TR2LevelUtilities.GetModelMeshes(level.Data, TR2Entities.LaraPonytail_H)) { foreach (TRFace4 r in mesh.TexturedRectangles) { r.Texture = (ushort)transparentTexture.Index; } foreach (TRFace3 t in mesh.TexturedTriangles) { t.Texture = (ushort)transparentTexture.Index; } } }