Skip to content
This repository has been archived by the owner on Sep 4, 2024. It is now read-only.

Commit

Permalink
corrected layering, added embedded tileset support, and added a example
Browse files Browse the repository at this point in the history
  • Loading branch information
nolemretaW committed Sep 12, 2023
1 parent b7b9ead commit ea19cff
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 83 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ TiledCSPlus is an extended, and up to date fork of [TiledCS](https://github.com/

## Planned features
* Support for Tiled 1.9 and 1.10 features.
* Embedded tilesets
* Better layer arrangement (layers will be arranged in order from top to bottom, instead of current tile layers, then object layers, and image layers at the end)
* ~~Embedded tilesets~~ Done!
* ~~Better layer arrangement (layers will be arranged in order from top to bottom, instead of current tile layers, then object layers, and image layers at the end)~~ Also done!

## Does it break compability?
**YES**, practically every field was renamed to be in PascalCase, and few fields were combined into one property eg. `offsetX` and `offsetY` into `Vector2` `offset`. Except those few changes, API didn't change much as of now.
Expand Down
37 changes: 37 additions & 0 deletions TiledCSPlus.Example/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using TiledCSPlus;

class Program
{
public static void Main(string[] args)
{
//load a tilemap
TiledMap TiledMap = new TiledMap("assets/tilemap.tmx");

//load a tileset by loading all used tilesets from a directory
Dictionary<int, TiledTileset> Tilesets = TiledMap.GetTiledTilesets("assets/");
//you can load them manually of course, like this
/* foreach (TiledMapTileset tiledMapTileset in TiledMap.Tilesets)
{
if tileset is not embedded into tilemap
if (!tiledMapTileset.IsTilesetEmbedded)
{
load a tileset file using tiledMapTileset.Source as a filename...
...using new TiledTileset()
TiledTileset tiledTileset = new TiledTileset(tiledMapTileset.Source);
..or other method that works for you, into a MemoryStream
MemoryStream ms = new MemoryStream(<loaded tileset file>); //file has to be loaded into a byte array
TiledTileset tiledTileset = new TiledTileset(ms);
//then, add into loaded tilesets as usual
Tilesets.Add(tiledMapTileset.FirstGid, tiledTileset);
}
} */

//get map tileset which some tile belongs to
TiledMapTileset tileMapTileset = TiledMap.GetTiledMapTileset(TiledMap.Layers[0].Data[0]);
//now that you have tileset laded into Tilesets dictionary, you can get the tileset by
TiledTileset tileTileset = Tilesets[tileMapTileset.FirstGid];
//and now, get the rect for tile's position in the tileset image
TiledSourceRect rect = TiledMap.GetSourceRect(tileMapTileset, tileTileset, TiledMap.Layers[0].Data[0]);
}
}
26 changes: 26 additions & 0 deletions TiledCSPlus.Example/TiledCSPlus.Example.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\TiledCSPlus\TiledCSPlus.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="assets\tilemap.tmx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="assets\tileset.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="assets\tileset.tsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
9 changes: 9 additions & 0 deletions TiledCSPlus.Example/assets/tilemap.tmx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="10" height="10" tilewidth="16" tileheight="16" infinite="0" nextlayerid="5" nextobjectid="1">
<tileset firstgid="1" source="tileset.tsx"/>
<layer id="1" name="Tile Layer 1" width="10" height="10">
<data encoding="base64">
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==
</data>
</layer>
</map>
Binary file added TiledCSPlus.Example/assets/tileset.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions TiledCSPlus.Example/assets/tileset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.8" tiledversion="1.10.2" name="tileset" tilewidth="16" tileheight="16" tilecount="1" columns="1">
<image source="tileset.png" width="16" height="16"/>
</tileset>
11 changes: 10 additions & 1 deletion TiledCSPlus.Test/TiledMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,22 @@ public void MapMetadata()
[Test]
public void Tileset()
{
Tilesets[1].Name.ShouldBe("tileset");
TiledMap.Tilesets[0].FirstGid.ShouldBe(1);
TiledMap.Tilesets[0].Source.ShouldBe("tileset.tsx");
TiledMap.Tilesets[0].IsTilesetEmbedded.ShouldBe(false);
TiledMap.Tilesets[1].FirstGid.ShouldBe(2);
TiledMap.Tilesets[1].Source.ShouldBe(null);
TiledMap.Tilesets[1].IsTilesetEmbedded.ShouldBe(true);

Tilesets[1].Image.Source.ShouldBe("tileset.png");
TiledMap.EmbeddedTilesets[2].Name.ShouldBe("tileset-embedded");

}

[Test]
public void Layers()
{
TiledMap.Layers[0].TintColor.ShouldBe(new Color(255, 254, 253, 252));
TiledMap.Layers[2].Name.ShouldBe("Image Layer 1");
}
}
31 changes: 25 additions & 6 deletions TiledCSPlus.Test/assets/TiledCSPlus_test.tiled-session
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"height": 4300,
"width": 2
},
"activeFile": "tilemap.tmx",
"activeFile": "D:/Projects/csharp/TiledCSPlus/TiledCSPlus.Example/assets/tilemap.tmx",
"expandedProjectPaths": [
"."
],
Expand All @@ -12,17 +12,34 @@
"": {
"scaleInDock": 1
},
"D:/Projects/csharp/TiledCSPlus/TiledCSPlus.Example/assets/tilemap.tmx": {
"scale": 7.43375,
"selectedLayer": 0,
"viewCenter": {
"x": 84.54683033462251,
"y": 79.50227005212713
}
},
"D:/Projects/csharp/TiledCSPlus/TiledCSPlus.Example/assets/tilemap.tmx#tileset-embedded": {
"scaleInDock": 1
},
"D:/Projects/csharp/TiledCSPlus/TiledCSPlus.Example/assets/tileset.tsx": {
"scaleInDock": 1
},
"tilemap.tmx": {
"scale": 4,
"selectedLayer": 0,
"viewCenter": {
"x": -35.375,
"y": 27.25
"x": 79.875,
"y": 80
}
},
"tilemap.tmx#tileset": {
"scaleInDock": 1
},
"tilemap.tmx#tileset-embedded": {
"scaleInDock": 1
},
"tileset.tsx": {
"scaleInDock": 1,
"scaleInEditor": 1
Expand All @@ -36,13 +53,15 @@
"map.tileWidth": 16,
"map.width": 10,
"openFiles": [
"tileset.tsx",
"tilemap.tmx"
"tilemap.tmx",
"D:/Projects/csharp/TiledCSPlus/TiledCSPlus.Example/assets/tilemap.tmx",
"tileset.tsx"
],
"project": "TiledCSPlus_test.tiled-project",
"recentFiles": [
"tilemap.tmx",
"tileset.tsx",
"tilemap.tmx"
"D:/Projects/csharp/TiledCSPlus/TiledCSPlus.Example/assets/tilemap.tmx"
],
"tileset.embedInMap": true,
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)",
Expand Down
10 changes: 8 additions & 2 deletions TiledCSPlus.Test/assets/tilemap.tmx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="10" height="10" tilewidth="16" tileheight="16" infinite="0" backgroundcolor="#04010203" nextlayerid="2" nextobjectid="1">
<map version="1.8" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="10" height="10" tilewidth="16" tileheight="16" infinite="0" backgroundcolor="#04010203" nextlayerid="5" nextobjectid="1">
<tileset firstgid="1" source="tileset.tsx"/>
<tileset firstgid="2" name="tileset-embedded" tilewidth="16" tileheight="16" tilecount="1" columns="1">
<image source="tileset.png" width="16" height="16"/>
</tileset>
<layer id="1" name="Tile Layer 1" width="10" height="10" tintcolor="#fcfffefd">
<data encoding="base64">
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAQAAAAEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
</data>
</layer>
<objectgroup id="2" name="Object Layer 1"/>
<imagelayer id="3" name="Image Layer 1"/>
<group id="4" name="Group Layer 1"/>
</map>
75 changes: 48 additions & 27 deletions TiledCSPlus/TiledMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ public class TiledMap
/// </summary>
public Color BackgroundColor { get; internal set; }

