using System.Collections.Generic; using UnityEngine; public class FogOverlay2 : 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 int minFogZoom = 13; private Texture2D defaultFog; private List visitedTiles; private void ApplyPointToTiles(OnlineMapsVector2i newTile) { lock (OnlineMapsTile.tiles) { foreach (OnlineMapsTile tile in OnlineMapsTile.tiles) { Texture2D texture = tile.overlayBackTexture; if (texture == null) continue; if (tile.zoom == 17) { if (visitedTiles.Contains(new OnlineMapsVector2i(tile.x, tile.y))) { OnlineMapsUtils.DestroyImmediate(tile.overlayBackTexture); tile.overlayBackTexture = null; } } else if (tile.zoom > 17) { int ptx = tile.x / (1 << tile.zoom - 17); int pty = tile.y / (1 << tile.zoom - 17); if (visitedTiles.Contains(new OnlineMapsVector2i(ptx, pty))) { OnlineMapsUtils.DestroyImmediate(tile.overlayBackTexture); tile.overlayBackTexture = null; } } else { double lng, lat, tx, ty; OnlineMaps.instance.projection.TileToCoordinates(newTile.x, newTile.y, 17, out lng, out lat); OnlineMaps.instance.projection.CoordinatesToTile(lng, lat, tile.zoom, out tx, out ty); if ((int) tx == tile.x && (int) ty == tile.y) { double s = 1 << (17 - tile.zoom); tx -= tile.x; ty -= tile.y; if (tx < 0 || tx > 1 || ty < 0 || ty > 1) continue; double stx = tx * fogTextureResolution; double sty = ty * fogTextureResolution; double etx = stx + fogTextureResolution / s; double ety = sty + fogTextureResolution / s; int sx = (int)stx; if (sx < 0) sx = 0; else if (sx >= fogTextureResolution) continue; int sy = (int)sty; if (sy < 0) sy = 0; else if (sy >= fogTextureResolution) continue; int ex = (int)etx; if (ex >= fogTextureResolution) ex = fogTextureResolution - 1; else if (ex < 0) continue; int ey = (int)ety; if (ey >= fogTextureResolution) ey = fogTextureResolution - 1; else if (ey < 0) continue; Color[] colors = texture.GetPixels(); for (int y = sy; y < ey + 1; y++) { int cy = (fogTextureResolution - y - 1) * fogTextureResolution; for (int x = sx; x < ex + 1; x++) colors[cy + x] = noFogColor; } texture.SetPixels(colors); texture.Apply(); } } } } } private void ApplyPointsToTile(OnlineMapsTile tile) { Texture2D texture = tile.overlayBackTexture; if (texture == null) return; int fr2 = fogTextureResolution - 1; if (tile.zoom == 17) { if (visitedTiles.Contains(new OnlineMapsVector2i(tile.x, tile.y))) { OnlineMapsUtils.DestroyImmediate(tile.overlayBackTexture); tile.overlayBackTexture = null; } } else if (tile.zoom > 17) { int ptx = tile.x / (1 << tile.zoom - 17); int pty = tile.y / (1 << tile.zoom - 17); if (visitedTiles.Contains(new OnlineMapsVector2i(ptx, pty))) { OnlineMapsUtils.DestroyImmediate(tile.overlayBackTexture); tile.overlayBackTexture = null; } } else { Color[] colors = null; bool textureChanged = false; foreach (OnlineMapsVector2i t in visitedTiles) { double s = 1 << (17 - tile.zoom); double tx = t.x / s - tile.x; double ty = t.y / s - tile.y; if (tx < 0 || tx > 1 || ty < 0 || ty > 1) continue; double fs = fogTextureResolution / s; double stx = tx * fogTextureResolution; double sty = ty * fogTextureResolution; double etx = stx + fs; double ety = sty + fs; int sx = (int)stx; if (sx < 0) sx = 0; else if (sx >= fogTextureResolution) continue; int sy = (int)sty; if (sy < 0) sy = 0; else if (sy >= fogTextureResolution) continue; int ex = (int)etx; if (ex >= fogTextureResolution) ex = fr2; else if (ex < 0) continue; int ey = (int)ety; if (ey >= fogTextureResolution) ey = fr2; else if (ey < 0) continue; textureChanged = true; if (colors == null) colors = texture.GetPixels(); for (int y = sy; y < ey + 1; y++) { int cy = (fr2 - y) * fogTextureResolution; for (int x = sx; x < ex + 1; x++) colors[cy + x] = noFogColor; } } if (textureChanged) { texture.SetPixels(colors); texture.Apply(); } } } private void OnLocationChanged(Vector2 newLocation) { double tx, ty; OnlineMaps.instance.projection.CoordinatesToTile(newLocation.x, newLocation.y, 17, out tx, out ty); OnlineMapsVector2i v = new OnlineMapsVector2i((int)tx, (int)ty); if (!visitedTiles.Contains(v)) { visitedTiles.Add(v); ApplyPointToTiles(v); } } 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() { visitedTiles = 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(); if (OnlineMapsCache.instance != null) { OnlineMapsCache.instance.OnLoadedFromCache += OnLoadedFromCache; OnlineMapsCache.instance.OnStartDownloadTile += OnStartDownloadTile; } else OnlineMaps.instance.OnStartDownloadTile += OnStartDownloadTile; //OnlineMapsLocationService.instance.OnLocationChanged += OnLocationChanged; OnlineMapsControlBase.instance.OnMapClick += OnMapClick; } private void OnLoadedFromCache(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); } } private void OnMapClick() { Vector2 newLocation = OnlineMapsControlBase.instance.GetCoords(); double tx, ty; OnlineMaps.instance.projection.CoordinatesToTile(newLocation.x, newLocation.y, 17, out tx, out ty); OnlineMapsVector2i v = new OnlineMapsVector2i((int)tx, (int)ty); if (!visitedTiles.Contains(v)) { visitedTiles.Add(v); ApplyPointToTiles(v); } } }