public Theater(TileSet tileset) { var allocated = false; Func <Sheet> allocate = () => { if (allocated) { throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); } allocated = true; return(new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true)); }; var sourceCache = new Dictionary <string, ISpriteSource>(); templates = new Dictionary <ushort, Sprite[]>(); sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); foreach (var t in tileset.Templates) { templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset) { var allocated = false; Func <Sheet> allocate = () => { if (allocated) { throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); } allocated = true; return(new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true)); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); templates = new Dictionary <ushort, Sprite[]>(); var frameCache = new FrameCache(Game.modData.SpriteLoaders, tileset.Extensions); foreach (var t in tileset.Templates) { var allFrames = frameCache[t.Value.Image]; var frames = t.Value.Frames != null?t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; templates.Add(t.Value.Id, frames.Select(f => sheetBuilder.Add(f)).ToArray()); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset) { this.tileset = tileset; var allocated = false; Func <Sheet> allocate = () => { if (allocated) { throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); } allocated = true; return(new Sheet(new Size(tileset.SheetSize, tileset.SheetSize))); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frames = t.Value.Frames != null?t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; variants.Add(frames.Select(f => sheetBuilder.Add(f)).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) { allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, float2.Zero, s.Channel, s.BlendMode)); } templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
/// <summary> /// Резервирует место под SPrite в текстуре opengl /// Определяет в какой канал текстуры будут записаны байты /// </summary> /// <param name="imageSize"></param> /// <param name="zRamp"></param> /// <param name="spriteOffset"></param> /// <returns></returns> public Sprite Allocate(Size imageSize, float zRamp, float3 spriteOffset) { //используется одномерный массив. Поэтому все разбито по Height(row) и смещение внутри row. if (imageSize.Width + p.X > currentSheet.Size.Width) //если дошли до смещения равного ширине картинки, то сбрасываем смещение до 0 и делаем переход на высоту равную предыдущей высоте. { p = new int2(0, p.Y + rowHeight); rowHeight = imageSize.Height; } if (imageSize.Height > rowHeight) { rowHeight = imageSize.Height; } if (p.Y + imageSize.Height > currentSheet.Size.Height) //если вышли за пределы высоты в одном канале, то переходим в другой канал. и скидываем p=int2.Zero { var next = NextChannel(channel); if (next == null) //если закончились каналы внутри текстуры , то создаем новый Sheet. { currentSheet.ReleaseBuffer(); currentSheet = allocateSheetDelegate(); sheets.Add(currentSheet); channel = Type == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA; } else { channel = next.Value; } rowHeight = imageSize.Height; p = int2.Zero; } var rect = new Sprite(currentSheet, new Rectangle(p.X, p.Y, imageSize.Width, imageSize.Height), zRamp, spriteOffset, channel, BlendMode.Alpha); p += new int2(imageSize.Width, 0); return(rect); }
public Sprite Allocate(Size imageSize, float2 spriteOffset) { if (imageSize.Width + p.X > current.Size.Width) { p = new Point(0, p.Y + rowHeight); rowHeight = imageSize.Height; } if (imageSize.Height > rowHeight) { rowHeight = imageSize.Height; } if (p.Y + imageSize.Height > current.Size.Height) { var next = NextChannel(channel); if (next == null) { current.ReleaseBuffer(); current = allocateSheet(); sheets.Add(current); channel = TextureChannel.Red; } else { channel = next.Value; } rowHeight = imageSize.Height; p = new Point(0, 0); } var rect = new Sprite(current, new Rectangle(p, imageSize), spriteOffset, channel, BlendMode.Alpha); p.X += imageSize.Width; return(rect); }
public Sprite Allocate(Size imageSize, float zRamp, float3 spriteOffset, float scale = 1f) { if (imageSize.Width + p.X + margin > current.Size.Width) { p = new int2(0, p.Y + rowHeight + margin); rowHeight = imageSize.Height; } if (imageSize.Height > rowHeight) { rowHeight = imageSize.Height; } if (p.Y + imageSize.Height + margin > current.Size.Height) { var next = NextChannel(channel); if (next == null) { current.ReleaseBuffer(); current = allocateSheet(); sheets.Add(current); channel = Type == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA; } else { channel = next.Value; } rowHeight = imageSize.Height; p = int2.Zero; } var rect = new Sprite(current, new Rectangle(p.X + margin, p.Y + margin, imageSize.Width, imageSize.Height), zRamp, spriteOffset, channel, BlendMode.Alpha, scale); p += new int2(imageSize.Width + margin, 0); return(rect); }
public Theater(TileSet tileset) { this.tileset = tileset; var allocated = false; Func <Sheet> allocate = () => { if (allocated) { throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); } allocated = true; return(new Sheet(SheetType.Indexed, new Size(tileset.SheetSize, tileset.SheetSize))); }; sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.Frames : Enumerable.Range(0, frameCount); variants.Add(indices.Select(j => { var f = allFrames[j]; var tile = t.Value.Contains(j) ? t.Value[j] : null; // The internal z axis is inverted from expectation (negative is closer) var zOffset = tile != null ? -tile.ZOffset : 0; var zRamp = tile != null ? tile.ZRamp : 1f; var offset = new float3(f.Offset, zOffset); var s = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(s, f.Data); if (tileset.EnableDepth) { var ss = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data); // s and ss are guaranteed to use the same sheet // because of the custom terrain sheet allocation s = new SpriteWithSecondaryData(s, ss.Bounds, ss.Channel); } return(s); }).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) { allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode)); } templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset) { this.tileset = tileset; var allocated = false; var type = tileset.EnableDepth ? SheetType.DualIndexed : SheetType.Indexed; Func <Sheet> allocate = () => { if (allocated) { throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); } allocated = true; return(new Sheet(type, new Size(tileset.SheetSize, tileset.SheetSize))); }; sheetBuilder = new SheetBuilder(type, allocate); random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { var allFrames = frameCache[i]; var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.Frames : Enumerable.Range(0, frameCount); variants.Add(indices.Select(j => { var f = allFrames[j]; var s = sheetBuilder.Allocate(f.Size, f.Offset); Util.FastCopyIntoChannel(s, 0, f.Data); if (tileset.EnableDepth) { Util.FastCopyIntoChannel(s, 1, allFrames[j + frameCount].Data); } return(s); }).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) { allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, float2.Zero, s.Channel, s.BlendMode)); } templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); Sheet.ReleaseBuffer(); }
public Theater(TileSet tileset, Action <uint, string> onMissingImage = null) { this.tileset = tileset; var allocated = false; Func <Sheet> allocate = () => { if (allocated) { throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); } allocated = true; return(new Sheet(SheetType.Indexed, new Size(tileset.SheetSize, tileset.SheetSize))); }; random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List <Sprite[]>(); foreach (var i in t.Value.Images) { ISpriteFrame[] allFrames; if (onMissingImage != null) { try { allFrames = frameCache[i]; } catch (FileNotFoundException) { onMissingImage(t.Key, i); continue; } } else { allFrames = frameCache[i]; } var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length; var indices = t.Value.Frames != null ? t.Value.Frames : Exts.MakeArray(t.Value.TilesCount, j => j); var start = indices.Min(); var end = indices.Max(); if (start < 0 || end >= frameCount) { throw new YamlException("Template `{0}` uses frames [{1}..{2}] of {3}, but only [0..{4}] actually exist" .F(t.Key, start, end, i, frameCount - 1)); } variants.Add(indices.Select(j => { var f = allFrames[j]; var tile = t.Value.Contains(j) ? t.Value[j] : null; // The internal z axis is inverted from expectation (negative is closer) var zOffset = tile != null ? -tile.ZOffset : 0; var zRamp = tile != null ? tile.ZRamp : 1f; var offset = new float3(f.Offset, zOffset); var type = SheetBuilder.FrameTypeToSheetType(f.Type); // Defer SheetBuilder creation until we know what type of frames we are loading! // TODO: Support mixed indexed and BGRA frames if (sheetBuilder == null) { sheetBuilder = new SheetBuilder(SheetBuilder.FrameTypeToSheetType(f.Type), allocate); } else if (type != sheetBuilder.Type) { throw new YamlException("Sprite type mismatch. Terrain sprites must all be either Indexed or RGBA."); } var s = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(s, f.Data); if (tileset.EnableDepth) { var ss = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data); // s and ss are guaranteed to use the same sheet // because of the custom terrain sheet allocation s = new SpriteWithSecondaryData(s, s.Sheet, ss.Bounds, ss.Channel); } return(s); }).ToArray()); } var allSprites = variants.SelectMany(s => s); // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) { allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode)); } if (onMissingImage != null && !variants.Any()) { continue; } templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[sheetBuilder.Type == SheetType.BGRA ? 4 : 1], new Size(1, 1)); Sheet.ReleaseBuffer(); }