public Sprite Add(byte[] src, Size size, float2 spriteOffset) { // Don't bother allocating empty sprites if (size.Width == 0 || size.Height == 0) { return(new Sprite(current, Rectangle.Empty, spriteOffset, channel, BlendMode.Alpha)); } var rect = Allocate(size, spriteOffset); Util.FastCopyIntoChannel(rect, src); current.CommitData(); return(rect); }
Vertex[] GenerateSlicePlane(int su, int sv, Func <int, int, VxlElement> first, Func <int, int, VxlElement> second, Func <int, int, float3> coord) { var colors = new byte[su * sv]; var normals = new byte[su * sv]; var c = 0; for (var v = 0; v < sv; v++) { for (var u = 0; u < su; u++) { var voxel = first(u, v) ?? second(u, v); colors[c] = voxel == null ? (byte)0 : voxel.Color; normals[c] = voxel == null ? (byte)0 : voxel.Normal; c++; } } var size = new Size(su, sv); var s = sheetBuilder.Allocate(size); var t = sheetBuilder.Allocate(size); Util.FastCopyIntoChannel(s, colors); Util.FastCopyIntoChannel(t, normals); // s and t are guaranteed to use the same sheet because // of the custom voxel sheet allocation implementation s.Sheet.CommitBufferedData(); var channelP = ChannelSelect[(int)s.Channel]; var channelC = ChannelSelect[(int)t.Channel]; return(new Vertex[6] { new Vertex(coord(0, 0), s.Left, s.Top, t.Left, t.Top, channelP, channelC), new Vertex(coord(su, 0), s.Right, s.Top, t.Right, t.Top, channelP, channelC), new Vertex(coord(su, sv), s.Right, s.Bottom, t.Right, t.Bottom, channelP, channelC), new Vertex(coord(su, sv), s.Right, s.Bottom, t.Right, t.Bottom, channelP, channelC), new Vertex(coord(0, sv), s.Left, s.Bottom, t.Left, t.Bottom, channelP, channelC), new Vertex(coord(0, 0), s.Left, s.Top, t.Left, t.Top, channelP, channelC) }); }
Vertex[] GenerateSlicePlane(int su, int sv, Func <int, int, VxlElement> first, Func <int, int, VxlElement> second, Func <int, int, float[]> coord) { var colors = new byte[su * sv]; var normals = new byte[su * sv]; var c = 0; for (var v = 0; v < sv; v++) { for (var u = 0; u < su; u++) { var voxel = first(u, v) ?? second(u, v); colors[c] = voxel == null ? (byte)0 : voxel.Color; normals[c] = voxel == null ? (byte)0 : voxel.Normal; c++; } } var s = sheetBuilder.Allocate(new Size(su, sv)); Util.FastCopyIntoChannel(s, 0, colors); Util.FastCopyIntoChannel(s, 1, normals); s.Sheet.CommitBufferedData(); var channelP = ChannelSelect[(int)s.Channel]; var channelC = ChannelSelect[(int)s.Channel + 1]; return(new Vertex[6] { new Vertex(coord(0, 0), s.Left, s.Top, channelP, channelC), new Vertex(coord(su, 0), s.Right, s.Top, channelP, channelC), new Vertex(coord(su, sv), s.Right, s.Bottom, channelP, channelC), new Vertex(coord(su, sv), s.Right, s.Bottom, channelP, channelC), new Vertex(coord(0, sv), s.Left, s.Bottom, channelP, channelC), new Vertex(coord(0, 0), s.Left, s.Top, channelP, channelC) }); }
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) { this.tileset = tileset; var allocated = false; //Func<Sheet2D> allocate = () => //{ // if (allocated) // throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter."); // allocated = true; // SheetBuilder2D shb= Game.worldRenderer.World.Map.Rules.Sequences.SpriteCache.SheetBuilder2D; // return new Sheet2D(SheetType.Indexed, shb., shb.TextureArrayIndex); //}; //SheetBuilder2D shb = Game.OrderManager.World.Map.Rules.Sequences.SpriteCache.SheetBuilder2D; //sheetBuilder2d = Game.OrderManager.World.Map.Rules.Sequences.SpriteCache.SheetBuilder2D; sheetBuilder2d = Game.SheetBuilder2D; if (!string.IsNullOrEmpty(tileset.MegaTexture)) { sbMegaTexture = sheetBuilder2d; LoadsbMegaTexture(tileset.MegaTexture); } random = new MersenneTwister(); var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); //дл¤ каждого templates есть сво¤ коллекци¤ Sprites , это заполн¤етс¤ в цикле по tileset.Templates ниже 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 = sheetBuilder2d.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(s, f.Data); if (tileset.EnableDepth) { var ss = sheetBuilder2d.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.Sheet2D, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode)); } if (t.Value.Variants == "Calc") { templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), 1, variants.First().Count())); } else { templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } } // 1x1px transparent tile missingTile = sheetBuilder2d.Add(new byte[1], new Size(1, 1)); //Sheet2D.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(); }