TiledMapWriter.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Content.Pipeline;
  6. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  7. using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
  8. using MonoGame.Extended.Content.Tiled;
  9. using MonoGame.Extended.Tiled;
  10. namespace MonoGame.Extended.Content.Pipeline.Tiled
  11. {
  12. [ContentTypeWriter]
  13. public class TiledMapWriter : ContentTypeWriter<TiledMapContentItem>
  14. {
  15. private TiledMapContentItem _contentItem;
  16. protected override void Write(ContentWriter writer, TiledMapContentItem contentItem)
  17. {
  18. _contentItem = contentItem;
  19. var map = contentItem.Data;
  20. try
  21. {
  22. WriteMetaData(writer, map);
  23. WriteTilesets(writer, map.Tilesets);
  24. WriteLayers(writer, map.Layers);
  25. }
  26. catch (Exception ex)
  27. {
  28. ContentLogger.Logger.LogImportantMessage(ex.StackTrace);
  29. throw;
  30. }
  31. }
  32. private static void WriteMetaData(ContentWriter writer, TiledMapContent map)
  33. {
  34. writer.Write(map.Class ?? map.Type ?? string.Empty);
  35. writer.Write(map.Width);
  36. writer.Write(map.Height);
  37. writer.Write(map.TileWidth);
  38. writer.Write(map.TileHeight);
  39. writer.Write(ColorHelper.FromHex(map.BackgroundColor));
  40. writer.Write((byte)map.RenderOrder);
  41. writer.Write((byte)map.Orientation);
  42. writer.WriteTiledMapProperties(map.Properties);
  43. }
  44. private void WriteTilesets(ContentWriter writer, IReadOnlyCollection<TiledMapTilesetContent> tilesets)
  45. {
  46. writer.Write(tilesets.Count);
  47. foreach (var tileset in tilesets)
  48. WriteTileset(writer, tileset);
  49. }
  50. private void WriteTileset(ContentWriter writer, TiledMapTilesetContent tileset)
  51. {
  52. writer.Write(tileset.FirstGlobalIdentifier);
  53. if (!string.IsNullOrWhiteSpace(tileset.Source))
  54. {
  55. writer.Write(true);
  56. writer.WriteExternalReference(_contentItem.GetExternalReference<TiledMapTilesetContent>(tileset.Source));
  57. }
  58. else
  59. {
  60. writer.Write(false);
  61. TiledMapTilesetWriter.WriteTileset(writer, tileset, _contentItem);
  62. }
  63. }
  64. private void WriteLayers(ContentWriter writer, IReadOnlyCollection<TiledMapLayerContent> layers)
  65. {
  66. writer.Write(layers.Count);
  67. foreach (var layer in layers)
  68. WriteLayer(writer, layer);
  69. }
  70. private void WriteLayer(ContentWriter writer, TiledMapLayerContent layer)
  71. {
  72. writer.Write((byte)layer.LayerType);
  73. writer.Write(layer.Name ?? string.Empty);
  74. writer.Write(layer.Class ?? layer.Type ?? string.Empty);
  75. writer.Write(layer.Visible);
  76. writer.Write(layer.Opacity);
  77. writer.Write(layer.OffsetX);
  78. writer.Write(layer.OffsetY);
  79. writer.Write(layer.ParallaxX);
  80. writer.Write(layer.ParallaxY);
  81. writer.WriteTiledMapProperties(layer.Properties);
  82. switch (layer.LayerType)
  83. {
  84. case TiledMapLayerType.ImageLayer:
  85. WriteImageLayer(writer, (TiledMapImageLayerContent)layer);
  86. break;
  87. case TiledMapLayerType.TileLayer:
  88. WriteTileLayer(writer, (TiledMapTileLayerContent)layer);
  89. break;
  90. case TiledMapLayerType.ObjectLayer:
  91. WriteObjectLayer(writer, (TiledMapObjectLayerContent)layer);
  92. break;
  93. case TiledMapLayerType.GroupLayer:
  94. WriteLayers(writer, ((TiledMapGroupLayerContent)layer).Layers);
  95. break;
  96. default:
  97. throw new ArgumentOutOfRangeException(nameof(layer.LayerType));
  98. }
  99. }
  100. private void WriteImageLayer(ContentWriter writer, TiledMapImageLayerContent imageLayer)
  101. {
  102. var externalReference = _contentItem.GetExternalReference<Texture2DContent>(imageLayer.Image.Source);
  103. writer.WriteExternalReference(externalReference);
  104. writer.Write(new Vector2(imageLayer.X, imageLayer.Y));
  105. }
  106. // ReSharper disable once SuggestBaseTypeForParameter
  107. private static void WriteTileLayer(ContentWriter writer, TiledMapTileLayerContent tileLayer)
  108. {
  109. writer.Write(tileLayer.Width);
  110. writer.Write(tileLayer.Height);
  111. writer.Write(tileLayer.Tiles.Length);
  112. foreach (var tile in tileLayer.Tiles)
  113. {
  114. writer.Write(tile.GlobalTileIdentifierWithFlags);
  115. writer.Write(tile.X);
  116. writer.Write(tile.Y);
  117. }
  118. }
  119. private static void WriteObjectLayer(ContentWriter writer, TiledMapObjectLayerContent layer)
  120. {
  121. writer.Write(ColorHelper.FromHex(layer.Color));
  122. writer.Write((byte)layer.DrawOrder);
  123. writer.Write(layer.Objects.Count);
  124. foreach (var @object in layer.Objects)
  125. WriteObject(writer, @object);
  126. }
  127. private static void WriteObject(ContentWriter writer, TiledMapObjectContent @object)
  128. {
  129. var type = GetObjectType(@object);
  130. writer.Write((byte)type);
  131. writer.Write(@object.Identifier);
  132. writer.Write(@object.Name ?? string.Empty);
  133. writer.Write(@object.Class ?? @object.Type ?? string.Empty);
  134. writer.Write(@object.X);
  135. writer.Write(@object.Y);
  136. writer.Write(@object.Width);
  137. writer.Write(@object.Height);
  138. writer.Write(@object.Rotation);
  139. writer.Write(@object.Visible);
  140. writer.WriteTiledMapProperties(@object.Properties);
  141. switch (type)
  142. {
  143. case TiledMapObjectType.Rectangle:
  144. case TiledMapObjectType.Ellipse:
  145. break;
  146. case TiledMapObjectType.Tile:
  147. writer.Write(@object.GlobalIdentifier);
  148. break;
  149. case TiledMapObjectType.Polygon:
  150. WritePolyPoints(writer, @object.Polygon.Points);
  151. break;
  152. case TiledMapObjectType.Polyline:
  153. WritePolyPoints(writer, @object.Polyline.Points);
  154. break;
  155. default:
  156. throw new ArgumentOutOfRangeException();
  157. }
  158. }
  159. // ReSharper disable once SuggestBaseTypeForParameter
  160. private static void WritePolyPoints(ContentWriter writer, string @string)
  161. {
  162. var stringPoints = @string.Split(' ');
  163. writer.Write(stringPoints.Length);
  164. foreach (var stringPoint in stringPoints)
  165. {
  166. var xy = stringPoint.Split(',');
  167. var x = float.Parse(xy[0], CultureInfo.InvariantCulture.NumberFormat);
  168. writer.Write(x);
  169. var y = float.Parse(xy[1], CultureInfo.InvariantCulture.NumberFormat);
  170. writer.Write(y);
  171. }
  172. }
  173. public static TiledMapObjectType GetObjectType(TiledMapObjectContent content)
  174. {
  175. if (content.GlobalIdentifier > 0)
  176. return TiledMapObjectType.Tile;
  177. if (content.Ellipse != null)
  178. return TiledMapObjectType.Ellipse;
  179. if (content.Polygon != null)
  180. return TiledMapObjectType.Polygon;
  181. // ReSharper disable once ConvertIfStatementToReturnStatement
  182. if (content.Polyline != null)
  183. return TiledMapObjectType.Polyline;
  184. return TiledMapObjectType.Rectangle;
  185. }
  186. public override string GetRuntimeType(TargetPlatform targetPlatform)
  187. {
  188. return typeof(TiledMap).AssemblyQualifiedName;
  189. }
  190. public override string GetRuntimeReader(TargetPlatform targetPlatform)
  191. {
  192. return typeof(TiledMapReader).AssemblyQualifiedName;
  193. }
  194. }
  195. }