CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

Tileset.cs (5829B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // The Command & Conquer Map Editor and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // The Command & Conquer Map Editor and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 using System;
     16 using System.Collections.Generic;
     17 using System.Drawing;
     18 using System.IO;
     19 using System.Linq;
     20 using System.Xml;
     21 
     22 namespace MobiusEditor.Utility
     23 {
     24     public class Tile
     25     {
     26         public Image Image { get; private set; }
     27 
     28         public Rectangle OpaqueBounds { get; private set; }
     29 
     30         public Tile(Image image, Rectangle opaqueBounds)
     31         {
     32             Image = image;
     33             OpaqueBounds = opaqueBounds;
     34         }
     35 
     36         public Tile(Image image)
     37             : this(image, new Rectangle(0, 0, image.Width, image.Height))
     38         {
     39         }
     40     }
     41 
     42     public class Tileset
     43     {
     44         private class TileData
     45         {
     46             public int FPS { get; set; }
     47             public string[] Frames { get; set; }
     48 
     49             public Dictionary<string, Tile[]> TeamColorTiles { get; } = new Dictionary<string, Tile[]>();
     50         }
     51 
     52         private readonly Dictionary<string, Dictionary<int, TileData>> tiles = new Dictionary<string, Dictionary<int, TileData>>(StringComparer.OrdinalIgnoreCase);
     53 
     54         private readonly TextureManager textureManager;
     55 
     56         private static readonly Bitmap transparentTileImage;
     57 
     58         static Tileset()
     59         {
     60             transparentTileImage = new Bitmap(Globals.TileWidth, Globals.TileHeight);
     61             transparentTileImage.MakeTransparent();
     62         }
     63 
     64         public Tileset(TextureManager textureManager)
     65         {
     66             this.textureManager = textureManager;
     67         }
     68 
     69         public void Reset()
     70         {
     71             foreach (var item in tiles)
     72             {
     73                 foreach (var tileItem in item.Value)
     74                 {
     75                     tileItem.Value.TeamColorTiles.Clear();
     76                 }
     77             }
     78         }
     79 
     80         public void Load(string xml, string texturesPath)
     81         {
     82             XmlDocument xmlDoc = new XmlDocument();
     83             xmlDoc.LoadXml(xml);
     84 
     85             var rootPath = Path.Combine(texturesPath, xmlDoc.SelectSingleNode("TilesetTypeClass/RootTexturePath").InnerText);
     86             foreach (XmlNode tileNode in xmlDoc.SelectNodes("TilesetTypeClass/Tiles/Tile"))
     87             {
     88                 TileData tileData = new TileData();
     89 
     90                 var name = tileNode.SelectSingleNode("Key/Name").InnerText;
     91                 var shape = int.Parse(tileNode.SelectSingleNode("Key/Shape").InnerText);
     92                 var fpsNode = tileNode.SelectSingleNode("Value/AnimationData/FPS");
     93                 tileData.FPS = (fpsNode != null) ? int.Parse(fpsNode.InnerText) : 0;
     94 
     95                 var frameNodes = tileNode.SelectNodes("Value/Frames/Frame");
     96 #if false
     97                 tileData.Frames = new string[frameNodes.Count];
     98 #else
     99                 tileData.Frames = new string[Math.Min(1, frameNodes.Count)];
    100 #endif
    101 
    102                 for (var i = 0; i < tileData.Frames.Length; ++i)
    103                 {
    104                     string filename = null;
    105                     if (!string.IsNullOrEmpty(frameNodes[i].InnerText))
    106                     {
    107                         filename = Path.Combine(rootPath, frameNodes[i].InnerText);
    108                     }
    109 
    110                     tileData.Frames[i] = filename;
    111                 }
    112 
    113                 if (!tiles.TryGetValue(name, out Dictionary<int, TileData> shapes))
    114                 {
    115                     shapes = new Dictionary<int, TileData>();
    116                     tiles[name] = shapes;
    117                 }
    118 
    119                 shapes[shape] = tileData;
    120             }
    121         }
    122 
    123         public bool GetTileData(string name, int shape, TeamColor teamColor, out int fps, out Tile[] tiles)
    124         {
    125             fps = 0;
    126             tiles = null;
    127 
    128             if (!this.tiles.TryGetValue(name, out Dictionary<int, TileData> shapes))
    129             {
    130                 return false;
    131             }
    132 
    133             if (shape < 0)
    134             {
    135                 shape = Math.Max(0, shapes.Max(kv => kv.Key) + shape + 1);
    136             }
    137             if (!shapes.TryGetValue(shape, out TileData tileData))
    138             {
    139                 return false;
    140             }
    141 
    142             var key = teamColor?.Name ?? string.Empty;
    143             if (!tileData.TeamColorTiles.TryGetValue(key, out Tile[] tileDataTiles))
    144             {
    145                 tileDataTiles = new Tile[tileData.Frames.Length];
    146                 tileData.TeamColorTiles[key] = tileDataTiles;
    147 
    148                 for (int i = 0; i < tileDataTiles.Length; ++i)
    149                 {
    150                     var filename = tileData.Frames[i];
    151                     if (!string.IsNullOrEmpty(filename))
    152                     {
    153                         (Bitmap bitmap, Rectangle opaqueBounds) = textureManager.GetTexture(filename, teamColor);
    154                         tileDataTiles[i] = new Tile(bitmap, opaqueBounds);
    155                     }
    156                     else
    157                     {
    158                         tileDataTiles[i] = new Tile(transparentTileImage);
    159                     }
    160                 }
    161             }
    162 
    163             fps = tileData.FPS;
    164             tiles = tileDataTiles;
    165 
    166             return true;
    167         }
    168     }
    169 }