using System; using UnityEngine; using System.Collections; using System.Collections.Generic; public class FogOverlay : MonoBehaviour { private const int fogTextureResolution = 256; private const int fogTextureSize = fogTextureResolution * fogTextureResolution; public Color fogColor = new Color(1, 1, 1, .3f); public Color noFogColor = new Color(1, 1, 1, 0); public float radius = 1; public int minFogZoom = 15; private Texture2D defaultFog; private List points; private void ApplyPointToTiles(Vector2 newLocation) { lock (OnlineMapsTile.tiles) { foreach (OnlineMapsTile tile in OnlineMapsTile.tiles) { Texture2D texture = tile.overlayBackTexture; if (texture == null) continue; double r = radius * (1 << tile.zoom) / (1 << 20); double r2 = r * r * 256 * 256; int tilex = tile.x * 256; int tiley = tile.y * 256; double tx, ty; OnlineMaps.instance.projection.CoordinatesToTile(newLocation.x, newLocation.y, tile.zoom, out tx, out ty); double stx = tx - r; double sty = ty - r; double etx = tx + r; double ety = ty + r; if ((int)stx <= tile.x && (int)sty <= tile.y && (int)etx >= tile.x && (int)ety >= tile.y) { int sx = (int)((stx - tile.x) * fogTextureResolution); if (sx < 0) sx = 0; else if (sx >= fogTextureResolution) continue; int sy = (int)((sty - tile.y) * fogTextureResolution); if (sy < 0) sy = 0; else if (sy >= fogTextureResolution) continue; int ex = (int)((etx - tile.x) * fogTextureResolution); if (ex >= fogTextureResolution) ex = fogTextureResolution - 1; else if (ex < 0) continue; int ey = (int)((ety - tile.y) * fogTextureResolution); if (ey >= fogTextureResolution) ey = fogTextureResolution - 1; else if (ey < 0) continue; int itx = (int)(tx * 256) - tilex; int ity = (int)(ty * 256) - tiley; Color[] colors = texture.GetPixels(); for (int y = sy; y < ey + 1; y++) { int cy = (fogTextureResolution - y - 1) * fogTextureResolution; double dy = ity - y; double dy2 = dy * dy; if (dy2 >= r2) continue; for (int x = sx; x < ex + 1; x++) { double dx = itx - x; if (dx * dx + dy2 < r2) { colors[cy + x] = noFogColor; } } } texture.SetPixels(colors); texture.Apply(); } } } } private void ApplyPointsToTile(OnlineMapsTile tile) { Texture2D texture = tile.overlayBackTexture; Color[] colors = texture.GetPixels(); bool textureChanged = false; double r = radius * (1 << tile.zoom) / (1 << 20); double r2 = r * r * 256 * 256; int tilex = tile.x * 256; int tiley = tile.y * 256; foreach (Vector2 point in points) { double tx, ty; OnlineMaps.instance.projection.CoordinatesToTile(point.x, point.y, tile.zoom, out tx, out ty); double stx = tx - r; double sty = ty - r; double etx = tx + r; double ety = ty + r; if ((int)stx <= tile.x && (int)sty <= tile.y && (int)etx >= tile.x && (int)ety >= tile.y) { int sx = (int)((stx - tile.x) * fogTextureResolution); if (sx < 0) sx = 0; else if (sx >= fogTextureResolution) continue; int sy = (int)((sty - tile.y) * fogTextureResolution); if (sy < 0) sy = 0; else if (sy >= fogTextureResolution) continue; int ex = (int)((etx - tile.x) * fogTextureResolution); if (ex >= fogTextureResolution) ex = fogTextureResolution - 1; else if (ex < 0) continue; int ey = (int)((ety - tile.y) * fogTextureResolution); if (ey >= fogTextureResolution) ey = fogTextureResolution - 1; else if (ey < 0) continue; textureChanged = true; int itx = (int) (tx * 256) - tilex; int ity = (int) (ty * 256) - tiley; for (int y = sy; y < ey + 1; y++) { int cy = (fogTextureResolution - y - 1) * fogTextureResolution; double dy = ity - y; double dy2 = dy * dy; if (dy2 >= r2) continue; for (int x = sx; x < ex + 1; x++) { double dx = itx - x; if (dx * dx + dy2 < r2) { colors[cy + x] = noFogColor; } } } } } if (textureChanged) { texture.SetPixels(colors); texture.Apply(); } } private void OnLocationChanged(Vector2 newLocation) { points.Add(newLocation); ApplyPointToTiles(newLocation); } private void OnStartDownloadTile(OnlineMapsTile tile) { if (tile.zoom >= minFogZoom) { tile.overlayBackTexture = Instantiate(defaultFog) as Texture2D; tile.overlayBackTexture.name = tile.zoom + "x" + tile.x + "x" + tile.y; ApplyPointsToTile(tile); } OnlineMaps.instance.StartDownloadTile(tile); } private void Start() { points = new List(); defaultFog = new Texture2D(fogTextureResolution, fogTextureResolution, TextureFormat.ARGB32, false); defaultFog.wrapMode = TextureWrapMode.Clamp; Color[] defaultFogColors = new Color[fogTextureSize]; for (int i = 0; i < fogTextureSize; i++) defaultFogColors[i] = fogColor; defaultFog.SetPixels(defaultFogColors); defaultFog.Apply(); OnlineMaps.instance.OnStartDownloadTile += OnStartDownloadTile; OnlineMapsLocationService.instance.OnLocationChanged += OnLocationChanged; } }