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); }
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); }
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)); } }
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); } }