mirror of
https://github.com/dcronqvist/DotTiled.git
synced 2025-02-05 08:52:50 +02:00
Add loader to make it easier to start using library
This commit is contained in:
parent
97307ccba2
commit
9133f8887c
10 changed files with 551 additions and 0 deletions
|
@ -235,6 +235,7 @@ dotnet_diagnostic.IDE0004.severity = silent
|
||||||
dotnet_diagnostic.IDE0005.severity = error
|
dotnet_diagnostic.IDE0005.severity = error
|
||||||
dotnet_diagnostic.IDE0008.severity = silent
|
dotnet_diagnostic.IDE0008.severity = silent
|
||||||
dotnet_diagnostic.IDE0055.severity = silent
|
dotnet_diagnostic.IDE0055.severity = silent
|
||||||
|
dotnet_diagnostic.IDE0058.severity = silent
|
||||||
dotnet_diagnostic.IDE0160.severity = none
|
dotnet_diagnostic.IDE0160.severity = none
|
||||||
dotnet_diagnostic.CA1707.severity = silent
|
dotnet_diagnostic.CA1707.severity = silent
|
||||||
dotnet_diagnostic.CA1852.severity = none
|
dotnet_diagnostic.CA1852.severity = none
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.1.0" />
|
||||||
<PackageReference Include="xunit" Version="2.5.3" />
|
<PackageReference Include="xunit" Version="2.5.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
using DotTiled.Serialization;
|
||||||
|
|
||||||
|
namespace DotTiled.Tests;
|
||||||
|
|
||||||
|
public class DefaultResourceCacheTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void GetTemplate_TemplateDoesNotExist_ReturnsEmptyOptional()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cache = new DefaultResourceCache();
|
||||||
|
var path = "template.tsx";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = cache.GetTemplate(path);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result.HasValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTemplate_TemplateHasBeenInserted_ReturnsTemplate()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cache = new DefaultResourceCache();
|
||||||
|
var path = "template.tsx";
|
||||||
|
var template = new Template
|
||||||
|
{
|
||||||
|
Object = new EllipseObject { }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
cache.InsertTemplate(path, template);
|
||||||
|
var result = cache.GetTemplate(path);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result.HasValue);
|
||||||
|
Assert.Same(template, result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTileset_TilesetDoesNotExist_ReturnsEmptyOptional()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cache = new DefaultResourceCache();
|
||||||
|
var path = "tileset.tsx";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = cache.GetTileset(path);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result.HasValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTileset_TilesetHasBeenInserted_ReturnsTileset()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cache = new DefaultResourceCache();
|
||||||
|
var path = "tileset.tsx";
|
||||||
|
var tileset = new Tileset
|
||||||
|
{
|
||||||
|
Name = "Tileset",
|
||||||
|
TileWidth = 32,
|
||||||
|
TileHeight = 32,
|
||||||
|
TileCount = 1,
|
||||||
|
Columns = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
cache.InsertTileset(path, tileset);
|
||||||
|
var result = cache.GetTileset(path);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result.HasValue);
|
||||||
|
Assert.Same(tileset, result.Value);
|
||||||
|
}
|
||||||
|
}
|
258
src/DotTiled.Tests/Serialization/LoaderTests.cs
Normal file
258
src/DotTiled.Tests/Serialization/LoaderTests.cs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using NSubstitute;
|
||||||
|
|
||||||
|
namespace DotTiled.Tests;
|
||||||
|
|
||||||
|
public class LoaderTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void LoadMap_Always_ReadsFromResourceReader()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resourceReader = Substitute.For<IResourceReader>();
|
||||||
|
resourceReader.Read("map.tmx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||||
|
<layer id="1" name="Tile Layer 1" width="5" height="5">
|
||||||
|
<data encoding="csv">
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
</map>
|
||||||
|
""");
|
||||||
|
|
||||||
|
var resourceCache = Substitute.For<IResourceCache>();
|
||||||
|
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
|
||||||
|
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
loader.LoadMap("map.tmx");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
resourceReader.Received(1).Read("map.tmx");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LoadMap_MapReferencesExternalTileset_ReadsTilesetFromResourceReaderAndAttemptsToRetrieveFromCache()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resourceReader = Substitute.For<IResourceReader>();
|
||||||
|
resourceReader.Read("map.tmx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||||
|
<tileset firstgid="1" source="tileset.tsx"/>
|
||||||
|
<layer id="1" name="Tile Layer 1" width="5" height="5">
|
||||||
|
<data encoding="csv">
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
</map>
|
||||||
|
""");
|
||||||
|
|
||||||
|
resourceReader.Read("tileset.tsx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tileset version="1.2" tiledversion="1.11.0" name="Tileset" tilewidth="32" tileheight="32" tilecount="1" columns="1">
|
||||||
|
<tile id="1">
|
||||||
|
<image width="32" height="32" source="tile.png"/>
|
||||||
|
</tile>
|
||||||
|
</tileset>
|
||||||
|
""");
|
||||||
|
|
||||||
|
var resourceCache = Substitute.For<IResourceCache>();
|
||||||
|
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
|
||||||
|
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional<Template>.Empty);
|
||||||
|
|
||||||
|
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
|
||||||
|
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
loader.LoadMap("map.tmx");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
resourceReader.Received(1).Read("tileset.tsx");
|
||||||
|
resourceCache.Received(1).GetTileset("tileset.tsx");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LoadMap_MapReferencesExternalTemplate_ReadsTemplateFromResourceReaderAndAttemptsToRetrieveFromCache()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resourceReader = Substitute.For<IResourceReader>();
|
||||||
|
resourceReader.Read("map.tmx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||||
|
<tileset firstgid="1" source="tileset.tsx"/>
|
||||||
|
<layer id="1" name="Tile Layer 1" width="5" height="5">
|
||||||
|
<data encoding="csv">
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
<objectgroup id="2" name="Object Layer 1" width="5" height="5">
|
||||||
|
<object id="1" name="Template" template="template.tx" x="0" y="0" width="32" height="32" gid="1"/>
|
||||||
|
</objectgroup>
|
||||||
|
</map>
|
||||||
|
""");
|
||||||
|
|
||||||
|
resourceReader.Read("tileset.tsx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tileset version="1.2" tiledversion="1.11.0" name="Tileset" tilewidth="32" tileheight="32" tilecount="1" columns="1">
|
||||||
|
<tile id="1">
|
||||||
|
<image width="32" height="32" source="tile.png"/>
|
||||||
|
</tile>
|
||||||
|
</tileset>
|
||||||
|
""");
|
||||||
|
|
||||||
|
resourceReader.Read("template.tx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<template>
|
||||||
|
<object name="Poly">
|
||||||
|
<properties>
|
||||||
|
<property name="templateprop" value="helo there"/>
|
||||||
|
</properties>
|
||||||
|
<polygon points="0,0 104,20 35.6667,32.3333"/>
|
||||||
|
</object>
|
||||||
|
</template>
|
||||||
|
""");
|
||||||
|
|
||||||
|
var resourceCache = Substitute.For<IResourceCache>();
|
||||||
|
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
|
||||||
|
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional<Template>.Empty);
|
||||||
|
|
||||||
|
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
|
||||||
|
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
loader.LoadMap("map.tmx");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
resourceReader.Received(1).Read("template.tx");
|
||||||
|
resourceCache.Received(1).GetTemplate("template.tx");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LoadMap_CacheReturnsTileset_ReturnsTilesetFromCache()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resourceReader = Substitute.For<IResourceReader>();
|
||||||
|
resourceReader.Read("map.tmx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||||
|
<tileset firstgid="1" source="tileset.tsx"/>
|
||||||
|
<layer id="1" name="Tile Layer 1" width="5" height="5">
|
||||||
|
<data encoding="csv">
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
</map>
|
||||||
|
""");
|
||||||
|
|
||||||
|
var resourceCache = Substitute.For<IResourceCache>();
|
||||||
|
resourceCache.GetTileset("tileset.tsx").Returns(new Optional<Tileset>(new Tileset { Name = "Tileset", TileWidth = 32, TileHeight = 32, TileCount = 1, Columns = 1 }));
|
||||||
|
|
||||||
|
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
|
||||||
|
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
loader.LoadMap("map.tmx");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
resourceReader.DidNotReceive().Read("tileset.tsx");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LoadMap_CacheReturnsTemplate_ReturnsTemplateFromCache()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var resourceReader = Substitute.For<IResourceReader>();
|
||||||
|
resourceReader.Read("map.tmx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||||
|
<tileset firstgid="1" source="tileset.tsx"/>
|
||||||
|
<layer id="1" name="Tile Layer 1" width="5" height="5">
|
||||||
|
<data encoding="csv">
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0,
|
||||||
|
0,0,0,0,0
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
<objectgroup id="2" name="Object Layer 1" width="5" height="5">
|
||||||
|
<object id="1" name="Template" template="template.tx" x="0" y="0" width="32" height="32" gid="1"/>
|
||||||
|
</objectgroup>
|
||||||
|
</map>
|
||||||
|
""");
|
||||||
|
|
||||||
|
resourceReader.Read("tileset.tsx").Returns(
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tileset version="1.2" tiledversion="1.11.0" name="Tileset" tilewidth="32" tileheight="32" tilecount="1" columns="1">
|
||||||
|
<tile id="1">
|
||||||
|
<image width="32" height="32" source="tile.png"/>
|
||||||
|
</tile>
|
||||||
|
</tileset>
|
||||||
|
""");
|
||||||
|
|
||||||
|
var resourceCache = Substitute.For<IResourceCache>();
|
||||||
|
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
|
||||||
|
resourceCache.GetTemplate("template.tx").Returns(new Optional<Template>(new Template
|
||||||
|
{
|
||||||
|
Object = new PolygonObject
|
||||||
|
{
|
||||||
|
Points = [
|
||||||
|
new Vector2(0,0),
|
||||||
|
new Vector2(104,20),
|
||||||
|
new Vector2(35.6667f,32.3333f)
|
||||||
|
],
|
||||||
|
Properties = [
|
||||||
|
new StringProperty { Name = "templateprop", Value = "helo there" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
|
||||||
|
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
loader.LoadMap("map.tmx");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
resourceReader.DidNotReceive().Read("template.tx");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string WhereAmI([CallerFilePath] string callerFilePath = "") => callerFilePath;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
var basePath = Path.GetDirectoryName(WhereAmI())!;
|
||||||
|
var mapPath = Path.Combine(basePath, "TestData/Map/map-with-external-tileset/map-with-external-tileset.tmx");
|
||||||
|
var loader = Loader.Default();
|
||||||
|
loader.LoadMap(mapPath);
|
||||||
|
}
|
||||||
|
}
|
|
@ -89,6 +89,11 @@ public class Optional<T>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public T GetValueOr(T defaultValue) => HasValue ? _value : defaultValue;
|
public T GetValueOr(T defaultValue) => HasValue ? _value : defaultValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current <see cref="Optional{T}"/> object if it has a value; otherwise, returns the specified default value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="defaultValue">The <see cref="Optional{T}"/> object to be returned if the current <see cref="Optional{T}"/> object has no value.</param>
|
||||||
|
/// <returns></returns>
|
||||||
public Optional<T> GetValueOrOptional(Optional<T> defaultValue) => HasValue ? this : defaultValue;
|
public Optional<T> GetValueOrOptional(Optional<T> defaultValue) => HasValue ? this : defaultValue;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
36
src/DotTiled/Serialization/DefaultResourceCache.cs
Normal file
36
src/DotTiled/Serialization/DefaultResourceCache.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DotTiled.Serialization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A default implementation of <see cref="IResourceCache"/> that uses an in-memory dictionary to cache resources.
|
||||||
|
/// </summary>
|
||||||
|
public class DefaultResourceCache : IResourceCache
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, Template> _templates = [];
|
||||||
|
private readonly Dictionary<string, Tileset> _tilesets = [];
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Optional<Template> GetTemplate(string path)
|
||||||
|
{
|
||||||
|
if (_templates.TryGetValue(path, out var template))
|
||||||
|
return new Optional<Template>(template);
|
||||||
|
|
||||||
|
return Optional<Template>.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Optional<Tileset> GetTileset(string path)
|
||||||
|
{
|
||||||
|
if (_tilesets.TryGetValue(path, out var tileset))
|
||||||
|
return new Optional<Tileset>(tileset);
|
||||||
|
|
||||||
|
return Optional<Tileset>.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void InsertTemplate(string path, Template template) => _templates[path] = template;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void InsertTileset(string path, Tileset tileset) => _tilesets[path] = tileset;
|
||||||
|
}
|
21
src/DotTiled/Serialization/FileSystemResourceReader.cs
Normal file
21
src/DotTiled/Serialization/FileSystemResourceReader.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace DotTiled.Serialization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses the underlying host file system to read Tiled resources from a given path.
|
||||||
|
/// </summary>
|
||||||
|
public class FileSystemResourceReader : IResourceReader
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="FileSystemResourceReader"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public FileSystemResourceReader() { }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Read(string resourcePath)
|
||||||
|
{
|
||||||
|
using var streamReader = new StreamReader(resourcePath);
|
||||||
|
return streamReader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
35
src/DotTiled/Serialization/IResourceCache.cs
Normal file
35
src/DotTiled/Serialization/IResourceCache.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
namespace DotTiled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for a cache that stores Tiled resources for faster retrieval and reuse.
|
||||||
|
/// </summary>
|
||||||
|
public interface IResourceCache
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts a tileset into the cache with the given <paramref name="path"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to the tileset file.</param>
|
||||||
|
/// <param name="tileset">The tileset to insert into the cache.</param>
|
||||||
|
void InsertTileset(string path, Tileset tileset);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a tileset from the cache with the given <paramref name="path"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to the tileset file.</param>
|
||||||
|
/// <returns>The tileset if it exists in the cache; otherwise, <see cref="Optional{Tileset}.Empty"/>.</returns>
|
||||||
|
Optional<Tileset> GetTileset(string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts a template into the cache with the given <paramref name="path"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to the template file.</param>
|
||||||
|
/// <param name="template">The template to insert into the cache.</param>
|
||||||
|
void InsertTemplate(string path, Template template);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a template from the cache with the given <paramref name="path"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to the template file.</param>
|
||||||
|
/// <returns>The template if it exists in the cache; otherwise, <see cref="Optional{Template}.Empty"/>.</returns>
|
||||||
|
Optional<Template> GetTemplate(string path);
|
||||||
|
}
|
14
src/DotTiled/Serialization/IResourceReader.cs
Normal file
14
src/DotTiled/Serialization/IResourceReader.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
namespace DotTiled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Able to read resources from a given path.
|
||||||
|
/// </summary>
|
||||||
|
public interface IResourceReader
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a Tiled resource from a given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="resourcePath">The path to the Tiled resource, which can be a Map file, Tileset file, Template file, etc.</param>
|
||||||
|
/// <returns>The content of the resource as a string.</returns>
|
||||||
|
string Read(string resourcePath);
|
||||||
|
}
|
102
src/DotTiled/Serialization/Loader.cs
Normal file
102
src/DotTiled/Serialization/Loader.cs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using DotTiled.Serialization;
|
||||||
|
|
||||||
|
namespace DotTiled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Able to load Tiled resources from a given path.
|
||||||
|
/// </summary>
|
||||||
|
public class Loader
|
||||||
|
{
|
||||||
|
private readonly IResourceReader _resourceReader;
|
||||||
|
private readonly IResourceCache _resourceCache;
|
||||||
|
private readonly IDictionary<string, ICustomTypeDefinition> _customTypeDefinitions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Loader"/> class with the given <paramref name="resourceReader"/>, <paramref name="resourceCache"/>, and <paramref name="customTypeDefinitions"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="resourceReader">A reader that is able to read Tiled resources from a given path.</param>
|
||||||
|
/// <param name="resourceCache">A cache that stores Tiled resources for faster retrieval and reuse.</param>
|
||||||
|
/// <param name="customTypeDefinitions">A collection of custom type definitions that can be used to resolve custom types in Tiled resources.</param>
|
||||||
|
public Loader(
|
||||||
|
IResourceReader resourceReader,
|
||||||
|
IResourceCache resourceCache,
|
||||||
|
IEnumerable<ICustomTypeDefinition> customTypeDefinitions)
|
||||||
|
{
|
||||||
|
_resourceReader = resourceReader;
|
||||||
|
_resourceCache = resourceCache;
|
||||||
|
_customTypeDefinitions = customTypeDefinitions.ToDictionary(ctd => ctd.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of a <see cref="Loader"/> with the default <see cref="FileSystemResourceReader"/> and <see cref="DefaultResourceCache"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="customTypeDefinitions">An optional collection of custom type definitions that can be used to resolve custom types in Tiled resources.</param>
|
||||||
|
/// <returns>A new instance of a <see cref="Loader"/>.</returns>
|
||||||
|
public static Loader Default(IEnumerable<ICustomTypeDefinition> customTypeDefinitions = null) => new Loader(new FileSystemResourceReader(), new DefaultResourceCache(), customTypeDefinitions ?? []);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a map from the given <paramref name="mapPath"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapPath">The path to the map file.</param>
|
||||||
|
/// <returns>The loaded map.</returns>
|
||||||
|
public Map LoadMap(string mapPath)
|
||||||
|
{
|
||||||
|
var basePath = Path.GetDirectoryName(mapPath);
|
||||||
|
string mapContent = _resourceReader.Read(mapPath);
|
||||||
|
using var mapReader = new MapReader(mapContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver);
|
||||||
|
return mapReader.ReadMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a tileset from the given <paramref name="tilesetPath"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tilesetPath">The path to the tileset file.</param>
|
||||||
|
/// <returns>The loaded tileset.</returns>
|
||||||
|
public Tileset LoadTileset(string tilesetPath)
|
||||||
|
{
|
||||||
|
var basePath = Path.GetDirectoryName(tilesetPath);
|
||||||
|
string tilesetContent = _resourceReader.Read(tilesetPath);
|
||||||
|
using var tilesetReader = new TilesetReader(tilesetContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver);
|
||||||
|
return tilesetReader.ReadTileset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Func<string, Tileset> GetTilesetResolver(string basePath)
|
||||||
|
{
|
||||||
|
return source =>
|
||||||
|
{
|
||||||
|
var tilesetPath = Path.Combine(basePath, source);
|
||||||
|
var cachedTileset = _resourceCache.GetTileset(source);
|
||||||
|
if (cachedTileset.HasValue)
|
||||||
|
return cachedTileset.Value;
|
||||||
|
|
||||||
|
string tilesetContent = _resourceReader.Read(tilesetPath);
|
||||||
|
using var tilesetReader = new TilesetReader(tilesetContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver);
|
||||||
|
var tileset = tilesetReader.ReadTileset();
|
||||||
|
_resourceCache.InsertTileset(source, tileset);
|
||||||
|
return tileset;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Func<string, Template> GetTemplateResolver(string basePath)
|
||||||
|
{
|
||||||
|
return source =>
|
||||||
|
{
|
||||||
|
var templatePath = Path.Combine(basePath, source);
|
||||||
|
var cachedTemplate = _resourceCache.GetTemplate(source);
|
||||||
|
if (cachedTemplate.HasValue)
|
||||||
|
return cachedTemplate.Value;
|
||||||
|
|
||||||
|
string templateContent = _resourceReader.Read(templatePath);
|
||||||
|
using var templateReader = new TemplateReader(templateContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver);
|
||||||
|
var template = templateReader.ReadTemplate();
|
||||||
|
_resourceCache.InsertTemplate(source, template);
|
||||||
|
return template;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private ICustomTypeDefinition CustomTypeResolver(string name) => _customTypeDefinitions[name];
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue