TiledMapReader.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Content;
  6. using Microsoft.Xna.Framework.Graphics;
  7. using MonoGame.Extended.Content;
  8. namespace MonoGame.Extended.Tiled
  9. {
  10. public class TiledMapReader : ContentTypeReader<TiledMap>
  11. {
  12. protected override TiledMap Read(ContentReader reader, TiledMap existingInstance)
  13. {
  14. if (existingInstance != null)
  15. return existingInstance;
  16. var map = ReadTiledMap(reader);
  17. reader.ReadTiledMapProperties(map.Properties);
  18. ReadTilesets(reader, map);
  19. ReadLayers(reader, map);
  20. return map;
  21. }
  22. private static TiledMap ReadTiledMap(ContentReader reader)
  23. {
  24. var name = reader.AssetName;
  25. var type = reader.ReadString();
  26. var width = reader.ReadInt32();
  27. var height = reader.ReadInt32();
  28. var tileWidth = reader.ReadInt32();
  29. var tileHeight = reader.ReadInt32();
  30. var backgroundColor = reader.ReadColor();
  31. var renderOrder = (TiledMapTileDrawOrder)reader.ReadByte();
  32. var orientation = (TiledMapOrientation)reader.ReadByte();
  33. return new TiledMap(name, type, width, height, tileWidth, tileHeight, renderOrder, orientation, backgroundColor);
  34. }
  35. private static void ReadTilesets(ContentReader reader, TiledMap map)
  36. {
  37. var tilesetCount = reader.ReadInt32();
  38. for (var i = 0; i < tilesetCount; i++)
  39. {
  40. var firstGlobalIdentifier = reader.ReadInt32();
  41. var tileset = ReadTileset(reader, map);
  42. map.AddTileset(tileset, firstGlobalIdentifier);
  43. }
  44. }
  45. private static TiledMapTileset ReadTileset(ContentReader reader, TiledMap map)
  46. {
  47. TiledMapTileset result;
  48. var external = reader.ReadBoolean();
  49. if (external)
  50. {
  51. var tileset = reader.ReadExternalReference<TiledMapTileset>();
  52. result = tileset
  53. ?? throw new InvalidOperationException($"Failed to load tileset: {nameof(reader.ReadExternalReference)} returned null.");
  54. }
  55. else
  56. {
  57. result = TiledMapTilesetReader.ReadTileset(reader);
  58. }
  59. return result;
  60. }
  61. private static void ReadLayers(ContentReader reader, TiledMap map)
  62. {
  63. foreach (var layer in ReadGroup(reader, map))
  64. map.AddLayer(layer);
  65. }
  66. private static List<TiledMapLayer> ReadGroup(ContentReader reader, TiledMap map)
  67. {
  68. var layerCount = reader.ReadInt32();
  69. var value = new List<TiledMapLayer>(layerCount);
  70. for (var i = 0; i < layerCount; i++)
  71. value.Add(ReadLayer(reader, map));
  72. return value;
  73. }
  74. private static TiledMapLayer ReadLayer(ContentReader reader, TiledMap map)
  75. {
  76. var layerType = (TiledMapLayerType)reader.ReadByte();
  77. var name = reader.ReadString();
  78. var type = reader.ReadString();
  79. var isVisible = reader.ReadBoolean();
  80. var opacity = reader.ReadSingle();
  81. var offsetX = reader.ReadSingle();
  82. var offsetY = reader.ReadSingle();
  83. var offset = new Vector2(offsetX, offsetY);
  84. var parallaxX = reader.ReadSingle();
  85. var parallaxY = reader.ReadSingle();
  86. var parallaxFactor = new Vector2(parallaxX, parallaxY);
  87. var properties = new TiledMapProperties();
  88. reader.ReadTiledMapProperties(properties);
  89. TiledMapLayer layer;
  90. switch (layerType)
  91. {
  92. case TiledMapLayerType.ImageLayer:
  93. layer = ReadImageLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible);
  94. break;
  95. case TiledMapLayerType.TileLayer:
  96. layer = ReadTileLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible, map);
  97. break;
  98. case TiledMapLayerType.ObjectLayer:
  99. layer = ReadObjectLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible, map);
  100. break;
  101. case TiledMapLayerType.GroupLayer:
  102. layer = new TiledMapGroupLayer(name, type, ReadGroup(reader, map), offset, parallaxFactor, opacity, isVisible);
  103. break;
  104. default:
  105. throw new ArgumentOutOfRangeException();
  106. }
  107. foreach (var property in properties)
  108. layer.Properties.Add(property.Key, property.Value);
  109. return layer;
  110. }
  111. private static TiledMapLayer ReadObjectLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible, TiledMap map)
  112. {
  113. var color = reader.ReadColor();
  114. var drawOrder = (TiledMapObjectDrawOrder)reader.ReadByte();
  115. var objectCount = reader.ReadInt32();
  116. var objects = new TiledMapObject[objectCount];
  117. for (var i = 0; i < objectCount; i++)
  118. objects[i] = ReadTiledMapObject(reader, map);
  119. return new TiledMapObjectLayer(name, type, objects, color, drawOrder, offset, parallaxFactor, opacity, isVisible);
  120. }
  121. private static TiledMapObject ReadTiledMapObject(ContentReader reader, TiledMap map)
  122. {
  123. var objectType = (TiledMapObjectType)reader.ReadByte();
  124. var identifier = reader.ReadInt32();
  125. var name = reader.ReadString();
  126. var type = reader.ReadString();
  127. var position = new Vector2(reader.ReadSingle(), reader.ReadSingle());
  128. var width = reader.ReadSingle();
  129. var height = reader.ReadSingle();
  130. var size = new SizeF(width, height);
  131. var rotation = reader.ReadSingle();
  132. var isVisible = reader.ReadBoolean();
  133. var properties = new TiledMapProperties();
  134. const float opacity = 1.0f;
  135. reader.ReadTiledMapProperties(properties);
  136. TiledMapObject mapObject;
  137. switch (objectType)
  138. {
  139. case TiledMapObjectType.Rectangle:
  140. mapObject = new TiledMapRectangleObject(identifier, name, size, position, rotation, opacity, isVisible, type);
  141. break;
  142. case TiledMapObjectType.Tile:
  143. var globalTileIdentifierWithFlags = reader.ReadUInt32();
  144. var tile = new TiledMapTile(globalTileIdentifierWithFlags, (ushort)position.X, (ushort)position.Y);
  145. var tileset = map.GetTilesetByTileGlobalIdentifier(tile.GlobalIdentifier);
  146. var localTileIdentifier = tile.GlobalIdentifier - map.GetTilesetFirstGlobalIdentifier(tileset);
  147. var tilesetTile = tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier);
  148. mapObject = new TiledMapTileObject(identifier, name, tileset, tilesetTile, size, position, rotation, opacity, isVisible, type);
  149. break;
  150. case TiledMapObjectType.Ellipse:
  151. mapObject = new TiledMapEllipseObject(identifier, name, size, position, rotation, opacity, isVisible);
  152. break;
  153. case TiledMapObjectType.Polygon:
  154. mapObject = new TiledMapPolygonObject(identifier, name, ReadPoints(reader), size, position, rotation, opacity, isVisible, type);
  155. break;
  156. case TiledMapObjectType.Polyline:
  157. mapObject = new TiledMapPolylineObject(identifier, name, ReadPoints(reader), size, position, rotation, opacity, isVisible, type);
  158. break;
  159. default:
  160. throw new ArgumentOutOfRangeException();
  161. }
  162. foreach (var property in properties)
  163. mapObject.Properties.Add(property.Key, property.Value);
  164. return mapObject;
  165. }
  166. private static Vector2[] ReadPoints(ContentReader reader)
  167. {
  168. var pointCount = reader.ReadInt32();
  169. var points = new Vector2[pointCount];
  170. for (var i = 0; i < pointCount; i++)
  171. {
  172. var x = reader.ReadSingle();
  173. var y = reader.ReadSingle();
  174. points[i] = new Vector2(x, y);
  175. }
  176. return points;
  177. }
  178. private static TiledMapImageLayer ReadImageLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible)
  179. {
  180. var texture = reader.ReadExternalReference<Texture2D>();
  181. var x = reader.ReadSingle();
  182. var y = reader.ReadSingle();
  183. var position = new Vector2(x, y);
  184. return new TiledMapImageLayer(name, type, texture, position, offset, parallaxFactor, opacity, isVisible);
  185. }
  186. private static TiledMapTileLayer ReadTileLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible, TiledMap map)
  187. {
  188. var width = reader.ReadInt32();
  189. var height = reader.ReadInt32();
  190. var tileWidth = map.TileWidth;
  191. var tileHeight = map.TileHeight;
  192. var tileCount = reader.ReadInt32();
  193. var layer = new TiledMapTileLayer(name, type, width, height, tileWidth, tileHeight, offset, parallaxFactor, opacity, isVisible);
  194. for (var i = 0; i < tileCount; i++)
  195. {
  196. var globalTileIdentifierWithFlags = reader.ReadUInt32();
  197. var x = reader.ReadUInt16();
  198. var y = reader.ReadUInt16();
  199. layer.Tiles[x + y * width] = new TiledMapTile(globalTileIdentifierWithFlags, x, y);
  200. }
  201. return layer;
  202. }
  203. }
  204. }