public void UpdateWorldImage(RectI area, bool isRenderedLayer = false, string renderMsg = "Render Update Complete.", WriteableBitmap img = null) { // validate area area.Rebound(_world.Header.WorldBounds); int width = area.Width; int height = area.Height; int rts = isRenderedLayer ? 8 : 1; string renderProgressMsg = isRenderedLayer ? "Rendering Textured World..." : "Rendering Pixel World..."; if (img == null) { img = isRenderedLayer ? _worldImage.Rendered : _worldImage.Image; } var pixels = new BytePixels(area.Size * rts, 4); var stride = img.PixelWidth * img.Format.BitsPerPixel / 8; for (int x = area.X; x <= area.Right; x++) { int dx = x - area.X; if (renderMsg != null) { OnProgressChanged(this, dx, width, renderProgressMsg); } for (int y = area.Y; y <= area.Bottom; y++) { int dy = y - area.Y; Tile tile = _world.Tiles[x, y]; if (tile != null) { var xy = (new PointInt32(x, y) - area.TopLeft) * rts; var bp = isRenderedLayer ? GetTexture(y, tile) : GetTextureLayer("TilePixel", y, tile); bp.PutData(pixels, xy); } } } SizeInt32 ts = new SizeInt32(rts, rts); var realArea = isRenderedLayer ? new RectI(new PointInt32(), area.Size * ts) : area; // Rendered layer starts at 0,0 img.Lock(); img.WritePixels(realArea, pixels.GetData(), stride, 0); if (!isRenderedLayer) { img.AddDirtyRect(realArea); } img.Unlock(); if (renderMsg != null) { OnProgressChanged(this, 100, 100, renderMsg); } }
private BytePixels GetTextureLayer(string layerType, int y, Tile tile) { var size = 8; var sizeI = new SizeInt32(size, size); var pixels = new BytePixels(sizeI, 4); var rect00 = new RectI(0, 0, sizeI); string key = String.Empty; switch (layerType) { case "TilePixel": Color c = GetTileColor(y, tile); var b = new byte[4]; b[0] = c.B; b[1] = c.G; b[2] = c.R; b[3] = c.A; pixels = new BytePixels(1, 1, b); break; case "Wall": key = GetTileKey(y, tile, 'W'); if (textureCache.Contains(key)) { return((BytePixels)textureCache.Get(key)); } // FIXME: A complete wall is actually 16x16 big, with 3x3 variations, depending how many tiles exist // if (tile.Wall > 0) { pixels = WorldSettings.Walls[tile.Wall].Texture.GetData(new RectI(166, 58, sizeI)); // tile with most coverage (will be eventually replaced per FIXME) } else { // FIXME: These are actually pretty large bitmaps // // Might need to go on a WallsBack layer... // if (y >= _world.Header.WorldBounds.Bottom - 192) { pixels = WorldSettings.GlobalColors["Hell"].Texture.GetData(rect00); } else if (y > _world.Header.WorldRockLayer) { pixels = WorldSettings.GlobalColors["Rock"].Texture.GetData(rect00); } else if (y > _world.Header.WorldSurface) { pixels = WorldSettings.GlobalColors["Earth"].Texture.GetData(rect00); } else { pixels = WorldSettings.GlobalColors["Sky"].Texture.GetData(rect00); } } break; case "TileBack": key = GetTileKey(y, tile, 'T'); if (textureCache.Contains(key)) { return((BytePixels)textureCache.Get(key)); } // FIXME: Need XML property for larger than 8x8 sizes if (tile.IsActive && !WorldSettings.Tiles[tile.Type].IsSolid) { var rect = (WorldSettings.Tiles[tile.Type].IsFramed) ? new RectI(tile.Frame.X / 2, tile.Frame.Y / 2, sizeI) : rect00; pixels = WorldSettings.Tiles[tile.Type].Texture.GetData(rect); } break; // FIXME: NPC layer would go here... // case "TileFront": key = GetTileKey(y, tile, 'T'); if (textureCache.Contains(key)) { return((BytePixels)textureCache.Get(key)); } // FIXME: Need XML property for larger than 8x8 sizes if (tile.IsActive && WorldSettings.Tiles[tile.Type].IsSolid) { var rect = (WorldSettings.Tiles[tile.Type].IsFramed) ? new RectI(tile.Frame.X / 2, tile.Frame.Y / 2, sizeI) : rect00; pixels = WorldSettings.Tiles[tile.Type].Texture.GetData(rect); } break; case "Liquid": key = GetTileKey(y, tile, 'L'); if (textureCache.Contains(key)) { return((BytePixels)textureCache.Get(key)); } if (tile.Liquid > 0) { // Should use Liquid levels to determine final height // // Actually, bottom 4x4 should be for 255, and top 4x4 for anything else // if (tile.IsLava) { pixels = WorldSettings.GlobalColors["Lava"].Texture.GetData(rect00); } else { pixels = WorldSettings.GlobalColors["Water"].Texture.GetData(rect00); } } break; } // Cache policy for new cache items var cachePolicy = new CacheItemPolicy(); cachePolicy.SlidingExpiration = new TimeSpan(0, 5, 0); // 5 minute duration if not used if (shortKeyRegEx.IsMatch(key)) { cachePolicy.Priority = CacheItemPriority.NotRemovable; // single unframed tiles and walls get perma-cached } textureCache.Add(key, pixels, cachePolicy); return(pixels); }