Tileset.cs 5.7 KB

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