From 7ce9911696ccc65ad7b83475c696d8ec3d8b388a Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Mon, 4 Jun 2018 17:26:03 -0500 Subject: [PATCH 01/14] TiledMapImageContent.Content Adds the `Content` field to `TiledMapImageContent` to reference the `Texture2DContent` instead of manually loading the content with the `ContentManager`. --- .../Tiled/TiledMapImageContent.cs | 5 +++++ .../Tiled/TiledMapImporter.cs | 13 +++++++++---- .../Tiled/TiledMapProcessor.cs | 6 ++++++ .../Tiled/TiledMapWriter.cs | 5 ++--- Source/MonoGame.Extended.Tiled/TiledMapReader.cs | 6 ++---- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs index 87748b91..73199fd0 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs @@ -1,9 +1,14 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using Microsoft.Xna.Framework.Content.Pipeline.Graphics; using System.Xml.Serialization; namespace MonoGame.Extended.Content.Pipeline.Tiled { public class TiledMapImageContent { + [XmlIgnore] + public ExternalReference Content; + [XmlAttribute(AttributeName = "source")] public string Source { get; set; } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs index 0abc7cec..e4e193d8 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs @@ -19,7 +19,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled ContentLogger.Logger = context.Logger; ContentLogger.Log($"Importing '{filePath}'"); - var map = DeserializeTiledMapContent(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}."); @@ -36,7 +36,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled } } - private static TiledMapContent DeserializeTiledMapContent(string mapFilePath) + private static TiledMapContent DeserializeTiledMapContent(string mapFilePath, ContentImporterContext context) { using (var reader = new StreamReader(mapFilePath)) { @@ -54,10 +54,14 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled if (!string.IsNullOrWhiteSpace(tileset.Source)) { var tilesetFilePath = GetTilesetFilePath(mapFilePath, tileset); - map.Tilesets[i] = ImportTileset(tilesetFilePath, tilesetSerializer, tileset); + map.Tilesets[i] = ImportTileset(tilesetFilePath, tilesetSerializer, tileset, context); } } + for (var i = 0; i < map.Layers.Count; i++) + if (map.Layers[i] is TiledMapImageLayerContent imageLayer) + context.AddDependency(imageLayer.Image.Source); + map.Name = mapFilePath; return map; } @@ -73,7 +77,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled return tilesetFilePath; } - private static TiledMapTilesetContent ImportTileset(string tilesetFilePath, XmlSerializer tilesetSerializer, TiledMapTilesetContent tileset) + private static TiledMapTilesetContent ImportTileset(string tilesetFilePath, XmlSerializer tilesetSerializer, TiledMapTilesetContent tileset, ContentImporterContext context) { TiledMapTilesetContent result; @@ -83,6 +87,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled { var importedTileset = (TiledMapTilesetContent)tilesetSerializer.Deserialize(file); importedTileset.FirstGlobalIdentifier = tileset.FirstGlobalIdentifier; + context.AddDependency(importedTileset.Image.Source); result = importedTileset; } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs index 4ce4232e..b8ab2279 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs @@ -4,6 +4,8 @@ using System.IO; using System.IO.Compression; using System.Linq; using Microsoft.Xna.Framework.Content.Pipeline; +using Microsoft.Xna.Framework.Content.Pipeline.Graphics; +using Microsoft.Xna.Framework.Graphics; using MonoGame.Utilities; using CompressionMode = System.IO.Compression.CompressionMode; @@ -26,6 +28,9 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled Environment.CurrentDirectory = newWorkingDirectory; + foreach (var tileset in map.Tilesets) + tileset.Image.Content = context.BuildAsset(new ExternalReference(tileset.Image.Source), ""); + foreach (var layer in map.Layers) { var imageLayer = layer as TiledMapImageLayerContent; @@ -33,6 +38,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled if (imageLayer != null) { ContentLogger.Log($"Processing image layer '{imageLayer.Name}'"); + imageLayer.Image.Content = context.BuildAsset(new ExternalReference(imageLayer.Image.Source), ""); ContentLogger.Log($"Processed image layer '{imageLayer.Name}'"); } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs index a582b08d..2c52d30e 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs @@ -50,7 +50,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled private static void WriteTileset(ContentWriter writer, TiledMapTilesetContent tileset) { - writer.Write(Path.ChangeExtension(tileset.Image.Source, null)); + writer.WriteExternalReference(tileset.Image.Content); writer.Write(tileset.FirstGlobalIdentifier); writer.Write(tileset.TileWidth); writer.Write(tileset.TileHeight); @@ -123,8 +123,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled private static void WriteImageLayer(ContentWriter writer, TiledMapImageLayerContent imageLayer) { - var textureAssetName = Path.ChangeExtension(imageLayer.Image.Source, null); - writer.Write(textureAssetName); + writer.WriteExternalReference(imageLayer.Image.Content); writer.Write(new Vector2(imageLayer.X, imageLayer.Y)); } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs index 715b91a3..5980cbe2 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs @@ -60,8 +60,7 @@ namespace MonoGame.Extended.Tiled private static TiledMapTileset ReadTileset(ContentReader reader, TiledMap map) { - var textureAssetName = reader.GetRelativeAssetName(reader.ReadString()); - var texture = reader.ContentManager.Load(textureAssetName); + var texture = reader.ReadExternalReference(); var firstGlobalIdentifier = reader.ReadInt32(); var tileWidth = reader.ReadInt32(); var tileHeight = reader.ReadInt32(); @@ -246,8 +245,7 @@ namespace MonoGame.Extended.Tiled private static TiledMapImageLayer ReadImageLayer(ContentReader reader, string name, Vector2 offset, float opacity, bool isVisible) { - var textureAssetName = reader.GetRelativeAssetName(reader.ReadString()); - var texture = reader.ContentManager.Load(textureAssetName); + var texture = reader.ReadExternalReference(); var x = reader.ReadSingle(); var y = reader.ReadSingle(); var position = new Vector2(x, y); From 184fba59280fdafac4fc444902102686c10cec62 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Tue, 5 Jun 2018 09:16:55 -0500 Subject: [PATCH 02/14] Include tileset textures internally Changed the reference of tileset textures so the `Texture2DContent` isn't referenced, but built into the file as tilesets don't reference the same texture more than once. --- .../Tiled/TiledMapImageContent.cs | 5 ++++- .../Tiled/TiledMapProcessor.cs | 4 ++-- .../Tiled/TiledMapWriter.cs | 4 ++-- Source/MonoGame.Extended.Tiled/TiledMapReader.cs | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs index 73199fd0..d9540d85 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImageContent.cs @@ -7,7 +7,10 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled public class TiledMapImageContent { [XmlIgnore] - public ExternalReference Content; + public Texture2DContent Content { get; set; } + + [XmlIgnore] + public ExternalReference ContentRef { get; set; } [XmlAttribute(AttributeName = "source")] public string Source { get; set; } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs index b8ab2279..dec019cf 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs @@ -29,7 +29,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled Environment.CurrentDirectory = newWorkingDirectory; foreach (var tileset in map.Tilesets) - tileset.Image.Content = context.BuildAsset(new ExternalReference(tileset.Image.Source), ""); + tileset.Image.Content = context.BuildAndLoadAsset(new ExternalReference(tileset.Image.Source), ""); foreach (var layer in map.Layers) { @@ -38,7 +38,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled if (imageLayer != null) { ContentLogger.Log($"Processing image layer '{imageLayer.Name}'"); - imageLayer.Image.Content = context.BuildAsset(new ExternalReference(imageLayer.Image.Source), ""); + imageLayer.Image.ContentRef = context.BuildAsset(new ExternalReference(imageLayer.Image.Source), ""); ContentLogger.Log($"Processed image layer '{imageLayer.Name}'"); } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs index 2c52d30e..d7889d32 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs @@ -50,7 +50,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled private static void WriteTileset(ContentWriter writer, TiledMapTilesetContent tileset) { - writer.WriteExternalReference(tileset.Image.Content); + writer.WriteObject(tileset.Image.Content); writer.Write(tileset.FirstGlobalIdentifier); writer.Write(tileset.TileWidth); writer.Write(tileset.TileHeight); @@ -123,7 +123,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled private static void WriteImageLayer(ContentWriter writer, TiledMapImageLayerContent imageLayer) { - writer.WriteExternalReference(imageLayer.Image.Content); + writer.WriteExternalReference(imageLayer.Image.ContentRef); writer.Write(new Vector2(imageLayer.X, imageLayer.Y)); } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs index 5980cbe2..01521311 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs @@ -60,7 +60,7 @@ namespace MonoGame.Extended.Tiled private static TiledMapTileset ReadTileset(ContentReader reader, TiledMap map) { - var texture = reader.ReadExternalReference(); + var texture = reader.ReadObject(); var firstGlobalIdentifier = reader.ReadInt32(); var tileWidth = reader.ReadInt32(); var tileHeight = reader.ReadInt32(); From 561c437023c99664a04e4b4d77f36b76691403e0 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Tue, 5 Jun 2018 14:51:36 -0500 Subject: [PATCH 03/14] Extract Writer and Reader for TIlesets Pulled out the methods for writing and reading the content files for tilesets into their own classes to allow loading tilesets independently from the maps. --- .../Tiled/TiledMapTilesetWriter.cs | 142 ++++++++++++++++ .../Tiled/TiledMapWriter.cs | 33 +--- .../MonoGame.Extended.Tiled/TiledMapReader.cs | 55 +----- .../TiledMapTilesetReader.cs | 157 ++++++++++++++++++ 4 files changed, 302 insertions(+), 85 deletions(-) create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetWriter.cs create mode 100644 Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetWriter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetWriter.cs new file mode 100644 index 00000000..0f45463b --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetWriter.cs @@ -0,0 +1,142 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; +using MonoGame.Extended.Tiled; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + [ContentTypeWriter] + class TiledMapTilesetWriter : ContentTypeWriter + { + public override string GetRuntimeReader(TargetPlatform targetPlatform) + => "MonoGame.Extended.Tiled.TiledMapTilesetReader, MonoGame.Extended.Tiled"; + + public override string GetRuntimeType(TargetPlatform targetPlatform) + => "MonoGame.Extended.Tiled.TiledMapTileset, MonoGame.Extended.Tiled"; + + protected override void Write(ContentWriter writer, TiledMapTilesetContent tileset) + { + try + { + WriteTileset(writer, tileset); + } + catch (Exception ex) + { + ContentLogger.Logger.LogImportantMessage(ex.StackTrace); + throw; + } + } + + public static void WriteTileset(ContentWriter writer, TiledMapTilesetContent tileset) + { + writer.WriteObject(tileset.Image.Content); + writer.Write(tileset.TileWidth); + writer.Write(tileset.TileHeight); + writer.Write(tileset.TileCount); + writer.Write(tileset.Spacing); + writer.Write(tileset.Margin); + writer.Write(tileset.Columns); + writer.Write(tileset.Tiles.Count); + + foreach (var tilesetTile in tileset.Tiles) + WriteTilesetTile(writer, tilesetTile); + + writer.WriteTiledMapProperties(tileset.Properties); + + } + + private static void WriteTilesetTile(ContentWriter writer, TiledMapTilesetTileContent tilesetTile) + { + writer.Write(tilesetTile.LocalIdentifier); + writer.Write(tilesetTile.Type); + writer.Write(tilesetTile.Frames.Count); + writer.Write(tilesetTile.Objects.Count); + + foreach (var @object in tilesetTile.Objects) + WriteObject(writer, @object); + + foreach (var frame in tilesetTile.Frames) + { + writer.Write(frame.TileIdentifier); + writer.Write(frame.Duration); + } + + writer.WriteTiledMapProperties(tilesetTile.Properties); + } + + private static void WriteObject(ContentWriter writer, TiledMapObjectContent @object) + { + var type = GetObjectType(@object); + + writer.Write((byte)type); + + writer.Write(@object.Identifier); + writer.Write(@object.Name ?? string.Empty); + writer.Write(@object.Type ?? string.Empty); + writer.Write(@object.X); + writer.Write(@object.Y); + writer.Write(@object.Width); + writer.Write(@object.Height); + writer.Write(@object.Rotation); + writer.Write(@object.Visible); + + writer.WriteTiledMapProperties(@object.Properties); + + switch (type) + { + case TiledMapObjectType.Rectangle: + case TiledMapObjectType.Ellipse: + break; + case TiledMapObjectType.Tile: + writer.Write(@object.GlobalIdentifier); + break; + case TiledMapObjectType.Polygon: + WritePolyPoints(writer, @object.Polygon.Points); + break; + case TiledMapObjectType.Polyline: + WritePolyPoints(writer, @object.Polyline.Points); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + // ReSharper disable once SuggestBaseTypeForParameter + private static void WritePolyPoints(ContentWriter writer, string @string) + { + var stringPoints = @string.Split(' '); + + writer.Write(stringPoints.Length); + + foreach (var stringPoint in stringPoints) + { + var xy = stringPoint.Split(','); + var x = float.Parse(xy[0], CultureInfo.InvariantCulture.NumberFormat); + writer.Write(x); + var y = float.Parse(xy[1], CultureInfo.InvariantCulture.NumberFormat); + writer.Write(y); + } + } + + public static TiledMapObjectType GetObjectType(TiledMapObjectContent content) + { + if (content.GlobalIdentifier > 0) + return TiledMapObjectType.Tile; + + if (content.Ellipse != null) + return TiledMapObjectType.Ellipse; + + if (content.Polygon != null) + return TiledMapObjectType.Polygon; + + // ReSharper disable once ConvertIfStatementToReturnStatement + if (content.Polyline != null) + return TiledMapObjectType.Polyline; + + return TiledMapObjectType.Rectangle; + } + } +} diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs index d7889d32..9ebe6102 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs @@ -50,39 +50,8 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled private static void WriteTileset(ContentWriter writer, TiledMapTilesetContent tileset) { - writer.WriteObject(tileset.Image.Content); writer.Write(tileset.FirstGlobalIdentifier); - writer.Write(tileset.TileWidth); - writer.Write(tileset.TileHeight); - writer.Write(tileset.TileCount); - writer.Write(tileset.Spacing); - writer.Write(tileset.Margin); - writer.Write(tileset.Columns); - writer.Write(tileset.Tiles.Count); - - foreach (var tilesetTile in tileset.Tiles) - WriteTilesetTile(writer, tilesetTile); - - writer.WriteTiledMapProperties(tileset.Properties); - } - - private static void WriteTilesetTile(ContentWriter writer, TiledMapTilesetTileContent tilesetTile) - { - writer.Write(tilesetTile.LocalIdentifier); - writer.Write(tilesetTile.Type); - writer.Write(tilesetTile.Frames.Count); - writer.Write(tilesetTile.Objects.Count); - - foreach (var @object in tilesetTile.Objects) - WriteObject(writer, @object); - - foreach (var frame in tilesetTile.Frames) - { - writer.Write(frame.TileIdentifier); - writer.Write(frame.Duration); - } - - writer.WriteTiledMapProperties(tilesetTile.Properties); + TiledMapTilesetWriter.WriteTileset(writer, tileset); } private static void WriteLayers(ContentWriter writer, IReadOnlyCollection layers) diff --git a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs index 01521311..a695e189 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs @@ -60,61 +60,10 @@ namespace MonoGame.Extended.Tiled private static TiledMapTileset ReadTileset(ContentReader reader, TiledMap map) { - var texture = reader.ReadObject(); var firstGlobalIdentifier = reader.ReadInt32(); - var tileWidth = reader.ReadInt32(); - var tileHeight = reader.ReadInt32(); - var tileCount = reader.ReadInt32(); - var spacing = reader.ReadInt32(); - var margin = reader.ReadInt32(); - var columns = reader.ReadInt32(); - var explicitTileCount = reader.ReadInt32(); + var tileset = TiledMapTilesetReader.ReadTileset(reader, firstGlobalIdentifier); - var tileset = new TiledMapTileset(texture, firstGlobalIdentifier, tileWidth, tileHeight, tileCount, spacing, margin, columns); - - for (var tileIndex = 0; tileIndex < explicitTileCount; tileIndex++) - { - var localTileIdentifier = reader.ReadInt32(); - var type = reader.ReadString(); - var animationFramesCount = reader.ReadInt32(); - var tilesetTile = animationFramesCount <= 0 - ? ReadTiledMapTilesetTile(reader, map, objects => - new TiledMapTilesetTile(localTileIdentifier, type, objects)) - : ReadTiledMapTilesetTile(reader, map, objects => - new TiledMapTilesetAnimatedTile(localTileIdentifier, ReadTiledMapTilesetAnimationFrames(reader, tileset, animationFramesCount), type, objects)); - - ReadProperties(reader, tilesetTile.Properties); - tileset.Tiles.Add(tilesetTile); - } - - ReadProperties(reader, tileset.Properties); - return tileset; - } - - private static TiledMapTilesetTileAnimationFrame[] ReadTiledMapTilesetAnimationFrames(ContentReader reader, TiledMapTileset tileset, int animationFramesCount) - { - var animationFrames = new TiledMapTilesetTileAnimationFrame[animationFramesCount]; - - for (var i = 0; i < animationFramesCount; i++) - { - var localTileIdentifierForFrame = reader.ReadInt32(); - var frameDurationInMilliseconds = reader.ReadInt32(); - var tileSetTileFrame = new TiledMapTilesetTileAnimationFrame(tileset, localTileIdentifierForFrame, frameDurationInMilliseconds); - animationFrames[i] = tileSetTileFrame; - } - - return animationFrames; - } - - private static TiledMapTilesetTile ReadTiledMapTilesetTile(ContentReader reader, TiledMap map, Func createTile) - { - var objectCount = reader.ReadInt32(); - var objects = new TiledMapObject[objectCount]; - - for (var i = 0; i < objectCount; i++) - objects[i] = ReadTiledMapObject(reader, map); - - return createTile(objects); + return tileset; } private static void ReadLayers(ContentReader reader, TiledMap map) diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs new file mode 100644 index 00000000..7b2e5942 --- /dev/null +++ b/Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs @@ -0,0 +1,157 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.Tiled; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MonoGame.Extended.Tiled +{ + public class TiledMapTilesetReader : ContentTypeReader + { + protected override TiledMapTileset Read(ContentReader reader, TiledMapTileset existingInstance) + { + if (existingInstance != null) + return existingInstance; + + return ReadTileset(reader, 0); + } + + public static TiledMapTileset ReadTileset(ContentReader reader, int firstGlobalIdentifier) + { + var texture = reader.ReadObject(); + var tileWidth = reader.ReadInt32(); + var tileHeight = reader.ReadInt32(); + var tileCount = reader.ReadInt32(); + var spacing = reader.ReadInt32(); + var margin = reader.ReadInt32(); + var columns = reader.ReadInt32(); + var explicitTileCount = reader.ReadInt32(); + + var tileset = new TiledMapTileset(texture, firstGlobalIdentifier, tileWidth, tileHeight, tileCount, spacing, margin, columns); + + for (var tileIndex = 0; tileIndex < explicitTileCount; tileIndex++) + { + var localTileIdentifier = reader.ReadInt32(); + var type = reader.ReadString(); + var animationFramesCount = reader.ReadInt32(); + var tilesetTile = animationFramesCount <= 0 + ? ReadTiledMapTilesetTile(reader, tileset, objects => + new TiledMapTilesetTile(localTileIdentifier, type, objects)) + : ReadTiledMapTilesetTile(reader, tileset, objects => + new TiledMapTilesetAnimatedTile(localTileIdentifier, ReadTiledMapTilesetAnimationFrames(reader, tileset, animationFramesCount), type, objects)); + + ReadProperties(reader, tilesetTile.Properties); + tileset.Tiles.Add(tilesetTile); + } + + ReadProperties(reader, tileset.Properties); + return tileset; + } + + private static TiledMapTilesetTileAnimationFrame[] ReadTiledMapTilesetAnimationFrames(ContentReader reader, TiledMapTileset tileset, int animationFramesCount) + { + var animationFrames = new TiledMapTilesetTileAnimationFrame[animationFramesCount]; + + for (var i = 0; i < animationFramesCount; i++) + { + var localTileIdentifierForFrame = reader.ReadInt32(); + var frameDurationInMilliseconds = reader.ReadInt32(); + var tileSetTileFrame = new TiledMapTilesetTileAnimationFrame(tileset, localTileIdentifierForFrame, frameDurationInMilliseconds); + animationFrames[i] = tileSetTileFrame; + } + + return animationFrames; + } + + private static TiledMapTilesetTile ReadTiledMapTilesetTile(ContentReader reader, TiledMapTileset tileset, Func createTile) + { + var objectCount = reader.ReadInt32(); + var objects = new TiledMapObject[objectCount]; + + for (var i = 0; i < objectCount; i++) + objects[i] = ReadTiledMapObject(reader, tileset); + + return createTile(objects); + } + + private static TiledMapObject ReadTiledMapObject(ContentReader reader, TiledMapTileset tileset) + { + var objectType = (TiledMapObjectType)reader.ReadByte(); + var identifier = reader.ReadInt32(); + var name = reader.ReadString(); + var type = reader.ReadString(); + var position = new Vector2(reader.ReadSingle(), reader.ReadSingle()); + var width = reader.ReadSingle(); + var height = reader.ReadSingle(); + var size = new Size2(width, height); + var rotation = reader.ReadSingle(); + var isVisible = reader.ReadBoolean(); + var properties = new TiledMapProperties(); + const float opacity = 1.0f; + + ReadProperties(reader, properties); + + TiledMapObject mapObject; + + switch (objectType) + { + case TiledMapObjectType.Rectangle: + mapObject = new TiledMapRectangleObject(identifier, name, size, position, rotation, opacity, isVisible, type); + break; + case TiledMapObjectType.Tile: + var globalTileIdentifierWithFlags = reader.ReadUInt32(); + var tile = new TiledMapTile(globalTileIdentifierWithFlags, (ushort)position.X, (ushort)position.Y); + var localTileIdentifier = tile.GlobalIdentifier - tileset.FirstGlobalIdentifier; + var tilesetTile = tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier); + mapObject = new TiledMapTileObject(identifier, name, tileset, tilesetTile, size, position, rotation, opacity, isVisible, type); + break; + case TiledMapObjectType.Ellipse: + mapObject = new TiledMapEllipseObject(identifier, name, size, position, rotation, opacity, isVisible); + break; + case TiledMapObjectType.Polygon: + mapObject = new TiledMapPolygonObject(identifier, name, ReadPoints(reader), size, position, rotation, opacity, isVisible, type); + break; + case TiledMapObjectType.Polyline: + mapObject = new TiledMapPolylineObject(identifier, name, ReadPoints(reader), size, position, rotation, opacity, isVisible, type); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + foreach (var property in properties) + mapObject.Properties.Add(property.Key, property.Value); + + return mapObject; + } + + private static Point2[] ReadPoints(ContentReader reader) + { + var pointCount = reader.ReadInt32(); + var points = new Point2[pointCount]; + + for (var i = 0; i < pointCount; i++) + { + var x = reader.ReadSingle(); + var y = reader.ReadSingle(); + points[i] = new Point2(x, y); + } + + return points; + } + + private static void ReadProperties(ContentReader reader, TiledMapProperties properties) + { + var count = reader.ReadInt32(); + + for (var i = 0; i < count; i++) + { + var key = reader.ReadString(); + var value = reader.ReadString(); + properties[key] = value; + } + } + } +} From 0ca4ae70da253b7ff438b96754593277c97df1e8 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Wed, 6 Jun 2018 11:53:46 -0500 Subject: [PATCH 04/14] Importer and Processor Added importer and processor for `TiledMapTilesetContent` --- .../Tiled/TiledMapProcessor.cs | 9 +++- .../Tiled/TiledMapTilesetContent.cs | 4 ++ .../Tiled/TiledMapTilesetImporter.cs | 49 +++++++++++++++++++ .../Tiled/TiledMapTilesetProcessor.cs | 31 ++++++++++++ .../Tiled/TiledMapWriter.cs | 11 ++++- .../MonoGame.Extended.Tiled/TiledMapReader.cs | 10 +++- .../TiledMapTileset.cs | 2 +- 7 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs index dec019cf..8bfca1f1 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs @@ -29,7 +29,14 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled Environment.CurrentDirectory = newWorkingDirectory; foreach (var tileset in map.Tilesets) - tileset.Image.Content = context.BuildAndLoadAsset(new ExternalReference(tileset.Image.Source), ""); + { + if (String.IsNullOrWhiteSpace(tileset.Source)) + tileset.Image.Content = context.BuildAndLoadAsset(new ExternalReference(tileset.Image.Source), ""); + else + { + tileset.Content = context.BuildAsset(new ExternalReference(tileset.Source), ""); + } + } foreach (var layer in map.Layers) { diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs index 71a58328..430ce74f 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs @@ -1,3 +1,4 @@ +using Microsoft.Xna.Framework.Content.Pipeline; using System.Collections.Generic; using System.Xml.Serialization; @@ -6,6 +7,9 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled [XmlRoot(ElementName = "tileset")] public class TiledMapTilesetContent { + [XmlIgnore] + public ExternalReference Content { get; set; } + [XmlAttribute(AttributeName = "firstgid")] public int FirstGlobalIdentifier { get; set; } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs new file mode 100644 index 00000000..2bcf905c --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs @@ -0,0 +1,49 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml.Serialization; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + [ContentImporter(".tsx", DefaultProcessor = "TiledMapTilesetProcessor", DisplayName = "Tiled Map Tileset Importer - MonoGame.Extended")] + public class TiledMapTilesetImporter : ContentImporter + { + public override TiledMapTilesetContent Import(string filePath, ContentImporterContext context) + { + try + { + if (filePath == null) + throw new ArgumentNullException(nameof(filePath)); + + ContentLogger.Logger = context.Logger; + ContentLogger.Log($"Importing '{filePath}'"); + + var tileset = DeserializeTiledMapTilesetContent(filePath, context); + + ContentLogger.Log($"Imported '{filePath}'"); + + return tileset; + } + catch (Exception e) + { + context.Logger.LogImportantMessage(e.StackTrace); + return null; + } + } + + private TiledMapTilesetContent DeserializeTiledMapTilesetContent(string filePath, ContentImporterContext context) + { + using (var reader = new StreamReader(filePath)) + { + var tilesetSerializer = new XmlSerializer(typeof(TiledMapTilesetContent)); + var tileset = (TiledMapTilesetContent)tilesetSerializer.Deserialize(reader); + + context.AddDependency(tileset.Image.Source); + + return tileset; + } + } + } +} diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs new file mode 100644 index 00000000..d71aa528 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs @@ -0,0 +1,31 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using Microsoft.Xna.Framework.Content.Pipeline.Graphics; +using System; +using System.Collections.Generic; +using System.Text; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + [ContentProcessor(DisplayName = "Tiled Map Tileset Processor - MonoGame.Extended")] + public class TiledMapTilesetProcessor : ContentProcessor + { + public override TiledMapTilesetContent Process(TiledMapTilesetContent tileset, ContentProcessorContext context) + { + try + { + ContentLogger.Logger = context.Logger; + + ContentLogger.Log($"Processing tileset '{tileset.Name}'"); + tileset.Image.Content = context.BuildAndLoadAsset(new ExternalReference(tileset.Image.Source), ""); + ContentLogger.Log($"Processed tileset '{tileset.Name}'"); + + return tileset; + } + catch (Exception ex) + { + context.Logger.LogImportantMessage(ex.Message); + return null; + } + } + } +} diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs index 9ebe6102..736a3d00 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs @@ -51,7 +51,16 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled private static void WriteTileset(ContentWriter writer, TiledMapTilesetContent tileset) { writer.Write(tileset.FirstGlobalIdentifier); - TiledMapTilesetWriter.WriteTileset(writer, tileset); + if (tileset.Content != null) + { + writer.Write(true); + writer.WriteExternalReference(tileset.Content); + } + else + { + writer.Write(false); + TiledMapTilesetWriter.WriteTileset(writer, tileset); + } } private static void WriteLayers(ContentWriter writer, IReadOnlyCollection layers) diff --git a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs index a695e189..97504ef6 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs @@ -60,8 +60,16 @@ namespace MonoGame.Extended.Tiled private static TiledMapTileset ReadTileset(ContentReader reader, TiledMap map) { + TiledMapTileset tileset; var firstGlobalIdentifier = reader.ReadInt32(); - var tileset = TiledMapTilesetReader.ReadTileset(reader, firstGlobalIdentifier); + var external = reader.ReadBoolean(); + if (external) + { + tileset = reader.ReadExternalReference(); + tileset.FirstGlobalIdentifier = firstGlobalIdentifier; + } + else + tileset = TiledMapTilesetReader.ReadTileset(reader, firstGlobalIdentifier); return tileset; } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs b/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs index 7540c775..09a9c2d3 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs @@ -23,7 +23,7 @@ namespace MonoGame.Extended.Tiled public string Name => Texture.Name; public Texture2D Texture { get; } - public int FirstGlobalIdentifier { get; } + public int FirstGlobalIdentifier { get; internal set; } public int TileWidth { get; } public int TileHeight { get; } public int Spacing { get; } From 119026ea50c427df3ac7a192e1661a5ff9ffbf09 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Wed, 6 Jun 2018 14:59:38 -0500 Subject: [PATCH 05/14] Decoupled FirstGlobalIdentifier from Tileset `FirstGlobalIdentifier` is only used with the map to reference the tileset which contains the tile referenced. It isn't really part of the definition of a `TiledMapTileset` even though the `.TMX` format includes it with the `` tag --- .../Renderers/TiledMapModelBuilder.cs | 6 ++++-- Source/MonoGame.Extended.Tiled/TiledMap.cs | 17 ++++++++++++++--- .../MonoGame.Extended.Tiled/TiledMapReader.cs | 11 ++++------- .../MonoGame.Extended.Tiled/TiledMapTileset.cs | 13 ++++++------- .../TiledMapTilesetReader.cs | 13 +++++-------- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs b/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs index 87f38c48..d4a85846 100644 --- a/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs +++ b/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs @@ -44,12 +44,14 @@ namespace MonoGame.Extended.Tiled.Renderers foreach (var tileset in map.Tilesets) { + var firstGlobalIdentifier = map.GetTilesetFirstGlobalIdentifier(tileset); + var lastGlobalIdentifier = tileset.TileCount + firstGlobalIdentifier - 1; var texture = tileset.Texture; - foreach (var tile in tileLayer.Tiles.Where(t => tileset.ContainsGlobalIdentifier(t.GlobalIdentifier))) + foreach (var tile in tileLayer.Tiles.Where(t => firstGlobalIdentifier <= t.GlobalIdentifier && t.GlobalIdentifier <= lastGlobalIdentifier)) { var tileGid = tile.GlobalIdentifier; - var localTileIdentifier = tileGid - tileset.FirstGlobalIdentifier; + var localTileIdentifier = tileGid - firstGlobalIdentifier; var position = GetTilePosition(map, tile); var tilesetColumns = tileset.Columns == 0 ? 1 : tileset.Columns; // fixes a problem (what problem exactly?) var sourceRectangle = TiledMapHelper.GetTileSourceRectangle(localTileIdentifier, tileset.TileWidth, tileset.TileHeight, tilesetColumns, tileset.Margin, tileset.Spacing); diff --git a/Source/MonoGame.Extended.Tiled/TiledMap.cs b/Source/MonoGame.Extended.Tiled/TiledMap.cs index dc822bf0..76fe316d 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMap.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMap.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Microsoft.Xna.Framework; @@ -13,6 +14,7 @@ namespace MonoGame.Extended.Tiled private readonly List _objectLayers = new List(); private readonly List _tileLayers = new List(); private readonly List _tilesets = new List(); + private readonly List> _firstGlobalIdentifiers = new List>(); public string Name { get; } public int Width { get; } @@ -55,9 +57,10 @@ namespace MonoGame.Extended.Tiled BackgroundColor = backgroundColor; } - public void AddTileset(TiledMapTileset tileset) + public void AddTileset(TiledMapTileset tileset, int firstGlobalIdentifier) { _tilesets.Add(tileset); + _firstGlobalIdentifiers.Add(new Tuple(tileset, firstGlobalIdentifier)); } public void AddLayer(TiledMapLayer layer) @@ -93,7 +96,15 @@ namespace MonoGame.Extended.Tiled public TiledMapTileset GetTilesetByTileGlobalIdentifier(int tileIdentifier) { - return _tilesets.FirstOrDefault(tileset => tileset.ContainsGlobalIdentifier(tileIdentifier)); + foreach (var tileset in _firstGlobalIdentifiers) + if (tileIdentifier >= tileset.Item2 && tileIdentifier < tileset.Item2 + tileset.Item1.TileCount) + return tileset.Item1; + return null; } + + public int GetTilesetFirstGlobalIdentifier(TiledMapTileset tileset) + { + return _firstGlobalIdentifiers.FirstOrDefault(t => t.Item1 == tileset).Item2; + } } } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs index 97504ef6..56a1fd02 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs @@ -53,23 +53,20 @@ namespace MonoGame.Extended.Tiled for (var i = 0; i < tilesetCount; i++) { + var firstGlobalIdentifier = reader.ReadInt32(); var tileset = ReadTileset(reader, map); - map.AddTileset(tileset); + map.AddTileset(tileset, firstGlobalIdentifier); } } private static TiledMapTileset ReadTileset(ContentReader reader, TiledMap map) { TiledMapTileset tileset; - var firstGlobalIdentifier = reader.ReadInt32(); var external = reader.ReadBoolean(); if (external) - { tileset = reader.ReadExternalReference(); - tileset.FirstGlobalIdentifier = firstGlobalIdentifier; - } else - tileset = TiledMapTilesetReader.ReadTileset(reader, firstGlobalIdentifier); + tileset = TiledMapTilesetReader.ReadTileset(reader); return tileset; } @@ -162,7 +159,7 @@ namespace MonoGame.Extended.Tiled var globalTileIdentifierWithFlags = reader.ReadUInt32(); var tile = new TiledMapTile(globalTileIdentifierWithFlags, (ushort)position.X, (ushort)position.Y); var tileset = map.GetTilesetByTileGlobalIdentifier(tile.GlobalIdentifier); - var localTileIdentifier = tile.GlobalIdentifier - tileset.FirstGlobalIdentifier; + var localTileIdentifier = tile.GlobalIdentifier - map.GetTilesetFirstGlobalIdentifier(tileset); var tilesetTile = tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier); mapObject = new TiledMapTileObject(identifier, name, tileset, tilesetTile, size, position, rotation, opacity, isVisible, type); break; diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs b/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs index 09a9c2d3..ae117e1b 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs @@ -7,10 +7,9 @@ namespace MonoGame.Extended.Tiled { public class TiledMapTileset { - public TiledMapTileset(Texture2D texture, int firstGlobalIdentifier, int tileWidth, int tileHeight, int tileCount, int spacing, int margin, int columns) + public TiledMapTileset(Texture2D texture, int tileWidth, int tileHeight, int tileCount, int spacing, int margin, int columns) { Texture = texture; - FirstGlobalIdentifier = firstGlobalIdentifier; TileWidth = tileWidth; TileHeight = tileHeight; TileCount = tileCount; @@ -23,7 +22,7 @@ namespace MonoGame.Extended.Tiled public string Name => Texture.Name; public Texture2D Texture { get; } - public int FirstGlobalIdentifier { get; internal set; } + //public int FirstGlobalIdentifier { get; internal set; } public int TileWidth { get; } public int TileHeight { get; } public int Spacing { get; } @@ -46,9 +45,9 @@ namespace MonoGame.Extended.Tiled // //return animatedTile; //} - public bool ContainsGlobalIdentifier(int globalIdentifier) - { - return globalIdentifier >= FirstGlobalIdentifier && globalIdentifier < FirstGlobalIdentifier + TileCount; - } + //public bool ContainsGlobalIdentifier(int globalIdentifier) + //{ + // return globalIdentifier >= FirstGlobalIdentifier && globalIdentifier < FirstGlobalIdentifier + TileCount; + //} } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs index 7b2e5942..ce54fac0 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapTilesetReader.cs @@ -16,10 +16,10 @@ namespace MonoGame.Extended.Tiled if (existingInstance != null) return existingInstance; - return ReadTileset(reader, 0); + return ReadTileset(reader); } - public static TiledMapTileset ReadTileset(ContentReader reader, int firstGlobalIdentifier) + public static TiledMapTileset ReadTileset(ContentReader reader) { var texture = reader.ReadObject(); var tileWidth = reader.ReadInt32(); @@ -30,7 +30,7 @@ namespace MonoGame.Extended.Tiled var columns = reader.ReadInt32(); var explicitTileCount = reader.ReadInt32(); - var tileset = new TiledMapTileset(texture, firstGlobalIdentifier, tileWidth, tileHeight, tileCount, spacing, margin, columns); + var tileset = new TiledMapTileset(texture, tileWidth, tileHeight, tileCount, spacing, margin, columns); for (var tileIndex = 0; tileIndex < explicitTileCount; tileIndex++) { @@ -102,11 +102,8 @@ namespace MonoGame.Extended.Tiled mapObject = new TiledMapRectangleObject(identifier, name, size, position, rotation, opacity, isVisible, type); break; case TiledMapObjectType.Tile: - var globalTileIdentifierWithFlags = reader.ReadUInt32(); - var tile = new TiledMapTile(globalTileIdentifierWithFlags, (ushort)position.X, (ushort)position.Y); - var localTileIdentifier = tile.GlobalIdentifier - tileset.FirstGlobalIdentifier; - var tilesetTile = tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier); - mapObject = new TiledMapTileObject(identifier, name, tileset, tilesetTile, size, position, rotation, opacity, isVisible, type); + reader.ReadUInt32(); // Tile objects within TiledMapTilesetTiles currently ignore the gid and behave like rectangle objects. + mapObject = new TiledMapRectangleObject(identifier, name, size, position, rotation, opacity, isVisible, type); break; case TiledMapObjectType.Ellipse: mapObject = new TiledMapEllipseObject(identifier, name, size, position, rotation, opacity, isVisible); From 92dc95109945949623cdacf8718479abb502e812 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Thu, 7 Jun 2018 15:17:15 -0500 Subject: [PATCH 06/14] Object Templates Added handling of `TiledMapObject` templates. Tile object templates are currently not working as the tileset info is currently ignored. --- .../Tiled/TiledMapImporter.cs | 12 ++ .../Tiled/TiledMapObjectContent.cs | 123 ++++++++++++------ .../Tiled/TiledMapObjectTemplateContent.cs | 21 +++ .../Tiled/TiledMapObjectTemplateImporter.cs | 52 ++++++++ .../Tiled/TiledMapProcessor.cs | 46 ++++--- .../Tiled/TiledMapTilesetImporter.cs | 5 + .../Tiled/TiledMapTilesetProcessor.cs | 5 + .../TestData/template.tx | 4 + 8 files changed, 210 insertions(+), 58 deletions(-) create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateContent.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs create mode 100644 Source/Tests/MonoGame.Extended.Content.Pipeline.Tests.Tiled/TestData/template.tx diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs index e4e193d8..686eef95 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs @@ -59,8 +59,14 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled } for (var i = 0; i < map.Layers.Count; i++) + { if (map.Layers[i] is TiledMapImageLayerContent imageLayer) context.AddDependency(imageLayer.Image.Source); + if (map.Layers[i] is TiledMapObjectLayerContent objectLayer) + foreach (var obj in objectLayer.Objects) + if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) + context.AddDependency(obj.TemplateSource); + } map.Name = mapFilePath; return map; @@ -88,6 +94,12 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled var importedTileset = (TiledMapTilesetContent)tilesetSerializer.Deserialize(file); importedTileset.FirstGlobalIdentifier = tileset.FirstGlobalIdentifier; context.AddDependency(importedTileset.Image.Source); + + foreach (var tile in importedTileset.Tiles) + foreach (var obj in tile.Objects) + if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) + context.AddDependency(obj.TemplateSource); + result = importedTileset; } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs index 7dae5495..56fea253 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs @@ -1,57 +1,106 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using MonoGame.Extended.Tiled; +using System; using System.Collections.Generic; using System.Xml.Serialization; namespace MonoGame.Extended.Content.Pipeline.Tiled { - public class TiledMapObjectContent - { - [XmlAttribute(DataType = "int", AttributeName = "id")] - public int Identifier { get; set; } + public class TiledMapObjectContent + { + private uint? _globalIdentifier; + private int? _identifier; + private float? _height; + private float? _rotation; + private bool? _visible; + private float? _width; + private float? _x; + private float? _y; - [XmlAttribute(DataType = "string", AttributeName = "name")] - public string Name { get; set; } + [XmlAttribute(DataType = "int", AttributeName = "id")] + public int Identifier { get => _identifier ?? 0; set => _identifier = value; } - [XmlAttribute(DataType = "string", AttributeName = "type")] - public string Type { get; set; } + [XmlAttribute(DataType = "string", AttributeName = "name")] + public string Name { get; set; } - [XmlAttribute(DataType = "float", AttributeName = "x")] - public float X { get; set; } + [XmlAttribute(DataType = "string", AttributeName = "type")] + public string Type { get; set; } - [XmlAttribute(DataType = "float", AttributeName = "y")] - public float Y { get; set; } + [XmlAttribute(DataType = "float", AttributeName = "x")] + public float X { get => _x ?? 0; set => _x = value; } - [XmlAttribute(DataType = "float", AttributeName = "width")] - public float Width { get; set; } + [XmlAttribute(DataType = "float", AttributeName = "y")] + public float Y { get => _y ?? 0; set => _y = value; } - [XmlAttribute(DataType = "float", AttributeName = "height")] - public float Height { get; set; } + [XmlAttribute(DataType = "float", AttributeName = "width")] + public float Width { get => _width ?? 0; set => _width = value; } - [XmlAttribute(DataType = "float", AttributeName = "rotation")] - public float Rotation { get; set; } + [XmlAttribute(DataType = "float", AttributeName = "height")] + public float Height { get => _height ?? 0; set => _height = value; } - [XmlAttribute(DataType = "boolean", AttributeName = "visible")] - public bool Visible { get; set; } + [XmlAttribute(DataType = "float", AttributeName = "rotation")] + public float Rotation { get => _rotation ?? 0; set => _rotation = value; } - [XmlArray("properties")] - [XmlArrayItem("property")] - public List Properties { get; set; } + [XmlAttribute(DataType = "boolean", AttributeName = "visible")] + public bool Visible { get => _visible ?? true; set => _visible = value; } - [XmlAttribute(DataType = "unsignedInt", AttributeName = "gid")] - public uint GlobalIdentifier { get; set; } + [XmlArray("properties")] + [XmlArrayItem("property")] + public List Properties { get; set; } - [XmlElement(ElementName = "ellipse")] - public TiledMapEllipseContent Ellipse { get; set; } + [XmlAttribute(DataType = "unsignedInt", AttributeName = "gid")] + public uint GlobalIdentifier { get => _globalIdentifier??0; set => _globalIdentifier = value; } - [XmlElement(ElementName = "polygon")] - public TiledMapPolygonContent Polygon { get; set; } + [XmlElement(ElementName = "ellipse")] + public TiledMapEllipseContent Ellipse { get; set; } - [XmlElement(ElementName = "polyline")] - public TiledMapPolylineContent Polyline { get; set; } + [XmlElement(ElementName = "polygon")] + public TiledMapPolygonContent Polygon { get; set; } - public TiledMapObjectContent() - { - GlobalIdentifier = 0; - Visible = true; - } - } + [XmlElement(ElementName = "polyline")] + public TiledMapPolylineContent Polyline { get; set; } + + [XmlAttribute(DataType = "string", AttributeName = "template")] + public string TemplateSource { get; set; } + + internal static void Process(TiledMapObjectContent obj, ContentProcessorContext context) + { + if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) + { + var template = context.BuildAndLoadAsset(new ExternalReference(obj.TemplateSource), ""); + + Process(template.Object, context); + + if (!obj._globalIdentifier.HasValue && template.Object._globalIdentifier.HasValue) + obj.GlobalIdentifier = template.Object.GlobalIdentifier; + if (!obj._height.HasValue && template.Object._height.HasValue) + obj.Height = template.Object.Height; + if (!obj._identifier.HasValue && template.Object._identifier.HasValue) + obj.Identifier = template.Object.Identifier; + if (!obj._rotation.HasValue && template.Object._rotation.HasValue) + obj.Rotation = template.Object.Rotation; + if (!obj._visible.HasValue && template.Object._visible.HasValue) + obj.Visible = template.Object.Visible; + if (!obj._width.HasValue && template.Object._width.HasValue) + obj.Width = template.Object.Width; + if (!obj._x.HasValue && template.Object._x.HasValue) + obj.X = template.Object.X; + if (!obj._y.HasValue && template.Object._y.HasValue) + obj.Y = template.Object.Y; + if (obj.Ellipse == null && template.Object.Ellipse != null) + obj.Ellipse = template.Object.Ellipse; + if (String.IsNullOrWhiteSpace(obj.Name) && !String.IsNullOrWhiteSpace(template.Object.Name)) + obj.Name = template.Object.Name; + if (obj.Polygon == null && template.Object.Polygon != null) + obj.Polygon = template.Object.Polygon; + if (obj.Polyline == null && template.Object.Polyline != null) + obj.Polyline = template.Object.Polyline; + foreach (var tProperty in template.Object.Properties) + if (!obj.Properties.Exists(p => p.Name == tProperty.Name)) + obj.Properties.Add(tProperty); + if (String.IsNullOrWhiteSpace(obj.Type) && !String.IsNullOrWhiteSpace(template.Object.Type)) + obj.Type = template.Object.Type; + } + } + } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateContent.cs new file mode 100644 index 00000000..32e1a027 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateContent.cs @@ -0,0 +1,21 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml.Serialization; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + [XmlRoot(ElementName = "template")] + public class TiledMapObjectTemplateContent + { + [XmlElement(ElementName = "tileset")] + public TiledMapTilesetContent Tileset { get; set; } + + [XmlIgnore] + public ExternalReference TilesetReference { get; set; } + + [XmlElement(ElementName = "object")] + public TiledMapObjectContent Object { get; set; } + } +} diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs new file mode 100644 index 00000000..e68b6185 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs @@ -0,0 +1,52 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml.Serialization; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + [ContentImporter(".tx", DefaultProcessor = "TiledMapObjectTemplateProcessor", DisplayName = "Tiled Map Object Template Importer - MonoGame.Extended")] + public class TiledMapObjectTemplateImporter : ContentImporter + { + public override TiledMapObjectTemplateContent Import(string filePath, ContentImporterContext context) + { + try + { + if (filePath == null) + throw new ArgumentNullException(nameof(filePath)); + + ContentLogger.Logger = context.Logger; + ContentLogger.Log($"Importing '{filePath}'"); + + var template = DeserializeTileMapObjectTemplateContent(filePath, context); + + ContentLogger.Log($"Imported '{filePath}'"); + + return template; + } + catch (Exception e) + { + foreach (var data in e.Data) + context.Logger.LogImportantMessage(data.ToString()); + context.Logger.LogImportantMessage(e.StackTrace); + return null; + } + } + + private TiledMapObjectTemplateContent DeserializeTileMapObjectTemplateContent(string filePath, ContentImporterContext context) + { + using (var reader = new StreamReader(filePath)) + { + var templateSerializer = new XmlSerializer(typeof(TiledMapObjectTemplateContent)); + var template = (TiledMapObjectTemplateContent)templateSerializer.Deserialize(reader); + + if (!String.IsNullOrWhiteSpace(template.Tileset?.Source)) + context.AddDependency(template.Tileset.Source); + + return template; + } + } + } +} diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs index 8bfca1f1..0892ef14 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs @@ -40,33 +40,37 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled foreach (var layer in map.Layers) { - var imageLayer = layer as TiledMapImageLayerContent; - - if (imageLayer != null) - { - ContentLogger.Log($"Processing image layer '{imageLayer.Name}'"); + if (layer is TiledMapImageLayerContent imageLayer) + { + ContentLogger.Log($"Processing image layer '{imageLayer.Name}'"); imageLayer.Image.ContentRef = context.BuildAsset(new ExternalReference(imageLayer.Image.Source), ""); - ContentLogger.Log($"Processed image layer '{imageLayer.Name}'"); - } + ContentLogger.Log($"Processed image layer '{imageLayer.Name}'"); + } - var tileLayer = layer as TiledMapTileLayerContent; + if (layer is TiledMapTileLayerContent tileLayer) + { + var data = tileLayer.Data; + var encodingType = data.Encoding ?? "xml"; + var compressionType = data.Compression ?? "xml"; - if (tileLayer != null) - { - var data = tileLayer.Data; - var encodingType = data.Encoding ?? "xml"; - var compressionType = data.Compression ?? "xml"; + ContentLogger.Log( + $"Processing tile layer '{tileLayer.Name}': Encoding: '{encodingType}', Compression: '{compressionType}'"); - ContentLogger.Log( - $"Processing tile layer '{tileLayer.Name}': Encoding: '{encodingType}', Compression: '{compressionType}'"); + var tileData = DecodeTileLayerData(encodingType, tileLayer); + var tiles = CreateTiles(map.RenderOrder, map.Width, map.Height, tileData); + tileLayer.Tiles = tiles; - var tileData = DecodeTileLayerData(encodingType, tileLayer); - var tiles = CreateTiles(map.RenderOrder, map.Width, map.Height, tileData); - tileLayer.Tiles = tiles; + ContentLogger.Log($"Processed tile layer '{tileLayer}': {tiles.Length} tiles"); + } - ContentLogger.Log($"Processed tile layer '{tileLayer}': {tiles.Length} tiles"); - } - } + if (layer is TiledMapObjectLayerContent objectLayer) + { + ContentLogger.Log($"Processing object layer '{objectLayer.Name}'"); + foreach (var obj in objectLayer.Objects) + TiledMapObjectContent.Process(obj, context); + ContentLogger.Log($"Processed object layer '{objectLayer.Name}'"); + } + } Environment.CurrentDirectory = previousWorkingDirectory; return map; diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs index 2bcf905c..ccd693b2 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs @@ -42,6 +42,11 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled context.AddDependency(tileset.Image.Source); + foreach (var tile in tileset.Tiles) + foreach (var obj in tile.Objects) + if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) + context.AddDependency(obj.TemplateSource); + return tileset; } } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs index d71aa528..cb2cdf65 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs @@ -17,6 +17,11 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled ContentLogger.Log($"Processing tileset '{tileset.Name}'"); tileset.Image.Content = context.BuildAndLoadAsset(new ExternalReference(tileset.Image.Source), ""); + + foreach (var tile in tileset.Tiles) + foreach (var obj in tile.Objects) + TiledMapObjectContent.Process(obj, context); + ContentLogger.Log($"Processed tileset '{tileset.Name}'"); return tileset; diff --git a/Source/Tests/MonoGame.Extended.Content.Pipeline.Tests.Tiled/TestData/template.tx b/Source/Tests/MonoGame.Extended.Content.Pipeline.Tests.Tiled/TestData/template.tx new file mode 100644 index 00000000..1f00d197 --- /dev/null +++ b/Source/Tests/MonoGame.Extended.Content.Pipeline.Tests.Tiled/TestData/template.tx @@ -0,0 +1,4 @@ + + From 1cf24d01ae0201a430dfba1056d603211269f961 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Fri, 8 Jun 2018 14:53:57 -0500 Subject: [PATCH 07/14] Added Rough Group Layer Support Added the ability to load files with groups. Rendering system still doesn't understand layer groups yet, so this allows groups to be initially loaded, but the sub layers of the group are extracted to the layer root, things like offsets for the group are applied directly to the sub layers, and the groups themselves are removed. --- .../Tiled/TiledMapContent.cs | 1 + .../Tiled/TiledMapGroupLayerContent.cs | 21 +++ .../Tiled/TiledMapImporter.cs | 64 +++++---- .../Tiled/TiledMapProcessor.cs | 125 ++++++++++++------ .../TiledMapLayerType.cs | 3 +- 5 files changed, 142 insertions(+), 72 deletions(-) create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapGroupLayerContent.cs diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs index 9f287c8e..0976feb0 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs @@ -42,6 +42,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled [XmlElement(ElementName = "layer", Type = typeof(TiledMapTileLayerContent))] [XmlElement(ElementName = "imagelayer", Type = typeof(TiledMapImageLayerContent))] [XmlElement(ElementName = "objectgroup", Type = typeof(TiledMapObjectLayerContent))] + [XmlElement(ElementName = "group", Type = typeof(TiledMapGroupLayerContent))] public List Layers { get; set; } [XmlArray("properties")] diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapGroupLayerContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapGroupLayerContent.cs new file mode 100644 index 00000000..2db41fe3 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapGroupLayerContent.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml.Serialization; +using MonoGame.Extended.Tiled; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + public class TiledMapGroupLayerContent : TiledMapLayerContent + { + [XmlElement(ElementName = "layer", Type = typeof(TiledMapTileLayerContent))] + [XmlElement(ElementName = "imagelayer", Type = typeof(TiledMapImageLayerContent))] + [XmlElement(ElementName = "objectgroup", Type = typeof(TiledMapObjectLayerContent))] + [XmlElement(ElementName = "group", Type = typeof(TiledMapGroupLayerContent))] + public List Layers { get; set; } + + protected TiledMapGroupLayerContent() : base(TiledMapLayerType.GroupLayer) + { + } + } +} diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs index 686eef95..8ee81d6a 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Xml.Serialization; @@ -39,41 +40,48 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled 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); + { + var mapSerializer = new XmlSerializer(typeof(TiledMapContent)); + var map = (TiledMapContent)mapSerializer.Deserialize(reader); - map.FilePath = mapFilePath; + map.FilePath = mapFilePath; - var tilesetSerializer = new XmlSerializer(typeof(TiledMapTilesetContent)); + var tilesetSerializer = new XmlSerializer(typeof(TiledMapTilesetContent)); - for (var i = 0; i < map.Tilesets.Count; i++) - { - var tileset = map.Tilesets[i]; - - if (!string.IsNullOrWhiteSpace(tileset.Source)) - { - var tilesetFilePath = GetTilesetFilePath(mapFilePath, tileset); - map.Tilesets[i] = ImportTileset(tilesetFilePath, tilesetSerializer, tileset, context); - } - } - - for (var i = 0; i < map.Layers.Count; i++) + for (var i = 0; i < map.Tilesets.Count; i++) { - if (map.Layers[i] is TiledMapImageLayerContent imageLayer) - context.AddDependency(imageLayer.Image.Source); - if (map.Layers[i] is TiledMapObjectLayerContent objectLayer) - foreach (var obj in objectLayer.Objects) - if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) - context.AddDependency(obj.TemplateSource); + var tileset = map.Tilesets[i]; + + if (!string.IsNullOrWhiteSpace(tileset.Source)) + { + var tilesetFilePath = GetTilesetFilePath(mapFilePath, tileset); + map.Tilesets[i] = ImportTileset(tilesetFilePath, tilesetSerializer, tileset, context); + } } - map.Name = mapFilePath; - return map; - } - } + ImportLayers(context, map.Layers); - private static string GetTilesetFilePath(string mapFilePath, TiledMapTilesetContent tileset) + map.Name = mapFilePath; + return map; + } + } + + private static void ImportLayers(ContentImporterContext context, List layers) + { + for (var i = 0; i < layers.Count; i++) + { + if (layers[i] is TiledMapImageLayerContent imageLayer) + context.AddDependency(imageLayer.Image.Source); + if (layers[i] is TiledMapObjectLayerContent objectLayer) + foreach (var obj in objectLayer.Objects) + if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) + context.AddDependency(obj.TemplateSource); + if (layers[i] is TiledMapGroupLayerContent groupLayer) + ImportLayers(context, groupLayer.Layers); + } + } + + private static string GetTilesetFilePath(string mapFilePath, TiledMapTilesetContent tileset) { var directoryName = Path.GetDirectoryName(mapFilePath); Debug.Assert(directoryName != null, "directoryName != null"); diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs index 0892ef14..c7a2ae66 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs @@ -17,16 +17,16 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled public override TiledMapContent Process(TiledMapContent map, ContentProcessorContext context) { try - { - ContentLogger.Logger = context.Logger; + { + ContentLogger.Logger = context.Logger; - var previousWorkingDirectory = Environment.CurrentDirectory; - var newWorkingDirectory = Path.GetDirectoryName(map.FilePath); + var previousWorkingDirectory = Environment.CurrentDirectory; + var newWorkingDirectory = Path.GetDirectoryName(map.FilePath); - if (string.IsNullOrEmpty(newWorkingDirectory)) - throw new NullReferenceException(); + if (string.IsNullOrEmpty(newWorkingDirectory)) + throw new NullReferenceException(); - Environment.CurrentDirectory = newWorkingDirectory; + Environment.CurrentDirectory = newWorkingDirectory; foreach (var tileset in map.Tilesets) { @@ -38,44 +38,17 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled } } - foreach (var layer in map.Layers) - { - if (layer is TiledMapImageLayerContent imageLayer) - { - ContentLogger.Log($"Processing image layer '{imageLayer.Name}'"); - imageLayer.Image.ContentRef = context.BuildAsset(new ExternalReference(imageLayer.Image.Source), ""); - ContentLogger.Log($"Processed image layer '{imageLayer.Name}'"); - } + ProcessLayers(map, context, map.Layers); - if (layer is TiledMapTileLayerContent tileLayer) - { - var data = tileLayer.Data; - var encodingType = data.Encoding ?? "xml"; - var compressionType = data.Compression ?? "xml"; + map.Layers = FlattenGroups(map.Layers, out var hadGroups); - ContentLogger.Log( - $"Processing tile layer '{tileLayer.Name}': Encoding: '{encodingType}', Compression: '{compressionType}'"); + if (hadGroups) ContentLogger.Log($"FYI, TiledMap '{map.Name}' contains group layers. These are currently not supported " + + $"as is, and they will be discarded with the sub layers moved to the root."); - var tileData = DecodeTileLayerData(encodingType, tileLayer); - var tiles = CreateTiles(map.RenderOrder, map.Width, map.Height, tileData); - tileLayer.Tiles = tiles; - - ContentLogger.Log($"Processed tile layer '{tileLayer}': {tiles.Length} tiles"); - } - - if (layer is TiledMapObjectLayerContent objectLayer) - { - ContentLogger.Log($"Processing object layer '{objectLayer.Name}'"); - foreach (var obj in objectLayer.Objects) - TiledMapObjectContent.Process(obj, context); - ContentLogger.Log($"Processed object layer '{objectLayer.Name}'"); - } - } - - Environment.CurrentDirectory = previousWorkingDirectory; - return map; - } - catch (Exception ex) + Environment.CurrentDirectory = previousWorkingDirectory; + return map; + } + catch (Exception ex) { context.Logger.LogImportantMessage(ex.Message); context.Logger.LogImportantMessage("Hello World!"); @@ -83,7 +56,73 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled } } - private static List DecodeTileLayerData(string encodingType, TiledMapTileLayerContent tileLayer) + private static void ProcessLayers(TiledMapContent map, ContentProcessorContext context, List layers) + { + foreach (var layer in layers) + { + if (layer is TiledMapImageLayerContent imageLayer) + { + ContentLogger.Log($"Processing image layer '{imageLayer.Name}'"); + imageLayer.Image.ContentRef = context.BuildAsset(new ExternalReference(imageLayer.Image.Source), ""); + ContentLogger.Log($"Processed image layer '{imageLayer.Name}'"); + } + + if (layer is TiledMapTileLayerContent tileLayer) + { + var data = tileLayer.Data; + var encodingType = data.Encoding ?? "xml"; + var compressionType = data.Compression ?? "xml"; + + ContentLogger.Log( + $"Processing tile layer '{tileLayer.Name}': Encoding: '{encodingType}', Compression: '{compressionType}'"); + + var tileData = DecodeTileLayerData(encodingType, tileLayer); + var tiles = CreateTiles(map.RenderOrder, map.Width, map.Height, tileData); + tileLayer.Tiles = tiles; + + ContentLogger.Log($"Processed tile layer '{tileLayer}': {tiles.Length} tiles"); + } + + if (layer is TiledMapObjectLayerContent objectLayer) + { + ContentLogger.Log($"Processing object layer '{objectLayer.Name}'"); + foreach (var obj in objectLayer.Objects) + TiledMapObjectContent.Process(obj, context); + ContentLogger.Log($"Processed object layer '{objectLayer.Name}'"); + } + + if (layer is TiledMapGroupLayerContent groupLayer) + ProcessLayers(map, context, groupLayer.Layers); + } + } + + private static List FlattenGroups(List layers, out bool hadGroups) + { + hadGroups = false; + var result = new List(); + + foreach (var layer in layers) + { + if (layer is TiledMapGroupLayerContent groupLayer) + { + hadGroups = true; + foreach (var sublayer in groupLayer.Layers) + { + sublayer.OffsetX += groupLayer.OffsetX; + sublayer.OffsetY += groupLayer.OffsetY; + sublayer.Opacity *= groupLayer.Opacity; + sublayer.Visible &= groupLayer.Visible; + } + result.AddRange(FlattenGroups(groupLayer.Layers, out var subHadGroups)); + } + else + result.Add(layer); + } + + return result; + } + + private static List DecodeTileLayerData(string encodingType, TiledMapTileLayerContent tileLayer) { List tiles; diff --git a/Source/MonoGame.Extended.Tiled/TiledMapLayerType.cs b/Source/MonoGame.Extended.Tiled/TiledMapLayerType.cs index b8dafeb3..8af5a2e4 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapLayerType.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapLayerType.cs @@ -4,6 +4,7 @@ { ImageLayer = 0, TileLayer = 1, - ObjectLayer = 2 + ObjectLayer = 2, + GroupLayer = 3 } } \ No newline at end of file From 044712f6aa0952095ae466a87246997d09f28817 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Sat, 9 Jun 2018 13:45:02 -0500 Subject: [PATCH 08/14] Added remaining .TMX format features Added the remaining features of the .TMX Tiled Map format. Removed the parts of the format which aren't needed for rendering, like `TiledMapTerrainContent`. Terrains and the newer WangSets are only used in constructing a map, not for rendering. Added exception throws for non-implemented parts of the format. --- .../Tiled/TiledMapContent.cs | 9 +++++++ .../Tiled/TiledMapOrientationContent.cs | 3 ++- .../Tiled/TiledMapProcessor.cs | 10 +++++-- .../Tiled/TiledMapStaggerAxisContent.cs | 10 +++++++ .../Tiled/TiledMapStaggerIndexContent.cs | 10 +++++++ .../Tiled/TiledMapTerrainContent.cs | 27 ------------------- .../TiledMapTileLayerDataChunkContent.cs | 26 ++++++++++++++++++ .../Tiled/TiledMapTileLayerDataContent.cs | 3 +++ .../Tiled/TiledMapTilesetContent.cs | 8 +++--- .../Tiled/TiledMapTilesetGridContent.cs | 16 +++++++++++ .../Tiled/TiledMapTilesetTileContent.cs | 7 ----- .../Renderers/TiledMapModelBuilder.cs | 4 +-- 12 files changed, 88 insertions(+), 45 deletions(-) create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerAxisContent.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerIndexContent.cs delete mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTerrainContent.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataChunkContent.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetGridContent.cs diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs index 0976feb0..e3f844c7 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapContent.cs @@ -36,6 +36,15 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled [XmlAttribute(AttributeName = "tileheight")] public int TileHeight { get; set; } + [XmlAttribute(AttributeName = "hexsidelength")] + public int HexSideLength { get; set; } + + [XmlAttribute(AttributeName = "staggeraxis")] + public TiledMapStaggerAxisContent StaggerAxis { get; set; } + + [XmlAttribute(AttributeName = "staggerindex")] + public TiledMapStaggerIndexContent StaggerIndex { get; set; } + [XmlElement(ElementName = "tileset")] public List Tilesets { get; set; } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapOrientationContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapOrientationContent.cs index 87dcc2b2..624563f6 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapOrientationContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapOrientationContent.cs @@ -6,6 +6,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled { [XmlEnum(Name = "orthogonal")] Orthogonal, [XmlEnum(Name = "isometric")] Isometric, - [XmlEnum(Name = "staggered")] Staggered + [XmlEnum(Name = "staggered")] Staggered, + [XmlEnum(Name = "hexagonal")] Hexagonal } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs index c7a2ae66..b8d52a10 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs @@ -28,6 +28,9 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled Environment.CurrentDirectory = newWorkingDirectory; + if (map.Orientation == TiledMapOrientationContent.Hexagonal || map.Orientation == TiledMapOrientationContent.Staggered) + throw new NotSupportedException($"{map.Orientation} Tiled Maps are currently not implemented!"); + foreach (var tileset in map.Tilesets) { if (String.IsNullOrWhiteSpace(tileset.Source)) @@ -42,8 +45,8 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled map.Layers = FlattenGroups(map.Layers, out var hadGroups); - if (hadGroups) ContentLogger.Log($"FYI, TiledMap '{map.Name}' contains group layers. These are currently not supported " + - $"as is, and they will be discarded with the sub layers moved to the root."); + if (hadGroups) ContentLogger.Log($"FYI, TiledMap '{map.FilePath}' contains group layers. These are currently not supported \n" + + $"as is, and they will be discarded with the sub layers moved to root."); Environment.CurrentDirectory = previousWorkingDirectory; return map; @@ -69,6 +72,9 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled if (layer is TiledMapTileLayerContent tileLayer) { + if (tileLayer.Data.Chunks.Count > 0) + throw new NotSupportedException($"{map.FilePath} contains data chunks. These are currently not supported."); + var data = tileLayer.Data; var encodingType = data.Encoding ?? "xml"; var compressionType = data.Compression ?? "xml"; diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerAxisContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerAxisContent.cs new file mode 100644 index 00000000..52d573cc --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerAxisContent.cs @@ -0,0 +1,10 @@ +using System.Xml.Serialization; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + public enum TiledMapStaggerAxisContent : byte + { + [XmlEnum("x")]X, + [XmlEnum("y")]Y + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerIndexContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerIndexContent.cs new file mode 100644 index 00000000..bf92e6d9 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapStaggerIndexContent.cs @@ -0,0 +1,10 @@ +using System.Xml.Serialization; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + public enum TiledMapStaggerIndexContent : byte + { + [XmlEnum("even")]Even, + [XmlEnum("odd")]Odd + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTerrainContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTerrainContent.cs deleted file mode 100644 index d6179857..00000000 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTerrainContent.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using System.Xml.Serialization; - -namespace MonoGame.Extended.Content.Pipeline.Tiled -{ - public class TiledMapTerrainContent - { - [XmlAttribute(AttributeName = "name")] - public string Name { get; set; } - - [XmlAttribute(AttributeName = "tile")] - public string TileId { get; set; } - - [XmlArray("properties"), XmlArrayItem("property")] - public List Properties { get; set; } - - public TiledMapTerrainContent() - { - Properties = new List(); - } - - public override string ToString() - { - return Name; - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataChunkContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataChunkContent.cs new file mode 100644 index 00000000..e296c0b8 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataChunkContent.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + public class TiledMapTileLayerDataChunkContent + { + [XmlAttribute(AttributeName = "x")] + public int X { get; set; } + + [XmlAttribute(AttributeName = "y")] + public int Y { get; set; } + + [XmlAttribute(AttributeName = "width")] + public int Width { get; set; } + + [XmlAttribute(AttributeName = "height")] + public int Height { get; set; } + + [XmlElement(ElementName = "tile")] + public List Tiles { get; set; } + + [XmlText] + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataContent.cs index bfd5ce31..52ece3b7 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTileLayerDataContent.cs @@ -14,6 +14,9 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled [XmlElement(ElementName = "tile")] public List Tiles { get; set; } + [XmlElement(ElementName = "chunk")] + public List Chunks { get; set; } + [XmlText] public string Value { get; set; } diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs index 430ce74f..ff2a4cc2 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetContent.cs @@ -40,6 +40,9 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled [XmlElement(ElementName = "tileoffset")] public TiledMapTileOffsetContent TileOffset { get; set; } + [XmlElement(ElementName = "grid")] + public TiledMapTilesetGridContent Grid { get; set; } + [XmlElement(ElementName = "tile")] public List Tiles { get; set; } @@ -50,16 +53,11 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled [XmlElement(ElementName = "image")] public TiledMapImageContent Image { get; set; } - [XmlArray("terraintypes")] - [XmlArrayItem("terrain")] - public List TerrainTypes { get; set; } - public TiledMapTilesetContent() { TileOffset = new TiledMapTileOffsetContent(); Tiles = new List(); Properties = new List(); - TerrainTypes = new List(); } public bool ContainsGlobalIdentifier(int globalIdentifier) diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetGridContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetGridContent.cs new file mode 100644 index 00000000..b931a2a5 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetGridContent.cs @@ -0,0 +1,16 @@ +using System.Xml.Serialization; + +namespace MonoGame.Extended.Content.Pipeline.Tiled +{ + public class TiledMapTilesetGridContent + { + [XmlAttribute(AttributeName = "orientation")] + public TiledMapOrientationContent Orientation { get; set; } + + [XmlAttribute(AttributeName = "width")] + public int Width { get; set; } + + [XmlAttribute(AttributeName = "height")] + public int Height { get; set; } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetTileContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetTileContent.cs index c5bd619a..796bb9ba 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetTileContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetTileContent.cs @@ -7,7 +7,6 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled { public TiledMapTilesetTileContent() { - Probability = 1.0f; Properties = new List(); Type = string.Empty; } @@ -18,12 +17,6 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled [XmlAttribute(AttributeName = "type")] public string Type { get; set; } - [XmlElement(ElementName = "terrain")] - public TiledMapTerrainContent Terrain { get; set; } - - [XmlAttribute(AttributeName = "probability")] - public float Probability { get; set; } - [XmlElement(ElementName = "image")] public TiledMapImageContent Image { get; set; } diff --git a/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs b/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs index d4a85846..e43b3b95 100644 --- a/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs +++ b/Source/MonoGame.Extended.Tiled/Renderers/TiledMapModelBuilder.cs @@ -106,10 +106,8 @@ namespace MonoGame.Extended.Tiled.Renderers return TiledMapHelper.GetOrthogonalPosition(mapTile.X, mapTile.Y, map.TileWidth, map.TileHeight); case TiledMapOrientation.Isometric: return TiledMapHelper.GetIsometricPosition(mapTile.X, mapTile.Y, map.TileWidth, map.TileHeight); - case TiledMapOrientation.Staggered: - throw new NotImplementedException("Staggered maps are not yet implemented."); default: - throw new NotSupportedException($"Tiled Map {map.Orientation} is not supported."); + throw new NotSupportedException($"{map.Orientation} Tiled Maps are not yet implemented."); } } } From a0e3c57c300223df6a4491621cb6ea3d2ac33465 Mon Sep 17 00:00:00 2001 From: stefanrbk Date: Mon, 11 Jun 2018 18:33:02 -0500 Subject: [PATCH 09/14] Comments and remove file accessing Added comments into the importers and processors to show off what the new code does. Removed unneeded code involving locating external files as `Content` handles this for us automatically. --- .../Tiled/TiledMapImporter.cs | 27 ++++++++----------- .../Tiled/TiledMapObjectContent.cs | 9 +++++++ .../Tiled/TiledMapObjectTemplateImporter.cs | 3 +-- .../Tiled/TiledMapProcessor.cs | 16 +++-------- .../Tiled/TiledMapTilesetImporter.cs | 1 + .../Tiled/TiledMapTilesetProcessor.cs | 1 + 6 files changed, 27 insertions(+), 30 deletions(-) diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs index 8ee81d6a..0b674b09 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapImporter.cs @@ -53,10 +53,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled var tileset = map.Tilesets[i]; if (!string.IsNullOrWhiteSpace(tileset.Source)) - { - var tilesetFilePath = GetTilesetFilePath(mapFilePath, tileset); - map.Tilesets[i] = ImportTileset(tilesetFilePath, tilesetSerializer, tileset, context); - } + map.Tilesets[i] = ImportTileset(tileset.Source, tilesetSerializer, tileset, context); } ImportLayers(context, map.Layers); @@ -71,41 +68,39 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled for (var i = 0; i < layers.Count; i++) { if (layers[i] is TiledMapImageLayerContent imageLayer) + // 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)) + // 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); } } - private static string GetTilesetFilePath(string mapFilePath, TiledMapTilesetContent tileset) - { - var directoryName = Path.GetDirectoryName(mapFilePath); - Debug.Assert(directoryName != null, "directoryName != null"); - - var tilesetLocation = tileset.Source.Replace('/', Path.DirectorySeparatorChar); - var tilesetFilePath = Path.Combine(directoryName, tilesetLocation); - return tilesetFilePath; - } - private static TiledMapTilesetContent ImportTileset(string tilesetFilePath, XmlSerializer tilesetSerializer, TiledMapTilesetContent tileset, ContentImporterContext context) { TiledMapTilesetContent result; ContentLogger.Log($"Importing tileset '{tilesetFilePath}'"); - using (var file = new FileStream(tilesetFilePath, FileMode.Open)) + using (var reader = new StreamReader(tilesetFilePath)) { - var importedTileset = (TiledMapTilesetContent)tilesetSerializer.Deserialize(file); + var importedTileset = (TiledMapTilesetContent)tilesetSerializer.Deserialize(reader); importedTileset.FirstGlobalIdentifier = tileset.FirstGlobalIdentifier; + // We depend on the tileset. If the tileset changes, the map also needs to rebuild. context.AddDependency(importedTileset.Image.Source); foreach (var tile in importedTileset.Tiles) foreach (var obj in tile.Objects) if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) + // We depend on the template. context.AddDependency(obj.TemplateSource); result = importedTileset; diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs index 56fea253..3e518a8a 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectContent.cs @@ -6,6 +6,13 @@ using System.Xml.Serialization; namespace MonoGame.Extended.Content.Pipeline.Tiled { + // This content class is going to be a lot more complex than the others we use. + // Objects can reference a template file which has starting values for the + // object. The value in the object file overrides any value specified in the + // template. All values have to be able to store a null value so we know if the + // XML parser actually found a value for the property and not just a default + // value. Default values are used when the object and any templates don't + // specify a value. public class TiledMapObjectContent { private uint? _globalIdentifier; @@ -69,6 +76,8 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled { var template = context.BuildAndLoadAsset(new ExternalReference(obj.TemplateSource), ""); + // Nothing says a template can't reference another template. + // Yay recusion! Process(template.Object, context); if (!obj._globalIdentifier.HasValue && template.Object._globalIdentifier.HasValue) diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs index e68b6185..bb0abc9c 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapObjectTemplateImporter.cs @@ -28,8 +28,6 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled } catch (Exception e) { - foreach (var data in e.Data) - context.Logger.LogImportantMessage(data.ToString()); context.Logger.LogImportantMessage(e.StackTrace); return null; } @@ -43,6 +41,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled var template = (TiledMapObjectTemplateContent)templateSerializer.Deserialize(reader); if (!String.IsNullOrWhiteSpace(template.Tileset?.Source)) + // We depend on this tileset. context.AddDependency(template.Tileset.Source); return template; diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs index b8d52a10..62033d10 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapProcessor.cs @@ -20,25 +20,18 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled { ContentLogger.Logger = context.Logger; - var previousWorkingDirectory = Environment.CurrentDirectory; - var newWorkingDirectory = Path.GetDirectoryName(map.FilePath); - - if (string.IsNullOrEmpty(newWorkingDirectory)) - throw new NullReferenceException(); - - Environment.CurrentDirectory = newWorkingDirectory; - if (map.Orientation == TiledMapOrientationContent.Hexagonal || map.Orientation == TiledMapOrientationContent.Staggered) throw new NotSupportedException($"{map.Orientation} Tiled Maps are currently not implemented!"); foreach (var tileset in map.Tilesets) { if (String.IsNullOrWhiteSpace(tileset.Source)) + // Load the Texture2DContent for the tileset as it will be saved into the map content file. tileset.Image.Content = context.BuildAndLoadAsset(new ExternalReference(tileset.Image.Source), ""); else - { + // Link to the tileset for the content loader to load at runtime. tileset.Content = context.BuildAsset(new ExternalReference(tileset.Source), ""); - } + } ProcessLayers(map, context, map.Layers); @@ -47,8 +40,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled if (hadGroups) ContentLogger.Log($"FYI, TiledMap '{map.FilePath}' contains group layers. These are currently not supported \n" + $"as is, and they will be discarded with the sub layers moved to root."); - - Environment.CurrentDirectory = previousWorkingDirectory; + return map; } catch (Exception ex) diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs index ccd693b2..1f04e7ec 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetImporter.cs @@ -45,6 +45,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled foreach (var tile in tileset.Tiles) foreach (var obj in tile.Objects) if (!String.IsNullOrWhiteSpace(obj.TemplateSource)) + // We depend on the template. context.AddDependency(obj.TemplateSource); return tileset; diff --git a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs index cb2cdf65..841e313d 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapTilesetProcessor.cs @@ -16,6 +16,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled ContentLogger.Logger = context.Logger; ContentLogger.Log($"Processing tileset '{tileset.Name}'"); + // Build the Texture2D asset and load it as it will be saved as part of this tileset file. tileset.Image.Content = context.BuildAndLoadAsset(new ExternalReference(tileset.Image.Source), ""); foreach (var tile in tileset.Tiles) From 4c9a0136b1ba6702743bda8a2e6074122fd197d0 Mon Sep 17 00:00:00 2001 From: Jon Seaman Date: Mon, 18 Jun 2018 06:29:40 -0400 Subject: [PATCH 10/14] [WIP] Demo conversion to .net core (#514) * Demo.SpaceGame working * Delete unused files, update icon * Demo.StarWarrior building * Removed unused files * Demo.Features Collision * Platform Demo Building * Nuclex Gui Project * got the old platformer demo running but it's still missing stuff * Demo.Features added to solution * Demo.Features building Currently, most demos don't build and were excluded from the project. * Demo.Features.NetCore building * Demo.Features building and running * First demo usable * Close button * Tiles + Sprite Demo * More demos working * Fix Back() for new Gui * Remove old project files --- .../Demo.Features.NetCore.csproj | 28 +++ .../Demo.Features.WindowsDirectX.csproj | 99 -------- .../Demo.Features.WindowsOpenGL.csproj | 142 ------------ .../Properties/AssemblyInfo.cs | 36 --- .../Demos/Demo.Features.Windows/app.manifest | 42 ---- .../Demos/Demo.Features/Content/Content.mgcb | 2 +- .../Demos/Demo.Features/Demo.Features.csproj | 212 +++--------------- .../Demo.Features/Demos/CollisionDemo.cs | 28 +-- Source/Demos/Demo.Features/GameMain.cs | 27 ++- .../Demo.Features/Properties/AssemblyInfo.cs | 30 --- .../Demo.Features/Screens/SelectDemoScreen.cs | 141 ++++++------ Source/Demos/Demo.Features/packages.config | 5 - .../Demos/Demo.NuclexGui/Content/Content.mgcb | 2 +- .../Demo.NuclexGui/Demo.NuclexGui.csproj | 146 ++---------- .../MonoGame.Framework.dll.config | 9 - Source/Demos/Demo.NuclexGui/OpenTK.dll.config | 27 --- .../Demo.NuclexGui/Properties/AssemblyInfo.cs | 39 ---- Source/Demos/Demo.NuclexGui/app.config | 7 - Source/Demos/Demo.NuclexGui/app.manifest | 42 ---- Source/Demos/Demo.NuclexGui/packages.config | 4 - .../Demo.Platformer/Content/Content.mgcb | 2 +- .../Demo.Platformer/Demo.Platformer.csproj | 174 ++------------ .../Demo.Platformer/Entities/EntityFactory.cs | 5 + .../Properties/AssemblyInfo.cs | 39 ---- .../Services/TiledObjectToEntityService.cs | 2 +- .../Demos/Demo.SpaceGame/Content/Content.mgcb | 2 +- .../Demo.SpaceGame/Demo.SpaceGame.csproj | 169 ++------------ .../Demos/Demo.SpaceGame/Entities/Meteor.cs | 2 +- .../Demo.SpaceGame/Entities/Spaceship.cs | 27 ++- Source/Demos/Demo.SpaceGame/Game1.cs | 14 +- .../MonoGame.Framework.dll.config | 9 - Source/Demos/Demo.SpaceGame/OpenTK.dll.config | 27 --- .../Demo.SpaceGame/Properties/AssemblyInfo.cs | 39 ---- Source/Demos/Demo.SpaceGame/app.config | 7 - Source/Demos/Demo.SpaceGame/app.manifest | 42 ---- Source/Demos/Demo.SpaceGame/packages.config | 4 - .../Demo.StarWarrior/Content/Content.mgcb | 2 +- .../Demo.StarWarrior/Demo.StarWarrior.csproj | 173 ++------------ .../MonoGame.Framework.dll.config | 9 - .../Properties/AssemblyInfo.cs | 36 --- Source/Demos/Demo.StarWarrior/app.config | 7 - Source/Demos/Demo.StarWarrior/app.manifest | 42 ---- Source/Demos/Demo.StarWarrior/packages.config | 5 - .../MonoGame.Extended.Content.Pipeline.csproj | 6 + .../Newtonsoft.Json.dll | Bin 0 -> 656384 bytes .../MonoGame.Extended.NuclexGui.csproj | 6 + Source/MonoGame.Extended.sln | 66 ++++++ 47 files changed, 342 insertions(+), 1642 deletions(-) create mode 100644 Source/Demos/Demo.Features.Windows/Demo.Features.NetCore.csproj delete mode 100644 Source/Demos/Demo.Features.Windows/Demo.Features.WindowsDirectX.csproj delete mode 100644 Source/Demos/Demo.Features.Windows/Demo.Features.WindowsOpenGL.csproj delete mode 100644 Source/Demos/Demo.Features.Windows/Properties/AssemblyInfo.cs delete mode 100644 Source/Demos/Demo.Features.Windows/app.manifest delete mode 100644 Source/Demos/Demo.Features/Properties/AssemblyInfo.cs delete mode 100644 Source/Demos/Demo.Features/packages.config delete mode 100644 Source/Demos/Demo.NuclexGui/MonoGame.Framework.dll.config delete mode 100644 Source/Demos/Demo.NuclexGui/OpenTK.dll.config delete mode 100644 Source/Demos/Demo.NuclexGui/Properties/AssemblyInfo.cs delete mode 100644 Source/Demos/Demo.NuclexGui/app.config delete mode 100644 Source/Demos/Demo.NuclexGui/app.manifest delete mode 100644 Source/Demos/Demo.NuclexGui/packages.config delete mode 100644 Source/Demos/Demo.Platformer/Properties/AssemblyInfo.cs delete mode 100644 Source/Demos/Demo.SpaceGame/MonoGame.Framework.dll.config delete mode 100644 Source/Demos/Demo.SpaceGame/OpenTK.dll.config delete mode 100644 Source/Demos/Demo.SpaceGame/Properties/AssemblyInfo.cs delete mode 100644 Source/Demos/Demo.SpaceGame/app.config delete mode 100644 Source/Demos/Demo.SpaceGame/app.manifest delete mode 100644 Source/Demos/Demo.SpaceGame/packages.config delete mode 100644 Source/Demos/Demo.StarWarrior/MonoGame.Framework.dll.config delete mode 100644 Source/Demos/Demo.StarWarrior/Properties/AssemblyInfo.cs delete mode 100644 Source/Demos/Demo.StarWarrior/app.config delete mode 100644 Source/Demos/Demo.StarWarrior/app.manifest delete mode 100644 Source/Demos/Demo.StarWarrior/packages.config create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Newtonsoft.Json.dll diff --git a/Source/Demos/Demo.Features.Windows/Demo.Features.NetCore.csproj b/Source/Demos/Demo.Features.Windows/Demo.Features.NetCore.csproj new file mode 100644 index 00000000..feab699c --- /dev/null +++ b/Source/Demos/Demo.Features.Windows/Demo.Features.NetCore.csproj @@ -0,0 +1,28 @@ + + + WinExe + netcoreapp2.0 + Icon.ico + + + + + + + + + + + + + + true + + + + + + + + + diff --git a/Source/Demos/Demo.Features.Windows/Demo.Features.WindowsDirectX.csproj b/Source/Demos/Demo.Features.Windows/Demo.Features.WindowsDirectX.csproj deleted file mode 100644 index 5651630f..00000000 --- a/Source/Demos/Demo.Features.Windows/Demo.Features.WindowsDirectX.csproj +++ /dev/null @@ -1,99 +0,0 @@ - - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {BDAEDFAF-2EDA-4BCA-9675-3625456FAB78} - WinExe - Properties - Demo.Features.Windows - Demo.Features.Windows - 512 - DesktopGL - v4.5 - - - true - bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\ - DEBUG;TRACE;LINUX - full - AnyCPU - prompt - false - 4 - 6 - 1591 - - - bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\ - TRACE;LINUX - true - pdbonly - AnyCPU - prompt - false - 4 - - - Icon.ico - - - app.manifest - - - - - - - - False - $(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\Windows\MonoGame.Framework.dll - - - - - - - - - - - Raw\title-screen.json - PreserveNewest - - - Raw\adventure-gui-skin.json - PreserveNewest - - - Content\Content.mgcb - - - - - - {8e425575-378a-4f83-88c9-f8bebad227c9} - MonoGame.Extended.Gui - - - {41724c52-3d50-45bb-81eb-3c8a247eafd1} - MonoGame.Extended - - - {d8c6d896-5abf-4823-84da-f1191beec004} - Demo.Features - - - - - - \ No newline at end of file diff --git a/Source/Demos/Demo.Features.Windows/Demo.Features.WindowsOpenGL.csproj b/Source/Demos/Demo.Features.Windows/Demo.Features.WindowsOpenGL.csproj deleted file mode 100644 index 1e065169..00000000 --- a/Source/Demos/Demo.Features.Windows/Demo.Features.WindowsOpenGL.csproj +++ /dev/null @@ -1,142 +0,0 @@ - - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {57C47653-BC51-43BA-98F4-1D0EEE78782D} - WinExe - Properties - Demo.Features.Windows - Demo.Features.Windows - 512 - DesktopGL - v4.5 - - - true - bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\ - DEBUG;TRACE;LINUX - full - AnyCPU - prompt - false - 4 - 6 - 1591 - - - bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\ - TRACE;LINUX - true - pdbonly - AnyCPU - prompt - false - 4 - - - Icon.ico - - - app.manifest - - - - - - - - $(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll - - - - - - - - - - - x86\SDL2.dll - PreserveNewest - - - x64\SDL2.dll - PreserveNewest - - - x86\soft_oal.dll - PreserveNewest - - - x64\soft_oal.dll - PreserveNewest - - - x86\libSDL2-2.0.so.0 - PreserveNewest - - - x64\libSDL2-2.0.so.0 - PreserveNewest - - - x86\libopenal.so.1 - PreserveNewest - - - x64\libopenal.so.1 - PreserveNewest - - - libSDL2-2.0.0.dylib - PreserveNewest - - - libopenal.1.dylib - PreserveNewest - - - MonoGame.Framework.dll.config - PreserveNewest - - - Raw\title-screen.json - PreserveNewest - - - Raw\adventure-gui-skin.json - PreserveNewest - - - Content\Content.mgcb - - - - - - {8e425575-378a-4f83-88c9-f8bebad227c9} - MonoGame.Extended.Gui - - - {41724c52-3d50-45bb-81eb-3c8a247eafd1} - MonoGame.Extended - - - {d8c6d896-5abf-4823-84da-f1191beec004} - Demo.Features - - - - - - \ No newline at end of file diff --git a/Source/Demos/Demo.Features.Windows/Properties/AssemblyInfo.cs b/Source/Demos/Demo.Features.Windows/Properties/AssemblyInfo.cs deleted file mode 100644 index 264773dd..00000000 --- a/Source/Demos/Demo.Features.Windows/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Demo.Windows")] -[assembly: AssemblyProduct("Demo.Windows")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyCopyright("Copyright © 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("958dc6a4-0d1f-4d40-aae6-d71bef2aa584")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/Demos/Demo.Features.Windows/app.manifest b/Source/Demos/Demo.Features.Windows/app.manifest deleted file mode 100644 index 5606c0aa..00000000 --- a/Source/Demos/Demo.Features.Windows/app.manifest +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true/pm - - - - diff --git a/Source/Demos/Demo.Features/Content/Content.mgcb b/Source/Demos/Demo.Features/Content/Content.mgcb index efb9e9f9..3fa77c22 100644 --- a/Source/Demos/Demo.Features/Content/Content.mgcb +++ b/Source/Demos/Demo.Features/Content/Content.mgcb @@ -10,7 +10,7 @@ #-------------------------------- References --------------------------------# -/reference:..\..\..\MonoGame.Extended.Content.Pipeline\bin\MonoGame.Extended.Content.Pipeline.dll +/reference:../../../MonoGame.Extended.Content.Pipeline/bin/netstandard2.0/MonoGame.Extended.Content.Pipeline.dll #---------------------------------- Content ---------------------------------# diff --git a/Source/Demos/Demo.Features/Demo.Features.csproj b/Source/Demos/Demo.Features/Demo.Features.csproj index 5b111200..e7948d22 100644 --- a/Source/Demos/Demo.Features/Demo.Features.csproj +++ b/Source/Demos/Demo.Features/Demo.Features.csproj @@ -1,188 +1,50 @@ - - - + - 10.0 - Debug - AnyCPU - {D8C6D896-5ABF-4823-84DA-F1191BEEC004} Library - Demo.Features - Demo.Features - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile111 - v4.5 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - 6 - 1591 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + netcoreapp2.0 + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - Designer - - - Designer - - - - - - - - + + + + - - {587ce536-216f-41a1-b223-ae502c125b09} - MonoGame.Extended.Animations - - - {02562c6f-5bfb-467e-8a95-68b6ce2d635a} - MonoGame.Extended.Collisions - - - {9b3ab8a1-78aa-471a-afd0-b10b932115bc} - MonoGame.Extended.Graphics - - - {8e425575-378a-4f83-88c9-f8bebad227c9} - MonoGame.Extended.Gui - - - {49c87598-994c-49b5-bbb3-7ffc342635d3} - MonoGame.Extended.Input - - - {6C8B9E29-D09B-4901-80FD-45AAA35882C6} - MonoGame.Extended.Particles - - - {fe61c3d7-d96d-4aa4-9ef1-17e457bb2c7c} - MonoGame.Extended.SceneGraphs - - - {07b2ade2-73e3-41c4-aea1-d5566a5ab902} - MonoGame.Extended.Tiled - - - {1cf61f4f-a2ee-49bf-95d0-379e870de90e} - MonoGame.Extended.Tweening - - - {41724c52-3d50-45bb-81eb-3c8a247eafd1} - MonoGame.Extended + + + true + + + + + + + + + + - - - - - - - - - - - - - - - - + - - - - - - - - ..\..\packages\MonoGame.Framework.Portable.3.6.0.1625\lib\portable-net45+win8+wpa81\MonoGame.Framework.dll - - - ..\..\packages\Newtonsoft.Json.9.0.1\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll - - - - \ No newline at end of file + diff --git a/Source/Demos/Demo.Features/Demos/CollisionDemo.cs b/Source/Demos/Demo.Features/Demos/CollisionDemo.cs index 333374e1..45ce7280 100644 --- a/Source/Demos/Demo.Features/Demos/CollisionDemo.cs +++ b/Source/Demos/Demo.Features/Demos/CollisionDemo.cs @@ -38,7 +38,7 @@ namespace Demo.Features.Demos var demoBall1 = new DemoBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(200, 240), - BoundingBox = new RectangleF(200, 240, 20, 20), + Bounds = new RectangleF(200, 240, 20, 20), Velocity = new Vector2(0, -120) }; _actors.Add(demoBall1); @@ -46,17 +46,17 @@ namespace Demo.Features.Demos var demoBall2 = new DemoBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(600, 240), - BoundingBox = new RectangleF(600, 240, 20, 20), + Bounds = new RectangleF(600, 240, 20, 20), Velocity = new Vector2(0, 120) }; _actors.Add(demoBall2); var wall1 = new DemoWall(new Sprite(_blankTexture)); - wall1.BoundingBox = new RectangleF(0, 0, 800, 20); + wall1.Bounds = new RectangleF(0, 0, 800, 20); _actors.Add(wall1); var wall2 = new DemoWall(new Sprite(_blankTexture)); - wall2.BoundingBox = new RectangleF(0, 460, 800, 20); + wall2.Bounds = new RectangleF(0, 460, 800, 20); _actors.Add(wall2); foreach (var actor in _actors) @@ -87,7 +87,7 @@ namespace Demo.Features.Demos _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp); foreach (var actor in _actors) { - _spriteBatch.Draw(_blankTexture, actor.BoundingBox.ToRectangle(), Color.WhiteSmoke); + //_spriteBatch.Draw(_blankTexture, actor.BoundingBox.ToRectangle(), Color.WhiteSmoke); actor.Draw(_spriteBatch); } _spriteBatch.End(); @@ -98,30 +98,30 @@ namespace Demo.Features.Demos #region Collision Demo Implementation - class DemoActor : IActorTarget, IUpdate + class DemoActor : ICollisionActor, IUpdate { private readonly Sprite _sprite; public DemoActor(Sprite sprite) { _sprite = sprite; - BoundingBox = sprite.BoundingRectangle; + Bounds = sprite.GetBoundingRectangle(new Transform2()); } public Vector2 Position { get; set; } - public RectangleF BoundingBox { get; set; } + public IShapeF Bounds { get; set; } + public Vector2 Velocity { get; set; } - public virtual void OnCollision(CollisionInfo collisionInfo) + public virtual void OnCollision(CollisionEventArgs collisionInfo) { } public void Draw(SpriteBatch spriteBatch) { - _sprite.Position = Position; - _sprite.Draw(spriteBatch); + _sprite.Draw(spriteBatch, Position, 0, Vector2.One); } public virtual void Update(GameTime gameTime) @@ -149,15 +149,15 @@ namespace Demo.Features.Demos public override void Update(GameTime gameTime) { base.Update(gameTime); - BoundingBox = new RectangleF(Position.X, Position.Y, BoundingBox.Width, BoundingBox.Height); + Bounds.Position = Position; } - public override void OnCollision(CollisionInfo collisionInfo) + public override void OnCollision(CollisionEventArgs collisionInfo) { Velocity *= -1; Position -= collisionInfo.PenetrationVector; - BoundingBox = new RectangleF(Position.X, Position.Y, BoundingBox.Width, BoundingBox.Height); + Bounds.Position = Position; base.OnCollision(collisionInfo); } } diff --git a/Source/Demos/Demo.Features/GameMain.cs b/Source/Demos/Demo.Features/GameMain.cs index e5f6d29c..66f42f6a 100644 --- a/Source/Demos/Demo.Features/GameMain.cs +++ b/Source/Demos/Demo.Features/GameMain.cs @@ -5,6 +5,7 @@ using Demo.Features.Screens; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using MonoGame.Extended; +using MonoGame.Extended.BitmapFonts; using MonoGame.Extended.Gui; using MonoGame.Extended.ViewportAdapters; @@ -41,16 +42,16 @@ namespace Demo.Features _demos = new DemoBase[] { - new GuiLayoutDemo(this), - new GuiDemo(this), + //new GuiLayoutDemo(this), + //new GuiDemo(this), //new ScreensDemo(this), new ViewportAdaptersDemo(this), - new CollisionDemo(this), + new CollisionDemo(this), new TiledMapsDemo(this), new AnimationsDemo(this), new SpritesDemo(this), new BatchingDemo(this), - new TweeningDemo(this), + //new TweeningDemo(this), new InputListenersDemo(this), new SceneGraphsDemo(this), new ParticlesDemo(this), @@ -85,15 +86,18 @@ namespace Demo.Features { ViewportAdapter = new BoxingViewportAdapter(Window, GraphicsDevice, 800, 480); - var skin = GuiSkin.FromFile(Content, @"Raw/adventure-gui-skin.json"); + //var skin = GuiSkin.FromFile(Content, @"Raw/adventure-gui-skin.json"); var guiRenderer = new GuiSpriteBatchRenderer(GraphicsDevice, ViewportAdapter.GetScaleMatrix); + var font = Content.Load("small-font"); + BitmapFont.UseKernings = false; + Skin.CreateDefault(font); + _selectDemoScreen = new SelectDemoScreen(_demos, LoadDemo, Exit); + _guiSystem = new GuiSystem(ViewportAdapter, guiRenderer) { - Screens = { new SelectDemoScreen(skin, _demos, LoadDemo, Exit) } + ActiveScreen = _selectDemoScreen, }; - - //LoadDemo(_demoIndex); } private void LoadDemo(string name) @@ -106,6 +110,7 @@ namespace Demo.Features } private KeyboardState _previousKeyboardState; + private SelectDemoScreen _selectDemoScreen; protected override void Update(GameTime gameTime) { @@ -124,11 +129,13 @@ namespace Demo.Features public void Back() { - if (_guiSystem.Screens[0].IsVisible) + if (_selectDemoScreen.IsVisible) Exit(); IsMouseVisible = false; - _guiSystem.Screens[0].Show(); + _currentDemo = null; + _selectDemoScreen.IsVisible = true; + _guiSystem.ActiveScreen = _selectDemoScreen; } protected override void Draw(GameTime gameTime) diff --git a/Source/Demos/Demo.Features/Properties/AssemblyInfo.cs b/Source/Demos/Demo.Features/Properties/AssemblyInfo.cs deleted file mode 100644 index 5d2e7125..00000000 --- a/Source/Demos/Demo.Features/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Resources; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Demo")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Demo")] -[assembly: AssemblyCopyright("Copyright © 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/Demos/Demo.Features/Screens/SelectDemoScreen.cs b/Source/Demos/Demo.Features/Screens/SelectDemoScreen.cs index d620b52b..03efa18b 100644 --- a/Source/Demos/Demo.Features/Screens/SelectDemoScreen.cs +++ b/Source/Demos/Demo.Features/Screens/SelectDemoScreen.cs @@ -4,6 +4,7 @@ using System.Linq; using Demo.Features.Demos; using Microsoft.Xna.Framework; using MonoGame.Extended; +using MonoGame.Extended.BitmapFonts; using MonoGame.Extended.Gui; using MonoGame.Extended.Gui.Controls; using MonoGame.Extended.TextureAtlases; @@ -20,36 +21,28 @@ namespace Demo.Features.Screens _demos = demos; _loadDemo = loadDemo; - var dialog = Skin.Create("dialog"); - var grid = new UniformGrid { Columns = 3 }; + var grid = new UniformGrid(); foreach (var demo in _demos.Values.OrderBy(i => i.Name)) { - var button = Skin.Create