Beispiel #1
0
        private TRColour4[] PopulateColourPalette16(byte[] palette)
        {
            TRColour4[] colourPalette = new TRColour4[MAX_PALETTE_SIZE];

            int ci = 0;

            for (int i = 0; i < MAX_PALETTE_SIZE; i++)
            {
                TRColour4 col = new TRColour4();

                col.Red = palette[ci];
                ci++;

                col.Green = palette[ci];
                ci++;

                col.Blue = palette[ci];
                ci++;

                col.Unused = palette[ci];
                ci++;

                colourPalette[i] = col;
            }

            return(colourPalette);
        }
Beispiel #2
0
        // #159 Using high indices as we were doing previously appears not to work in TR2Main,
        // so instead we will check for the next available palette slot and use that. Each level
        // seems to only have around 30-40 used colours. We still use the Unused field to track
        // what we are making use of during imports.
        public static int GetNextPaletteIndex(TR2Level lvl)
        {
            int highestUsedPalette = -1;

            foreach (TRMesh mesh in lvl.Meshes)
            {
                foreach (TRFace4 t in mesh.ColouredRectangles)
                {
                    highestUsedPalette = Math.Max(highestUsedPalette, BitConverter.GetBytes(t.Texture)[1]);
                }
                foreach (TRFace3 t in mesh.ColouredTriangles)
                {
                    highestUsedPalette = Math.Max(highestUsedPalette, BitConverter.GetBytes(t.Texture)[1]);
                }
            }

            while (highestUsedPalette < lvl.Palette16.Length - 1)
            {
                TRColour4 palette = lvl.Palette16[++highestUsedPalette];
                if (palette.Unused == 0)
                {
                    return(highestUsedPalette);
                }
            }

            return(-1);
        }
Beispiel #3
0
        public static int Import(TR2Level lvl, TRColour4 c)
        {
            int nextAvailableIndex = GetNextPaletteIndex(lvl);

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

            lvl.Palette16[nextAvailableIndex] = c;
            c.Unused = 255; // Avoid anything else trying to use this index
            return(nextAvailableIndex);
        }
Beispiel #4
0
        public override void Import()
        {
            List <TRColour4>      palette16 = Level.Palette16.ToList();
            Dictionary <int, int> indexMap  = new Dictionary <int, int>();

            foreach (int paletteIndex in Definition.Colours.Keys)
            {
                TRColour4 newColour     = Definition.Colours[paletteIndex];
                int       existingIndex = palette16.FindIndex
                                          (
                    e => e.Red == newColour.Red && e.Green == newColour.Green && e.Blue == newColour.Blue// && e.Unused == newColour.Unused
                                          );

                if (existingIndex != -1)
                {
                    indexMap[paletteIndex] = existingIndex;
                }
                else
                {
                    indexMap[paletteIndex] = P16Importer.Import(Level, newColour);
                }
            }

            foreach (TRMesh mesh in Definition.Meshes)
            {
                foreach (TRFace4 rect in mesh.ColouredRectangles)
                {
                    rect.Texture = ReindexTexture(rect.Texture, indexMap);
                }
                foreach (TRFace3 tri in mesh.ColouredTriangles)
                {
                    tri.Texture = ReindexTexture(tri.Texture, indexMap);
                }
            }

            P16Importer.ResetPaletteTracking(Level);
        }
        public void RedrawStaticTargets(StaticTextureSource source, string variant, Dictionary <TextureCategory, bool> options)
        {
            if (source.Categories != null)
            {
                // Exclude it if any of its categories are in the options and switched off
                foreach (TextureCategory category in source.Categories)
                {
                    if (options.ContainsKey(category) && !options[category])
                    {
                        return;
                    }
                }
            }

            // For sprite sequence sources, the targets are mapped dynamically.
            if (source.IsSpriteSequence && (!StaticMapping.ContainsKey(source) || StaticMapping[source].Count == 0))
            {
                GenerateSpriteSequenceTargets(source);
            }

            // This can happen if we have a source grouped for this level,
            // but the source is actually only in place on certain conditions
            // - an example is the flame in Venice, which is only added if
            // the Flamethrower has been imported.
            if (!StaticMapping.ContainsKey(source))
            {
                return;
            }

            List <Rectangle> segments = source.VariantMap[variant];

            foreach (StaticTextureTarget target in StaticMapping[source])
            {
                if (target.Segment < 0 || target.Segment >= segments.Count)
                {
                    throw new IndexOutOfRangeException(string.Format("Segment {0} is invalid for texture source {1}.", target.Segment, source.PNGPath));
                }

                GetBitmapGraphics(target.Tile).ImportSegment(source, target, segments[target.Segment]);
            }

            if (source.EntityColourMap != null)
            {
                foreach (TR2Entities entity in source.EntityColourMap.Keys)
                {
                    TRMesh[]   meshes        = TR2LevelUtilities.GetModelMeshes(_level, entity);
                    ISet <int> colourIndices = new HashSet <int>();
                    foreach (TRMesh mesh in meshes)
                    {
                        foreach (TRFace4 t in mesh.ColouredRectangles)
                        {
                            colourIndices.Add(BitConverter.GetBytes(t.Texture)[1]);
                        }
                        foreach (TRFace3 t in mesh.ColouredTriangles)
                        {
                            colourIndices.Add(BitConverter.GetBytes(t.Texture)[1]);
                        }
                    }

                    Dictionary <int, int> remapIndices = new Dictionary <int, int>();
                    foreach (Color targetColour in source.EntityColourMap[entity].Keys)
                    {
                        int matchedIndex = -1;
                        foreach (int currentIndex in colourIndices)
                        {
                            TRColour4 currentColour = _level.Palette16[currentIndex];
                            if (currentColour.Red == targetColour.R && currentColour.Green == targetColour.G && currentColour.Blue == targetColour.B)
                            {
                                matchedIndex = currentIndex;
                            }
                        }

                        if (matchedIndex == -1)
                        {
                            continue;
                        }

                        // Extract the colour from the top-left of the rectangle specified in the source, and import that into the level
                        int sourceRectangle = source.EntityColourMap[entity][targetColour];
                        int newColourIndex  = P16Importer.Import(_level, source.Bitmap.GetPixel(segments[sourceRectangle].X, segments[sourceRectangle].Y));
                        remapIndices.Add(matchedIndex, newColourIndex);
                    }

                    // Remap the affected mesh textures to the newly inserted colours
                    foreach (TRMesh mesh in meshes)
                    {
                        foreach (TRFace4 t in mesh.ColouredRectangles)
                        {
                            t.Texture = ConvertMeshTexture(t.Texture, remapIndices);
                        }
                        foreach (TRFace3 t in mesh.ColouredTriangles)
                        {
                            t.Texture = ConvertMeshTexture(t.Texture, remapIndices);
                        }
                    }
                }

                // Reset the palette tracking
                P16Importer.ResetPaletteTracking(_level);
            }
        }
