diff --git a/Source/MonoGame.Extended.Tiled/ContentReaderExtensions.cs b/Source/MonoGame.Extended.Tiled/ContentReaderExtensions.cs deleted file mode 100644 index 6a717064..00000000 --- a/Source/MonoGame.Extended.Tiled/ContentReaderExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.Xna.Framework.Content; - -namespace MonoGame.Extended.Tiled -{ - public static class ContentReaderExtensions - { - public static void ReadTiledMapProperties(this 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; - } - } - } -} diff --git a/Source/MonoGame.Extended.Tiled/Graphics/TiledMapRenderer.cs b/Source/MonoGame.Extended.Tiled/Graphics/TiledMapRenderer.cs index 53a4c44e..9bc082a6 100644 --- a/Source/MonoGame.Extended.Tiled/Graphics/TiledMapRenderer.cs +++ b/Source/MonoGame.Extended.Tiled/Graphics/TiledMapRenderer.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended.Tiled.Graphics.Effects; @@ -7,82 +9,84 @@ namespace MonoGame.Extended.Tiled.Graphics { public class TiledMapRenderer : IDisposable { + private readonly TiledMap _map; private readonly TiledMapEffect _defaultEffect; private Matrix _worldMatrix = Matrix.Identity; + private readonly GraphicsDevice _graphicsDevice; - /// - /// Gets the associated with this . - /// - /// - /// The associated with this . - /// - public GraphicsDevice GraphicsDevice { get; } + private readonly Dictionary> _animatedTilesByTileset; - public TiledMapRenderer(GraphicsDevice graphicsDevice) + public TiledMapRenderer(GraphicsDevice graphicsDevice, TiledMap map) { - if (graphicsDevice == null) - throw new ArgumentNullException(nameof(graphicsDevice)); - - GraphicsDevice = graphicsDevice; + if (graphicsDevice == null) throw new ArgumentNullException(nameof(graphicsDevice)); + if (map == null) throw new ArgumentNullException(nameof(map)); + _map = map; + _graphicsDevice = graphicsDevice; _defaultEffect = new TiledMapEffect(graphicsDevice); + + _animatedTilesByTileset = _map.Tilesets.ToDictionary(i => i, i => i.Tiles.OfType().ToList()); } - public void Update(TiledMap map, GameTime gameTime) + public void Dispose() { - // ReSharper disable once ForCanBeConvertedToForeach - for (var tilesetIndex = 0; tilesetIndex < map.Tilesets.Count; tilesetIndex++) + _defaultEffect.Dispose(); + } + + public void Update(GameTime gameTime) + { + for (var tilesetIndex = 0; tilesetIndex < _map.Tilesets.Count; tilesetIndex++) { - var tileset = map.Tilesets[tilesetIndex]; - // ReSharper disable once ForCanBeConvertedToForeach - for (var animatedTileIndex = 0; animatedTileIndex < tileset.AnimatedTiles.Count; animatedTileIndex++) + var tileset = _map.Tilesets[tilesetIndex]; + var animatedTiles = _animatedTilesByTileset[tileset]; + + for (var animatedTileIndex = 0; animatedTileIndex < animatedTiles.Count; animatedTileIndex++) { - var animatedTilesetTile = tileset.AnimatedTiles[animatedTileIndex]; + var animatedTilesetTile = animatedTiles[animatedTileIndex]; animatedTilesetTile.Update(gameTime); } } - // ReSharper disable once ForCanBeConvertedToForeach - for (var index = 0; index < map.TileLayers.Count; index++) + for (var index = 0; index < _map.TileLayers.Count; index++) { - var layer = map.TileLayers[index]; + var layer = _map.TileLayers[index]; UpdateAnimatedModels(layer.AnimatedModels); } } - public void Draw(TiledMap map, Matrix? viewMatrix = null, Matrix? projectionMatrix = null, Effect effect = null, float depth = 0.0f) + public void Draw(Matrix? viewMatrix = null, Matrix? projectionMatrix = null, Effect effect = null, float depth = 0.0f) { var viewMatrix1 = viewMatrix ?? Matrix.Identity; - var projectionMatrix1 = projectionMatrix ?? Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, -1); - Draw(map, ref viewMatrix1, ref projectionMatrix1, effect, depth); + var projectionMatrix1 = projectionMatrix ?? Matrix.CreateOrthographicOffCenter(0, _graphicsDevice.Viewport.Width, _graphicsDevice.Viewport.Height, 0, 0, -1); + + Draw(ref viewMatrix1, ref projectionMatrix1, effect, depth); } - public void Draw(TiledMap map, ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect = null, float depth = 0.0f) + public void Draw(ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect = null, float depth = 0.0f) { - // ReSharper disable once ForCanBeConvertedToForeach - for (var index = 0; index < map.Layers.Count; index++) - { - var layer = map.Layers[index]; - Draw(layer, ref viewMatrix, ref projectionMatrix, effect, depth); - } + for (var index = 0; index < _map.Layers.Count; index++) + Draw(index, ref viewMatrix, ref projectionMatrix, effect, depth); } - public void Draw(TiledMapLayer layer, Matrix? viewMatrix = null, Matrix? projectionMatrix = null, Effect effect = null, float depth = 0.0f) + public void Draw(int layerIndex, Matrix? viewMatrix = null, Matrix? projectionMatrix = null, Effect effect = null, float depth = 0.0f) { var viewMatrix1 = viewMatrix ?? Matrix.Identity; - var projectionMatrix1 = projectionMatrix ?? Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, -1); - Draw(layer, ref viewMatrix1, ref projectionMatrix1, effect, depth); + var projectionMatrix1 = projectionMatrix ?? Matrix.CreateOrthographicOffCenter(0, _graphicsDevice.Viewport.Width, _graphicsDevice.Viewport.Height, 0, 0, -1); + + Draw(layerIndex, ref viewMatrix1, ref projectionMatrix1, effect, depth); } - public void Draw(TiledMapLayer layer, ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect = null, float depth = 0.0f) + public void Draw(int layerIndex, ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect = null, float depth = 0.0f) { + var layer = _map.Layers[layerIndex]; + if (!layer.IsVisible) return; if (layer is TiledMapObjectLayer) return; - _worldMatrix.Translation = new Vector3(layer.OffsetX, layer.OffsetY, depth); + _worldMatrix.Translation = new Vector3(layer.Offset.X, layer.Offset.Y, depth); var effect1 = effect ?? _defaultEffect; var tiledMapEffect = effect1 as ITiledMapEffect; @@ -103,8 +107,8 @@ namespace MonoGame.Extended.Tiled.Graphics tiledMapEffect.Texture = model.Texture; // bind the vertex and index buffer - GraphicsDevice.SetVertexBuffer(model.VertexBuffer); - GraphicsDevice.Indices = model.IndexBuffer; + _graphicsDevice.SetVertexBuffer(model.VertexBuffer); + _graphicsDevice.Indices = model.IndexBuffer; // for each pass in our effect foreach (var pass in effect1.CurrentTechnique.Passes) @@ -113,7 +117,7 @@ namespace MonoGame.Extended.Tiled.Graphics pass.Apply(); // draw the geometry from the vertex buffer / index buffer - GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, model.TrianglesCount); + _graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, model.TrianglesCount); } } } @@ -143,27 +147,5 @@ namespace MonoGame.Extended.Tiled.Graphics animatedModel.VertexBuffer.SetData(animatedModel.Vertices, 0, animatedModel.Vertices.Length); } } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// - /// true to release both managed and unmanaged resources; false to release only - /// unmanaged resources. - /// - protected virtual void Dispose(bool diposing) - { - if (diposing) - _defaultEffect.Dispose(); - } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj b/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj index 2ae5acca..566fe215 100644 --- a/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj +++ b/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj @@ -49,7 +49,6 @@ - diff --git a/Source/MonoGame.Extended.Tiled/TiledMap.cs b/Source/MonoGame.Extended.Tiled/TiledMap.cs index 1115c634..27c9685e 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMap.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMap.cs @@ -1,20 +1,18 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; namespace MonoGame.Extended.Tiled { public sealed class TiledMap : IDisposable { - private readonly List _imageLayers; - private readonly List _layers; - private readonly Dictionary _layersByName; - private readonly List _objectLayers; - private readonly List _tileLayers; - private readonly List _tilesets; + private readonly List _imageLayers = new List(); + private readonly List _layers = new List(); + private readonly Dictionary _layersByName = new Dictionary(); + private readonly List _objectLayers = new List(); + private readonly List _tileLayers = new List(); + private readonly List _tilesets = new List(); public string Name { get; } public int Width { get; } @@ -31,28 +29,20 @@ namespace MonoGame.Extended.Tiled public ReadOnlyCollection ObjectLayers { get; } public Color? BackgroundColor { get; set; } - public int WidthInPixels => Width * TileWidth; public int HeightInPixels => Height * TileHeight; private TiledMap() { - _layers = new List(); Layers = new ReadOnlyCollection(_layers); - _imageLayers = new List(); ImageLayers = new ReadOnlyCollection(_imageLayers); - _tileLayers = new List(); TileLayers = new ReadOnlyCollection(_tileLayers); - _objectLayers = new List(); ObjectLayers = new ReadOnlyCollection(_objectLayers); - _layersByName = new Dictionary(); - _tilesets = new List(); Tilesets = new ReadOnlyCollection(_tilesets); Properties = new TiledMapProperties(); } - public TiledMap(string name, int width, int height, int tileWidth, int tileHeight, - TiledMapTileDrawOrder renderOrder, TiledMapOrientation orientation) + public TiledMap(string name, int width, int height, int tileWidth, int tileHeight, TiledMapTileDrawOrder renderOrder, TiledMapOrientation orientation, Color? backgroundColor = null) : this() { Name = name; @@ -62,6 +52,7 @@ namespace MonoGame.Extended.Tiled TileHeight = tileHeight; RenderOrder = renderOrder; Orientation = orientation; + BackgroundColor = backgroundColor; } public void Dispose() @@ -110,9 +101,12 @@ namespace MonoGame.Extended.Tiled { // ReSharper disable once LoopCanBeConvertedToQuery foreach (var tileset in _tilesets) + { if (tileset.ContainsGlobalIdentifier(tileIdentifier)) return tileset; + } + return null; } } -} \ No newline at end of file +} diff --git a/Source/MonoGame.Extended.Tiled/TiledMapEllipseObject.cs b/Source/MonoGame.Extended.Tiled/TiledMapEllipseObject.cs index 18a2678b..5addec74 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapEllipseObject.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapEllipseObject.cs @@ -1,20 +1,18 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content; namespace MonoGame.Extended.Tiled { public sealed class TiledMapEllipseObject : TiledMapObject { - public Vector2 Center { get; } - public float RadiusX { get; } - public float RadiusY { get; } - - internal TiledMapEllipseObject(ContentReader input) - : base(input) + public TiledMapEllipseObject(int identifier, string name, Size2 size, Vector2 position, float rotation = 0, float opacity = 1, bool isVisible = true) + : base(identifier, name, size, position, rotation, opacity, isVisible) { - RadiusX = Size.Width / 2.0f; - RadiusY = Size.Height / 2.0f; - Center = new Vector2(Position.X + RadiusX, Position.Y); + Radius = new Vector2(size.Width / 2.0f, size.Height / 2.0f); + Center = new Vector2(position.X + Radius.X, position.Y); } + + public Vector2 Center { get; } + public Vector2 Radius { get; } + public override TiledMapObjectType Type => TiledMapObjectType.Ellipse; } } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapImageLayer.cs b/Source/MonoGame.Extended.Tiled/TiledMapImageLayer.cs index 4115c0f1..6d7575ee 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapImageLayer.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapImageLayer.cs @@ -1,23 +1,18 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; -using MonoGame.Extended.Content; namespace MonoGame.Extended.Tiled { public class TiledMapImageLayer : TiledMapLayer, IMovable { - public Vector2 Position { get; set; } - public Texture2D Texture { get; } - - internal TiledMapImageLayer(ContentReader input) - : base(input) + public TiledMapImageLayer(string name, Texture2D image, Vector2? position = null, Vector2? offset = null, float opacity = 1.0f, bool isVisible = true) + : base(name, offset, opacity, isVisible) { - var textureAssetName = input.GetRelativeAssetName(input.ReadString()); - Texture = input.ContentManager.Load(textureAssetName); - var x = input.ReadSingle(); - var y = input.ReadSingle(); - Position = new Vector2(x, y); + Image = image; + Position = position ?? Vector2.Zero; } + + public Texture2D Image { get; } + public Vector2 Position { get; set; } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Tiled/TiledMapLayer.cs b/Source/MonoGame.Extended.Tiled/TiledMapLayer.cs index 0bf3294f..e2cf9ce0 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapLayer.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapLayer.cs @@ -1,5 +1,5 @@ using System; -using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework; using MonoGame.Extended.Tiled.Graphics; namespace MonoGame.Extended.Tiled @@ -10,27 +10,20 @@ namespace MonoGame.Extended.Tiled internal TiledMapLayerAnimatedModel[] AnimatedModels; public string Name { get; } - public TiledMapProperties Properties { get; } public bool IsVisible { get; set; } public float Opacity { get; set; } - public float OffsetX { get; } - public float OffsetY { get; } + public Vector2 Offset { get; set; } + public TiledMapProperties Properties { get; } - internal TiledMapLayer(ContentReader input) + protected TiledMapLayer(string name, Vector2? offset = null, float opacity = 1.0f, bool isVisible = true) { - Models = null; - AnimatedModels = null; - - Name = input.ReadString(); + Name = name; + Offset = offset ?? Vector2.Zero; + Opacity = opacity; + IsVisible = isVisible; Properties = new TiledMapProperties(); - IsVisible = input.ReadBoolean(); - Opacity = input.ReadSingle(); - OffsetX = input.ReadSingle(); - OffsetY = input.ReadSingle(); - - input.ReadTiledMapProperties(Properties); } - + public void Dispose() { Dispose(true); @@ -41,8 +34,10 @@ namespace MonoGame.Extended.Tiled { if (!diposing) return; + if (Models == null) return; + foreach (var model in Models) model.Dispose(); } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapObject.cs b/Source/MonoGame.Extended.Tiled/TiledMapObject.cs index 1e9c6bce..a9386a63 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapObject.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapObject.cs @@ -1,35 +1,30 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content; namespace MonoGame.Extended.Tiled { public abstract class TiledMapObject { + protected TiledMapObject(int identifier, string name, Size2 size, Vector2 position, float rotation = 0, float opacity = 1, bool isVisible = true) + { + Identifier = identifier; + Name = name; + IsVisible = isVisible; + Rotation = rotation; + Position = position; + Size = size; + Opacity = opacity; + Properties = new TiledMapProperties(); + } + public int Identifier { get; } public string Name { get; set; } - public string Type { get; } - public TiledMapProperties Properties { get; } + public abstract TiledMapObjectType Type { get; } public bool IsVisible { get; set; } public float Opacity { get; set; } public float Rotation { get; set; } public Vector2 Position { get; } public Size2 Size { get; set; } - - internal TiledMapObject(ContentReader input) - { - Identifier = input.ReadInt32(); - Name = input.ReadString(); - Type = input.ReadString(); - Position = new Vector2(input.ReadSingle(), input.ReadSingle()); - var width = input.ReadSingle(); - var height = input.ReadSingle(); - Size = new Size2(width, height); - Rotation = input.ReadSingle(); - IsVisible = input.ReadBoolean(); - - Properties = new TiledMapProperties(); - input.ReadTiledMapProperties(Properties); - } + public TiledMapProperties Properties { get; } public override string ToString() { diff --git a/Source/MonoGame.Extended.Tiled/TiledMapObjectLayer.cs b/Source/MonoGame.Extended.Tiled/TiledMapObjectLayer.cs index 180b61a6..0397203d 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapObjectLayer.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapObjectLayer.cs @@ -1,53 +1,20 @@ -using System; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework; namespace MonoGame.Extended.Tiled { public class TiledMapObjectLayer : TiledMapLayer { - public Color Color { get; } + public TiledMapObjectLayer(string name, TiledMapObject[] objects, Color? color = null, TiledMapObjectDrawOrder drawOrder = TiledMapObjectDrawOrder.TopDown, + Vector2? offset = null, float opacity = 1.0f, bool isVisible = true) + : base(name, offset, opacity, isVisible) + { + Color = color; + DrawOrder = drawOrder; + Objects = objects; + } + + public Color? Color { get; } public TiledMapObjectDrawOrder DrawOrder { get; } public TiledMapObject[] Objects { get; } - - internal TiledMapObjectLayer(ContentReader input, TiledMap map) - : base(input) - { - Color = input.ReadColor(); - DrawOrder = (TiledMapObjectDrawOrder)input.ReadByte(); - - var objectCount = input.ReadInt32(); - - Objects = new TiledMapObject[objectCount]; - - for (var i = 0; i < objectCount; i++) - { - TiledMapObject @object; - - var objectType = (TiledMapObjectType)input.ReadByte(); - switch (objectType) - { - case TiledMapObjectType.Rectangle: - @object = new TiledMapRectangleObject(input); - break; - case TiledMapObjectType.Tile: - @object = new TiledMapTileObject(input, map); - break; - case TiledMapObjectType.Ellipse: - @object = new TiledMapEllipseObject(input); - break; - case TiledMapObjectType.Polygon: - @object = new TiledMapPolygonObject(input); - break; - case TiledMapObjectType.Polyline: - @object = new TiledMapPolylineObject(input); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - Objects[i] = @object; - } - } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Tiled/TiledMapPolygonObject.cs b/Source/MonoGame.Extended.Tiled/TiledMapPolygonObject.cs index 333cf4ae..8e19ef74 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapPolygonObject.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapPolygonObject.cs @@ -1,23 +1,16 @@ -using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework; namespace MonoGame.Extended.Tiled { public sealed class TiledMapPolygonObject : TiledMapObject { - public Point2[] Points { get; } - - internal TiledMapPolygonObject(ContentReader input) - : base(input) + public TiledMapPolygonObject(int identifier, string name, Point2[] points, Size2 size, Vector2 position, float rotation = 0, float opacity = 1, bool isVisible = true) + : base(identifier, name, size, position, rotation, opacity, isVisible) { - var pointCount = input.ReadInt32(); - Points = new Point2[pointCount]; - - for (var i = 0; i < pointCount; i++) - { - var x = input.ReadSingle(); - var y = input.ReadSingle(); - Points[i] = new Point2(x, y); - } + Points = points; } + + public Point2[] Points { get; } + public override TiledMapObjectType Type => TiledMapObjectType.Polygon; } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Tiled/TiledMapPolylineObject.cs b/Source/MonoGame.Extended.Tiled/TiledMapPolylineObject.cs index 361a4a73..dcc79620 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapPolylineObject.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapPolylineObject.cs @@ -1,23 +1,16 @@ -using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework; namespace MonoGame.Extended.Tiled { public sealed class TiledMapPolylineObject : TiledMapObject { - public Point2[] Points { get; } - - internal TiledMapPolylineObject(ContentReader input) - : base(input) + public TiledMapPolylineObject(int identifier, string name, Point2[] points, Size2 size, Vector2 position, float rotation = 0, float opacity = 1, bool isVisible = true) + : base(identifier, name, size, position, rotation, opacity, isVisible) { - var pointCount = input.ReadInt32(); - Points = new Point2[pointCount]; - - for (var i = 0; i < pointCount; i++) - { - var x = input.ReadSingle(); - var y = input.ReadSingle(); - Points[i] = new Point2(x, y); - } + Points = points; } + + public Point2[] Points { get; } + public override TiledMapObjectType Type => TiledMapObjectType.Polyline; } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs index b72a2533..952bd8a9 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapReader.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapReader.cs @@ -1,91 +1,265 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.Content; using MonoGame.Extended.Tiled.Graphics; namespace MonoGame.Extended.Tiled { public class TiledMapReader : ContentTypeReader { - protected override TiledMap Read(ContentReader input, TiledMap existingInstance) + protected override TiledMap Read(ContentReader reader, TiledMap existingInstance) { if (existingInstance != null) return existingInstance; - ; - - var value = ReadMetaData(input); - ReadTilesets(input, value); - ReadLayers(input, value); - - return value; - } - - private static TiledMap ReadMetaData(ContentReader input) - { - var name = input.AssetName; - var width = input.ReadInt32(); - var height = input.ReadInt32(); - var tileWidth = input.ReadInt32(); - var tileHeight = input.ReadInt32(); - var backgroundColor = input.ReadColor(); - var renderOrder = (TiledMapTileDrawOrder)input.ReadByte(); - var orientation = (TiledMapOrientation)input.ReadByte(); - - var map = new TiledMap(name, width, height, tileWidth, tileHeight, renderOrder, orientation) - { - BackgroundColor = backgroundColor - }; - - input.ReadTiledMapProperties(map.Properties); + var map = ReadTiledMap(reader); + ReadProperties(reader, map.Properties); + ReadTilesets(reader, map); + ReadLayers(reader, map); return map; } - private static void ReadTilesets(ContentReader input, TiledMap map) + private static void ReadProperties(ContentReader reader, TiledMapProperties properties) { - var tilesetCount = input.ReadInt32(); + var count = reader.ReadInt32(); + + for (var i = 0; i < count; i++) + { + var key = reader.ReadString(); + var value = reader.ReadString(); + properties[key] = value; + } + } + + private static TiledMap ReadTiledMap(ContentReader reader) + { + var name = reader.AssetName; + var width = reader.ReadInt32(); + var height = reader.ReadInt32(); + var tileWidth = reader.ReadInt32(); + var tileHeight = reader.ReadInt32(); + var backgroundColor = reader.ReadColor(); + var renderOrder = (TiledMapTileDrawOrder)reader.ReadByte(); + var orientation = (TiledMapOrientation)reader.ReadByte(); + + return new TiledMap(name, width, height, tileWidth, tileHeight, renderOrder, orientation, backgroundColor); + } + + private static void ReadTilesets(ContentReader reader, TiledMap map) + { + var tilesetCount = reader.ReadInt32(); for (var i = 0; i < tilesetCount; i++) { - var tileset = new TiledMapTileset(input); + var tileset = ReadTileset(reader, map); map.AddTileset(tileset); } } - private static void ReadLayers(ContentReader input, TiledMap map) + + + private static TiledMapTileset ReadTileset(ContentReader input, TiledMap map) { - var layerCount = input.ReadInt32(); + var textureAssetName = input.GetRelativeAssetName(input.ReadString()); + var texture = input.ContentManager.Load(textureAssetName); + var firstGlobalIdentifier = input.ReadInt32(); + var tileWidth = input.ReadInt32(); + var tileHeight = input.ReadInt32(); + var tileCount = input.ReadInt32(); + var spacing = input.ReadInt32(); + var margin = input.ReadInt32(); + var columns = input.ReadInt32(); + var explicitTileCount = input.ReadInt32(); + + var tileset = new TiledMapTileset(texture, firstGlobalIdentifier, tileWidth, tileHeight, tileCount, spacing, margin, columns); + + for (var tileIndex = 0; tileIndex < explicitTileCount; tileIndex++) + { + var localTileIdentifier = input.ReadInt32(); + var animationFramesCount = input.ReadInt32(); + var tilesetTile = animationFramesCount <= 0 + ? new TiledMapTilesetTile(localTileIdentifier, input) + : new TiledMapTilesetAnimatedTile(tileset, input, localTileIdentifier, animationFramesCount); + + ReadProperties(input, tilesetTile.Properties); + tileset.Tiles.Add(tilesetTile); + } + + ReadProperties(input, tileset.Properties); + return tileset; + } + + private static void ReadLayers(ContentReader reader, TiledMap map) + { + var layerCount = reader.ReadInt32(); for (var i = 0; i < layerCount; i++) { - TiledMapLayer layer; - - var layerType = (TiledMapLayerType)input.ReadByte(); - switch (layerType) - { - case TiledMapLayerType.ImageLayer: - layer = new TiledMapImageLayer(input); - break; - case TiledMapLayerType.TileLayer: - layer = new TiledMapTileLayer(input, map); - break; - case TiledMapLayerType.ObjectLayer: - layer = new TiledMapObjectLayer(input, map); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - if (layerType != TiledMapLayerType.ObjectLayer) - ReadModels(input, layer, map); - + var layer = ReadLayer(reader, map); map.AddLayer(layer); } } - private static void ReadModels(ContentReader input, TiledMapLayer layer, TiledMap map) + private static TiledMapLayer ReadLayer(ContentReader reader, TiledMap map) { - var modelCount = input.ReadInt32(); - var animatedModelCount = input.ReadInt32(); + var layerType = (TiledMapLayerType)reader.ReadByte(); + var name = reader.ReadString(); + var isVisible = reader.ReadBoolean(); + var opacity = reader.ReadSingle(); + var offsetX = reader.ReadSingle(); + var offsetY = reader.ReadSingle(); + var offset = new Vector2(offsetX, offsetY); + var properties = new TiledMapProperties(); + + ReadProperties(reader, properties); + + TiledMapLayer layer; + + switch (layerType) + { + case TiledMapLayerType.ImageLayer: + layer = ReadImageLayer(reader, name, offset, opacity, isVisible); + break; + case TiledMapLayerType.TileLayer: + layer = ReadTileLayer(reader, name, offset, opacity, isVisible, map); + break; + case TiledMapLayerType.ObjectLayer: + layer = ReadObjectLayer(reader, name, offset, opacity, isVisible, map); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + if (layerType != TiledMapLayerType.ObjectLayer) + ReadModels(reader, layer, map); + + foreach (var property in properties) + layer.Properties.Add(property.Key, property.Value); + + return layer; + } + + private static TiledMapLayer ReadObjectLayer(ContentReader reader, string name, Vector2 offset, float opacity, bool isVisible, TiledMap map) + { + var color = reader.ReadColor(); + var drawOrder = (TiledMapObjectDrawOrder)reader.ReadByte(); + var objectCount = reader.ReadInt32(); + var objects = new TiledMapObject[objectCount]; + + for (var i = 0; i < objectCount; i++) + objects[i] = ReadTiledMapObject(reader, map); + + return new TiledMapObjectLayer(name, objects, color, drawOrder, offset, opacity, isVisible); + } + + private static TiledMapObject ReadTiledMapObject(ContentReader reader, TiledMap map) + { + 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); + break; + case TiledMapObjectType.Tile: + var globalTileIdentifierWithFlags = reader.ReadUInt32(); + var tile = new TiledMapTile(globalTileIdentifierWithFlags); + var tileset = map.GetTilesetByTileGlobalIdentifier(tile.GlobalIdentifier); + 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); + 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); + break; + case TiledMapObjectType.Polyline: + var points = ReadPoints(reader); + mapObject = new TiledMapPolylineObject(identifier, name, ReadPoints(reader), size, position, rotation, opacity, isVisible); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + foreach (var property in properties) + mapObject.Properties.Add(property.Key, property.Value); + + throw new ArgumentOutOfRangeException(); + } + + 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 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 x = reader.ReadSingle(); + var y = reader.ReadSingle(); + var position = new Vector2(x, y); + return new TiledMapImageLayer(name, texture, position, offset, opacity, isVisible); + } + + private static TiledMapTileLayer ReadTileLayer(ContentReader reader, string name, Vector2 offset, float opacity, bool isVisible, TiledMap map) + { + var width = reader.ReadInt32(); + var height = reader.ReadInt32(); + var tileWidth = map.TileWidth; + var tileHeight = map.TileHeight; + + var tileCount = reader.ReadInt32(); + var tiles = new TiledMapTile[width * height]; + + for (var i = 0; i < tileCount; i++) + { + var globalTileIdentifierWithFlags = reader.ReadUInt32(); + var x = reader.ReadUInt16(); + var y = reader.ReadUInt16(); + + tiles[x + y * width] = new TiledMapTile(globalTileIdentifierWithFlags); + } + + return new TiledMapTileLayer(name, width, height, tileWidth, tileHeight, tiles, offset, opacity, isVisible); + } + + private static void ReadModels(ContentReader reader, TiledMapLayer layer, TiledMap map) + { + var modelCount = reader.ReadInt32(); + var animatedModelCount = reader.ReadInt32(); var models = layer.Models = new TiledMapLayerModel[modelCount]; var animatedModels = layer.AnimatedModels = new TiledMapLayerAnimatedModel[animatedModelCount]; @@ -94,8 +268,8 @@ namespace MonoGame.Extended.Tiled for (var modelIndex = 0; modelIndex < modelCount; modelIndex++) { - var isAnimated = input.ReadBoolean(); - var model = isAnimated ? new TiledMapLayerAnimatedModel(input, map) : new TiledMapLayerModel(input); + var isAnimated = reader.ReadBoolean(); + var model = isAnimated ? new TiledMapLayerAnimatedModel(reader, map) : new TiledMapLayerModel(reader); models[modelIndex] = model; if (isAnimated) diff --git a/Source/MonoGame.Extended.Tiled/TiledMapRectangleObject.cs b/Source/MonoGame.Extended.Tiled/TiledMapRectangleObject.cs index fd2ff101..886ec40b 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapRectangleObject.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapRectangleObject.cs @@ -1,12 +1,14 @@ -using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework; namespace MonoGame.Extended.Tiled { public sealed class TiledMapRectangleObject : TiledMapObject { - internal TiledMapRectangleObject(ContentReader input) - : base(input) + public TiledMapRectangleObject(int identifier, string name, Size2 size, Vector2 position, float rotation = 0, float opacity = 1, bool isVisible = true) + : base(identifier, name, size, position, rotation, opacity, isVisible) { } + + public override TiledMapObjectType Type => TiledMapObjectType.Rectangle; } } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTileLayer.cs b/Source/MonoGame.Extended.Tiled/TiledMapTileLayer.cs index ab37f332..9f36070b 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapTileLayer.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapTileLayer.cs @@ -1,45 +1,33 @@ -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content; namespace MonoGame.Extended.Tiled { public class TiledMapTileLayer : TiledMapLayer { - // immutable + public TiledMapTileLayer(string name, int width, int height, int tileWidth, int tileHeight, IList tiles, + Vector2? offset = null, float opacity = 1, bool isVisible = true) + : base(name, offset, opacity, isVisible) + { + Width = width; + Height = height; + TileWidth = tileWidth; + TileHeight = tileHeight; + Tiles = new ReadOnlyCollection(tiles); + } + public int Width { get; } public int Height { get; } public int TileWidth { get; } public int TileHeight { get; } public ReadOnlyCollection Tiles { get; } - internal TiledMapTileLayer(ContentReader input, TiledMap map) - : base(input) - { - Width = input.ReadInt32(); - Height = input.ReadInt32(); - TileWidth = map.TileWidth; - TileHeight = map.TileHeight; - - var tileCount = input.ReadInt32(); - var tiles = new TiledMapTile[Width * Height]; - Tiles = new ReadOnlyCollection(tiles); - - for (var i = 0; i < tileCount; i++) - { - var globalTileIdentifierWithFlags = input.ReadUInt32(); - var x = input.ReadUInt16(); - var y = input.ReadUInt16(); - tiles[x + y * Width] = new TiledMapTile(globalTileIdentifierWithFlags); - } - } - public bool TryGetTile(int x, int y, out TiledMapTile? tile) { var index = x + y * Width; - if ((index < 0) || (index >= Tiles.Count)) + + if (index < 0 || index >= Tiles.Count) { tile = null; return false; diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTileObject.cs b/Source/MonoGame.Extended.Tiled/TiledMapTileObject.cs index 1a86db7d..b917cba5 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapTileObject.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapTileObject.cs @@ -1,23 +1,19 @@ -using System.Linq; -using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework; namespace MonoGame.Extended.Tiled { public sealed class TiledMapTileObject : TiledMapObject { - public TiledMapTilesetTile TilesetTile { get; } - - public TiledMapTileset Tileset { get; } - - public TiledMapTileObject(ContentReader input, TiledMap map) - : base(input) + public TiledMapTileObject(int identifier, string name, TiledMapTileset tileset, TiledMapTilesetTile tile, + Size2 size, Vector2 position, float rotation = 0, float opacity = 1, bool isVisible = true) + : base(identifier, name, size, position, rotation, opacity, isVisible) { - var globalTileIdentifierWithFlags = input.ReadUInt32(); - var tile = new TiledMapTile(globalTileIdentifierWithFlags); - Tileset = map.GetTilesetByTileGlobalIdentifier(tile.GlobalIdentifier); - - var localTileIdentifier = tile.GlobalIdentifier - Tileset.FirstGlobalIdentifier; - TilesetTile = Tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier); + Tileset = tileset; + Tile = tile; } + + public TiledMapTilesetTile Tile { get; } + public TiledMapTileset Tileset { get; } + public override TiledMapObjectType Type => TiledMapObjectType.Tile; } } diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs b/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs index 1c5393b9..085617e2 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapTileset.cs @@ -1,15 +1,25 @@ +using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; -using MonoGame.Extended.Content; namespace MonoGame.Extended.Tiled { public class TiledMapTileset { - private readonly Dictionary _animatedTilesByLocalTileIdentifier; + public TiledMapTileset(Texture2D texture, int firstGlobalIdentifier, int tileWidth, int tileHeight, int tileCount, int spacing, int margin, int columns) + { + Texture = texture; + FirstGlobalIdentifier = firstGlobalIdentifier; + TileWidth = tileWidth; + TileHeight = tileHeight; + TileCount = tileCount; + Spacing = spacing; + Margin = margin; + Columns = columns; + Properties = new TiledMapProperties(); + Tiles = new List(); + } public string Name => Texture.Name; public Texture2D Texture { get; } @@ -20,60 +30,9 @@ namespace MonoGame.Extended.Tiled public int Margin { get; } public int TileCount { get; } public int Columns { get; } - public ReadOnlyCollection Tiles { get; private set; } - public ReadOnlyCollection AnimatedTiles { get; private set; } + public List Tiles { get; } public TiledMapProperties Properties { get; } - internal TiledMapTileset(ContentReader input) - { - var textureAssetName = input.GetRelativeAssetName(input.ReadString()); - var animatedTiles = new List(); - var tiles = new List(); - - _animatedTilesByLocalTileIdentifier = new Dictionary(); - - Texture = input.ContentManager.Load(textureAssetName); - FirstGlobalIdentifier = input.ReadInt32(); - TileWidth = input.ReadInt32(); - TileHeight = input.ReadInt32(); - TileCount = input.ReadInt32(); - Spacing = input.ReadInt32(); - Margin = input.ReadInt32(); - Columns = input.ReadInt32(); - Properties = new TiledMapProperties(); - - var explicitTileCount = input.ReadInt32(); - - for (var tileIndex = 0; tileIndex < explicitTileCount; tileIndex++) - { - var localTileIdentifier = input.ReadInt32(); - var animationFramesCount = input.ReadInt32(); - - TiledMapTilesetTile tilesetTile; - - if (animationFramesCount <= 0) - { - tilesetTile = new TiledMapTilesetTile(localTileIdentifier,input); - } - else - { - var animatedTilesetTile = new TiledMapTilesetAnimatedTile(this, input, localTileIdentifier, animationFramesCount); - animatedTiles.Add(animatedTilesetTile); - _animatedTilesByLocalTileIdentifier.Add(localTileIdentifier, animatedTilesetTile); - tilesetTile = animatedTilesetTile; - } - - tiles.Add(tilesetTile); - - input.ReadTiledMapProperties(tilesetTile.Properties); - } - - input.ReadTiledMapProperties(Properties); - - Tiles = new ReadOnlyCollection(tiles); - AnimatedTiles = new ReadOnlyCollection(animatedTiles); - } - public Rectangle GetTileRegion(int localTileIdentifier) { return TiledMapHelper.GetTileSourceRectangle(localTileIdentifier, TileWidth, TileHeight, Columns, Margin, Spacing); @@ -81,9 +40,10 @@ namespace MonoGame.Extended.Tiled public TiledMapTilesetAnimatedTile GetAnimatedTilesetTileByLocalTileIdentifier(int localTileIdentifier) { - TiledMapTilesetAnimatedTile animatedTile; - _animatedTilesByLocalTileIdentifier.TryGetValue(localTileIdentifier, out animatedTile); - return animatedTile; + throw new NotImplementedException(); + //TiledMapTilesetAnimatedTile animatedTile; + //_animatedTilesByLocalTileIdentifier.TryGetValue(localTileIdentifier, out animatedTile); + //return animatedTile; } public bool ContainsGlobalIdentifier(int globalIdentifier) diff --git a/Source/MonoGame.Extended.Tiled/TiledMapTilesetTile.cs b/Source/MonoGame.Extended.Tiled/TiledMapTilesetTile.cs index 6dd708d7..6da36e2b 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMapTilesetTile.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMapTilesetTile.cs @@ -43,7 +43,7 @@ namespace MonoGame.Extended.Tiled } public int LocalTileIdentifier { get; set; } - public TiledMapProperties Properties { get; private set; } + public TiledMapProperties Properties { get; } public TiledMapObject[] Objects { get; set; } } } \ No newline at end of file