114 lines
3.2 KiB
C#
114 lines
3.2 KiB
C#
using Cryville.EEW.Core.Map;
|
|
using System;
|
|
using System.IO;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.Networking;
|
|
|
|
namespace Cryville.EEW.Unity.Map {
|
|
[RequireComponent(typeof(SpriteRenderer))]
|
|
sealed class MapTile : MonoBehaviour {
|
|
static readonly SemaphoreSlim _semaphore = new(2);
|
|
|
|
static readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(10) };
|
|
|
|
[SerializeField] Transform _idView;
|
|
|
|
public MapTileIndex Index { get; set; }
|
|
public bool IsEmpty { get; private set; }
|
|
|
|
Action<MapTile> _callback;
|
|
|
|
SpriteRenderer _renderer;
|
|
|
|
UnityWebRequest _req;
|
|
DownloadHandlerTexture _texHandler;
|
|
Texture2D _tex;
|
|
Sprite _sprite;
|
|
|
|
void Awake() {
|
|
_renderer = GetComponent<SpriteRenderer>();
|
|
}
|
|
|
|
FileInfo _localFile;
|
|
bool _downloadDone;
|
|
public void Load(MapTileIndex index, string cacheDir, Action<MapTile> onUpdated) {
|
|
Index = index;
|
|
_callback = onUpdated;
|
|
_localFile = new(Path.Combine(cacheDir, $"map/{Index.Z}/{Index.NX}/{Index.NY}"));
|
|
float z = 1 << index.Z;
|
|
transform.localPosition = new(index.X / z, -(index.Y + 1) / z, -index.Z / 100f);
|
|
transform.localScale = new Vector3(1 / z, 1 / z, 1);
|
|
_idView.gameObject.SetActive(true);
|
|
byte e = SharedSettings.Instance.IdBytes[((index.X << 2) + index.Y) & 0x1f];
|
|
int ex = e >> 4, ey = e & 0xf;
|
|
_idView.localPosition = new(ex / 16f, 1 - ey / 16f, -1 / 200f);
|
|
if (_localFile.Exists) {
|
|
_downloadDone = true;
|
|
}
|
|
else {
|
|
Task.Run(() => RunAsync($"https://server.arcgisonline.com/ArcGIS/rest/services/Ocean/World_Ocean_Base/MapServer/tile/{Index.Z}/{Index.NY}/{Index.NX}"));
|
|
}
|
|
}
|
|
async Task RunAsync(string url) {
|
|
await _semaphore.WaitAsync().ConfigureAwait(true);
|
|
try {
|
|
Directory.CreateDirectory(_localFile.DirectoryName);
|
|
using var webStream = await _httpClient.GetStreamAsync(new Uri(url)).ConfigureAwait(true);
|
|
using var fileStream = new FileStream(_localFile.FullName, FileMode.Create, FileAccess.Write);
|
|
await webStream.CopyToAsync(fileStream).ConfigureAwait(true);
|
|
}
|
|
finally {
|
|
_semaphore.Release();
|
|
}
|
|
_downloadDone = true;
|
|
}
|
|
|
|
void Update() {
|
|
if (_downloadDone) {
|
|
try {
|
|
_texHandler = new DownloadHandlerTexture();
|
|
_req = new UnityWebRequest($"file:///{_localFile}") {
|
|
downloadHandler = _texHandler,
|
|
disposeDownloadHandlerOnDispose = true,
|
|
};
|
|
_req.SendWebRequest();
|
|
}
|
|
catch (Exception ex) {
|
|
Debug.LogException(ex);
|
|
}
|
|
_downloadDone = false;
|
|
}
|
|
if (_req == null || !_req.isDone) return;
|
|
if (_texHandler.isDone) {
|
|
_tex = _texHandler.texture;
|
|
_tex.wrapMode = TextureWrapMode.Clamp;
|
|
_sprite = Sprite.Create(_tex, new Rect(0, 0, _tex.width, _tex.height), Vector2.zero, _tex.height, 0, SpriteMeshType.FullRect, Vector4.zero, false);
|
|
_renderer.sprite = _sprite;
|
|
}
|
|
else {
|
|
Debug.LogError(_req.error);
|
|
_localFile.Delete();
|
|
IsEmpty = true;
|
|
}
|
|
_req.Dispose();
|
|
_req = null;
|
|
_callback?.Invoke(this);
|
|
}
|
|
|
|
void OnDestroy() {
|
|
if (_req != null) {
|
|
_req.Abort();
|
|
_req.Dispose();
|
|
_texHandler.Dispose();
|
|
}
|
|
if (_sprite) Destroy(_sprite);
|
|
if (_tex) Destroy(_tex);
|
|
IsEmpty = true;
|
|
_callback?.Invoke(this);
|
|
}
|
|
}
|
|
}
|