/// <summary>
/// Returns tilesets embedded in the map
/// </summary>
public Dictionary<int, TiledTileset> EmbeddedTilesets { get; internal set; }

/// <summary>
/// Returns an empty instance of TiledMap
/// </summary>
Expand Down Expand Up @@ -158,31 +163,32 @@ public void ParseXml(string xml)

var nodeMap = document.SelectSingleNode("map");
var nodesProperty = nodeMap.SelectNodes("properties/property");
var nodesLayer = nodeMap.SelectNodes("layer");
var nodesImageLayer = nodeMap.SelectNodes("imagelayer");
var nodesObjectGroup = nodeMap.SelectNodes("objectgroup");
var nodesLayer = nodeMap.SelectNodes("layer | objectgroup | imagelayer");
var nodesTileset = nodeMap.SelectNodes("tileset");
var nodesGroup = nodeMap.SelectNodes("group");
var attrParallaxOriginX = nodeMap.Attributes["parallaxoriginx"];
var attrParallaxOriginY = nodeMap.Attributes["parallaxoriginy"];
var attrBackgroundColor = nodeMap.Attributes["backgroundcolor"];

TiledVersion = nodeMap.Attributes["tiledversion"].Value;
Orientation = nodeMap.Attributes["orientation"].Value;
RenderOrder = nodeMap.Attributes["renderorder"].Value;
BackgroundColor = ParseColor(nodeMap.Attributes["backgroundcolor"]?.Value);
Infinite = nodeMap.Attributes["infinite"].Value == "1";
EmbeddedTilesets = new Dictionary<int, TiledTileset>();

