2
0
Эх сурвалжийг харах

Support external tileset
Change namespace

Nick Kastellanos 4 жил өмнө
parent
commit
3d48deaf30

+ 1 - 1
Atlas/Aether.Atlas.PORTABLE.csproj

@@ -6,7 +6,7 @@
     <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
     <ProjectGuid>{E5907795-BC19-4CAA-9909-9F7145E1BB0D}</ProjectGuid>
     <OutputType>Library</OutputType>
-    <RootNamespace>tainicom.Aether.Atlas</RootNamespace>
+    <RootNamespace>tainicom.Aether.Graphics</RootNamespace>
     <AssemblyName>Aether.Atlas</AssemblyName>
     <TargetFrameworkProfile>Profile328</TargetFrameworkProfile>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>

+ 1 - 1
Atlas/Aether.Atlas.WINDOWS.MG.csproj

@@ -7,7 +7,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <OutputType>Library</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>tainicom.Aether.Atlas</RootNamespace>
+    <RootNamespace>tainicom.Aether.Graphics</RootNamespace>
     <AssemblyName>Aether.Atlas</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <TargetFrameworkProfile>Client</TargetFrameworkProfile>

+ 1 - 1
Atlas/Aether.Atlas.WINDOWS.XNA.csproj

@@ -7,7 +7,7 @@
     <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
     <OutputType>Library</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>tainicom.Aether.Atlas</RootNamespace>
+    <RootNamespace>tainicom.Aether.Graphics</RootNamespace>
     <AssemblyName>Aether.Atlas</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <TargetFrameworkProfile>Client</TargetFrameworkProfile>

+ 4 - 4
Atlas/Atlas/Extensions.cs

@@ -1,5 +1,5 @@
 #region License
-//   Copyright 2016 Kastellanos Nikolaos
+//   Copyright 2016-2021 Kastellanos Nikolaos
 //
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
 #endregion
 
 using Microsoft.Xna.Framework;
-using tainicom.Aether.Atlas;
+using tainicom.Aether.Graphics;
 
 namespace Microsoft.Xna.Framework.Graphics
 {
@@ -23,12 +23,12 @@ namespace Microsoft.Xna.Framework.Graphics
     {
         public static void Draw(this SpriteBatch spriteBatch, Sprite sprite, Vector2 position, Color color)
         {
-            spriteBatch.Draw(sprite.Texture, position, sprite.SourceRectangle, color);         
+            spriteBatch.Draw(sprite.Texture, position, sprite.Bounds, color);
         }
         
         public static void Draw(this SpriteBatch spriteBatch, Sprite sprite, Rectangle destinationRectangle, Color color)
         {
-            spriteBatch.Draw(sprite.Texture, destinationRectangle, sprite.SourceRectangle, color);
+            spriteBatch.Draw(sprite.Texture, destinationRectangle, sprite.Bounds, color);
         }
     }
 }

+ 5 - 5
Atlas/Atlas/Sprite.cs

@@ -1,5 +1,5 @@
 #region License
-//   Copyright 2016 Kastellanos Nikolaos
+//   Copyright 2016-2021 Kastellanos Nikolaos
 //
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -17,17 +17,17 @@
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Graphics;
 
-namespace tainicom.Aether.Atlas
+namespace tainicom.Aether.Graphics
 {
     public class Sprite
     {
         public readonly Texture2D Texture;
-        public readonly Rectangle SourceRectangle;
+        public readonly Rectangle Bounds;
 
-        internal Sprite(Texture2D texture, Rectangle sourceRectangle)
+        internal Sprite(Texture2D texture, Rectangle bounds)
         {
             this.Texture = texture;
-            this.SourceRectangle = sourceRectangle;
+            this.Bounds = bounds;
         }
     }
 }

+ 4 - 3
Atlas/Atlas/TextureAtlas.cs

@@ -1,5 +1,5 @@
 #region License
-//   Copyright 2016 Kastellanos Nikolaos
+//   Copyright 2016-2021 Kastellanos Nikolaos
 //
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -17,12 +17,13 @@
 using System.Collections.Generic;
 using Microsoft.Xna.Framework.Graphics;
 
