示例#1
0
        Sprite LoadSprite(string url, int density)
        {
            var spriteSize = IconSize * density;
            var sprite     = sheetBuilder.Allocate(new Size(spriteSize, spriteSize), 1f / density);

            Action <DownloadDataCompletedEventArgs> onComplete = i =>
            {
                if (i.Error != null)
                {
                    return;
                }

                try
                {
                    var icon = new Png(new MemoryStream(i.Result));
                    if (icon.Width == spriteSize && icon.Height == spriteSize)
                    {
                        Game.RunAfterTick(() =>
                        {
                            Util.FastCopyIntoSprite(sprite, icon);
                            sprite.Sheet.CommitBufferedData();
                        });
                    }
                }
                catch { }
            };

            new Download(url, _ => { }, onComplete);

            return(sprite);
        }
        public PlayerBadge LoadBadge(MiniYaml yaml)
        {
            if (sheetBuilder == null)
            {
                sheetBuilder = new SheetBuilder(SheetType.BGRA, 128);

                // We must manually force the buffer creation to avoid a crash
                // that is indirectly triggered by rendering from a Sheet that
                // has not yet been written to.
                sheetBuilder.Current.CreateBuffer();
            }

            var labelNode  = yaml.Nodes.FirstOrDefault(n => n.Key == "Label");
            var icon24Node = yaml.Nodes.FirstOrDefault(n => n.Key == "Icon24");

            if (labelNode == null || icon24Node == null)
            {
                return(null);
            }

            Sprite sprite;

            lock (syncObject)
            {
                if (!spriteCache.TryGetValue(icon24Node.Value.Value, out sprite))
                {
                    sprite = spriteCache[icon24Node.Value.Value] = sheetBuilder.Allocate(new Size(24, 24));

                    Action <DownloadDataCompletedEventArgs> onComplete = i =>
                    {
                        if (i.Error != null)
                        {
                            return;
                        }

                        try
                        {
                            var icon = new Bitmap(new MemoryStream(i.Result));
                            if (icon.Width == 24 && icon.Height == 24)
                            {
                                Game.RunAfterTick(() =>
                                {
                                    Util.FastCopyIntoSprite(sprite, icon);
                                    sprite.Sheet.CommitBufferedData();
                                });
                            }
                        }
                        catch { }
                    };

                    new Download(icon24Node.Value.Value, _ => { }, onComplete);
                }
            }

            return(new PlayerBadge(labelNode.Value.Value, sprite));
        }
示例#3
0
        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];
            int drawmode = 1;

            return(new Vertex[6]
            {
                new Vertex(coord(0, 0), s.Left, s.Top, t.Left, t.Top, channelP, channelC, drawmode, 0, 0, 0, 0, 0, 0, 0),
                new Vertex(coord(su, 0), s.Right, s.Top, t.Right, t.Top, channelP, channelC, drawmode, 0, 0, 0, 0, 0, 0, 0),
                new Vertex(coord(su, sv), s.Right, s.Bottom, t.Right, t.Bottom, channelP, channelC, drawmode, 0, 0, 0, 0, 0, 0, 0),
                new Vertex(coord(su, sv), s.Right, s.Bottom, t.Right, t.Bottom, channelP, channelC, drawmode, 0, 0, 0, 0, 0, 0, 0),
                new Vertex(coord(0, sv), s.Left, s.Bottom, t.Left, t.Bottom, channelP, channelC, drawmode, 0, 0, 0, 0, 0, 0, 0),
                new Vertex(coord(0, 0), s.Left, s.Top, t.Left, t.Top, channelP, channelC, drawmode, 0, 0, 0, 0, 0, 0, 0)
            });
        }
示例#4
0
        public DefaultTileCache(DefaultTerrain terrainInfo, Action <uint, string> onMissingImage = null)
        {
            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(terrainInfo.SheetSize, terrainInfo.SheetSize)));
            };

            random = new MersenneTwister();

            var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders);

            foreach (var t in terrainInfo.Templates)
            {
                var variants     = new List <Sprite[]>();
                var templateInfo = (DefaultTerrainTemplateInfo)t.Value;

                foreach (var i in templateInfo.Images)
                {
                    ISpriteFrame[] allFrames;
                    if (onMissingImage != null)
                    {
                        try
                        {
                            allFrames = frameCache[i];
                        }
                        catch (FileNotFoundException)
                        {
                            onMissingImage(t.Key, i);
                            continue;
                        }
                    }
                    else
                    {
                        allFrames = frameCache[i];
                    }

                    var frameCount = terrainInfo.EnableDepth ? allFrames.Length / 2 : allFrames.Length;
                    var indices    = templateInfo.Frames != null ? templateInfo.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) ? (DefaultTerrainTileInfo)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);
                        OpenRA.Graphics.Util.FastCopyIntoChannel(s, f.Data, f.Type);

                        if (terrainInfo.EnableDepth)
                        {
                            var depthFrame = allFrames[j + frameCount];
                            var ss         = sheetBuilder.Allocate(f.Size, zRamp, offset);
                            OpenRA.Graphics.Util.FastCopyIntoChannel(ss, depthFrame.Data, depthFrame.Type);

                            // 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 (terrainInfo.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(), templateInfo.Images.Length));
            }

            // 1x1px transparent tile
            if (sheetBuilder.Type == SheetType.BGRA)
            {
                missingTile = sheetBuilder.Add(new byte[4], SpriteFrameType.Bgra32, new Size(1, 1));
            }
            else
            {
                missingTile = sheetBuilder.Add(new byte[1], SpriteFrameType.Indexed8, new Size(1, 1));
            }

            Sheet.ReleaseBuffer();
        }