Ejemplo n.º 1
0
        public void AddPalette(string name, ImmutablePalette p, bool allowModifiers)
        {
            if (palettes.ContainsKey(name))
            {
                throw new InvalidOperationException($"Palette {name} has already been defined");
            }

            // PERF: the first row in the palette textures is reserved as a placeholder for non-indexed sprites
            // that do not have a color-shift applied. This provides a quick shortcut to avoid querying the
            // color-shift texture for every pixel only to find that most are not shifted.
            var index = palettes.Count + 1;

            indices.Add(name, index);
            palettes.Add(name, p);

            if (index >= Height)
            {
                Height = Exts.NextPowerOf2(index + 1);
                Array.Resize(ref buffer, Height * Palette.Size * 4);
                Array.Resize(ref colorShiftBuffer, Height * 4);
            }

            if (allowModifiers)
            {
                mutablePalettes.Add(name, new MutablePalette(p));
            }
            else
            {
                CopyPaletteToBuffer(index, p);
            }
        }
Ejemplo n.º 2
0
        public static Bitmap ActorsBitmap(World world)
        {
            var map = world.Map;
            var b   = map.Bounds;

            var size       = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
            var bitmap     = new Bitmap(size, size);
            var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                var colors = (int *)bitmapData.Scan0;
                var stride = bitmapData.Stride / 4;
                foreach (var t in world.ActorsWithTrait <IRadarSignature>())
                {
                    if (!t.Actor.IsInWorld || world.FogObscures(t.Actor))
                    {
                        continue;
                    }

                    foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
                    {
                        var uv = cell.First.ToMPos(map);
                        if (b.Contains(uv.U, uv.V))
                        {
                            colors[(uv.V - b.Top) * stride + uv.U - b.Left] = cell.Second.ToArgb();
                        }
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 3
0
        public static Bitmap ActorsBitmap(World world)
        {
            var map        = world.Map;
            var size       = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
            var bitmap     = new Bitmap(size, size);
            var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                int *c = (int *)bitmapData.Scan0;

                foreach (var t in world.ActorsWithTrait <IRadarSignature>())
                {
                    if (world.FogObscures(t.Actor))
                    {
                        continue;
                    }

                    var color = t.Trait.RadarSignatureColor(t.Actor);
                    foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
                    {
                        if (world.Map.IsInMap(cell))
                        {
                            *(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb();
                        }
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 4
0
        public void Open(CpsD2Loader video)
        {
            this.image = video;

            stopped = true;
            paused  = true;
            //onComplete = () => { };
            TypeDictionary   metadata;
            ImmutablePalette cpspalette;

            using (var stream = Game.ModData.DefaultFileSystem.Open(image.SpriteFilename))
            {
                video.TryParseSpritePlusPalette(stream, out imageSprite, out metadata, out cpspalette);
                if (cpspalette != null)
                {
                    LoadPalette(cpspalette, image.SpriteFilename);
                }
            }

            var imwidth  = imageSprite[0].FrameSize.Width;
            var imheight = imageSprite[0].FrameSize.Height;


            var size        = Math.Max(imwidth, imheight);
            var textureSize = Exts.NextPowerOf2(size);

            var scale = Math.Min((float)RenderBounds.Width / imwidth, (float)RenderBounds.Height / imheight * AspectRatio);

            videoOrigin = new float2(
                RenderBounds.X + (RenderBounds.Width - scale * imwidth) / 2,
                RenderBounds.Y + (RenderBounds.Height - scale * imheight * AspectRatio) / 2);

            // Round size to integer pixels. Round up to be consistent with the scale calculation.
            videoSize = new float2((int)Math.Ceiling(imwidth * scale), (int)Math.Ceiling(imheight * AspectRatio * scale));
        }
Ejemplo n.º 5
0
        public static Bitmap CustomTerrainBitmap(World world)
        {
            var map        = world.Map;
            var size       = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
            var bitmap     = new Bitmap(size, size);
            var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                int *c = (int *)bitmapData.Scan0;

                for (var x = 0; x < map.Bounds.Width; x++)
                {
                    for (var y = 0; y < map.Bounds.Height; y++)
                    {
                        var mapX   = x + map.Bounds.Left;
                        var mapY   = y + map.Bounds.Top;
                        var custom = map.CustomTerrain[mapX, mapY];
                        if (custom == null)
                        {
                            continue;
                        }
                        *(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[custom].Color.ToArgb();
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 6
0
        public void Open(IVideo video)
        {
            this.video = video;

            stopped = true;
            paused  = true;
            Game.Sound.StopVideo();
            onComplete = () => { };

            invLength = video.Framerate * 1f / video.Frames;

            var size        = Math.Max(video.Width, video.Height);
            var textureSize = Exts.NextPowerOf2(size);
            var videoSheet  = new Sheet(SheetType.BGRA, new Size(textureSize, textureSize));

            videoSheet.GetTexture().ScaleFilter = TextureScaleFilter.Linear;
            videoSheet.GetTexture().SetData(video.FrameData);

            videoSprite = new Sprite(videoSheet,
                                     new Rectangle(
                                         0,
                                         0,
                                         video.Width,
                                         video.Height),
                                     TextureChannel.RGBA);

            var scale = Math.Min((float)RenderBounds.Width / video.Width, RenderBounds.Height / (video.Height * AspectRatio));

            videoOrigin = new float2(
                RenderBounds.X + (RenderBounds.Width - scale * video.Width) / 2,
                RenderBounds.Y + (RenderBounds.Height - scale * video.Height * AspectRatio) / 2);

            // Round size to integer pixels. Round up to be consistent with the scale calculation.
            videoSize = new float2((int)Math.Ceiling(video.Width * scale), (int)Math.Ceiling(video.Height * AspectRatio * scale));
        }
Ejemplo n.º 7
0
        public static Bitmap CustomTerrainBitmap(World world)
        {
            var map = world.Map;
            var b   = map.Bounds;

            var size       = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
            var bitmap     = new Bitmap(size, size);
            var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                var colors = (int *)bitmapData.Scan0;
                var stride = bitmapData.Stride / 4;
                for (var y = 0; y < b.Height; y++)
                {
                    for (var x = 0; x < b.Width; x++)
                    {
                        var mapX   = x + b.Left;
                        var mapY   = y + b.Top;
                        var custom = map.CustomTerrain[new MPos(mapX, mapY)];
                        if (custom == byte.MaxValue)
                        {
                            continue;
                        }
                        colors[y * stride + x] = world.TileSet[custom].Color.ToArgb();
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 8
0
        private void LoadFrame()
        {
            var textData = "";

            if (CurrentFrame == 0)
            {
                frame    = new uint[Height / stride, Width];
                palette  = new uint[256];
                TextData = "";
            }
            else
            {
                frame = frames[CurrentFrame - 1].ApplyFrame(frame, ref palette, ref textData);
            }

            TextData += textData;

            // TODO for better performance, we should get rid of this copying as soon we can use non-power-of-2 textures
            FrameData = new uint[Exts.NextPowerOf2(Height), Exts.NextPowerOf2(Width)];

            for (var y = 0; y < Height / stride; y++)
            {
                for (var i = 0; i < stride; i++)
                {
                    Buffer.BlockCopy(frame, y * Width * 4, FrameData, (y * stride + i) * FrameData.GetLength(1) * 4, Width * 4);
                }
            }
        }
Ejemplo n.º 9
0
        public void AddPalette(string name, ImmutablePalette p, bool allowModifiers)
        {
            if (palettes.ContainsKey(name))
            {
                throw new InvalidOperationException("Palette {0} has already been defined".F(name));
            }

            int index = palettes.Count;

            indices.Add(name, index);
            palettes.Add(name, p);

            if (palettes.Count > Height)
            {
                Height = Exts.NextPowerOf2(palettes.Count);
                Array.Resize(ref buffer, Height * Palette.Size * 4);
            }

            if (allowModifiers)
            {
                modifiablePalettes.Add(name, new MutablePalette(p));
            }
            else
            {
                CopyPaletteToBuffer(index, p);
            }
        }
Ejemplo n.º 10
0
        public void Open(VqaReader video)
        {
            this.video = video;

            stopped = true;
            paused  = true;
            Game.Sound.StopVideo();
            onComplete = () => { };

            invLength = video.Framerate * 1f / video.Frames;

            var size        = Math.Max(video.Width, video.Height);
            var textureSize = Exts.NextPowerOf2(size);
            var videoSheet  = new Sheet(SheetType.BGRA, new Size(textureSize, textureSize));

            videoSheet.AssignOrGetOrSetDataGLTexture().ScaleFilter = TextureScaleFilter.Linear;
            videoSheet.AssignOrGetOrSetDataGLTexture().SetData(video.FrameData);

            videoSprite = new Sprite(videoSheet,
                                     new Rectangle(
                                         0,
                                         0,
                                         video.Width,
                                         video.Height),
                                     TextureChannel.RGBA);

            var scale = Math.Min((float)RenderBounds.Width / video.Width, (float)RenderBounds.Height / video.Height * AspectRatio);

            videoOrigin = new float2(
                RenderBounds.X + (RenderBounds.Width - scale * video.Width) / 2,
                RenderBounds.Y + (RenderBounds.Height - scale * video.Height * AspectRatio) / 2);

            // Round size to integer pixels. Round up to be consistent with the scale calculation.
            videoSize = new float2((int)Math.Ceiling(video.Width * scale), (int)Math.Ceiling(video.Height * AspectRatio * scale));

            if (!DrawOverlay)
            {
                return;
            }

            var scaledHeight = (int)videoSize.Y;

            overlay = new uint[Exts.NextPowerOf2(scaledHeight), 1];
            var black = 255U << 24;

            for (var y = 0; y < scaledHeight; y += 2)
            {
                overlay[y, 0] = black;
            }

            var overlaySheet = new Sheet(SheetType.BGRA, new Size(1, Exts.NextPowerOf2(scaledHeight)));

            overlaySheet.AssignOrGetOrSetDataGLTexture().SetData(overlay);
            overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, 1, scaledHeight), TextureChannel.RGBA);
        }
Ejemplo n.º 11
0
        public void Load(string filename)
        {
            if (filename == cachedVideo)
            {
                return;
            }

            stopped = true;
            paused  = true;
            Sound.StopVideo();
            onComplete = () => { };

            cachedVideo = filename;
            video       = new VqaReader(GlobalFileSystem.Open(filename));

            invLength = video.Framerate * 1f / video.Frames;

            var size        = Math.Max(video.Width, video.Height);
            var textureSize = Exts.NextPowerOf2(size);
            var videoSheet  = new Sheet(new Size(textureSize, textureSize), false);

            videoSheet.Texture.ScaleFilter = TextureScaleFilter.Linear;
            videoSheet.Texture.SetData(video.FrameData);
            videoSprite = new Sprite(videoSheet, new Rectangle(0, 0, video.Width, video.Height), TextureChannel.Alpha);

            var scale = Math.Min(RenderBounds.Width / video.Width, RenderBounds.Height / (video.Height * AspectRatio));

            videoOrigin = new float2(RenderBounds.X + (RenderBounds.Width - scale * video.Width) / 2, RenderBounds.Y + (RenderBounds.Height - scale * AspectRatio * video.Height) / 2);

            // Round size to integer pixels. Round up to be consistent with the scale calcuation.
            videoSize = new float2((int)Math.Ceiling(video.Width * scale), (int)Math.Ceiling(video.Height * scale * AspectRatio));

            if (!DrawOverlay)
            {
                return;
            }

            var scaledHeight = (int)videoSize.Y;

            overlay = new uint[Exts.NextPowerOf2(scaledHeight), 1];
            var black = (uint)255 << 24;

            for (var y = 0; y < scaledHeight; y += 2)
            {
                overlay[y, 0] = black;
            }

            var overlaySheet = new Sheet(new Size(1, Exts.NextPowerOf2(scaledHeight)), false);

            overlaySheet.Texture.SetData(overlay);
            overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, 1, scaledHeight), TextureChannel.Alpha);
        }
Ejemplo n.º 12
0
        public void Load(string filename)
        {
            if (filename == cachedVideo)
            {
                return;
            }

            stopped = true;
            paused  = true;
            Sound.StopVideo();
            onComplete = () => { };

            cachedVideo = filename;
            video       = new VqaReader(GlobalFileSystem.Open(filename));

            invLength = video.Framerate * 1f / video.Frames;

            var size        = Math.Max(video.Width, video.Height);
            var textureSize = Exts.NextPowerOf2(size);
            var videoSheet  = new Sheet(new Size(textureSize, textureSize), false);

            videoSheet.Texture.SetData(video.FrameData);
            videoSprite = new Sprite(videoSheet, new Rectangle(0, 0, video.Width, video.Height), TextureChannel.Alpha);

            var scale = Math.Min(RenderBounds.Width / video.Width, RenderBounds.Height / video.Height);

            videoOrigin = new float2(RenderBounds.X + (RenderBounds.Width - scale * video.Width) / 2, RenderBounds.Y + (RenderBounds.Height - scale * video.Height) / 2);
            videoSize   = new float2(video.Width * scale, video.Height * scale);

            if (!DrawOverlay)
            {
                return;
            }

            overlay = new uint[2 * textureSize, 2 * textureSize];
            var black = (uint)255 << 24;

            for (var y = 0; y < video.Height; y++)
            {
                for (var x = 0; x < video.Width; x++)
                {
                    overlay[2 * y, x] = black;
                }
            }

            var overlaySheet = new Sheet(new Size(2 * textureSize, 2 * textureSize), false);

            overlaySheet.Texture.SetData(overlay);
            overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, video.Width, 2 * video.Height), TextureChannel.Alpha);
        }
Ejemplo n.º 13
0
        public void SetSize(int w, int h)
        {
            var size        = Math.Max(w, h);
            var textureSize = Exts.NextPowerOf2(size);

            var scale = Math.Min((float)RenderBounds.Width / w, (float)RenderBounds.Height / h * AspectRatio);

            videoOrigin = new float2(
                RenderBounds.X + (RenderBounds.Width - scale * w) / 2,
                RenderBounds.Y + (RenderBounds.Height - scale * h * AspectRatio) / 2);

            // Round size to integer pixels. Round up to be consistent with the scale calculation.
            videoSize = new float2((int)Math.Ceiling(w * scale), (int)Math.Ceiling(h * AspectRatio * scale));
        }
Ejemplo n.º 14
0
        public static Bitmap ShroudBitmap(World world)
        {
            var map = world.Map;
            var b   = map.Bounds;

            var size   = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
            var bitmap = new Bitmap(size, size);

            if (world.RenderPlayer == null)
            {
                return(bitmap);
            }

            var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            var shroud = Color.Black.ToArgb();
            var fog    = Color.FromArgb(128, Color.Black).ToArgb();
            var offset = new CVec(b.Left, b.Top);

            unsafe
            {
                var colors         = (int *)bitmapData.Scan0;
                var stride         = bitmapData.Stride / 4;
                var shroudObscured = world.ShroudObscuresTest(map.Cells);
                var fogObscured    = world.FogObscuresTest(map.Cells);
                foreach (var cell in map.Cells)
                {
                    var uv = Map.CellToMap(map.TileShape, cell) - offset;
                    if (shroudObscured(cell))
                    {
                        colors[uv.Y * stride + uv.X] = shroud;
                    }
                    else if (fogObscured(cell))
                    {
                        colors[uv.Y * stride + uv.X] = fog;
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 15
0
        static Sheet SpriteFrameToSheet(ISpriteFrame frame, PaletteReference p)
        {
            var          size         = Exts.NextPowerOf2(Math.Max(frame.FrameSize.Width, frame.FrameSize.Height));
            SheetBuilder sheetBuilder = new SheetBuilder(SheetType.BGRA, size);

            byte[] data;
            if (frame.Type == SpriteFrameType.Indexed)
            {
                data = IndexedSpriteFrameToData(frame, p);
            }
            else
            {
                data = frame.Data;
            }

            var sprite = sheetBuilder.Add(data, frame.FrameSize);

            return(sprite.Sheet);
        }
Ejemplo n.º 16
0
        public void SetData(Bitmap bitmap)
        {
            if (!IsPowerOf2(bitmap.Width) || !IsPowerOf2(bitmap.Height))
            {
                //throw new InvalidOperationException( "non-power-of-2-texture" );
                bitmap = new Bitmap(bitmap, new Size(Exts.NextPowerOf2(bitmap.Width), Exts.NextPowerOf2(bitmap.Height)));
            }

            var bits = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb);

            PrepareTexture();
            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, bits.Width, bits.Height,
                            0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bits.Scan0);            // todo: weird strides
            ErrorHandler.CheckGlError();
            bitmap.UnlockBits(bits);
        }
Ejemplo n.º 17
0
        public static Bitmap ShroudBitmap(World world)
        {
            var map    = world.Map;
            var size   = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
            var bitmap = new Bitmap(size, size);

            if (world.LocalShroud.Disabled)
            {
                return(bitmap);
            }

            var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            var shroud = Color.Black.ToArgb();
            var fog    = Color.FromArgb(128, Color.Black).ToArgb();

            unsafe
            {
                int *c = (int *)bitmapData.Scan0;

                for (var x = 0; x < map.Bounds.Width; x++)
                {
                    for (var y = 0; y < map.Bounds.Height; y++)
                    {
                        var mapX = x + map.Bounds.Left;
                        var mapY = y + map.Bounds.Top;
                        if (!world.LocalShroud.IsExplored(mapX, mapY))
                        {
                            *(c + (y * bitmapData.Stride >> 2) + x) = shroud;
                        }
                        else if (!world.LocalShroud.IsVisible(mapX, mapY))
                        {
                            *(c + (y * bitmapData.Stride >> 2) + x) = fog;
                        }
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 18
0
        void LoadFrame()
        {
            if (currentFrame >= frameCount)
            {
                return;
            }

            stream.Seek(frameOffsets[currentFrame], SeekOrigin.Begin);

            var dataLength = frameOffsets[currentFrame + 1] - frameOffsets[currentFrame];

            var rawData          = StreamExts.ReadBytes(stream, (int)dataLength);
            var intermediateData = new byte[width * height];

            // Format80 decompression
            LCWCompression.DecodeInto(rawData, intermediateData);

            // and Format40 decompression
            currentFrameData = new byte[width * height];
            if (previousFrameData == null)
            {
                Array.Clear(currentFrameData, 0, currentFrameData.Length);
            }
            else
            {
                Array.Copy(previousFrameData, currentFrameData, currentFrameData.Length);
            }

            XORDeltaCompression.DecodeInto(intermediateData, currentFrameData, 0);

            var c         = 0;
            var frameSize = Exts.NextPowerOf2(Math.Max(width, height));

            coloredFrameData = new uint[frameSize, frameSize];
            for (var y = 0; y < height; y++)
            {
                for (var x = 0; x < width; x++)
                {
                    coloredFrameData[y, x] = palette[currentFrameData[c++]];
                }
            }
        }
Ejemplo n.º 19
0
        public void Open(WsaReader video)
        {
            this.video = video;

            stopped    = true;
            paused     = true;
            onComplete = () => { };

            var size        = Math.Max(video.Width, video.Height);
            var textureSize = Exts.NextPowerOf2(size);

            var scale = Math.Min((float)RenderBounds.Width / video.Width, (float)RenderBounds.Height / video.Height * AspectRatio);

            videoOrigin = new float2(
                RenderBounds.X + (RenderBounds.Width - scale * video.Width) / 2,
                RenderBounds.Y + (RenderBounds.Height - scale * video.Height * AspectRatio) / 2);

            // Round size to integer pixels. Round up to be consistent with the scale calculation.
            videoSize = new float2((int)Math.Ceiling(video.Width * scale), (int)Math.Ceiling(video.Height * AspectRatio * scale));
        }
Ejemplo n.º 20
0
        public static Bitmap ShroudBitmap(World world)
        {
            var map    = world.Map;
            var size   = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
            var bitmap = new Bitmap(size, size);

            if (world.RenderPlayer == null)
            {
                return(bitmap);
            }

            var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            var shroud = Color.Black.ToArgb();
            var fog    = Color.FromArgb(128, Color.Black).ToArgb();

            unsafe
            {
                int *c = (int *)bitmapData.Scan0;

                for (var x = 0; x < map.Bounds.Width; x++)
                {
                    for (var y = 0; y < map.Bounds.Height; y++)
                    {
                        var p = new CPos(x + map.Bounds.Left, y + map.Bounds.Top);
                        if (world.ShroudObscures(p))
                        {
                            *(c + (y * bitmapData.Stride >> 2) + x) = shroud;
                        }
                        else if (world.FogObscures(p))
                        {
                            *(c + (y * bitmapData.Stride >> 2) + x) = fog;
                        }
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 21
0
        public static Bitmap TerrainBitmap(Map map, bool actualSize)
        {
            var tileset = Rules.TileSets[map.Tileset];
            var width   = map.Bounds.Width;
            var height  = map.Bounds.Height;

            if (!actualSize)
            {
                width = height = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
            }

            var terrain = new Bitmap(width, height);

            var bitmapData = terrain.LockBits(terrain.Bounds(),
                                              ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                int *c = (int *)bitmapData.Scan0;

                for (var x = 0; x < map.Bounds.Width; x++)
                {
                    for (var y = 0; y < map.Bounds.Height; y++)
                    {
                        var mapX = x + map.Bounds.Left;
                        var mapY = y + map.Bounds.Top;
                        var type = tileset.GetTerrainType(map.MapTiles.Value[mapX, mapY]);
                        if (!tileset.Terrain.ContainsKey(type))
                        {
                            throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type));
                        }

                        *(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
                    }
                }
            }

            terrain.UnlockBits(bitmapData);
            return(terrain);
        }
Ejemplo n.º 22
0
        public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
        {
            var b      = map.Bounds;
            var width  = b.Width;
            var height = b.Height;

            if (!actualSize)
            {
                width = height = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
            }

            var terrain = new Bitmap(width, height);

            var bitmapData = terrain.LockBits(terrain.Bounds(),
                                              ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            var mapTiles = map.MapTiles.Value;

            unsafe
            {
                var colors = (int *)bitmapData.Scan0;
                var stride = bitmapData.Stride / 4;
                for (var y = 0; y < b.Height; y++)
                {
                    for (var x = 0; x < b.Width; x++)
                    {
                        var mapX  = x + b.Left;
                        var mapY  = y + b.Top;
                        var type  = tileset.GetTileInfo(mapTiles[new MPos(mapX, mapY)]);
                        var color = type != null ? type.LeftColor : Color.Black;

                        colors[y * stride + x] = color.ToArgb();
                    }
                }
            }

            terrain.UnlockBits(bitmapData);
            return(terrain);
        }
Ejemplo n.º 23
0
        private void LoadFrame()
        {
            if (this.CurrentFrame == 0)
            {
                this.currentFrame = new uint[this.Height / this.stride, this.Width];
                this.palette      = new uint[256];
                this.TextData     = "";
            }
            else
            {
                var nextFrame = this.frames[this.CurrentFrame - 1];

                this.currentFrame = nextFrame.ApplyFrame(this.currentFrame, ref this.palette);

                if (nextFrame.Text != null)
                {
                    this.TextData += nextFrame.Text;
                }
            }

            // TODO for better performance, we should get rid of this copying as soon we can use non-power-of-2 textures
            this.FrameData = new uint[Exts.NextPowerOf2(this.Height), Exts.NextPowerOf2(this.Width)];

            for (var y = 0; y < this.Height / this.stride; y++)
            {
                for (var i = 0; i < this.stride; i++)
                {
                    Buffer.BlockCopy(
                        this.currentFrame,
                        y * this.Width * 4,
                        this.FrameData,
                        (y * this.stride + i) * this.FrameData.GetLength(1) * 4,
                        this.Width * 4
                        );
                }
            }
        }
Ejemplo n.º 24
0
        public static Bitmap ActorsBitmap(World world)
        {
            var map = world.Map;
            var b   = map.Bounds;

            var size       = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
            var bitmap     = new Bitmap(size, size);
            var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                                             ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                var c = (int *)bitmapData.Scan0;

                foreach (var t in world.ActorsWithTrait <IRadarSignature>())
                {
                    if (world.FogObscures(t.Actor))
                    {
                        continue;
                    }

                    var color = t.Trait.RadarSignatureColor(t.Actor);
                    foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
                    {
                        var uv = Map.CellToMap(map.TileShape, cell);
                        if (b.Contains(uv.X, uv.Y))
                        {
                            *(c + ((uv.Y - b.Top) * bitmapData.Stride >> 2) + uv.X - b.Left) = color.ToArgb();
                        }
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            return(bitmap);
        }
Ejemplo n.º 25
0
        public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
        {
            var isRectangularIsometric = map.Grid.Type == MapGridType.RectangularIsometric;
            var b = map.Bounds;

            // Fudge the heightmap offset by adding as much extra as we need / can.
            // This tries to correct for our incorrect assumption that MPos == PPos
            var heightOffset = Math.Min(map.Grid.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
            var width        = b.Width;
            var height       = b.Height + heightOffset;

            var bitmapWidth = width;

            if (isRectangularIsometric)
            {
                bitmapWidth = 2 * bitmapWidth - 1;
            }

            if (!actualSize)
            {
                bitmapWidth = height = Exts.NextPowerOf2(Math.Max(bitmapWidth, height));
            }

            var terrain = new Bitmap(bitmapWidth, height);

            var bitmapData = terrain.LockBits(terrain.Bounds(),
                                              ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            var mapTiles = map.MapTiles.Value;

            unsafe
            {
                var colors = (int *)bitmapData.Scan0;
                var stride = bitmapData.Stride / 4;
                for (var y = 0; y < height; y++)
                {
                    for (var x = 0; x < width; x++)
                    {
                        var uv        = new MPos(x + b.Left, y + b.Top);
                        var type      = tileset.GetTileInfo(mapTiles[uv]);
                        var leftColor = type != null ? type.LeftColor : Color.Black;

                        if (isRectangularIsometric)
                        {
                            // Odd rows are shifted right by 1px
                            var dx         = uv.V & 1;
                            var rightColor = type != null ? type.RightColor : Color.Black;
                            if (x + dx > 0)
                            {
                                colors[y * stride + 2 * x + dx - 1] = leftColor.ToArgb();
                            }

                            if (2 * x + dx < stride)
                            {
                                colors[y * stride + 2 * x + dx] = rightColor.ToArgb();
                            }
                        }
                        else
                        {
                            colors[y * stride + x] = leftColor.ToArgb();
                        }
                    }
                }
            }

            terrain.UnlockBits(bitmapData);
            return(terrain);
        }
Ejemplo n.º 26
0
        public VqaReader(Stream stream)
        {
            this.stream = stream;

            // Decode FORM chunk
            if (stream.ReadASCII(4) != "FORM")
            {
                throw new InvalidDataException("Invalid vqa (invalid FORM section)");
            }
            /*var length = */ stream.ReadUInt32();

            if (stream.ReadASCII(8) != "WVQAVQHD")
            {
                throw new InvalidDataException("Invalid vqa (not WVQAVQHD)");
            }
            /*var length2 = */ stream.ReadUInt32();

            /*var version = */ stream.ReadUInt16();
            videoFlags = stream.ReadUInt16();
            Frames     = stream.ReadUInt16();
            Width      = stream.ReadUInt16();
            Height     = stream.ReadUInt16();

            blockWidth       = stream.ReadUInt8();
            blockHeight      = stream.ReadUInt8();
            Framerate        = stream.ReadUInt8();
            chunkBufferParts = stream.ReadUInt8();
            blocks           = new int2(Width / blockWidth, Height / blockHeight);

            numColors = stream.ReadUInt16();
            /*var maxBlocks = */ stream.ReadUInt16();
            /*var unknown1 = */ stream.ReadUInt16();
            /*var unknown2 = */ stream.ReadUInt32();

            // Audio
            sampleRate    = stream.ReadUInt16();
            audioChannels = stream.ReadByte();
            sampleBits    = stream.ReadByte();

            /*var unknown3 =*/ stream.ReadUInt32();
            /*var unknown4 =*/ stream.ReadUInt16();
            /*maxCbfzSize =*/ stream.ReadUInt32();            // Unreliable

            /*var unknown5 =*/ stream.ReadUInt32();

            var frameSize = Exts.NextPowerOf2(Math.Max(Width, Height));

            if (IsHqVqa)
            {
                cbfBuffer = new byte[maxCbfzSize];
                cbf       = new byte[maxCbfzSize * 3];
                origData  = new byte[maxCbfzSize];
            }
            else
            {
                cbfBuffer = new byte[Width * Height];
                cbf       = new byte[Width * Height];
                cbp       = new byte[Width * Height];
                origData  = new byte[2 * blocks.X * blocks.Y];
            }

            palette   = new uint[numColors];
            frameData = new uint[frameSize, frameSize];
            var type = stream.ReadASCII(4);

            while (type != "FINF")
            {
                // Sub type is a file tag
                if (type[3] == 'F')
                {
                    var jmp = int2.Swap(stream.ReadUInt32());
                    stream.Seek(jmp, SeekOrigin.Current);
                    type = stream.ReadASCII(4);
                }
                else
                {
                    throw new NotSupportedException("Vqa uses unknown Subtype: {0}".F(type));
                }
            }

            /*var length = */ stream.ReadUInt16();
            /*var unknown4 = */ stream.ReadUInt16();

            // Frame offsets
            offsets = new uint[Frames];
            for (var i = 0; i < Frames; i++)
            {
                offsets[i] = stream.ReadUInt32();
                if (offsets[i] > 0x40000000)
                {
                    offsets[i] -= 0x40000000;
                }
                offsets[i] <<= 1;
            }

            CollectAudioData();

            Reset();
        }
Ejemplo n.º 27
0
        public WsaVideo(Stream stream, bool useFramePadding)
        {
            this.stream = stream;

            FrameCount = stream.ReadUInt16();

            /*var x = */ stream.ReadUInt16();
            /*var y = */ stream.ReadUInt16();

            Width  = stream.ReadUInt16();
            Height = stream.ReadUInt16();

            var delta = stream.ReadUInt16() + 37;
            var flags = stream.ReadUInt16();

            frameOffsets = new uint[FrameCount + 2];
            for (var i = 0; i < frameOffsets.Length; i++)
            {
                frameOffsets[i] = stream.ReadUInt32();
            }

            if (flags == 1)
            {
                paletteBytes = new byte[1024];
                for (var i = 0; i < paletteBytes.Length;)
                {
                    var r = (byte)(stream.ReadByte() << 2);
                    var g = (byte)(stream.ReadByte() << 2);
                    var b = (byte)(stream.ReadByte() << 2);

                    // Replicate high bits into the (currently zero) low bits.
                    r |= (byte)(r >> 6);
                    g |= (byte)(g >> 6);
                    b |= (byte)(b >> 6);

                    paletteBytes[i++] = b;
                    paletteBytes[i++] = g;
                    paletteBytes[i++] = r;
                    paletteBytes[i++] = 255;
                }

                for (var i = 0; i < frameOffsets.Length; i++)
                {
                    frameOffsets[i] += 768;
                }
            }

            if (useFramePadding)
            {
                var frameSize = Exts.NextPowerOf2(Math.Max(Width, Height));
                CurrentFrameData = new byte[frameSize * frameSize * 4];
                totalFrameWidth  = (ushort)frameSize;
            }
            else
            {
                CurrentFrameData = new byte[Width * Height * 4];
                totalFrameWidth  = Width;
            }

            Reset();
        }
Ejemplo n.º 28
0
        public override void Draw()
        {
            if (video == null)
            {
                return;
            }

            if (!stopped && !paused)
            {
                var nextFrame = 0;
                if (video.HasAudio && !Game.Sound.DummyEngine)
                {
                    nextFrame = (int)float2.Lerp(0, video.Frames, Game.Sound.VideoSeekPosition * invLength);
                }
                else
                {
                    nextFrame = video.CurrentFrame + 1;
                }

                // Without the 2nd check the sound playback sometimes ends before the final frame is displayed which causes the player to be stuck on the first frame
                if (nextFrame > video.Frames || nextFrame < video.CurrentFrame)
                {
                    Stop();
                    return;
                }

                var skippedFrames = 0;
                while (nextFrame > video.CurrentFrame)
                {
                    video.AdvanceFrame();
                    videoSprite.Sheet.GetTexture().SetData(video.FrameData);
                    skippedFrames++;
                }

                if (skippedFrames > 1)
                {
                    Log.Write("perf", "VqaPlayer : {0} skipped {1} frames at position {2}", cachedVideo, skippedFrames, video.CurrentFrame);
                }
            }

            WidgetUtils.DrawSprite(videoSprite, videoOrigin, videoSize);

            if (DrawOverlay)
            {
                // Create the scan line grid to render over the video
                // To avoid aliasing, this must be an integer number of screen pixels.
                // A few complications to be aware of:
                // - The video may have a different aspect ratio to the widget RenderBounds
                // - The RenderBounds coordinates may be a non-integer scale of the screen pixel size
                // - The screen pixel size may change while the video is playing back
                //   (user moves a window between displays with different DPI on macOS)
                var scale = Game.Renderer.WindowScale;
                if (overlaySheet == null || overlayScale != scale)
                {
                    overlaySheet?.Dispose();

                    // Calculate the scan line height by converting the video scale (copied from Open()) to screen
                    // pixels, halving it (scan lines cover half the pixel height), and rounding to the nearest integer.
                    var videoScale    = Math.Min((float)RenderBounds.Width / video.Width, RenderBounds.Height / (video.Height * AspectRatio));
                    var halfRowHeight = (int)(videoScale * scale / 2 + 0.5f);

                    // The overlay can be minimally stored in a 1px column which is stretched to cover the full screen
                    var overlayHeight    = (int)(RenderBounds.Height * scale / halfRowHeight);
                    var overlaySheetSize = new Size(1, Exts.NextPowerOf2(overlayHeight));
                    var overlay          = new byte[4 * Exts.NextPowerOf2(overlayHeight)];
                    overlaySheet = new Sheet(SheetType.BGRA, overlaySheetSize);

                    // Every second pixel is the scan line - set alpha to 128 to make the lines less harsh
                    for (var i = 3; i < 4 * overlayHeight; i += 8)
                    {
                        overlay[i] = 128;
                    }

                    overlaySheet.GetTexture().SetData(overlay, overlaySheetSize.Width, overlaySheetSize.Height);
                    overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, 1, overlayHeight), TextureChannel.RGBA);

                    // Overlay origin must be rounded to the nearest screen pixel to prevent aliasing
                    overlayOrigin = new float2((int)(RenderBounds.X * scale + 0.5f), (int)(RenderBounds.Y * scale + 0.5f)) / scale;
                    overlaySize   = new float2(RenderBounds.Width, overlayHeight * halfRowHeight / scale);
                    overlayScale  = scale;
                }

                WidgetUtils.DrawSprite(overlaySprite, overlayOrigin, overlaySize);
            }
        }
Ejemplo n.º 29
0
        public VqaReader(Stream stream)
        {
            this.stream = stream;

            // Decode FORM chunk
            if (stream.ReadASCII(4) != "FORM")
            {
                throw new InvalidDataException("Invalid vqa (invalid FORM section)");
            }
            /*var length = */ stream.ReadUInt32();

            if (stream.ReadASCII(8) != "WVQAVQHD")
            {
                throw new InvalidDataException("Invalid vqa (not WVQAVQHD)");
            }
            /* var length = */ stream.ReadUInt32();

            /*var version = */ stream.ReadUInt16();
            /*var flags = */ stream.ReadUInt16();
            Frames = stream.ReadUInt16();
            Width  = stream.ReadUInt16();
            Height = stream.ReadUInt16();

            blockWidth  = stream.ReadUInt8();
            blockHeight = stream.ReadUInt8();
            Framerate   = stream.ReadUInt8();
            cbParts     = stream.ReadUInt8();
            blocks      = new int2(Width / blockWidth, Height / blockHeight);

            numColors = stream.ReadUInt16();
            /*var maxBlocks = */ stream.ReadUInt16();
            /*var unknown1 = */ stream.ReadUInt16();
            /*var unknown2 = */ stream.ReadUInt32();

            // Audio
            /*var freq = */ stream.ReadUInt16();
            /*var channels = */ stream.ReadByte();
            /*var bits = */ stream.ReadByte();
            /*var unknown3 = */ stream.ReadBytes(14);

            var frameSize = Exts.NextPowerOf2(Math.Max(Width, Height));

            cbf       = new byte[Width * Height];
            cbp       = new byte[Width * Height];
            palette   = new uint[numColors];
            origData  = new byte[2 * blocks.X * blocks.Y];
            frameData = new uint[frameSize, frameSize];

            var type = stream.ReadASCII(4);

            if (type != "FINF")
            {
                stream.Seek(27, SeekOrigin.Current);
                type = stream.ReadASCII(4);
            }

            /*var length = */ stream.ReadUInt16();
            /*var unknown4 = */ stream.ReadUInt16();

            // Frame offsets
            offsets = new UInt32[Frames];
            for (int i = 0; i < Frames; i++)
            {
                offsets[i] = stream.ReadUInt32();
                if (offsets[i] > 0x40000000)
                {
                    offsets[i] -= 0x40000000;
                }
                offsets[i] <<= 1;
            }

            CollectAudioData();

            Reset();
        }