Merge pull request #827 from craftworkgames/fix_tiled_bigobject_tileset

Add support of "Collection of Images" tileset type.
This commit is contained in:
Max Kopjev
2023-12-25 19:21:08 +01:00
committed by GitHub
15 changed files with 131 additions and 76 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>3.9.0</Version>
<Version>3.9.0.9145</Version>
<Authors>craftworkgames</Authors>
<PackageProjectUrl>https://github.com/craftworkgames/MonoGame.Extended</PackageProjectUrl>
<RepositoryUrl>https://github.com/craftworkgames/MonoGame.Extended</RepositoryUrl>
@@ -0,0 +1,15 @@
using System.IO;
using Microsoft.Xna.Framework.Content.Pipeline;
namespace MonoGame.Extended.Content.Pipeline;
public static class ContentImporterContextExtensions
{
public static string AddDependencyWithLogging(this ContentImporterContext context, string filePath, string source)
{
source = Path.Combine(Path.GetDirectoryName(filePath), source);
ContentLogger.Log($"Adding dependency '{source}'");
context.AddDependency(source);
return source;
}
}
@@ -28,10 +28,10 @@ namespace MonoGame.Extended.Content.Pipeline
public ExternalReference<TInput> GetExternalReference<TInput>(string source)
{
if (_externalReferences.TryGetValue(source, out var contentItem))
if (source is not null && _externalReferences.TryGetValue(source, out var contentItem))
return contentItem as ExternalReference<TInput>;
return null;
}
}
}
}
@@ -0,0 +1,22 @@
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using MonoGame.Extended.Tiled.Serialization;
namespace MonoGame.Extended.Content.Pipeline.Tiled;
public class TiledContentItem<T>: ContentItem<T>
{
public TiledContentItem(T data) : base(data)
{
}
public void BuildExternalReference<T>(ContentProcessorContext context, TiledMapImageContent image)
{
var parameters = new OpaqueDataDictionary
{
{ "ColorKeyColor", image.TransparentColor },
{ "ColorKeyEnabled", true }
};
BuildExternalReference<Texture2DContent>(context, image.Source, parameters);
}
}
@@ -2,11 +2,11 @@
namespace MonoGame.Extended.Content.Pipeline.Tiled
{
public class TiledMapContentItem : ContentItem<TiledMapContent>
public class TiledMapContentItem : TiledContentItem<TiledMapContent>
{
public TiledMapContentItem(TiledMapContent data)
public TiledMapContentItem(TiledMapContent data)
: base(data)
{
}
}
}
}
@@ -75,7 +75,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
}
}
}
[ContentProcessor(DisplayName = "Tiled Map Processor - MonoGame.Extended")]
public class TiledMapProcessor : ContentProcessor<TiledMapContentItem, TiledMapContentItem>
@@ -95,14 +95,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
if (string.IsNullOrWhiteSpace(tileset.Source))
{
// Load the Texture2DContent for the tileset as it will be saved into the map content file.
//var externalReference = new ExternalReference<Texture2DContent>(tileset.Image.Source);
var parameters = new OpaqueDataDictionary
{
{ "ColorKeyColor", tileset.Image.TransparentColor },
{ "ColorKeyEnabled", true }
};
//tileset.Image.ContentRef = context.BuildAsset<Texture2DContent, Texture2DContent>(externalReference, "", parameters, "", "");
contentItem.BuildExternalReference<Texture2DContent>(context, tileset.Image.Source, parameters);
contentItem.BuildExternalReference<Texture2DContent>(context, tileset.Image);
}
else
{
@@ -114,7 +107,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
}
ProcessLayers(contentItem, map, context, map.Layers);
return contentItem;
}
catch (Exception ex)
@@ -132,14 +125,7 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
{
case TiledMapImageLayerContent imageLayer:
ContentLogger.Log($"Processing image layer '{imageLayer.Name}'");
//var externalReference = new ExternalReference<Texture2DContent>(imageLayer.Image.Source);
var parameters = new OpaqueDataDictionary
{
{ "ColorKeyColor", imageLayer.Image.TransparentColor },
{ "ColorKeyEnabled", true }
};
//imageLayer.Image.ContentRef = context.BuildAsset<Texture2DContent, Texture2DContent>(externalReference, "", parameters, "", "");
contentItem.BuildExternalReference<Texture2DContent>(context, imageLayer.Image.Source, parameters);
contentItem.BuildExternalReference<Texture2DContent>(context, imageLayer.Image);
ContentLogger.Log($"Processed image layer '{imageLayer.Name}'");
break;
@@ -335,4 +321,4 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
};
}
}
}
}
@@ -1,12 +1,14 @@
using MonoGame.Extended.Tiled.Serialization;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using MonoGame.Extended.Tiled.Serialization;
namespace MonoGame.Extended.Content.Pipeline.Tiled
{
public class TiledMapTilesetContentItem : ContentItem<TiledMapTilesetContent>
public class TiledMapTilesetContentItem : TiledContentItem<TiledMapTilesetContent>
{
public TiledMapTilesetContentItem(TiledMapTilesetContent data)
public TiledMapTilesetContentItem(TiledMapTilesetContent data)
: base(data)
{
}
}
}
}
@@ -39,23 +39,18 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
var tilesetSerializer = new XmlSerializer(typeof(TiledMapTilesetContent));
var tileset = (TiledMapTilesetContent)tilesetSerializer.Deserialize(reader);
tileset.Image.Source = Path.Combine(Path.GetDirectoryName(filePath), tileset.Image.Source);
ContentLogger.Log($"Adding dependency '{tileset.Image.Source}'");
context.AddDependency(tileset.Image.Source);
if (tileset.Image is not null)
tileset.Image.Source = context.AddDependencyWithLogging(filePath, tileset.Image.Source);
foreach (var tile in tileset.Tiles)
{
foreach (var obj in tile.Objects)
{
if (!string.IsNullOrWhiteSpace(obj.TemplateSource))
{
obj.TemplateSource = Path.Combine(Path.GetDirectoryName(filePath), obj.TemplateSource);
ContentLogger.Log($"Adding dependency '{obj.TemplateSource}'");
// We depend on the template.
context.AddDependency(obj.TemplateSource);
}
obj.TemplateSource = context.AddDependencyWithLogging(filePath, obj.TemplateSource);
}
if (tile.Image is not null)
tile.Image.Source = context.AddDependencyWithLogging(filePath, tile.Image.Source);
}
return tileset;
@@ -15,16 +15,10 @@ 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.
//var externalReference = new ExternalReference<Texture2DContent>(tileset.Image.Source);
var parameters = new OpaqueDataDictionary
{
{ "ColorKeyColor", tileset.Image.TransparentColor },
{ "ColorKeyEnabled", true }
};
//tileset.Image.ContentRef = context.BuildAsset<Texture2DContent, Texture2DContent>(externalReference, "", parameters, "", "");
contentItem.BuildExternalReference<Texture2DContent>(context, tileset.Image.Source, parameters);
if (tileset.Image is not null)
contentItem.BuildExternalReference<Texture2DContent>(context, tileset.Image);
foreach (var tile in tileset.Tiles)
{
@@ -32,6 +26,8 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
{
TiledMapContentHelper.Process(obj, context);
}
if (tile.Image is not null)
contentItem.BuildExternalReference<Texture2DContent>(context, tile.Image);
}
ContentLogger.Log($"Processed tileset '{tileset.Name}'");
@@ -30,9 +30,9 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
public static void WriteTileset(ContentWriter writer, TiledMapTilesetContent tileset, IExternalReferenceRepository externalReferenceRepository)
{
var externalReference = externalReferenceRepository.GetExternalReference<Texture2DContent>(tileset.Image.Source);
var externalReference = externalReferenceRepository.GetExternalReference<Texture2DContent>(tileset.Image?.Source);
writer.WriteExternalReference(externalReference);
writer.Write(tileset.TileWidth);
writer.Write(tileset.TileHeight);
writer.Write(tileset.TileCount);
@@ -42,13 +42,17 @@ namespace MonoGame.Extended.Content.Pipeline.Tiled
writer.Write(tileset.Tiles.Count);
foreach (var tilesetTile in tileset.Tiles)
WriteTilesetTile(writer, tilesetTile);
WriteTilesetTile(writer, tilesetTile, externalReferenceRepository);
writer.WriteTiledMapProperties(tileset.Properties);
}
private static void WriteTilesetTile(ContentWriter writer, TiledMapTilesetTileContent tilesetTile)
private static void WriteTilesetTile(ContentWriter writer, TiledMapTilesetTileContent tilesetTile,
IExternalReferenceRepository externalReferenceRepository)
{
var externalReference = externalReferenceRepository.GetExternalReference<Texture2DContent>(tilesetTile.Image?.Source);
writer.WriteExternalReference(externalReference);
writer.Write(tilesetTile.LocalIdentifier);
writer.Write(tilesetTile.Type);
writer.Write(tilesetTile.Frames.Count);
@@ -52,12 +52,16 @@ namespace MonoGame.Extended.Tiled.Renderers
var tileGid = tile.GlobalIdentifier;
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);
var sourceRectangle = tileset.GetTileRegion(localTileIdentifier);
var flipFlags = tile.Flags;
// animated tiles
var tilesetTile = tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier);
if (tilesetTile?.Texture is not null)
{
position.Y += map.TileHeight - sourceRectangle.Height;
texture = tilesetTile.Texture;
}
if (tilesetTile is TiledMapTilesetAnimatedTile animatedTilesetTile)
{
@@ -117,4 +121,4 @@ namespace MonoGame.Extended.Tiled.Renderers
}
}
}
}
}
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.TextureAtlases;
@@ -58,7 +59,10 @@ namespace MonoGame.Extended.Tiled
public Rectangle GetTileRegion(int localTileIdentifier)
{
return TiledMapHelper.GetTileSourceRectangle(localTileIdentifier, TileWidth, TileHeight, Columns, Margin, Spacing);
return Texture is not null
? TiledMapHelper.GetTileSourceRectangle(localTileIdentifier, TileWidth, TileHeight, Columns, Margin,
Spacing)
: Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier).Texture.Bounds;
}
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Tiled
{
@@ -12,8 +13,9 @@ namespace MonoGame.Extended.Tiled
public ReadOnlyCollection<TiledMapTilesetTileAnimationFrame> AnimationFrames { get; }
public TiledMapTilesetTileAnimationFrame CurrentAnimationFrame { get; private set; }
public TiledMapTilesetAnimatedTile(int localTileIdentifier, TiledMapTilesetTileAnimationFrame[] frames, string type = null, TiledMapObject[] objects = null)
: base(localTileIdentifier, type, objects)
public TiledMapTilesetAnimatedTile(int localTileIdentifier,
TiledMapTilesetTileAnimationFrame[] frames, string type = null, TiledMapObject[] objects = null, Texture2D texture = null)
: base(localTileIdentifier, type, objects, texture)
{
if (frames.Length == 0) throw new InvalidOperationException("There must be at least one tileset animation frame");
@@ -33,4 +35,4 @@ namespace MonoGame.Extended.Tiled
CurrentAnimationFrame = AnimationFrames[_frameIndex];
}
}
}
}
@@ -29,25 +29,35 @@ namespace MonoGame.Extended.Tiled
var tileset = new TiledMapTileset(texture, 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);
}
ReadTile(reader, tileset);
ReadProperties(reader, tileset.Properties);
return tileset;
}
private static TiledMapTilesetTileAnimationFrame[] ReadTiledMapTilesetAnimationFrames(ContentReader reader, TiledMapTileset tileset, int animationFramesCount)
private static void ReadTile(ContentReader reader, TiledMapTileset tileset)
{
var texture = reader.ReadExternalReference<Texture2D>();
var localTileIdentifier = reader.ReadInt32();
var type = reader.ReadString();
var animationFramesCount = reader.ReadInt32();
var objectCount = reader.ReadInt32();
var objects = new TiledMapObject[objectCount];
for (var i = 0; i < objectCount; i++)
objects[i] = ReadTiledMapObject(reader, tileset);
var tilesetTile = animationFramesCount <= 0
? new TiledMapTilesetTile(localTileIdentifier, type, objects, texture)
: new TiledMapTilesetAnimatedTile(localTileIdentifier,
ReadTiledMapTilesetAnimationFrames(reader, tileset, animationFramesCount), type, objects, texture);
ReadProperties(reader, tilesetTile.Properties);
tileset.Tiles.Add(tilesetTile);
}
private static TiledMapTilesetTileAnimationFrame[] ReadTiledMapTilesetAnimationFrames(ContentReader reader, TiledMapTileset tileset, int animationFramesCount)
{
var animationFrames = new TiledMapTilesetTileAnimationFrame[animationFramesCount];
@@ -64,6 +74,7 @@ namespace MonoGame.Extended.Tiled
private static TiledMapTilesetTile ReadTiledMapTilesetTile(ContentReader reader, TiledMapTileset tileset, Func<TiledMapObject[], TiledMapTilesetTile> createTile)
{
var texture = reader.ReadExternalReference<Texture2D>();
var objectCount = reader.ReadInt32();
var objects = new TiledMapObject[objectCount];
@@ -1,12 +1,15 @@
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Tiled
{
[DebuggerDisplay("{LocalTileIdentifier}: Type: {Type}, Properties: {Properties.Count}, Objects: {Objects.Count}")]
public class TiledMapTilesetTile
{
public TiledMapTilesetTile(int localTileIdentifier, string type = null, TiledMapObject[] objects = null)
// For remove libraries
public TiledMapTilesetTile(int localTileIdentifier, string type = null,
TiledMapObject[] objects = null)
{
LocalTileIdentifier = localTileIdentifier;
Type = type;
@@ -14,9 +17,20 @@ namespace MonoGame.Extended.Tiled
Properties = new TiledMapProperties();
}
public TiledMapTilesetTile(int localTileIdentifier, string type = null,
TiledMapObject[] objects = null, Texture2D texture = null)
{
Texture = texture;
LocalTileIdentifier = localTileIdentifier;
Type = type;
Objects = objects != null ? new List<TiledMapObject>(objects) : new List<TiledMapObject>();
Properties = new TiledMapProperties();
}
public int LocalTileIdentifier { get; }
public string Type { get; }
public TiledMapProperties Properties { get; }
public List<TiledMapObject> Objects { get; }
public Texture2D Texture { get; }
}
}
}