Last active
September 28, 2020 18:13
-
-
Save mattj1/367612d16bb8ede88a0e75ae6ea25f06 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Reflection; | |
using System.Xml; | |
using System.Xml.Serialization; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using MonoGame.Extended.Tiled.Serialization; | |
namespace MonoGame.Extended.Tiled | |
{ | |
public class TMXLoader | |
{ | |
private readonly string _fileName; | |
public delegate Texture2D TextureLoader(string source); | |
public delegate Stream XmlLoader(string source); | |
private TextureLoader _textureLoader; | |
private XmlLoader _xmlLoader; | |
private TMXLoader(string path, TextureLoader textureLoader, XmlLoader xmlLoader) | |
{ | |
_fileName = path; | |
_textureLoader = textureLoader; | |
_xmlLoader = xmlLoader; | |
Console.WriteLine($"TMX Loader: {path}"); | |
} | |
private TiledMapObjectLayer ConvertTiledMapObjectLayer(TiledMap tiledMap | |
, TiledMapObjectLayerContent lc) | |
{ | |
List<TiledMapObject> objects = new List<TiledMapObject>(); | |
for (int i = 0; i < lc.Objects.Count; i++) | |
{ | |
TiledMapObjectContent c = lc.Objects[i]; | |
if (c.Ellipse != null) | |
{ | |
// Not supported | |
} | |
else if (c.Polygon != null) | |
{ | |
// TODO | |
// List<Point2> points = new List<Point2>(); | |
// var ob = new TiledMapPolygonObject(c.Identifier, c.Name, null, new Size2(c.Width, c.Height), new Vector2(c.X, c.Y), c.Rotation, 1.0f, c.Visible, c.Type ); | |
// objects.Add(ob); | |
} | |
else if (c.Polyline != null) | |
{ | |
// TODO | |
} | |
else | |
{ | |
TiledMapTileset tileSet = tiledMap.GetTilesetByTileGlobalIdentifier((int) c.GlobalIdentifier); | |
if (tileSet != null) | |
{ | |
var fgi = tiledMap.GetTilesetFirstGlobalIdentifier(tileSet); | |
int localIdentifier = (int) (c.GlobalIdentifier - fgi); | |
TiledMapTilesetTile tile = null; | |
foreach (var t in tileSet.Tiles) | |
{ | |
if (t.LocalTileIdentifier == localIdentifier) | |
{ | |
tile = t; | |
break; | |
} | |
} | |
// Copy properties | |
var tmo = new TiledMapTileObject(c.Identifier, c.Name, tileSet, tile, | |
new Vector2(c.Width, c.Height), new Vector2(c.X, c.Y), c.Rotation | |
, 1.0f, c.Visible, c.Type); | |
foreach (var prop in c.Properties) | |
{ | |
tmo.Properties.Add(prop.Name, prop.Value); | |
} | |
objects.Add(tmo); | |
} | |
else | |
{ | |
Console.WriteLine($"Warning: no tileset for object gid {c.GlobalIdentifier}"); | |
} | |
} | |
} | |
TiledMapObjectLayer layer = new TiledMapObjectLayer(lc.Name, objects.ToArray(), | |
ColorHelper.FromHex(lc.Color), | |
(TiledMapObjectDrawOrder) lc.DrawOrder, | |
new Vector2(lc.OffsetX, lc.OffsetY), lc.Opacity, lc.Visible); | |
return layer; | |
} | |
private TiledMapTileLayer ConvertTiledMapTileLayer(TiledMap tiledMap, TiledMapTileLayerContent lc) | |
{ | |
TiledMapTileLayer layer = new TiledMapTileLayer(lc.Name, lc.Width, lc.Height, tiledMap.TileWidth, | |
tiledMap.TileHeight, null, lc.Opacity, lc.Visible); | |
// Copy properties | |
foreach (var prop in lc.Properties) | |
{ | |
layer.Properties.Add(prop.Name, prop.Value); | |
} | |
// Copy tiles | |
if (lc.Data.Encoding == "csv") | |
{ | |
string[] tileIds = lc.Data.Value.Split(","); | |
int offs = 0; | |
for (ushort y = 0; y < layer.Height; y++) | |
{ | |
for (ushort x = 0; x < layer.Width; x++) | |
{ | |
layer.Tiles[offs] = new TiledMapTile(uint.Parse(tileIds[offs]), x, y); | |
offs++; | |
} | |
} | |
} | |
return layer; | |
} | |
private TiledMapTileset ConvertTiledMapTileset(TiledMapTilesetContent tsc) | |
{ | |
var texture = _textureLoader(tsc.Image.Source); | |
var ts = new TiledMapTileset(texture, tsc.TileWidth, tsc.TileHeight, tsc.TileCount, tsc.Spacing, tsc.Margin, | |
tsc.Columns); | |
foreach (var t in tsc.Tiles) | |
{ | |
// TODO: Objects? | |
TiledMapTilesetTile tile; | |
if (t.Frames.Count == 0) | |
{ | |
tile = new TiledMapTilesetTile(t.LocalIdentifier, t.Type, null); | |
} | |
else | |
{ | |
// Animation frames | |
TiledMapTilesetTileAnimationFrame[] frames = new TiledMapTilesetTileAnimationFrame[t.Frames.Count]; | |
for (int i = 0; i < t.Frames.Count; i++) | |
{ | |
var frameContent = t.Frames[i]; | |
BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance; | |
object[] parameters = {ts, frameContent.TileIdentifier, frameContent.Duration}; | |
object instantiatedType = | |
Activator.CreateInstance(typeof(TiledMapTilesetTileAnimationFrame), | |
bindingFlags, | |
null, parameters, null); | |
frames[i] = (TiledMapTilesetTileAnimationFrame) instantiatedType; | |
} | |
tile = new TiledMapTilesetAnimatedTile(t.LocalIdentifier, frames, t.Type, null); | |
} | |
// Copy properties | |
foreach (var prop in t.Properties) | |
{ | |
tile.Properties[prop.Name] = prop.Value; | |
} | |
ts.Tiles.Add(tile); | |
} | |
foreach (var prop in tsc.Properties) | |
{ | |
ts.Properties[prop.Name] = prop.Value; | |
} | |
return ts; | |
} | |
private TiledMap ConvertTiledMap() | |
{ | |
var xmlSerializer = new XmlSerializer(typeof(TiledMapContent)); | |
var stream = _xmlLoader(_fileName); | |
TiledMapContent tiledMapContent = (TiledMapContent) xmlSerializer.Deserialize(XmlReader.Create(stream)); | |
TiledMap tiledMap = new TiledMap(tiledMapContent.Name, tiledMapContent.Width, tiledMapContent.Height, | |
tiledMapContent.TileWidth, tiledMapContent.TileHeight, | |
(TiledMapTileDrawOrder) tiledMapContent.RenderOrder, | |
TiledMapOrientation.Orthogonal, ColorHelper.FromHex(tiledMapContent.BackgroundColor)); | |
foreach (var prop in tiledMapContent.Properties) | |
{ | |
tiledMap.Properties[prop.Name] = prop.Value; | |
} | |
foreach (var tileSetContent in tiledMapContent.Tilesets) | |
{ | |
TiledMapTilesetContent content = tileSetContent; | |
if (tileSetContent.Source != null) | |
{ | |
Stream stream1 = _xmlLoader(tileSetContent.Source); | |
// load content from file | |
content = | |
(TiledMapTilesetContent) new XmlSerializer(typeof(TiledMapTilesetContent)).Deserialize( | |
XmlReader.Create(stream1)); | |
stream1.Close(); | |
} | |
TiledMapTileset tileSet = ConvertTiledMapTileset(content); | |
tiledMap.AddTileset(tileSet, tileSetContent.FirstGlobalIdentifier); | |
} | |
foreach (var layerContent in tiledMapContent.Layers) | |
{ | |
switch (layerContent.Type) | |
{ | |
case TiledMapLayerType.TileLayer: | |
TiledMapTileLayer layer = | |
ConvertTiledMapTileLayer(tiledMap, (TiledMapTileLayerContent) layerContent); | |
tiledMap.AddLayer(layer); | |
break; | |
case TiledMapLayerType.ObjectLayer: | |
var objectLayer = | |
ConvertTiledMapObjectLayer(tiledMap, (TiledMapObjectLayerContent) layerContent); | |
tiledMap.AddLayer(objectLayer); | |
break; | |
} | |
} | |
stream.Close(); | |
return tiledMap; | |
} | |
public static TiledMap LoadTiledMap(string path, TextureLoader textureLoader, XmlLoader xmlLoader) | |
{ | |
var loader = new TMXLoader(path, textureLoader, xmlLoader); | |
return loader.ConvertTiledMap(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment