summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Serialization/TiledMapLayerModelContent.cs
blob: 4c2a761b9af4bdb6da14a33ef13ce8bfa053766b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MonoGame.Extended.Tiled.Serialization
{
    public class TiledMapLayerModelContent
    {
        private readonly List<VertexPositionTexture> _vertices;
        private readonly List<ushort> _indices;

        public string LayerName { get; }
        public ReadOnlyCollection<VertexPositionTexture> Vertices { get; }
        public ReadOnlyCollection<ushort> Indices { get; }
        public Size2 ImageSize { get; }
        public string TextureAssetName { get; }

        public TiledMapLayerModelContent(string layerName, TiledMapImageContent image)
        {
            LayerName = layerName;
            _vertices = new List<VertexPositionTexture>();
            Vertices = new ReadOnlyCollection<VertexPositionTexture>(_vertices);
            _indices = new List<ushort>();
            Indices = new ReadOnlyCollection<ushort>(_indices);
            ImageSize = new Size2(image.Width, image.Height);
            TextureAssetName = Path.ChangeExtension(image.Source, null);
        }

        public TiledMapLayerModelContent(string layerName, TiledMapTilesetContent tileset)
            : this(layerName, tileset.Image)
        {
        }

        public void AddTileVertices(Point2 position, Rectangle? sourceRectangle = null, TiledMapTileFlipFlags flags = TiledMapTileFlipFlags.None)
        {
            float texelLeft, texelTop, texelRight, texelBottom;
            var sourceRectangle1 = sourceRectangle ?? new Rectangle(0, 0, (int)ImageSize.Width, (int)ImageSize.Height);

            if (sourceRectangle.HasValue)
            {
                var reciprocalWidth = 1f / ImageSize.Width;
                var reciprocalHeight = 1f / ImageSize.Height;
                texelLeft = sourceRectangle1.X * reciprocalWidth;
                texelTop = sourceRectangle1.Y * reciprocalHeight;
                texelRight = (sourceRectangle1.X + sourceRectangle1.Width) * reciprocalWidth;
                texelBottom = (sourceRectangle1.Y + sourceRectangle1.Height) * reciprocalHeight;
            }
            else
            {
                texelLeft = 0;
                texelTop = 0;
                texelBottom = 1;
                texelRight = 1;
            }

            VertexPositionTexture vertexTopLeft, vertexTopRight, vertexBottomLeft, vertexBottomRight;

            vertexTopLeft.Position = new Vector3(position, 0);
            vertexTopRight.Position = new Vector3(position + new Vector2(sourceRectangle1.Width, 0), 0);
            vertexBottomLeft.Position = new Vector3(position + new Vector2(0, sourceRectangle1.Height), 0);
            vertexBottomRight.Position =
                new Vector3(position + new Vector2(sourceRectangle1.Width, sourceRectangle1.Height), 0);

            vertexTopLeft.TextureCoordinate.Y = texelTop;
            vertexTopLeft.TextureCoordinate.X = texelLeft;

            vertexTopRight.TextureCoordinate.Y = texelTop;
            vertexTopRight.TextureCoordinate.X = texelRight;

            vertexBottomLeft.TextureCoordinate.Y = texelBottom;
            vertexBottomLeft.TextureCoordinate.X = texelLeft;

            vertexBottomRight.TextureCoordinate.Y = texelBottom;
            vertexBottomRight.TextureCoordinate.X = texelRight;

            var flipDiagonally = (flags & TiledMapTileFlipFlags.FlipDiagonally) != 0;
            var flipHorizontally = (flags & TiledMapTileFlipFlags.FlipHorizontally) != 0;
            var flipVertically = (flags & TiledMapTileFlipFlags.FlipVertically) != 0;

            if (flipDiagonally)
            {
                FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.X, ref vertexBottomLeft.TextureCoordinate.X);
                FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.Y, ref vertexBottomLeft.TextureCoordinate.Y);
            }

            if (flipHorizontally)
            {
                if (flipDiagonally)
                {
                    FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.Y, ref vertexTopRight.TextureCoordinate.Y);
                    FloatHelper.Swap(ref vertexBottomLeft.TextureCoordinate.Y, ref vertexBottomRight.TextureCoordinate.Y);
                }
                else
                {
                    FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.X, ref vertexTopRight.TextureCoordinate.X);
                    FloatHelper.Swap(ref vertexBottomLeft.TextureCoordinate.X, ref vertexBottomRight.TextureCoordinate.X);
                }
            }

            if (flipVertically)
                if (flipDiagonally)
                {
                    FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.X, ref vertexBottomLeft.TextureCoordinate.X);
                    FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.X, ref vertexBottomRight.TextureCoordinate.X);
                }
                else
                {
                    FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.Y, ref vertexBottomLeft.TextureCoordinate.Y);
                    FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.Y, ref vertexBottomRight.TextureCoordinate.Y);
                }

            _vertices.Add(vertexTopLeft);
            _vertices.Add(vertexTopRight);
            _vertices.Add(vertexBottomLeft);
            _vertices.Add(vertexBottomRight);

            Debug.Assert(Vertices.Count <= TiledMapHelper.MaximumVerticesPerModel);
        }

        public void AddTileIndices()
        {
            var indexOffset = Vertices.Count;

            Debug.Assert(3 + indexOffset <= TiledMapHelper.MaximumVerticesPerModel);

            _indices.Add((ushort)(0 + indexOffset));
            _indices.Add((ushort)(1 + indexOffset));
            _indices.Add((ushort)(2 + indexOffset));
            _indices.Add((ushort)(1 + indexOffset));
            _indices.Add((ushort)(3 + indexOffset));
            _indices.Add((ushort)(2 + indexOffset));

            Debug.Assert(Indices.Count <= TiledMapHelper.MaximumIndicesPerModel);
        }
    }
}