Beispiel #1
0
        public TextureAtlas.SpriteAtlasEntry AddDynamicSheet(String Name, TileSheetDefinition Sheet, Texture2D Texture)
        {
            if (!String.IsNullOrEmpty(Name) && DynamicAtlasEntries.ContainsKey(Name))
            {
                DynamicAtlasEntries[Name].ReferenceCount += 1;
                return(DynamicAtlasEntries[Name]);
            }

            if (String.IsNullOrEmpty(Name))
            {
                Name = System.Guid.NewGuid().ToString();
            }

            var newEntry = new TextureAtlas.SpriteAtlasEntry
            {
                SourceDefinition = Sheet,
                SourceTexture    = Texture,
                AtlasBounds      = new Rectangle(0, 0, Texture.Width, Texture.Height),
                ReferenceCount   = 1
            };

            newEntry.TileSheet = MakeTileSheet(newEntry, Texture.Bounds);
            DynamicAtlasEntries.Add(Name, newEntry);
            AtlasValid = false;

            return(newEntry);
        }
Beispiel #2
0
        private void BlitSheet(TextureAtlas.SpriteAtlasEntry Sheet, Texture2D Into)
        {
            Sheet.NeedsBlitToAtlas = false;

            var memTexture = TextureTool.MemoryTextureFromTexture2D(Sheet.SourceTexture);

            if (Sheet.SourceDefinition.Type == TileSheetType.VariableWidthFont)
            {
                memTexture.Filter(c => (c.R == 0 && c.G == 0 && c.B == 0) ? new Color(0, 0, 0, 0) : c);
            }

            Into.SetData(0, Sheet.AtlasBounds, memTexture.Data, 0, memTexture.Width * memTexture.Height);
        }
Beispiel #3
0
 private ITileSheet MakeTileSheet(TextureAtlas.SpriteAtlasEntry Sheet, Rectangle AtlasBounds)
 {
     if (Sheet.SourceDefinition.Type == TileSheetType.VariableWidthFont)
     {
         return(new VariableWidthFont(Sheet.SourceTexture, AtlasBounds.Width, AtlasBounds.Height, Sheet.AtlasBounds));
     }
     else if (Sheet.SourceDefinition.Type == TileSheetType.JsonFont)
     {
         return(new JsonFont(Sheet.SourceDefinition.Texture, AtlasBounds, Sheet.AtlasBounds));
     }
     else
     {
         return(new TileSheet(AtlasBounds.Width, AtlasBounds.Height, Sheet.AtlasBounds, Sheet.SourceDefinition.TileWidth, Sheet.SourceDefinition.TileHeight, Sheet.SourceDefinition.RepeatWhenUsedAsBorder));
     }
 }
Beispiel #4
0
        public SpriteAtlas(GraphicsDevice Device, ContentManager Content)
        {
            this.Device = Device;

            var coreSheets = FileUtils.LoadJsonListFromMultipleSources <TileSheetDefinition>(ContentPaths.GUI.Skin, null, (s) => s.Name);

            SheetGenerators = FindGenerators();

            CoreAtlasEntries = coreSheets.Select(s =>
            {
                Texture2D realTexture = null;

                switch (s.Type)
                {
                case TileSheetType.TileSheet:
                case TileSheetType.VariableWidthFont:
                case TileSheetType.JsonFont:
                    realTexture = AssetManager.GetContentTexture(s.Texture);
                    break;

                case TileSheetType.Generated:
                    realTexture = SheetGenerators[s.Texture](Device, Content, s);
                    break;
                }

                var r = new TextureAtlas.SpriteAtlasEntry
                {
                    SourceDefinition = s,
                    AtlasBounds      = new Rectangle(0, 0, realTexture.Width, realTexture.Height),
                    SourceTexture    = realTexture
                };

                r.TileSheet = MakeTileSheet(r, realTexture.Bounds);

                return(r);
            }).ToList();

            NamedTileSheets = new Dictionary <string, ITileSheet>();
            foreach (var coreSheet in CoreAtlasEntries)
            {
                NamedTileSheets.Upsert(coreSheet.SourceDefinition.Name, coreSheet.TileSheet);
            }

            Prerender();
        }
        /// <summary>
        /// Attempt to place textures into the space defined by Dimensions until no more can be fit.
        /// Subdivide the space after each insertion. Assume textures are sorted by size.
        /// </summary>
        /// <param name="Dimensions"></param>
        /// <param name="Textures"></param>
        internal static void TryPlaceTextures(Rectangle Dimensions, List <SpriteAtlasEntry> Textures)
        {
            SpriteAtlasEntry tex = null;

            //Find largest entry that fits within the dimensions.
            for (int i = 0; i < Textures.Count; ++i)
            {
                var Entry = Textures[i];
                if (Entry.AtlasBounds.Width > Dimensions.Width || Entry.AtlasBounds.Height > Dimensions.Height)
                {
                    continue;
                }
                Textures.RemoveAt(i);
                tex = Entry;
                break;
            }

            // Quit if nothing fit.
            if (tex == null)
            {
                return;
            }

            tex.AtlasBounds.X = Dimensions.X;
            tex.AtlasBounds.Y = Dimensions.Y;

            //Subdivide remaining space.
            int HorizontalDifference = Dimensions.Width - tex.AtlasBounds.Width;
            int VerticalDifference   = Dimensions.Height - tex.AtlasBounds.Height;

            if (HorizontalDifference == 0 && VerticalDifference == 0) //Perfect fit!
            {
                return;
            }

            Rectangle?ASpace = null;
            Rectangle?BSpace = null;

            // Subdivide the space on the shortest axis of the texture we just placed.
            if (HorizontalDifference >= VerticalDifference)
            {
                ASpace = new Rectangle(Dimensions.X + tex.AtlasBounds.Width, Dimensions.Y, HorizontalDifference, Dimensions.Height);

                // Remember that this isn't a perfect split - a chunk belongs to the placed texture.
                if (VerticalDifference > 0)
                {
                    BSpace = new Rectangle(Dimensions.X, Dimensions.Y + tex.AtlasBounds.Height, tex.AtlasBounds.Width, VerticalDifference);
                }
            }
            else
            {
                ASpace = new Rectangle(Dimensions.X, Dimensions.Y + tex.AtlasBounds.Height, Dimensions.Width, VerticalDifference);
                if (HorizontalDifference > 0)
                {
                    BSpace = new Rectangle(Dimensions.X + tex.AtlasBounds.Width, Dimensions.Y, HorizontalDifference, tex.AtlasBounds.Height);
                }
            }

            TryPlaceTextures(ASpace.Value, Textures);
            if (BSpace.HasValue)
            {
                TryPlaceTextures(BSpace.Value, Textures);
            }
        }