diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Map/Tile.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Map/Tile.cs
index af5fd383d..25fa73db6 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Map/Tile.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Map/Tile.cs
@@ -11,6 +11,7 @@ namespace Mapbox.Map
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+ using Mapbox.Unity.Utilities;
///
@@ -38,7 +39,9 @@ public enum State
/// Data loaded and parsed.
Loaded,
/// Data loading cancelled.
- Canceled
+ Canceled,
+ /// Data has been loaded before and got updated.
+ Updated
}
/// Gets the identifier.
@@ -103,6 +106,10 @@ public State CurrentState
}
}
+
+ public HttpRequestType RequestType { get { return _request.RequestType; } }
+
+
public bool IsCompleted
{
get
@@ -209,7 +216,7 @@ private void HandleTileResponse(Response response)
ids.Add(_id.ToString());
else
return;
-
+
response.Exceptions.ToList().ForEach(e => AddException(e));
}
else
@@ -225,7 +232,14 @@ private void HandleTileResponse(Response response)
// Cancelled is not the same as loaded!
if (_state != State.Canceled)
{
- _state = State.Loaded;
+ if (response.IsUpdate)
+ {
+ _state = State.Updated;
+ }
+ else
+ {
+ _state = State.Loaded;
+ }
}
_callback();
}
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CacheItem.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CacheItem.cs
new file mode 100644
index 000000000..b3be547f5
--- /dev/null
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CacheItem.cs
@@ -0,0 +1,19 @@
+
+namespace Mapbox.Platform.Cache
+{
+
+ using System;
+
+
+ public class CacheItem
+ {
+ /// Raw response data-
+ public byte[] Data;
+ /// UTC ticks when item was added to the cache.
+ public long AddedToCacheTicksUtc;
+ /// ETag value of API response. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
+ public string ETag;
+ /// Can be 'null' as not all APIs populated this value. Last-Modified value of API response in GMT: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified
+ public DateTime? LastModified;
+ }
+}
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CacheItem.cs.meta b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CacheItem.cs.meta
new file mode 100644
index 000000000..452583767
--- /dev/null
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CacheItem.cs.meta
@@ -0,0 +1,13 @@
+fileFormatVersion: 2
+guid: 3bad456c58de85d47b4ff050dbd99915
+timeCreated: 1510665832
+licenseType: Pro
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CachingWebFileSource.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CachingWebFileSource.cs
index b11dba12f..e563e8a55 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CachingWebFileSource.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/CachingWebFileSource.cs
@@ -6,6 +6,8 @@
using Mapbox.Unity.Utilities;
using Mapbox.Map;
using System.Collections;
+ using System.Linq;
+
public class CachingWebFileSource : IFileSource, IDisposable
{
@@ -14,11 +16,13 @@ public class CachingWebFileSource : IFileSource, IDisposable
private bool _disposed;
private List _caches = new List();
private string _accessToken;
+ private bool _autoRefreshCache;
- public CachingWebFileSource(string accessToken)
+ public CachingWebFileSource(string accessToken, bool autoRefreshCache)
{
_accessToken = accessToken;
+ _autoRefreshCache = autoRefreshCache;
}
@@ -104,64 +108,160 @@ string uri
throw new Exception("Cannot cache without a map id");
}
- byte[] data = null;
+ CacheItem cachedItem = null;
// go through existing caches and check if we already have the requested tile available
foreach (var cache in _caches)
{
- data = cache.Get(mapId, tileId);
- if (null != data)
+ cachedItem = cache.Get(mapId, tileId);
+ if (null != cachedItem)
{
break;
}
}
- // if tile was available propagate to all other caches and return
- if (null != data)
+ var uriBuilder = new UriBuilder(uri);
+ if (!string.IsNullOrEmpty(_accessToken))
{
- foreach (var cache in _caches)
+ string accessTokenQuery = "access_token=" + _accessToken;
+ if (uriBuilder.Query != null && uriBuilder.Query.Length > 1)
+ {
+ uriBuilder.Query = uriBuilder.Query.Substring(1) + "&" + accessTokenQuery;
+ }
+ else
{
- cache.Add(mapId, tileId, data);
+ uriBuilder.Query = accessTokenQuery;
+ }
+ }
+ string finalUrl = uriBuilder.ToString();
+
+
+ // if tile was available call callback with it, propagate to all other caches and check if a newer one is available
+ if (null != cachedItem)
+ {
+ // immediately return cached tile
+ callback(Response.FromCache(cachedItem.Data));
+
+ // check for updated tiles online if this is enabled in the settings
+ if (_autoRefreshCache)
+ {
+ // check if tile on the web is newer than the one we already have locally
+ IAsyncRequestFactory.CreateRequest(
+ finalUrl,
+ (Response headerOnly) =>
+ {
+ // on error getting information from API just return. tile we have locally has already been returned above
+ if (headerOnly.HasError)
+ {
+ return;
+ }
+
+ // TODO: remove Debug.Log before PR
+ //UnityEngine.Debug.LogFormat(
+ // "{1}{0}cached:{2}{0}header:{3}"
+ // , Environment.NewLine
+ // , finalUrl
+ // , cachedItem.ETag
+ // , headerOnly.Headers["ETag"]
+ //);
+
+ // data from cache is the same as on the web:
+ // * tile has already been returned above
+ // * make sure all all other caches have it too, but don't force insert via cache.add(false)
+ // additional ETag empty check: for backwards compability with old caches
+ if (!string.IsNullOrEmpty(cachedItem.ETag) && cachedItem.ETag.Equals(headerOnly.Headers["ETag"]))
+ {
+ foreach (var cache in _caches)
+ {
+ cache.Add(mapId, tileId, cachedItem, false);
+ }
+ }
+ else
+ {
+ // TODO: remove Debug.Log before PR
+ UnityEngine.Debug.LogWarningFormat(
+ "updating cached tile {1} mapid:{2}{0}cached etag:{3}{0}remote etag:{4}{0}{5}"
+ , Environment.NewLine
+ , tileId
+ , mapId
+ , cachedItem.ETag
+ , headerOnly.Headers["ETag"]
+ , finalUrl
+ );
+
+ // request updated tile and pass callback to return new data to subscribers
+ requestTileAndCache(finalUrl, mapId, tileId, timeout, callback);
+ }
+ }
+ , timeout
+ , HttpRequestType.Head
+ );
}
- callback(Response.FromCache(data));
return new MemoryCacheAsyncRequest(uri);
}
else
{
// requested tile is not in any of the caches yet, get it
- var uriBuilder = new UriBuilder(uri);
+ return requestTileAndCache(finalUrl, mapId, tileId, timeout, callback);
+ }
+ }
- if (!string.IsNullOrEmpty(_accessToken))
+
+ private IAsyncRequest requestTileAndCache(string url, string mapId, CanonicalTileId tileId, int timeout, Action callback)
+ {
+ return IAsyncRequestFactory.CreateRequest(
+ url,
+ (Response r) =>
{
- string accessTokenQuery = "access_token=" + _accessToken;
- if (uriBuilder.Query != null && uriBuilder.Query.Length > 1)
+ // if the request was successful add tile to all caches
+ if (!r.HasError && null != r.Data)
{
- uriBuilder.Query = uriBuilder.Query.Substring(1) + "&" + accessTokenQuery;
- }
- else
- {
- uriBuilder.Query = accessTokenQuery;
- }
- }
+ //UnityEngine.Debug.Log(uri);
+ string eTag = string.Empty;
+ DateTime? lastModified = null;
- return IAsyncRequestFactory.CreateRequest(
- uriBuilder.ToString(),
- (Response r) =>
- {
- // if the request was successful add tile to all caches
- if (!r.HasError && null != r.Data)
+ if (!r.Headers.ContainsKey("ETag"))
{
- foreach (var cache in _caches)
- {
- cache.Add(mapId, tileId, r.Data);
- }
+ UnityEngine.Debug.LogWarningFormat("no 'ETag' header present in response for {0}", url);
+ }
+ else
+ {
+ eTag = r.Headers["ETag"];
+ }
+
+ // not all APIs populate 'Last-Modified' header
+ // don't log error if it's missing
+ if (r.Headers.ContainsKey("Last-Modified"))
+ {
+ lastModified = DateTime.ParseExact(r.Headers["Last-Modified"], "r", null);
+ }
+
+ // propagate to all caches forcing update
+ foreach (var cache in _caches)
+ {
+ cache.Add(
+ mapId
+ , tileId
+ , new CacheItem()
+ {
+ Data = r.Data,
+ ETag = eTag,
+ LastModified = lastModified
+ }
+ , true // force insert/update
+ );
}
+ }
+ if (null != callback)
+ {
+ r.IsUpdate = true;
callback(r);
- }, timeout);
- }
+ }
+ }, timeout);
}
+
class MemoryCacheAsyncRequest : IAsyncRequest
{
@@ -184,6 +284,9 @@ public bool IsCompleted
}
+ public HttpRequestType RequestType { get { return HttpRequestType.Get; } }
+
+
public void Cancel()
{
// Empty. We can't cancel an instantaneous response.
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/ICache.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/ICache.cs
index 0579ea90e..7a69903ba 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/ICache.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/ICache.cs
@@ -1,11 +1,10 @@
-using Mapbox.Map;
-using System.Collections;
-using System.Collections.Generic;
-
namespace Mapbox.Platform.Cache
{
+ using Mapbox.Map;
+ using System;
+
public interface ICache
{
@@ -20,8 +19,9 @@ public interface ICache
///
/// Tile set name
/// Tile ID
- /// Tile data
- void Add(string mapId, CanonicalTileId tileId, byte[] data);
+ /// Item to cache
+ /// Force insert even if item already exists.
+ void Add(string mapId, CanonicalTileId tileId, CacheItem item, bool replaceIfExists);
///
@@ -30,7 +30,7 @@ public interface ICache
///
///
/// byte[] with tile data. Null if requested tile is not in cache
- byte[] Get(string mapId, CanonicalTileId tileId);
+ CacheItem Get(string mapId, CanonicalTileId tileId);
/// Clear cache for all tile sets
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MbTilesCache.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MbTilesCache.cs
index 7bf09b722..d83ff7341 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MbTilesCache.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MbTilesCache.cs
@@ -53,7 +53,7 @@ protected virtual void Dispose(bool disposeManagedResources)
#endregion
-
+
private bool _disposed;
private uint _maxCacheSize;
@@ -67,7 +67,7 @@ public uint MaxCacheSize
}
- public void Add(string mapId, CanonicalTileId tileId, byte[] data)
+ public void Add(string mapId, CanonicalTileId tileId, CacheItem item, bool forceInsert)
{
mapId = cleanMapId(mapId);
@@ -82,9 +82,9 @@ public void Add(string mapId, CanonicalTileId tileId, byte[] data)
MbTilesDb currentMbTiles = _mbTiles[mapId];
- if (!currentMbTiles.TileExists(tileId))
+ if (!currentMbTiles.TileExists(tileId) || forceInsert)
{
- _mbTiles[mapId].AddTile(tileId, data);
+ _mbTiles[mapId].AddTile(tileId, item, forceInsert);
}
}
@@ -114,7 +114,7 @@ private void initializeMbTiles(string mapId)
- public byte[] Get(string mapId, CanonicalTileId tileId)
+ public CacheItem Get(string mapId, CanonicalTileId tileId)
{
mapId = cleanMapId(mapId);
lock (_lock)
@@ -125,7 +125,13 @@ public byte[] Get(string mapId, CanonicalTileId tileId)
}
}
- return _mbTiles[mapId].GetTile(tileId);
+ CacheItem item = _mbTiles[mapId].GetTile(tileId);
+ if (null == item)
+ {
+ return null;
+ }
+
+ return item;
}
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MemoryCache.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MemoryCache.cs
index b039f28a0..a1d9d7a2d 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MemoryCache.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Cache/MemoryCache.cs
@@ -12,13 +12,6 @@ public class MemoryCache : ICache
{
- private struct CacheItem
- {
- public long Timestamp;
- public byte[] Data;
- }
-
-
// TODO: add support for disposal strategy (timestamp, distance, etc.)
public MemoryCache(uint maxCacheSize)
{
@@ -38,7 +31,7 @@ public uint MaxCacheSize
}
- public void Add(string mapdId, CanonicalTileId tileId, byte[] data)
+ public void Add(string mapdId, CanonicalTileId tileId, CacheItem item, bool forceInsert)
{
string key = mapdId + "||" + tileId;
@@ -46,18 +39,20 @@ public void Add(string mapdId, CanonicalTileId tileId, byte[] data)
{
if (_cachedResponses.Count >= _maxCacheSize)
{
- _cachedResponses.Remove(_cachedResponses.OrderBy(c => c.Value.Timestamp).First().Key);
+ _cachedResponses.Remove(_cachedResponses.OrderBy(c => c.Value.AddedToCacheTicksUtc).First().Key);
}
+ // TODO: forceInsert
if (!_cachedResponses.ContainsKey(key))
{
- _cachedResponses.Add(key, new CacheItem() { Timestamp = DateTime.Now.Ticks, Data = data });
+ item.AddedToCacheTicksUtc = DateTime.UtcNow.Ticks;
+ _cachedResponses.Add(key, item);
}
}
}
- public byte[] Get(string mapId, CanonicalTileId tileId)
+ public CacheItem Get(string mapId, CanonicalTileId tileId)
{
string key = mapId + "||" + tileId;
@@ -68,7 +63,7 @@ public byte[] Get(string mapId, CanonicalTileId tileId)
return null;
}
- return _cachedResponses[key].Data;
+ return _cachedResponses[key];
}
}
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequest.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequest.cs
index ae08c4a73..f26596af1 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequest.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequest.cs
@@ -4,8 +4,11 @@
//
//-----------------------------------------------------------------------
+
namespace Mapbox.Platform {
+ using Mapbox.Unity.Utilities;
+
/// A handle to an asynchronous request.
public interface IAsyncRequest {
@@ -15,5 +18,8 @@ public interface IAsyncRequest {
/// Cancel the ongoing request, preventing it from firing a callback.
void Cancel();
+
+ /// Type of request: GET, HEAD, ...
+ HttpRequestType RequestType { get; }
}
}
\ No newline at end of file
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequestFactory.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequestFactory.cs
index cf95c0783..195d1e428 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequestFactory.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/IAsyncRequestFactory.cs
@@ -11,7 +11,8 @@
namespace Mapbox.Platform {
using Mapbox.Map;
- using System;
+ using Mapbox.Unity.Utilities;
+ using System;
/// A handle to an asynchronous request.
public static class IAsyncRequestFactory {
@@ -20,6 +21,7 @@ public static IAsyncRequest CreateRequest(
string url
, Action callback
, int timeout
+ , HttpRequestType requestType= HttpRequestType.Get
) {
#if !UNITY
if (Environment.ProcessorCount > 2) {
@@ -28,7 +30,7 @@ string url
return new HTTPRequestNonThreaded(url, callback, timeout);
}
#else
- return new Mapbox.Unity.Utilities.HTTPRequest(url, callback, timeout);
+ return new Mapbox.Unity.Utilities.HTTPRequest(url, callback, timeout, requestType);
#endif
}
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/MbTiles.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/MbTiles.cs
index 28360f31c..550a960ff 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/MbTiles.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/MbTiles.cs
@@ -1,16 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using SQLite4Unity3d;
-using Mapbox.Utils;
-using UnityEngine;
-using Mapbox.Map;
-
-
-namespace Mapbox.Platform.MbTiles
+namespace Mapbox.Platform.MbTiles
{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using SQLite4Unity3d;
+ using Mapbox.Utils;
+ using UnityEngine;
+ using Mapbox.Map;
+ using Mapbox.Platform.Cache;
public class MbTilesDb : IDisposable
{
@@ -43,11 +42,13 @@ public MbTilesDb(string tileset, uint? maxTileCount = null)
//_sqlite.CreateTable();
string cmdCreateTTbliles = @"CREATE TABLE tiles(
-zoom_level INTEGER NOT NULL,
-tile_column BIGINT NOT NULL,
-tile_row BIGINT NOT NULL,
-tile_data BLOB NOT NULL,
-timestamp INTEGER NOT NULL,
+zoom_level INTEGER NOT NULL,
+tile_column BIGINT NOT NULL,
+tile_row BIGINT NOT NULL,
+tile_data BLOB NOT NULL,
+timestamp INTEGER NOT NULL,
+etag TEXT,
+lastmodified INTEGER,
PRIMARY KEY(
zoom_level ASC,
tile_column ASC,
@@ -60,6 +61,18 @@ tile_row ASC
_sqlite.Execute(cmdIdxTimestamp);
}
+ // auto migrate old caches
+ if (
+ 0 != colInfo.Count
+ && null == colInfo.FirstOrDefault(ci => ci.Name.Equals("etag"))
+ )
+ {
+ string sql = "ALTER TABLE tiles ADD COLUMN etag text;";
+ _sqlite.Execute(sql);
+ sql = "ALTER TABLE tiles ADD COLUMN lastmodified INTEGER;";
+ _sqlite.Execute(sql);
+ }
+
//some pragmas to speed things up a bit :-)
string[] cmds = new string[]
{
@@ -162,18 +175,23 @@ public void CreateMetaData(MetaDataRequired md)
}
- public void AddTile(CanonicalTileId tileId, byte[] data)
+ public void AddTile(CanonicalTileId tileId, CacheItem item, bool update = false)
{
- _sqlite.Insert(new tiles
+ _sqlite.InsertOrReplace(new tiles
{
zoom_level = tileId.Z,
tile_column = tileId.X,
tile_row = tileId.Y,
- tile_data = data,
- timestamp = (int)UnixTimestampUtils.To(DateTime.Now)
+ tile_data = item.Data,
+ timestamp = (int)UnixTimestampUtils.To(DateTime.Now),
+ etag = item.ETag
});
- _pruneCacheCounter++;
+ // update counter only when new tile gets inserted
+ if (!update)
+ {
+ _pruneCacheCounter++;
+ }
if (0 == _pruneCacheCounter % _pruneCacheDelta)
{
_pruneCacheCounter = 0;
@@ -204,7 +222,7 @@ private void prune()
///
/// Canonical tile id to identify the tile
/// tile data as byte[], if tile is not cached returns null
- public byte[] GetTile(CanonicalTileId tileId)
+ public CacheItem GetTile(CanonicalTileId tileId)
{
tiles tile = _sqlite
.Table()
@@ -216,7 +234,16 @@ public byte[] GetTile(CanonicalTileId tileId)
return null;
}
- return tile.tile_data;
+ DateTime? lastModified = null;
+ if (tile.lastmodified.HasValue) { lastModified = UnixTimestampUtils.From((double)tile.lastmodified.Value); }
+
+ return new CacheItem()
+ {
+ Data = tile.tile_data,
+ AddedToCacheTicksUtc = tile.timestamp,
+ ETag = tile.etag,
+ LastModified = lastModified
+ };
}
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/Tiles.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/Tiles.cs
index 6a5b3b732..2b7edb878 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/Tiles.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/MbTiles/Tiles.cs
@@ -29,5 +29,11 @@ public class tiles
/// Unix epoch for simple FIFO pruning
public int timestamp { get; set; }
+
+ /// ETag Header value of the reponse for auto updating cache
+ public string etag { get; set; }
+
+ /// Last-Modified header value of API response. Not all APIs populate it, will be -1 in that case.
+ public int? lastmodified { get; set; }
}
}
\ No newline at end of file
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Response.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Response.cs
index f9c52dd46..e8fe97e81 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Response.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Platform/Response.cs
@@ -25,6 +25,7 @@ namespace Mapbox.Platform
#endif
#if UNITY
using UnityEngine.Networking;
+ using Mapbox.Unity.Utilities;
#endif
/// A response from a request.
@@ -50,8 +51,12 @@ public bool HasError
get { return _exceptions == null ? false : _exceptions.Count > 0; }
}
+ /// Flag to indicate if the request was fullfilled from a local cache
public bool LoadedFromCache;
+ /// Flag to indicate if the request was issued before but was issued again and updated
+ public bool IsUpdate = false;
+
public string RequestUrl;
@@ -257,9 +262,12 @@ public static Response FromWebResponse(IAsyncRequest request, UnityWebRequest ap
response.AddException(new Exception(apiResponse.error));
}
- if (null == apiResponse.downloadHandler.data)
+ if (request.RequestType != HttpRequestType.Head)
{
- response.AddException(new Exception("Response has no data."));
+ if (null == apiResponse.downloadHandler.data)
+ {
+ response.AddException(new Exception("Response has no data."));
+ }
}
#if NETFX_CORE
@@ -316,7 +324,10 @@ public static Response FromWebResponse(IAsyncRequest request, UnityWebRequest ap
response.AddException(new Exception("Rate limit hit"));
}
- response.Data = apiResponse.downloadHandler.data;
+ if (request.RequestType != HttpRequestType.Head)
+ {
+ response.Data = apiResponse.downloadHandler.data;
+ }
return response;
}
diff --git a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Utils/UnixTimestampUtils.cs b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Utils/UnixTimestampUtils.cs
index 4a110aa66..502a440f5 100644
--- a/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Utils/UnixTimestampUtils.cs
+++ b/sdkproject/Assets/Mapbox/Core/mapbox-sdk-cs/Utils/UnixTimestampUtils.cs
@@ -33,7 +33,8 @@ public static double To(DateTime date) {
///
///
///
- public static DateTime From(double timestamp) {
+ public static DateTime From(double timestamp)
+ {
//return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Add(TimeSpan.FromSeconds(timestamp)).ToLocalTime();
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Add(TimeSpan.FromSeconds(timestamp));
}
@@ -49,5 +50,6 @@ public static DateTime From(long timestamp)
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Add(TimeSpan.FromTicks(timestamp));
}
+
}
}
diff --git a/sdkproject/Assets/Mapbox/Unity/Editor/ClearMbTilesCache.cs b/sdkproject/Assets/Mapbox/Unity/Editor/ClearMbTilesCache.cs
index 12f0652b5..ddb5f36fc 100644
--- a/sdkproject/Assets/Mapbox/Unity/Editor/ClearMbTilesCache.cs
+++ b/sdkproject/Assets/Mapbox/Unity/Editor/ClearMbTilesCache.cs
@@ -9,13 +9,19 @@ public class ClearMbTilesCache : MonoBehaviour
{
- [MenuItem("Mapbox/Clear Caches")]
+ [MenuItem("Mapbox/Clear Caches/Current Scene")]
public static void ClearCachingFileSource()
{
- Mapbox.Unity.MapboxAccess.Instance.ClearCache();
+ Mapbox.Unity.MapboxAccess.Instance.ClearSceneCache();
}
+ [MenuItem("Mapbox/Clear Caches/All")]
+ public static void ClearAllCachFiles()
+ {
+ Mapbox.Unity.MapboxAccess.Instance.ClearAllCacheFiles();
+ }
+
}
}
\ No newline at end of file
diff --git a/sdkproject/Assets/Mapbox/Unity/Editor/MapboxConfigurationWindow.cs b/sdkproject/Assets/Mapbox/Unity/Editor/MapboxConfigurationWindow.cs
index 490f3a9f3..6e90f78ff 100644
--- a/sdkproject/Assets/Mapbox/Unity/Editor/MapboxConfigurationWindow.cs
+++ b/sdkproject/Assets/Mapbox/Unity/Editor/MapboxConfigurationWindow.cs
@@ -30,6 +30,7 @@ public class MapboxConfigurationWindow : EditorWindow
[Range(0, 3000)]
static int _mbtilesCacheSize = 2000;
static int _webRequestTimeout = 30;
+ static bool _autoRefreshCache = false;
//mapbox access callbacks
static bool _listeningForTokenValidation = false;
@@ -91,7 +92,7 @@ public static void ShowWindowOnImport()
[MenuItem("Mapbox/Setup")]
static void InitWhenLoaded()
{
- if(EditorApplication.isCompiling && !_waitingToLoad)
+ if (EditorApplication.isCompiling && !_waitingToLoad)
{
//subscribe to updates
_waitingToLoad = true;
@@ -99,10 +100,10 @@ static void InitWhenLoaded()
return;
}
- if(!EditorApplication.isCompiling)
+ if (!EditorApplication.isCompiling)
{
//unsubscribe from updates if waiting
- if(_waitingToLoad)
+ if (_waitingToLoad)
{
EditorApplication.update -= InitWhenLoaded;
_waitingToLoad = false;
@@ -130,6 +131,7 @@ static void Init()
AccessToken = _accessToken,
MemoryCacheSize = (uint)_memoryCacheSize,
MbTilesCacheSize = (uint)_mbtilesCacheSize,
+ AutoRefreshCache = _autoRefreshCache,
DefaultTimeout = _webRequestTimeout
};
var json = JsonUtility.ToJson(_mapboxConfig);
@@ -160,6 +162,7 @@ static void OpenWindow()
_accessToken = _mapboxConfig.AccessToken;
_memoryCacheSize = (int)_mapboxConfig.MemoryCacheSize;
_mbtilesCacheSize = (int)_mapboxConfig.MbTilesCacheSize;
+ _autoRefreshCache = _mapboxConfig.AutoRefreshCache;
_webRequestTimeout = (int)_mapboxConfig.DefaultTimeout;
}
@@ -232,6 +235,7 @@ private static void SubmitConfiguration()
AccessToken = _accessToken,
MemoryCacheSize = (uint)_memoryCacheSize,
MbTilesCacheSize = (uint)_mbtilesCacheSize,
+ AutoRefreshCache = _autoRefreshCache,
DefaultTimeout = _webRequestTimeout
};
_mapboxAccess.SetConfiguration(mapboxConfiguration, false);
@@ -531,6 +535,7 @@ void DrawConfigurationSettings()
EditorGUI.indentLevel = 2;
_memoryCacheSize = EditorGUILayout.IntSlider("Mem Cache Size (# of tiles)", _memoryCacheSize, 0, 1000);
_mbtilesCacheSize = EditorGUILayout.IntSlider("MBTiles Cache Size (# of tiles)", _mbtilesCacheSize, 0, 3000);
+ _autoRefreshCache = EditorGUILayout.Toggle(new GUIContent("Auto refresh cache", "Automatically update tiles in the local ambient cache if there is a newer version available online. ATTENTION: for every tile displayed (even a cached one) a webrequest needs to be made to check for updates."), _autoRefreshCache);
_webRequestTimeout = EditorGUILayout.IntField("Default Web Request Timeout (s)", _webRequestTimeout);
EditorGUILayout.BeginHorizontal(_horizontalGroup);
@@ -549,7 +554,7 @@ void DrawConfigurationSettings()
void DrawExampleLinks()
{
EditorGUI.BeginDisabledGroup(_currentTokenStatus != MapboxTokenStatus.TokenValid
- || _validating);
+ || _validating);
if (_currentTokenStatus == MapboxTokenStatus.TokenValid)
{
@@ -581,7 +586,7 @@ void DrawExampleLinks()
private void OpenAndPlayScene()
{
- if( EditorApplication.isPlaying)
+ if (EditorApplication.isPlaying)
{
return;
}
diff --git a/sdkproject/Assets/Mapbox/Unity/MapboxAccess.cs b/sdkproject/Assets/Mapbox/Unity/MapboxAccess.cs
index 9bf08ac1a..443d3cec6 100644
--- a/sdkproject/Assets/Mapbox/Unity/MapboxAccess.cs
+++ b/sdkproject/Assets/Mapbox/Unity/MapboxAccess.cs
@@ -91,10 +91,21 @@ public void SetConfiguration(MapboxConfiguration configuration, bool throwExecpt
ConfigureTelemetry();
}
+
///
- /// Clear all existing tile caches. Deletes MBTiles database files.
+ /// Deprecated. Use 'ClearSceneCache' or 'ClearAllCacheFiles' instead.
///
+ [Obsolete("Deprecated. Use 'ClearSceneCache' or 'ClearAllCacheFiles' instead.")]
public void ClearCache()
+ {
+ ClearSceneCache();
+ }
+
+
+ ///
+ /// Clear all existing tile caches. Deletes MBTiles database files.
+ ///
+ public void ClearSceneCache()
{
CachingWebFileSource cwfs = _fileSource as CachingWebFileSource;
if (null != cwfs)
@@ -104,6 +115,27 @@ public void ClearCache()
}
+ public void ClearAllCacheFiles()
+ {
+ // call ClearSceneCache to close any connections that might be open
+ ClearSceneCache();
+
+ string cacheDirectory = Path.Combine(Application.persistentDataPath, "cache");
+ if (!Directory.Exists(cacheDirectory)) { return; }
+
+ foreach (var file in Directory.GetFiles(cacheDirectory))
+ {
+ try
+ {
+ File.Delete(file);
+ }
+ catch (Exception deleteEx)
+ {
+ Debug.LogErrorFormat("Could not delete [{0}]: {1}", file, deleteEx);
+ }
+ }
+ }
+
///
/// Loads the access token from Resources folder.
///
@@ -122,7 +154,7 @@ private void LoadAccessToken()
void ConfigureFileSource()
{
- _fileSource = new CachingWebFileSource(_configuration.AccessToken)
+ _fileSource = new CachingWebFileSource(_configuration.AccessToken, _configuration.AutoRefreshCache)
.AddCache(new MemoryCache(_configuration.MemoryCacheSize))
#if !UNITY_WEBGL
.AddCache(new MbTilesCache(_configuration.MbTilesCacheSize))
@@ -271,5 +303,6 @@ public class MapboxConfiguration
public uint MemoryCacheSize = 500;
public uint MbTilesCacheSize = 2000;
public int DefaultTimeout = 30;
+ public bool AutoRefreshCache = false;
}
}
diff --git a/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Factories/VectorTileFactory.cs b/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Factories/VectorTileFactory.cs
index f7b0afb66..4f286ddc3 100644
--- a/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Factories/VectorTileFactory.cs
+++ b/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Factories/VectorTileFactory.cs
@@ -85,8 +85,7 @@ internal override void OnRegistered(UnityTile tile)
{
var vectorTile = new VectorTile();
tile.AddTile(vectorTile);
-
-
+
vectorTile.Initialize(_fileSource, tile.CanonicalTileId, _mapId, () =>
{
if (tile == null)
@@ -119,6 +118,19 @@ internal override void OnRegistered(UnityTile tile)
}
else
{
+ if (vectorTile.CurrentState == Tile.State.Updated)
+ {
+ foreach (var vis in Visualizers)
+ {
+ vis.UnregisterTile(tile);
+ }
+
+ //foreach (Transform t in tile.transform)
+ //{
+ // Destroy(t.gameObject);
+ //}
+ }
+
CreateMeshes(tile);
}
});
diff --git a/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/MergedModifierStack.cs b/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/MergedModifierStack.cs
index bef14fac5..9d30f5737 100644
--- a/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/MergedModifierStack.cs
+++ b/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/MergedModifierStack.cs
@@ -67,7 +67,10 @@ public override void OnUnregisterTile(UnityTile tile)
_counter = _activeObjects[tile].Count;
for (int i = 0; i < _counter; i++)
{
- _activeObjects[tile][i].GameObject.SetActive(false);
+ if (null != _activeObjects[tile][i].GameObject)
+ {
+ _activeObjects[tile][i].GameObject.SetActive(false);
+ }
_pool.Put(_activeObjects[tile][i]);
}
_activeObjects[tile].Clear();
diff --git a/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/ModifierStack.cs b/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/ModifierStack.cs
index 68cc974ec..ce8aeaedc 100644
--- a/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/ModifierStack.cs
+++ b/sdkproject/Assets/Mapbox/Unity/MeshGeneration/Modifiers/ModifierStack.cs
@@ -84,7 +84,10 @@ public override void OnUnregisterTile(UnityTile tile)
{
item.OnPoolItem(_activeObjects[tile][i]);
}
- _activeObjects[tile][i].GameObject.SetActive(false);
+ if (null != _activeObjects[tile][i].GameObject)
+ {
+ _activeObjects[tile][i].GameObject.SetActive(false);
+ }
_pool.Put(_activeObjects[tile][i]);
}
_activeObjects[tile].Clear();
diff --git a/sdkproject/Assets/Mapbox/Unity/Utilities/HTTPRequest.cs b/sdkproject/Assets/Mapbox/Unity/Utilities/HTTPRequest.cs
index df67bc3b8..b24287b97 100644
--- a/sdkproject/Assets/Mapbox/Unity/Utilities/HTTPRequest.cs
+++ b/sdkproject/Assets/Mapbox/Unity/Utilities/HTTPRequest.cs
@@ -17,18 +17,45 @@ namespace Mapbox.Unity.Utilities
using UnityEditor;
#endif
+ public enum HttpRequestType
+ {
+ Get,
+ Head
+ }
+
+
internal sealed class HTTPRequest : IAsyncRequest
{
+
private UnityWebRequest _request;
+ private HttpRequestType _requestType;
+ private int _timeout;
private readonly Action _callback;
public bool IsCompleted { get; private set; }
- public HTTPRequest(string url, Action callback, int timeout)
+ public HttpRequestType RequestType { get { return _requestType; } }
+
+ // TODO: simplify timeout for Unity 5.6+
+ // https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest-timeout.html
+ public HTTPRequest(string url, Action callback, int timeout, HttpRequestType requestType = HttpRequestType.Get)
{
- //UnityEngine.Debug.Log("HTTPRequest: " + url);
IsCompleted = false;
- _request = UnityWebRequest.Get(url);
+ _requestType = requestType;
+
+ switch (_requestType)
+ {
+ case HttpRequestType.Get:
+ _request = UnityWebRequest.Get(url);
+ break;
+ case HttpRequestType.Head:
+ _request = UnityWebRequest.Head(url);
+ break;
+ default:
+ _request = UnityWebRequest.Get(url);
+ break;
+ }
+
_request.timeout = timeout;
_callback = callback;