-namespace tainicom.Aether.Atlas
+namespace tainicom.Aether.Graphics
 {
     public class TextureAtlas
     {
-        public Texture2D Texture {get; internal set;}
+        public Texture2D Texture { get; internal set; }
         public readonly Dictionary<string, Sprite> Sprites;
+
         internal TextureAtlas()
         {
             this.Sprites = new Dictionary<string, Sprite>();

+ 4 - 4
Atlas/ContentReaders/TextureAtlasReader.cs

@@ -1,5 +1,5 @@
 #region License
-//   Copyright 2016-2019 Kastellanos Nikolaos
+//   Copyright 2016-2021 Kastellanos Nikolaos
 //
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ using System;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Content;
 using Microsoft.Xna.Framework.Graphics;
-using tainicom.Aether.Atlas;
+using tainicom.Aether.Graphics;
 
 namespace tainicom.Aether.Graphics.Content
 {
@@ -40,8 +40,8 @@ namespace tainicom.Aether.Graphics.Content
             for (int i = 0; i < count; i++)
             {
                 var name = input.ReadString();
-                var destinationRect = new Rectangle(input.ReadInt32(), input.ReadInt32(), input.ReadInt32(), input.ReadInt32());
-                output.Sprites[name] = new Sprite(output.Texture, destinationRect);
+                var bounds = new Rectangle(input.ReadInt32(), input.ReadInt32(), input.ReadInt32(), input.ReadInt32());
+                output.Sprites[name] = new Sprite(output.Texture, bounds);
             }
 
             return output;

+ 0 - 27
Content.Pipeline/AtlasImporter/Atlas/SourceContent.cs

@@ -1,27 +0,0 @@
-#region License
-//   Copyright 2016 Kastellanos Nikolaos
-//
-//   Licensed under the Apache License, Version 2.0 (the "License");
-//   you may not use this file except in compliance with the License.
-//   You may obtain a copy of the License at
-//
-//       http://www.apache.org/licenses/LICENSE-2.0
-//
-//   Unless required by applicable law or agreed to in writing, software
-//   distributed under the License is distributed on an "AS IS" BASIS,
-//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//   See the License for the specific language governing permissions and
-//   limitations under the License.
-#endregion
-
-using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
-
-namespace tainicom.Aether.Content.Pipeline.Atlas
-{
-    public class SourceContent
-    {
-        public TextureContent Texture;
-        public int Width;
-        public int Height;
-    }
-}

+ 14 - 2
Content.Pipeline/AtlasImporter/Atlas/SpriteContent.cs

@@ -17,12 +17,24 @@
 
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
+
 namespace tainicom.Aether.Content.Pipeline
 {
     public class SpriteContent
     {
         public TextureContent Texture;
-        public Rectangle DestinationRectangle;
-        public string Name;
+        public Rectangle Bounds;
+
+        public SpriteContent()
+        {
+            this.Texture = null;
+            this.Bounds = Rectangle.Empty;
+        }
+
+        public SpriteContent(SpriteContent other)
+        {
+            this.Texture = other.Texture;
+            this.Bounds = other.Bounds;
+        }
     }
 }

+ 17 - 4
Content.Pipeline/AtlasImporter/Atlas/TextureAtlasContent.cs

@@ -15,15 +15,28 @@
 #endregion
 
 using System.Collections.Generic;
+using Microsoft.Xna.Framework.Content.Pipeline;
 using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
 
-namespace tainicom.Aether.Content.Pipeline.Atlas
+namespace tainicom.Aether.Content.Pipeline
 {
     public class TextureAtlasContent : Texture2DContent
     {
-        public int Width, Height;
+        public Texture2DContent Texture { get { return this; } }
+        public readonly Dictionary<string, SpriteContent> Sprites = new Dictionary<string, SpriteContent>();
 
-        public List<SourceContent> Textures = new List<SourceContent>();
-        public List<SpriteContent> Sprites = new List<SpriteContent>();
+        internal readonly List<SpriteContent> SourceSprites = new List<SpriteContent>();
+        internal readonly List<SpriteContent> DestinationSprites = new List<SpriteContent>();
+
+        internal int MapColumns, MapRows;
+        internal int TileWidth, TileHeight;
+        internal int Width, Height;
+
+        internal string Renderorder;
+        internal int Firstgid;
+        internal int LayerColumns, LayerRows;
+        internal int[] MapData;
+        
+        
     }
 }

+ 0 - 1
Content.Pipeline/AtlasImporter/AtlasImporter.WINDOWS.MG.csproj

@@ -46,7 +46,6 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AtlasImporter.cs" />
-    <Compile Include="Atlas\SourceContent.cs" />
     <Compile Include="Atlas\TextureAtlasContent.cs" />
     <Compile Include="Atlas\SpriteContent.cs" />
     <Compile Include="Processors\TextureAtlasProcessor.cs" />

+ 0 - 1
Content.Pipeline/AtlasImporter/AtlasImporter.WINDOWS.XNA.csproj

@@ -44,7 +44,6 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AtlasImporter.cs" />
-    <Compile Include="Atlas\SourceContent.cs" />
     <Compile Include="Atlas\TextureAtlasContent.cs" />
     <Compile Include="Atlas\SpriteContent.cs" />
     <Compile Include="Processors\TextureAtlasProcessor.cs" />

+ 98 - 64
Content.Pipeline/AtlasImporter/AtlasImporter.cs

@@ -23,7 +23,6 @@ using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Content.Pipeline;
 using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
 using Microsoft.Xna.Framework.Graphics;
-using tainicom.Aether.Content.Pipeline.Atlas;
 
 namespace tainicom.Aether.Content.Pipeline
 {
@@ -39,6 +38,7 @@ namespace tainicom.Aether.Content.Pipeline
             else
                 throw new InvalidContentException("File type not supported");
 
+            PackSprites(output);
             RenderAtlas(output);
             
             return output;
@@ -56,45 +56,81 @@ namespace tainicom.Aether.Content.Pipeline
             var orientation = GetAttribute(map, "orientation");
             if (orientation != "orthogonal")
                 throw new InvalidContentException("Invalid orientation. Only 'orthogonal' is supported for atlases.");
-            var renderorder = GetAttribute(map, "renderorder");
-            var mapColumns = GetAttributeAsInt(map, "width").Value;
-            var mapRows = GetAttributeAsInt(map, "height").Value;
-            var tileWidth = GetAttributeAsInt(map, "tilewidth").Value;
-            var tileHeight = GetAttributeAsInt(map, "tileheight").Value;
-            output.Width = mapColumns * tileWidth;
-            output.Height = mapRows * tileHeight;
-            
+            output.Renderorder = GetAttribute(map, "renderorder");
+            output.MapColumns = GetAttributeAsInt(map, "width").Value;
+            output.MapRows = GetAttributeAsInt(map, "height").Value;
+            output.TileWidth = GetAttributeAsInt(map, "tilewidth").Value;
+            output.TileHeight = GetAttributeAsInt(map, "tileheight").Value;
+            output.Width = output.MapColumns * output.TileWidth;
+            output.Height = output.MapRows * output.TileHeight;
+
             XmlNode tileset = map["tileset"];
+            output.Firstgid = GetAttributeAsInt(tileset, "firstgid").Value;
+
             if (tileset.Attributes["source"] != null)
-                throw new InvalidContentException("External Tileset is not supported.");
+            {
+                var tsxFilename = tileset.Attributes["source"].Value;
+                var baseDirectory = Path.GetDirectoryName(filename);
+                tsxFilename = Path.Combine(baseDirectory, tsxFilename);
+                var sourceSprites = ImportTSX(tsxFilename, context);
+                output.SourceSprites.AddRange(sourceSprites);
+                context.AddDependency(tsxFilename);
+            }
+            else
+            {
+                var rootDirectory = Path.GetDirectoryName(filename);
+                var sourceSprites = ImportTileset(tileset, context, rootDirectory);
+                output.SourceSprites.AddRange(sourceSprites);
+            }
+
+            XmlNode layerNode = map["layer"];
+            var layerColumns = Convert.ToInt32(map.Attributes["width"].Value, CultureInfo.InvariantCulture);
+            var layerRows = Convert.ToInt32(map.Attributes["height"].Value, CultureInfo.InvariantCulture);
+            output.LayerColumns = layerColumns;
+            output.LayerRows = layerRows;
+
+            XmlNode layerDataNode = layerNode["data"];
+            var encoding = layerDataNode.Attributes["encoding"].Value;
+            if (encoding != "csv")
+                throw new InvalidContentException("Invalid encoding. Only 'csv' is supported for data.");
+            var data = layerDataNode.InnerText;
+            var dataStringList = data.Split(',');
+            var mapData = new int[dataStringList.Length];
+            for (int i = 0; i < dataStringList.Length; i++)
+                mapData[i] = Convert.ToInt32(dataStringList[i].Trim(), CultureInfo.InvariantCulture);
+            output.MapData = mapData;
+
+            return output;
+        }
+
+        private static List<SpriteContent> ImportTileset(XmlNode tileset, ContentImporterContext context, string baseDirectory)
+        {
+            List<SpriteContent> images = new List<SpriteContent>();
+
             if (tileset["tileoffset"] != null)
                 throw new InvalidContentException("tileoffset is not supported.");
-            var firstgid = GetAttributeAsInt(tileset, "firstgid").Value;
 
-            Dictionary<int, SourceContent> images = new Dictionary<int, SourceContent>();
-            TextureImporter txImporter = new TextureImporter();
-            
             foreach (XmlNode tileNode in tileset.ChildNodes)
             {
                 if (tileNode.Name != "tile") continue;
                 var tileId = GetAttributeAsInt(tileNode, "id").Value;
+                if (tileId != images.Count)
+                    throw new InvalidContentException("Invalid id");
                 XmlNode imageNode = tileNode["image"];
-                
-                var source = new SourceContent();
+
 
                 //var format = GetAttribute(imageNode, "format");
                 var imageSource = GetAttribute(imageNode, "source");
-                var fullImageSource = Path.Combine(Path.GetDirectoryName(filename), imageSource);
+                var fullImageSource = Path.Combine(baseDirectory, imageSource);
+                TextureImporter txImporter = new TextureImporter();
                 var textureContent = (Texture2DContent)txImporter.Import(fullImageSource, context);
                 textureContent.Name = Path.GetFileNameWithoutExtension(fullImageSource);
 
+                var source = new SpriteContent();
                 source.Texture = textureContent;
-
-                var width = GetAttributeAsInt(imageNode, "width");
-                var height = GetAttributeAsInt(imageNode, "height");
-
-                source.Width = width ?? textureContent.Mipmaps[0].Width;
-                source.Height = height ?? textureContent.Mipmaps[0].Height;
+                source.Bounds.Location = Point.Zero;
+                source.Bounds.Width  = textureContent.Mipmaps[0].Width;
+                source.Bounds.Height = textureContent.Mipmaps[0].Height;
 
                 var transKeyColor = GetAttributeAsColor(imageNode, "trans");
                 if (transKeyColor != null)
@@ -102,64 +138,62 @@ namespace tainicom.Aether.Content.Pipeline
                         foreach (var mip in mips)
                             ((PixelBitmapContent<Color>)mip).ReplaceColor(transKeyColor.Value, Color.Transparent);
 
-                images.Add(firstgid + tileId, source);
+                images.Add(source);
             }
 
-            output.Textures.AddRange(images.Values);
-            
-            XmlNode layerNode = map["layer"];
-            var layerColumns = Convert.ToInt32(map.Attributes["width"].Value, CultureInfo.InvariantCulture);
-            var layerRows = Convert.ToInt32(map.Attributes["height"].Value, CultureInfo.InvariantCulture);
+            return images;
+        }
 
-            XmlNode layerDataNode = layerNode["data"];
-            var encoding = layerDataNode.Attributes["encoding"].Value;
-            if (encoding!="csv")
-                throw new InvalidContentException("Invalid encoding. Only 'csv' is supported for data.");
-            var data = layerDataNode.InnerText;
-            var dataList = data.Split(',');
-            for (int i = 0; i < dataList.Length; i++)
-                dataList[i] = dataList[i].Trim();
-            
-            for(int y=0;y<layerRows;y++)
+        private static void PackSprites(TextureAtlasContent output)
+        {
+            for (int y = 0; y < output.LayerRows; y++)
             {
-                for(int x=0;x<layerColumns;x++ )
+                for (int x = 0; x < output.LayerColumns; x++)
                 {
-                    var posX = x * tileWidth;
-                    var posY = y * tileHeight;
-                    
-                    var tilegId = Convert.ToInt32(dataList[y * layerColumns + x], CultureInfo.InvariantCulture);
-                    SourceContent image; 
-                    if (!images.TryGetValue(tilegId, out image))
-                        continue;
-
-                    if (renderorder == "right-down" || renderorder == "right-up")
-                        posX += (tileWidth - image.Width);
-                    if (renderorder == "right-down" || renderorder == "left-down")
-                        posY += (tileHeight - image.Height);
-
-                    var sprite = new SpriteContent();
-                    sprite.Name = image.Texture.Name;
-                    sprite.Texture = image.Texture;
-                    sprite.DestinationRectangle = new Rectangle(posX, posY, image.Width, image.Height);
-
-                    output.Sprites.Add(sprite);
+                    var posX = x * output.TileWidth;
+                    var posY = y * output.TileHeight;
+
+                    var tilegId = output.MapData[y * output.LayerColumns + x];
+                    if (tilegId == 0) continue;
+                    tilegId -= output.Firstgid;
+
+                    SpriteContent srcSprite = output.SourceSprites[tilegId];
+
+                    if (output.Renderorder == "right-down" || output.Renderorder == "right-up")
+                        posX += (output.TileWidth - srcSprite.Bounds.Width);
+                    if (output.Renderorder == "right-down" || output.Renderorder == "left-down")
+                        posY += (output.TileHeight - srcSprite.Bounds.Height);
+
+                    var newSprite = new SpriteContent(srcSprite);
+                    newSprite.Bounds.Location = new Point(posX, posY);
+
+                    output.DestinationSprites.Add(newSprite);
+                    var name = srcSprite.Texture.Name;
+                    output.Sprites.Add(name, newSprite);
                 }
             }
-            
-            return output;
+        }
+
+        private static List<SpriteContent> ImportTSX(string tsxFilename, ContentImporterContext context)
+        {
+            XmlDocument xmlDoc = new XmlDocument();
+            xmlDoc.Load(tsxFilename);
+            XmlNode tileset = xmlDoc.DocumentElement;
+            var baseDirectory = Path.GetDirectoryName(tsxFilename);
+            return ImportTileset(tileset, context, baseDirectory);
         }
 
         private static void RenderAtlas(TextureAtlasContent output)
         {
             var outputBmp = new PixelBitmapContent<Color>(output.Width, output.Height);
-            foreach (var sprite in output.Sprites)
+            foreach (var sprite in output.DestinationSprites)
             {
                 var srcBmp = sprite.Texture.Faces[0][0];
                 var srcRect = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height);
-                BitmapContent.Copy(srcBmp, srcRect, outputBmp, sprite.DestinationRectangle);
+                BitmapContent.Copy(srcBmp, srcRect, outputBmp, sprite.Bounds);
             }
             var mipmapChain = new MipmapChain(outputBmp);
-            output.Mipmaps = mipmapChain;
+            output.Texture.Mipmaps = mipmapChain;
         }
         
         private static string GetAttribute(XmlNode xmlNode, string attributeName)

+ 10 - 11
Content.Pipeline/AtlasImporter/Processors/TextureAtlasProcessor.cs

@@ -20,7 +20,6 @@ using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Content.Pipeline;
 using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
 using Microsoft.Xna.Framework.Content.Pipeline.Processors;
-using tainicom.Aether.Content.Pipeline.Atlas;
 
 namespace tainicom.Aether.Content.Pipeline
 {
@@ -61,7 +60,7 @@ namespace tainicom.Aether.Content.Pipeline
         public TextureAtlasContent Process(TextureAtlasContent input, ContentProcessorContext context)
         {
             if (MipmapsPerSprite && GenerateMipmaps)
-                foreach (var texture in input.Textures)
+                foreach (var texture in input.SourceSprites)
                     texture.Texture.GenerateMipmaps(false);
 
             var output = input;
@@ -72,7 +71,7 @@ namespace tainicom.Aether.Content.Pipeline
                 {
                     var maxSpriteWidth = 1;
                     var maxSpriteHeight = 1;
-                    foreach (var sprite in input.Textures)
+                    foreach (var sprite in input.SourceSprites)
                     {
                         var face0 = sprite.Texture.Faces[0];
                         maxSpriteWidth = Math.Max(maxSpriteWidth, face0[0].Width);
@@ -89,12 +88,12 @@ namespace tainicom.Aether.Content.Pipeline
                         if ((maxSpriteWidth / mipLevel2) < 1 && (maxSpriteHeight / mipLevel2) < 1) break;
 
                         var mipmapBmp = new PixelBitmapContent<Color>(size.Width, size.Height);
-                        foreach (var sprite in input.Sprites)
+                        foreach (var sprite in input.DestinationSprites)
                         {
                             if (mipLevel >= sprite.Texture.Faces[0].Count) continue;
                             var srcBmp = sprite.Texture.Faces[0][mipLevel];
                             var srcRect = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height);
-                            var destRect = sprite.DestinationRectangle;
+                            var destRect = sprite.Bounds;
                             destRect.X = (int)Math.Ceiling((float)destRect.X / mipLevel2);
                             destRect.Y = (int)Math.Ceiling((float)destRect.Y / mipLevel2);
                             destRect.Width = (int)(destRect.Width / mipLevel2);
@@ -102,10 +101,10 @@ namespace tainicom.Aether.Content.Pipeline
                             if (destRect.Width > 1 && destRect.Height > 1)
                                 BitmapContent.Copy(srcBmp, srcRect, mipmapBmp, destRect);
                         }
-                        output.Mipmaps.Add(mipmapBmp);
+                        output.Texture.Mipmaps.Add(mipmapBmp);
                     }
 
-                    var outputFace0 = output.Faces[0];
+                    var outputFace0 = output.Texture.Faces[0];
                     while (outputFace0[outputFace0.Count - 1].Width > 1 || outputFace0[outputFace0.Count - 1].Height > 1)
                     {
                         var lastMipmap = outputFace0[outputFace0.Count - 1];
@@ -113,12 +112,12 @@ namespace tainicom.Aether.Content.Pipeline
                         var h = Math.Max(1, lastMipmap.Height/2);
                         var mipmapBmp = new PixelBitmapContent<Color>(w, h);
                         //PixelBitmapContent<Color>.Copy(lastMipmap, mipmapBmp);
-                        output.Mipmaps.Add(mipmapBmp);
+                        output.Texture.Mipmaps.Add(mipmapBmp);
                     }
                 }
                 else
                 {
-                    output.GenerateMipmaps(false);
+                    output.Texture.GenerateMipmaps(false);
                 }
             }
             
@@ -127,12 +126,12 @@ namespace tainicom.Aether.Content.Pipeline
             if (MipmapsPerSprite && GenerateMipmaps)
             {
                 GenerateMipmaps = false;
-                base.Process(output, context);
+                base.Process(output.Texture, context);
                 GenerateMipmaps = true;
             }
             else
             {
-                base.Process(output, context);
+                base.Process(output.Texture, context);
             }
             
             return output;

+ 10 - 10
Content.Pipeline/AtlasImporter/Serialization/TextureAtlasWriter.cs

@@ -14,12 +14,11 @@
 //   limitations under the License.
 #endregion
 
+using System;
 using Microsoft.Xna.Framework.Content.Pipeline;
 using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
 using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
-using tainicom.Aether.Content.Pipeline.Atlas;
 using Microsoft.Xna.Framework.Graphics;
-using System;
 
 namespace tainicom.Aether.Content.Pipeline.Serialization
 {
@@ -28,17 +27,18 @@ namespace tainicom.Aether.Content.Pipeline.Serialization
     {
         protected override void Write(ContentWriter output, TextureAtlasContent atlas)
         {
-            output.WriteRawObject((Texture2DContent)atlas);
+            output.WriteRawObject((Texture2DContent)atlas.Texture);
             
             // write Sprites
-            output.Write(atlas.Sprites.Count);
-            foreach(var sprite in atlas.Sprites)
+            output.Write(atlas.DestinationSprites.Count);
+            foreach(var name in atlas.Sprites.Keys)
             {
-                output.Write(sprite.Name);
-                output.Write(sprite.DestinationRectangle.X);
-                output.Write(sprite.DestinationRectangle.Y);
-                output.Write(sprite.DestinationRectangle.Width);
-                output.Write(sprite.DestinationRectangle.Height);
+                var sprite = atlas.Sprites[name];
+                output.Write(name);
+                output.Write(sprite.Bounds.X);
+                output.Write(sprite.Bounds.Y);
+                output.Write(sprite.Bounds.Width);
+                output.Write(sprite.Bounds.Height);
             }
             
             return;

+ 1 - 1
Samples/Atlas/Game1.cs

@@ -2,7 +2,7 @@ using System;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Graphics;
 using Microsoft.Xna.Framework.Input;
-using tainicom.Aether.Atlas;
+using tainicom.Aether.Graphics;
 
 namespace Samples.Atlas
 {

+ 1 - 89
Samples/AtlasContent/AtlasNoMipmap.tmx

@@ -1,94 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <map version="1.0" orientation="orthogonal" renderorder="right-down" width="8" height="4" tilewidth="128" tileheight="128" nextobjectid="1">
- <tileset firstgid="1" name="1" tilewidth="133" tileheight="128" tilecount="29" columns="0">
-  <tile id="0">
-   <image width="128" height="128" source="Tiles/1.png"/>
-  </tile>
-  <tile id="1">
-   <image width="128" height="128" source="Tiles/2.png"/>
-  </tile>
-  <tile id="2">
-   <image width="128" height="128" source="Tiles/3.png"/>
-  </tile>
-  <tile id="3">
-   <image width="128" height="128" source="Tiles/4.png"/>
-  </tile>
-  <tile id="4">
-   <image width="128" height="128" source="Tiles/5.png"/>
-  </tile>
-  <tile id="5">
-   <image width="128" height="128" source="Tiles/6.png"/>
-  </tile>
-  <tile id="6">
-   <image width="128" height="128" source="Tiles/7.png"/>
-  </tile>
-  <tile id="7">
-   <image width="128" height="128" source="Tiles/8.png"/>
-  </tile>
-  <tile id="8">
-   <image width="128" height="128" source="Tiles/9.png"/>
-  </tile>
-  <tile id="9">
-   <image width="128" height="128" source="Tiles/10.png"/>
-  </tile>
-  <tile id="10">
-   <image width="128" height="128" source="Tiles/11.png"/>
-  </tile>
-  <tile id="11">
-   <image width="128" height="128" source="Tiles/12.png"/>
-  </tile>
-  <tile id="12">
-   <image width="128" height="93" source="Tiles/13.png"/>
-  </tile>
-  <tile id="13">
-   <image width="128" height="93" source="Tiles/14.png"/>
-  </tile>
-  <tile id="14">
-   <image width="128" height="93" source="Tiles/15.png"/>
-  </tile>
-  <tile id="15">
-   <image width="128" height="128" source="Tiles/16.png"/>
-  </tile>
-  <tile id="16">
-   <image width="128" height="99" source="Tiles/17.png"/>
-  </tile>
-  <tile id="17">
-   <image width="128" height="128" source="Tiles/18.png"/>
-  </tile>
-  <tile id="18">
-   <image width="133" height="65" source="Object/Bush_1.png"/>
-  </tile>
-  <tile id="19">
-   <image width="133" height="65" source="Object/Bush_2.png"/>
-  </tile>
-  <tile id="20">
-   <image width="73" height="47" source="Object/Bush_3.png"/>
-  </tile>
-  <tile id="21">
-   <image width="73" height="46" source="Object/Bush_4.png"/>
-  </tile>
-  <tile id="22">
-   <image width="77" height="77" source="Object/Crate.png"/>
-  </tile>
-  <tile id="23">
-   <image width="49" height="41" source="Object/Mushroom_1.png"/>
-  </tile>
-  <tile id="24">
-   <image width="50" height="41" source="Object/Mushroom_2.png"/>
-  </tile>
-  <tile id="25">
-   <image width="63" height="65" source="Object/Sign_1.png"/>
-  </tile>
-  <tile id="26">
-   <image width="62" height="64" source="Object/Sign_2.png"/>
-  </tile>
-  <tile id="27">
-   <image width="90" height="54" source="Object/Stone.png"/>
-  </tile>
-  <tile id="28">
-   <image width="116" height="44" source="Object/Tree_1.png"/>
-  </tile>
- </tileset>
+ <tileset firstgid="1" source="AtlasNoMipmap.tsx"/>
  <layer name="Tile Layer 1" width="8" height="4">
   <data encoding="csv">
 13,14,15,0,0,0,0,0,

+ 90 - 0
Samples/AtlasContent/AtlasNoMipmap.tsx

@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tileset name="1" tilewidth="133" tileheight="128" tilecount="29" columns="0">
+  <tile id="0">
+   <image width="128" height="128" source="Tiles/1.png"/>
+  </tile>
+  <tile id="1">
+   <image width="128" height="128" source="Tiles/2.png"/>
+  </tile>
+  <tile id="2">
+   <image width="128" height="128" source="Tiles/3.png"/>
+  </tile>
+  <tile id="3">
+   <image width="128" height="128" source="Tiles/4.png"/>
+  </tile>
+  <tile id="4">
+   <image width="128" height="128" source="Tiles/5.png"/>
+  </tile>
+  <tile id="5">
+   <image width="128" height="128" source="Tiles/6.png"/>
+  </tile>
+  <tile id="6">
+   <image width="128" height="128" source="Tiles/7.png"/>
+  </tile>
+  <tile id="7">
+   <image width="128" height="128" source="Tiles/8.png"/>
+  </tile>
+  <tile id="8">
+   <image width="128" height="128" source="Tiles/9.png"/>
+  </tile>
+  <tile id="9">
+   <image width="128" height="128" source="Tiles/10.png"/>
+  </tile>
+  <tile id="10">
+   <image width="128" height="128" source="Tiles/11.png"/>
+  </tile>
+  <tile id="11">
+   <image width="128" height="128" source="Tiles/12.png"/>
+  </tile>
+  <tile id="12">
+   <image width="128" height="93" source="Tiles/13.png"/>
+  </tile>
+  <tile id="13">
+   <image width="128" height="93" source="Tiles/14.png"/>
+  </tile>
+  <tile id="14">
+   <image width="128" height="93" source="Tiles/15.png"/>
+  </tile>
+  <tile id="15">
+   <image width="128" height="128" source="Tiles/16.png"/>
+  </tile>
+  <tile id="16">
+   <image width="128" height="99" source="Tiles/17.png"/>
+  </tile>
+  <tile id="17">
+   <image width="128" height="128" source="Tiles/18.png"/>
+  </tile>
+  <tile id="18">
+   <image width="133" height="65" source="Object/Bush_1.png"/>
+  </tile>
+  <tile id="19">
+   <image width="133" height="65" source="Object/Bush_2.png"/>
+  </tile>
+  <tile id="20">
+   <image width="73" height="47" source="Object/Bush_3.png"/>
+  </tile>
+  <tile id="21">
+   <image width="73" height="46" source="Object/Bush_4.png"/>
+  </tile>
+  <tile id="22">
+   <image width="77" height="77" source="Object/Crate.png"/>
+  </tile>
+  <tile id="23">
+   <image width="49" height="41" source="Object/Mushroom_1.png"/>
+  </tile>
+  <tile id="24">
+   <image width="50" height="41" source="Object/Mushroom_2.png"/>
+  </tile>
+  <tile id="25">
+   <image width="63" height="65" source="Object/Sign_1.png"/>
+  </tile>
+  <tile id="26">
+   <image width="62" height="64" source="Object/Sign_2.png"/>
+  </tile>
+  <tile id="27">
+   <image width="90" height="54" source="Object/Stone.png"/>
+  </tile>
+  <tile id="28">
+   <image width="116" height="44" source="Object/Tree_1.png"/>
+  </tile>
+</tileset>

+ 1 - 89
Samples/AtlasContent/atlasMipmap.tmx

@@ -1,94 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <map version="1.0" orientation="orthogonal" renderorder="right-down" width="8" height="4" tilewidth="128" tileheight="128" nextobjectid="1">
- <tileset firstgid="1" name="1" tilewidth="133" tileheight="128" tilecount="29" columns="0">
-  <tile id="0">
-   <image width="128" height="128" source="Tiles/1.png"/>
-  </tile>
-  <tile id="1">
-   <image width="128" height="128" source="Tiles/2.png"/>
-  </tile>
-  <tile id="2">
-   <image width="128" height="128" source="Tiles/3.png"/>
-  </tile>
-  <tile id="3">
-   <image width="128" height="128" source="Tiles/4.png"/>
-  </tile>
-  <tile id="4">
-   <image width="128" height="128" source="Tiles/5.png"/>
-  </tile>
-  <tile id="5">
-   <image width="128" height="128" source="Tiles/6.png"/>
-  </tile>
-  <tile id="6">
-   <image width="128" height="128" source="Tiles/7.png"/>
-  </tile>
-  <tile id="7">
-   <image width="128" height="128" source="Tiles/8.png"/>
-  </tile>
-  <tile id="8">
-   <image width="128" height="128" source="Tiles/9.png"/>
-  </tile>
-  <tile id="9">
-   <image width="128" height="128" source="Tiles/10.png"/>
-  </tile>
-  <tile id="10">
-   <image width="128" height="128" source="Tiles/11.png"/>
-  </tile>
-  <tile id="11">
-   <image width="128" height="128" source="Tiles/12.png"/>
-  </tile>
-  <tile id="12">
-   <image width="128" height="93" source="Tiles/13.png"/>
-  </tile>
-  <tile id="13">
-   <image width="128" height="93" source="Tiles/14.png"/>
-  </tile>
-  <tile id="14">
-   <image width="128" height="93" source="Tiles/15.png"/>
-  </tile>
-  <tile id="15">
-   <image width="128" height="128" source="Tiles/16.png"/>
-  </tile>
-  <tile id="16">
-   <image width="128" height="99" source="Tiles/17.png"/>
-  </tile>
-  <tile id="17">
-   <image width="128" height="128" source="Tiles/18.png"/>
-  </tile>
-  <tile id="18">
-   <image width="133" height="65" source="Object/Bush_1.png"/>
-  </tile>
-  <tile id="19">
-   <image width="133" height="65" source="Object/Bush_2.png"/>
-  </tile>
-  <tile id="20">
-   <image width="73" height="47" source="Object/Bush_3.png"/>
-  </tile>
-  <tile id="21">
-   <image width="73" height="46" source="Object/Bush_4.png"/>
-  </tile>
-  <tile id="22">
-   <image width="77" height="77" source="Object/Crate.png"/>
-  </tile>
-  <tile id="23">
-   <image width="49" height="41" source="Object/Mushroom_1.png"/>
-  </tile>
-  <tile id="24">
-   <image width="50" height="41" source="Object/Mushroom_2.png"/>
-  </tile>
-  <tile id="25">
-   <image width="63" height="65" source="Object/Sign_1.png"/>
-  </tile>
-  <tile id="26">
-   <image width="62" height="64" source="Object/Sign_2.png"/>
-  </tile>
-  <tile id="27">
-   <image width="90" height="54" source="Object/Stone.png"/>
-  </tile>
-  <tile id="28">
-   <image width="116" height="44" source="Object/Tree_1.png"/>
-  </tile>
- </tileset>
+ <tileset firstgid="1" source="atlasMipmap.tsx"/>
  <layer name="Tile Layer 1" width="8" height="4">
   <data encoding="csv">
 13,14,15,0,0,0,0,0,

+ 90 - 0
Samples/AtlasContent/atlasMipmap.tsx

@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tileset name="1" tilewidth="133" tileheight="128" tilecount="29" columns="0">
+ <tile id="0">
+  <image width="128" height="128" source="Tiles/1.png"/>
+ </tile>
+ <tile id="1">
+  <image width="128" height="128" source="Tiles/2.png"/>
+ </tile>
+ <tile id="2">
+  <image width="128" height="128" source="Tiles/3.png"/>
+ </tile>
+ <tile id="3">
+  <image width="128" height="128" source="Tiles/4.png"/>
+ </tile>
+ <tile id="4">
+  <image width="128" height="128" source="Tiles/5.png"/>
+ </tile>
+ <tile id="5">
+  <image width="128" height="128" source="Tiles/6.png"/>
+ </tile>
+ <tile id="6">
+  <image width="128" height="128" source="Tiles/7.png"/>
+ </tile>
+ <tile id="7">
+  <image width="128" height="128" source="Tiles/8.png"/>
+ </tile>
+ <tile id="8">
+  <image width="128" height="128" source="Tiles/9.png"/>
+ </tile>
+ <tile id="9">
+  <image width="128" height="128" source="Tiles/10.png"/>
+ </tile>
+ <tile id="10">
+  <image width="128" height="128" source="Tiles/11.png"/>
+ </tile>
+ <tile id="11">
+  <image width="128" height="128" source="Tiles/12.png"/>
+ </tile>
+ <tile id="12">
+  <image width="128" height="93" source="Tiles/13.png"/>
+ </tile>
+ <tile id="13">
+  <image width="128" height="93" source="Tiles/14.png"/>
+ </tile>
+ <tile id="14">
+  <image width="128" height="93" source="Tiles/15.png"/>
+ </tile>
+ <tile id="15">
+  <image width="128" height="128" source="Tiles/16.png"/>
+ </tile>
+ <tile id="16">
+  <image width="128" height="99" source="Tiles/17.png"/>
+ </tile>
+ <tile id="17">
+  <image width="128" height="128" source="Tiles/18.png"/>
+ </tile>
+ <tile id="18">
+  <image width="133" height="65" source="Object/Bush_1.png"/>
+ </tile>
+ <tile id="19">
+  <image width="133" height="65" source="Object/Bush_2.png"/>
+ </tile>
+ <tile id="20">
+  <image width="73" height="47" source="Object/Bush_3.png"/>
+ </tile>
+ <tile id="21">
+  <image width="73" height="46" source="Object/Bush_4.png"/>
+ </tile>
+ <tile id="22">
+  <image width="77" height="77" source="Object/Crate.png"/>
+ </tile>
+ <tile id="23">
+  <image width="49" height="41" source="Object/Mushroom_1.png"/>
+ </tile>
+ <tile id="24">
+  <image width="50" height="41" source="Object/Mushroom_2.png"/>
+ </tile>
+ <tile id="25">
+  <image width="63" height="65" source="Object/Sign_1.png"/>
+ </tile>
+ <tile id="26">
+  <image width="62" height="64" source="Object/Sign_2.png"/>
+ </tile>
+ <tile id="27">
+  <image width="90" height="54" source="Object/Stone.png"/>
+ </tile>
+ <tile id="28">
+  <image width="116" height="44" source="Object/Tree_1.png"/>
+ </tile>
+</tileset>

+ 1 - 89
Samples/AtlasContent/atlasMipmapPerSprite.tmx

@@ -1,94 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <map version="1.0" orientation="orthogonal" renderorder="right-down" width="8" height="4" tilewidth="128" tileheight="128" nextobjectid="1">
- <tileset firstgid="1" name="1" tilewidth="133" tileheight="128" tilecount="29" columns="0">
-  <tile id="0">
-   <image width="128" height="128" source="Tiles/1.png"/>
-  </tile>
-  <tile id="1">
-   <image width="128" height="128" source="Tiles/2.png"/>
-  </tile>
-  <tile id="2">
-   <image width="128" height="128" source="Tiles/3.png"/>
-  </tile>
-  <tile id="3">
-   <image width="128" height="128" source="Tiles/4.png"/>
-  </tile>
-  <tile id="4">
-   <image width="128" height="128" source="Tiles/5.png"/>
-  </tile>
-  <tile id="5">
-   <image width="128" height="128" source="Tiles/6.png"/>
-  </tile>
-  <tile id="6">
-   <image width="128" height="128" source="Tiles/7.png"/>
-  </tile>
-  <tile id="7">
-   <image width="128" height="128" source="Tiles/8.png"/>
-  </tile>
-  <tile id="8">
-   <image width="128" height="128" source="Tiles/9.png"/>
-  </tile>
-  <tile id="9">
-   <image width="128" height="128" source="Tiles/10.png"/>
-  </tile>
-  <tile id="10">
-   <image width="128" height="128" source="Tiles/11.png"/>
-  </tile>
-  <tile id="11">
-   <image width="128" height="128" source="Tiles/12.png"/>
-  </tile>
-  <tile id="12">
-   <image width="128" height="93" source="Tiles/13.png"/>
-  </tile>
-  <tile id="13">
-   <image width="128" height="93" source="Tiles/14.png"/>
-  </tile>
-  <tile id="14">
-   <image width="128" height="93" source="Tiles/15.png"/>
-  </tile>
-  <tile id="15">
-   <image width="128" height="128" source="Tiles/16.png"/>
-  </tile>
-  <tile id="16">
-   <image width="128" height="99" source="Tiles/17.png"/>
-  </tile>
-  <tile id="17">
-   <image width="128" height="128" source="Tiles/18.png"/>
-  </tile>
-  <tile id="18">
-   <image width="133" height="65" source="Object/Bush_1.png"/>
-  </tile>
-  <tile id="19">
-   <image width="133" height="65" source="Object/Bush_2.png"/>
-  </tile>
-  <tile id="20">
-   <image width="73" height="47" source="Object/Bush_3.png"/>
-  </tile>
-  <tile id="21">
-   <image width="73" height="46" source="Object/Bush_4.png"/>
-  </tile>
-  <tile id="22">
-   <image width="77" height="77" source="Object/Crate.png"/>
-  </tile>
-  <tile id="23">
-   <image width="49" height="41" source="Object/Mushroom_1.png"/>
-  </tile>
-  <tile id="24">
-   <image width="50" height="41" source="Object/Mushroom_2.png"/>
-  </tile>
-  <tile id="25">
-   <image width="63" height="65" source="Object/Sign_1.png"/>
-  </tile>
-  <tile id="26">
-   <image width="62" height="64" source="Object/Sign_2.png"/>
-  </tile>
-  <tile id="27">
-   <image width="90" height="54" source="Object/Stone.png"/>
-  </tile>
-  <tile id="28">
-   <image width="116" height="44" source="Object/Tree_1.png"/>
-  </tile>
- </tileset>
+ <tileset firstgid="1" source="atlasMipmapPerSprite.tsx"/>
  <layer name="Tile Layer 1" width="8" height="4">
   <data encoding="csv">
 13,14,15,0,0,0,0,0,

+ 90 - 0
Samples/AtlasContent/atlasMipmapPerSprite.tsx

@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tileset name="1" tilewidth="133" tileheight="128" tilecount="29" columns="0">
+ <tile id="0">
+  <image width="128" height="128" source="Tiles/1.png"/>
+ </tile>
+ <tile id="1">
+  <image width="128" height="128" source="Tiles/2.png"/>
+ </tile>
+ <tile id="2">
+  <image width="128" height="128" source="Tiles/3.png"/>
+ </tile>
+ <tile id="3">
+  <image width="128" height="128" source="Tiles/4.png"/>
+ </tile>
+ <tile id="4">
+  <image width="128" height="128" source="Tiles/5.png"/>
+ </tile>
+ <tile id="5">
+  <image width="128" height="128" source="Tiles/6.png"/>
+ </tile>
+ <tile id="6">
+  <image width="128" height="128" source="Tiles/7.png"/>
+ </tile>
+ <tile id="7">
+  <image width="128" height="128" source="Tiles/8.png"/>
+ </tile>
+ <tile id="8">
+  <image width="128" height="128" source="Tiles/9.png"/>
+ </tile>
+ <tile id="9">
+  <image width="128" height="128" source="Tiles/10.png"/>
+ </tile>
+ <tile id="10">
+  <image width="128" height="128" source="Tiles/11.png"/>
+ </tile>
+ <tile id="11">
+  <image width="128" height="128" source="Tiles/12.png"/>
+ </tile>
+ <tile id="12">
+  <image width="128" height="93" source="Tiles/13.png"/>
+ </tile>
+ <tile id="13">
+  <image width="128" height="93" source="Tiles/14.png"/>
+ </tile>
+ <tile id="14">
+  <image width="128" height="93" source="Tiles/15.png"/>
+ </tile>
+ <tile id="15">
+  <image width="128" height="128" source="Tiles/16.png"/>
+ </tile>
+ <tile id="16">
+  <image width="128" height="99" source="Tiles/17.png"/>
+ </tile>
+ <tile id="17">
+  <image width="128" height="128" source="Tiles/18.png"/>
+ </tile>
+ <tile id="18">
+  <image width="133" height="65" source="Object/Bush_1.png"/>
+ </tile>
+ <tile id="19">
+  <image width="133" height="65" source="Object/Bush_2.png"/>
+ </tile>
+ <tile id="20">
+  <image width="73" height="47" source="Object/Bush_3.png"/>
+ </tile>
+ <tile id="21">
+  <image width="73" height="46" source="Object/Bush_4.png"/>
+ </tile>
+ <tile id="22">
+  <image width="77" height="77" source="Object/Crate.png"/>
+ </tile>
+ <tile id="23">
+  <image width="49" height="41" source="Object/Mushroom_1.png"/>
+ </tile>
+ <tile id="24">
+  <image width="50" height="41" source="Object/Mushroom_2.png"/>
+ </tile>
+ <tile id="25">
+  <image width="63" height="65" source="Object/Sign_1.png"/>
+ </tile>
+ <tile id="26">
+  <image width="62" height="64" source="Object/Sign_2.png"/>
+ </tile>
+ <tile id="27">
+  <image width="90" height="54" source="Object/Stone.png"/>
+ </tile>
+ <tile id="28">
+  <image width="116" height="44" source="Object/Tree_1.png"/>
+ </tile>
+</tileset>