using BruTile; using BruTile.MbTiles; using SQLite; using System.Collections.Generic; using System.IO; using System.Linq.Expressions; using System.Net; using UnityEngine; using UnityEngine.UI; // Overlay tiles received from mbtiles public class OverlayManager : MonoBehaviour { private OnlineMaps map; [Tooltip("Tiles has to be placed in StreamingAssets Folder")] public List OverlayTilesName; private int resolution = 256; private void Start() { map = OnlineMaps.instance; if (OnlineMapsCache.instance != null) { // Subscribe to the cache events. OnlineMapsCache.instance.OnLoadedFromCache += LoadTileFromMB; } // Subscribe to the tile download event. OnlineMapsTileManager.OnStartDownloadTile += OnStartDownloadTile; } public void ToggleOverlay(string overlayName) { ChangeEnableState(overlayName); } // This function updates information about the textures we want to overlay and should overlay a new update texture on the tiles private void ChangeEnableState(string overlayName) { overlayName = overlayName.ToLower(); foreach (Overlay overlay in OverlayTilesName) { if (overlay.Name.ToLower().Equals(overlayName)) { overlay.Enabled = !overlay.Enabled; } } // How to redraw/reload new texture onto the current tiles? OnlineMapsCache.instance.ClearAllCaches(); map.RedrawImmediately(); OnlineMaps.instance.tileManager.StartDownloading(); } // Create a texture from mbtiles sources and apply them as an overlay texture private void LoadTileFromMB(OnlineMapsTile tile) { List layers = new List(); // Add all texture layers to the TextureArray for (int i = 0; i < OverlayTilesName.Count; i++) { Texture2D tileTexture = new Texture2D(resolution, resolution); string path = $"{Application.streamingAssetsPath}/{OverlayTilesName[i].Path}.mbtiles"; // Check if path exist if (!File.Exists(path)) { Debug.LogError($"The {OverlayTilesName[i]} mbtile file does not exist"); } else if (!OverlayTilesName[i].Enabled) { continue; } else { MbTilesTileSource mbTileSource = new MbTilesTileSource(new SQLiteConnectionString(path, false)); // flip y because MBTiles is TMS schemed format, we need it in xyz int flippedY = (1 << tile.zoom) - 1 - tile.y; byte[] mbTilesTile = mbTileSource.GetTile(new TileInfo { Index = new TileIndex(tile.x, flippedY, tile.zoom) }); if (mbTilesTile != null) { tileTexture.LoadImage(mbTilesTile); layers.Add(tileTexture); } } } // If there's no new layers, just return if (layers.Count == 0) return; Texture2D finalTexture = MakeTexture(layers); finalTexture.wrapMode = TextureWrapMode.Clamp; tile.overlayBackTexture = Instantiate(finalTexture); // Destroy because it is no longer needed OnlineMapsUtils.Destroy(finalTexture); } // Make a texture from the given layers. Assumption is that all layers given are non empty. private Texture2D MakeTexture(List layers) { Texture2D finalTexture = new Texture2D(resolution, resolution); Color[] finalColorArray = new Color[resolution * resolution]; Color[][] sourceColorArray = new Color[layers.Count][]; // Assign texture's color to SrcArray for(int i = 0; i < layers.Count; i++) { sourceColorArray[i] = layers[i].GetPixels(); } // Loop through final color array for(int x = 0; x < finalTexture.height; x++) // loop through row { for(int y = 0; y < finalTexture.width; y++) // loop through column { int pixelIndex = y + x * finalTexture.width; // current index on a 1d array for(int i = 0; i < layers.Count; i++) { Color srcPixel = sourceColorArray[i][pixelIndex]; if (srcPixel.a > 0) // only add pixels to final color array if the pixel is not transparent finalColorArray[pixelIndex] = srcPixel; } } } finalTexture.SetPixels(finalColorArray); finalTexture.Apply(); return finalTexture; } private void OnStartDownloadTile(OnlineMapsTile tile) { LoadTileFromMB(tile); Debug.Log("On start called"); OnlineMapsTileManager.StartDownloadTile(tile); // Redraw map (using best redraw type) map.Redraw(); } }