Beispiel #6
0
        public void ExportAllTexturesToHtml(string filePath)
        {
            using (TexturePacker packer = new TexturePacker(_level))
            {
                StringBuilder tiles = new StringBuilder();
                foreach (TexturedTile tile in packer.Tiles)
                {
                    tiles.Append(string.Format("<div class=\"tile\" id=\"tile_{0}\">", tile.Index));

                    foreach (TexturedTileSegment segment in tile.Rectangles)
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            segment.Bitmap.Save(ms, ImageFormat.Png);

                            List <int> objectTextures = GetObjectTextureList(segment);
                            List <int> spriteTextures = GetSpriteTextureList(segment);

                            tiles.Append(string.Format("<img src=\"data:image/png;base64, {0}\" ", Convert.ToBase64String(ms.ToArray())));
                            tiles.Append(string.Format("style=\"top:{0}px;left:{1}px;width:{2}px;height:{3}px\" ", segment.Bounds.Y, segment.Bounds.X, segment.Bounds.Width, segment.Bounds.Height));
                            tiles.Append(string.Format("data-tile=\"{0}\" ", tile.Index));
                            tiles.Append(string.Format("data-rect=\"{0}\" ", RectangleToString(segment.Bounds)));

                            List <string> objectData = new List <string>();
                            List <string> spriteData = new List <string>();

                            foreach (AbstractIndexedTRTexture texture in segment.Textures)
                            {
                                if (texture is IndexedTRObjectTexture)
                                {
                                    objectData.Add(texture.Index + ": " + RectangleToString(texture.Bounds));
                                }
                                else
                                {
                                    spriteData.Add(texture.Index + ": " + RectangleToString(texture.Bounds));
                                }
                            }

                            if (objectData.Count > 0)
                            {
                                tiles.Append(string.Format("data-objects=\"{0}\" ", string.Join(";", objectData)));
                            }
                            if (spriteData.Count > 0)
                            {
                                tiles.Append(string.Format("data-sprites=\"{0}\" ", string.Join(";", spriteData)));
                            }

                            tiles.Append("/>");
                        }
                    }

                    tiles.Append("</div>");
                }

                StringBuilder levelSel = new StringBuilder();
                foreach (string lvl in LevelNames.AsList)
                {
                    levelSel.Append("<option");
                    if (lvl.ToUpper() == filePath.ToUpper())
                    {
                        levelSel.Append(" selected=\"selected\"");
                    }
                    levelSel.Append(" value=\"").Append(lvl).Append(".html\">").Append(lvl).Append("</option>");
                }

                StringBuilder skyboxInfo = new StringBuilder();
                Dictionary <int, TRColour4> skyColours = GetSkyBoxColours();
                if (skyColours.Count > 0)
                {
                    skyboxInfo.Append("<div><span>Palette #</span><span>RGB</span><span>Swatch</span></div>");
                    string rgbTpl    = "<span>[{0}, {1}, {2}]</span>";
                    string swatchTpl = "<span style=\"background:rgb({0},{1},{2})\">&nbsp;</span>";;
                    foreach (int index in skyColours.Keys)
                    {
                        TRColour4 c = skyColours[index];
                        skyboxInfo.Append("<div class=\"body-row\"><span>").Append(index).Append("</span>");
                        skyboxInfo.Append(string.Format(rgbTpl, c.Red, c.Green, c.Blue));
                        skyboxInfo.Append(string.Format(swatchTpl, c.Red, c.Green, c.Blue));
                        skyboxInfo.Append("</div>");
                    }
                }

                string tpl = File.ReadAllText(@"Resources\TileTemplate.html");
                tpl = tpl.Replace("{Title}", filePath);
                tpl = tpl.Replace("{Levels}", levelSel.ToString());
                tpl = tpl.Replace("{Tiles}", tiles.ToString());
                tpl = tpl.Replace("{SkyBox}", skyboxInfo.ToString());

                File.WriteAllText(filePath + ".html", tpl);
            }
        }