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 }