summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs')
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs108
1 files changed, 108 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs
new file mode 100644
index 0000000..70e2bee
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml.Serialization;
+using Microsoft.Xna.Framework.Content.Pipeline;
+using MonoGame.Extended.Tiled.Serialization;
+
+namespace MonoGame.Extended.Content.Pipeline.Tiled
+{
+ [ContentImporter(".tmx", DefaultProcessor = "TiledMapProcessor", DisplayName = "Tiled Map Importer - MonoGame.Extended")]
+ public class TiledMapImporter : ContentImporter<TiledMapContentItem>
+ {
+ public override TiledMapContentItem Import(string filePath, ContentImporterContext context)
+ {
+ try
+ {
+ if (filePath == null)
+ throw new ArgumentNullException(nameof(filePath));
+
+ ContentLogger.Logger = context.Logger;
+ ContentLogger.Log($"Importing '{filePath}'");
+
+ var map = DeserializeTiledMapContent(filePath, context);
+
+ if (map.Width > ushort.MaxValue || map.Height > ushort.MaxValue)
+ throw new InvalidContentException($"The map '{filePath} is much too large. The maximum supported width and height for a Tiled map is {ushort.MaxValue}.");
+
+ ContentLogger.Log($"Imported '{filePath}'");
+
+ return new TiledMapContentItem(map);
+
+ }
+ catch (Exception e)
+ {
+ context.Logger.LogImportantMessage(e.StackTrace);
+ throw;
+ }
+ }
+
+ private static TiledMapContent DeserializeTiledMapContent(string mapFilePath, ContentImporterContext context)
+ {
+ using (var reader = new StreamReader(mapFilePath))
+ {
+ var mapSerializer = new XmlSerializer(typeof(TiledMapContent));
+ var map = (TiledMapContent)mapSerializer.Deserialize(reader);
+
+ map.FilePath = mapFilePath;
+
+ for (var i = 0; i < map.Tilesets.Count; i++)
+ {
+ var tileset = map.Tilesets[i];
+
+ string getTilesetSource(string source)
+ => Path.GetFullPath(Path.Combine(Path.GetDirectoryName(mapFilePath), source));
+
+ if (!string.IsNullOrWhiteSpace(tileset.Source))
+ {
+ tileset.Source = getTilesetSource(tileset.Source);
+ ContentLogger.Log($"Adding dependency for {tileset.Source}");
+ // We depend on the tileset. If the tileset changes, the map also needs to rebuild.
+ context.AddDependency(tileset.Source);
+ }
+ else
+ {
+ tileset.Image.Source = getTilesetSource(tileset.Image.Source);
+ ContentLogger.Log($"Adding dependency for {tileset.Image.Source}");
+ context.AddDependency(tileset.Image.Source);
+ }
+ }
+
+ ImportLayers(context, map.Layers, Path.GetDirectoryName(mapFilePath));
+
+ map.Name = mapFilePath;
+ return map;
+ }
+ }
+
+ private static void ImportLayers(ContentImporterContext context, List<TiledMapLayerContent> layers, string path)
+ {
+ for (var i = 0; i < layers.Count; i++)
+ {
+ if (layers[i] is TiledMapImageLayerContent imageLayer)
+ {
+ imageLayer.Image.Source = Path.Combine(path, imageLayer.Image.Source);
+ ContentLogger.Log($"Adding dependency for '{imageLayer.Image.Source}'");
+
+ // Tell the pipeline that we depend on this image and need to rebuild the map if the image changes.
+ // (Maybe the image is a different size)
+ context.AddDependency(imageLayer.Image.Source);
+ }
+ if (layers[i] is TiledMapObjectLayerContent objectLayer)
+ foreach (var obj in objectLayer.Objects)
+ if (!String.IsNullOrWhiteSpace(obj.TemplateSource))
+ {
+ obj.TemplateSource = Path.Combine(path, obj.TemplateSource);
+ ContentLogger.Log($"Adding dependency for '{obj.TemplateSource}'");
+ // Tell the pipeline that we depend on this template and need to rebuild the map if the template changes.
+ // (Templates are loaded into objects on process, so all objects which depend on the template file
+ // need the change to the template)
+ context.AddDependency(obj.TemplateSource);
+ }
+ if (layers[i] is TiledMapGroupLayerContent groupLayer)
+ // Yay recursion!
+ ImportLayers(context, groupLayer.Layers, path);
+ }
+ }
+ }
+} \ No newline at end of file