Width = int.Parse(nodeMap.Attributes["width"].Value);
Height = int.Parse(nodeMap.Attributes["height"].Value);
TileWidth = int.Parse(nodeMap.Attributes["tilewidth"].Value);
TileHeight = int.Parse(nodeMap.Attributes["tileheight"].Value);


if (nodesProperty != null) Properties = ParseProperties(nodesProperty);
if (nodesTileset != null) Tilesets = ParseTilesets(nodesTileset);
if (nodesLayer != null) Layers = ParseLayers(nodesLayer, nodesObjectGroup, nodesImageLayer);
if (nodesLayer != null) Layers = ParseLayers(nodesLayer);
if (nodesGroup != null) Groups = ParseGroups(nodesGroup);
if (attrParallaxOriginX != null) ParallaxOriginX = float.Parse(attrParallaxOriginX.Value, CultureInfo.InvariantCulture);
if (attrParallaxOriginY != null) ParallaxOriginY = float.Parse(attrParallaxOriginY.Value, CultureInfo.InvariantCulture);
if (attrBackgroundColor != null) BackgroundColor = ParseColor(attrBackgroundColor.Value);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -230,11 +236,26 @@ private TiledMapTileset[] ParseTilesets(XmlNodeList nodeList)

foreach (XmlNode node in nodeList)
{
var tileset = new TiledMapTileset();
tileset.FirstGid = int.Parse(node.Attributes["firstgid"].Value);
tileset.Source = node.Attributes["source"]?.Value;

result.Add(tileset);
if (node.Attributes["source"] == null)
{
//tilemap is an embedded tilemap
TiledTileset tileset = new TiledTileset();
tileset.ParseXml(node.OuterXml);
int firstgid = int.Parse(node.Attributes["firstgid"].Value);
EmbeddedTilesets.Add(firstgid, tileset);
var maptileset = new TiledMapTileset();
maptileset.FirstGid = int.Parse(node.Attributes["firstgid"].Value);
maptileset.IsTilesetEmbedded = true;
result.Add(maptileset);
}
else
{
var tileset = new TiledMapTileset();
tileset.FirstGid = int.Parse(node.Attributes["firstgid"].Value);
tileset.Source = node.Attributes["source"]?.Value;
tileset.IsTilesetEmbedded = false;
result.Add(tileset);
}
}

return result.ToArray();
Expand All @@ -248,9 +269,7 @@ private TiledGroup[] ParseGroups(XmlNodeList nodeListGroups)
{
var nodesProperty = node.SelectNodes("properties/property");
var nodesGroup = node.SelectNodes("group");
var nodesLayer = node.SelectNodes("layer");
var nodesObjectGroup = node.SelectNodes("objectgroup");
var nodesImageLayer = node.SelectNodes("imagelayer");
var nodesLayer = node.SelectNodes("layer | objectgroup | imagelayer");
var attrVisible = node.Attributes["visible"];
var attrLocked = node.Attributes["locked"];

Expand All @@ -262,31 +281,33 @@ private TiledGroup[] ParseGroups(XmlNodeList nodeListGroups)
if (attrLocked != null) tiledGroup.Locked = attrLocked.Value == "1";
if (nodesProperty != null) tiledGroup.Properties = ParseProperties(nodesProperty);
if (nodesGroup != null) tiledGroup.Groups = ParseGroups(nodesGroup);
if (nodesLayer != null) tiledGroup.Layers = ParseLayers(nodesLayer, nodesObjectGroup, nodesImageLayer);
if (nodesLayer != null) tiledGroup.Layers = ParseLayers(nodesLayer);

result.Add(tiledGroup);
}

return result.ToArray();
}

private TiledLayer[] ParseLayers(XmlNodeList nodesLayer, XmlNodeList nodesObjectGroup, XmlNodeList nodesImageLayer)
private TiledLayer[] ParseLayers(XmlNodeList nodesLayer)
{
var result = new List<TiledLayer>();

foreach (XmlNode node in nodesLayer)
{
result.Add(ParseLayer(node, TiledLayerType.TileLayer));
}

foreach (XmlNode node in nodesObjectGroup)
{
result.Add(ParseLayer(node, TiledLayerType.ObjectLayer));
}

foreach (XmlNode node in nodesImageLayer)
{
result.Add(ParseLayer(node, TiledLayerType.ImageLayer));
switch (node.Name)
{
case "layer":
result.Add(ParseLayer(node, TiledLayerType.TileLayer));
break;
case "objectgroup":
result.Add(ParseLayer(node, TiledLayerType.ObjectLayer));
break;
case "imagelayer":
result.Add(ParseLayer(node, TiledLayerType.ImageLayer));
break;
default:
throw new TiledException($"Unknown layer type: {node.Name}");
}
}

return result.ToArray();
Expand Down
Loading

0 comments on commit ea19cff

Please sign in to comment.