diff options
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.cs | 108 |
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 |