// Used to create material data when a texture has finished downloading private IEnumerator FinishCreatingMaterialDataWithTexture( KeyValuePair <string, byte[]> materialDataKeyAndTexturePair) { var materialDataKey = materialDataKeyAndTexturePair.Key; while (!Monitor.TryEnter(_partiallyConstructedMaterialDatas)) { yield return(null); } MaterialData inProgressMaterialData; try { inProgressMaterialData = _partiallyConstructedMaterialDatas[materialDataKey]; _partiallyConstructedMaterialDatas.Remove(materialDataKey); } finally { Monitor.Exit(_partiallyConstructedMaterialDatas); } if (!CacheFill) { #if UNITY_IOS var texture = new Texture2D(1, 1, TextureFormat.RGB24, false); #else var texture = new Texture2D(1, 1, TextureFormat.DXT1, false); #endif texture.LoadImage(materialDataKeyAndTexturePair.Value); inProgressMaterialData.DiffuseTex = texture; inProgressMaterialData.DiffuseTex.name = inProgressMaterialData.Name; } while (!Monitor.TryEnter(MaterialDataCache)) { yield return(null); } try { MaterialDataCache[materialDataKey] = inProgressMaterialData; // Add reference until we add references for dependent requests MaterialDataCache.AddRef(materialDataKey); } finally { Monitor.Exit(MaterialDataCache); } // Move forward dependent requests that wanted this material data yield return(StartCoroutine(SucceedGetMaterialDataRequests(materialDataKey, inProgressMaterialData))); }
// Called when the material data has been constructed into the cache // The material data is constructed using a materialkey for reference // The method sets the material data for any dependent requests and moves them along private IEnumerator SucceedGetMaterialDataRequests(string materialDataKey, MaterialData materialData) { CheckIfMainThread(); // Check to see if any other requests were waiting on this model LinkedList <LoadCubeRequest> dependentRequests; while (!Monitor.TryEnter(_dependentCubes)) { yield return(null); } try { if (_dependentCubes.TryGetValue(materialDataKey, out dependentRequests)) { _dependentCubes.Remove(materialDataKey); } } finally { Monitor.Exit(_dependentCubes); } while (!Monitor.TryEnter(MaterialDataCache)) { yield return(null); } try { // If any were send them to their next stage if (dependentRequests != null) { foreach (var request in dependentRequests) { request.MaterialData = materialData; MaterialDataCache.AddRef(request.MaterialData.DiffuseTexPath); MoveRequestForward(request); } } // Now that added references for the dependent requests. We can release the interim reference MaterialDataCache.Release(materialData.DiffuseTexPath); } finally { Monitor.Exit(MaterialDataCache); } }
private IEnumerator GetMaterialForRequest(LoadCubeRequest loadRequest) { //var pyriteLevel = loadRequest.Query.DetailLevels[loadRequest.LodIndex]; //var textureCoordinates = pyriteLevel.TextureCoordinatesForCube(loadRequest.X, loadRequest.Y); //var texturePath = loadRequest.Query.GetTexturePath(loadRequest.LodIndex, (int)textureCoordinates.x, (int)textureCoordinates.y); var pyriteLevel = pyriteQuery.DetailLevels[loadRequest.LodIndex]; var textureCoordinates = pyriteLevel.TextureCoordinatesForCube(loadRequest.X, loadRequest.Y); var texturePath = pyriteQuery.GetTexturePath(loadRequest.LodIndex, (int)textureCoordinates.x, (int)textureCoordinates.y); while (!Monitor.TryEnter(MaterialDataCache)) { yield return(null); } // If the material data is not in the cache or in the middle of being constructed add this request as a dependency if (!MaterialDataCache.ContainsKey(texturePath) || MaterialDataCache[texturePath] == null) { // Add this request to list of requests that is waiting for the data yield return(StartCoroutine(AddDependentRequest(loadRequest, texturePath))); // Check if this is the first request for material (or it isn't in the cache) if (!MaterialDataCache.ContainsKey(texturePath)) { if (UseWwwForTextures) { // Material data was not in cache nor being constructed // Set to null to signal to other tasks that the key is in the process // of being filled MaterialDataCache[texturePath] = null; var materialData = CubeBuilderHelpers.GetDefaultMaterialData( (int)textureCoordinates.x, (int)textureCoordinates.y, loadRequest.LodIndex, texturePath); var cachePath = CacheWebRequest.GetCacheFilePath(texturePath); if (!CacheFill) { WWW textureWww; // = new WWW(texturePath); if (CacheWebRequest.IsItemInCache(cachePath)) { textureWww = new WWW("file:///" + cachePath); yield return(textureWww); } else { textureWww = new WWW(texturePath); yield return(textureWww); CacheWebRequest.AddToCache(cachePath, textureWww.bytes); } materialData.DiffuseTex = textureWww.texture; materialData.DiffuseTex.name = materialData.Name; } MaterialDataCache[texturePath] = materialData; MaterialDataCache.AddRef(texturePath); // Move forward dependent requests that wanted this material data yield return(StartCoroutine(SucceedGetMaterialDataRequests(texturePath, materialData))); } else { // Material data was not in cache nor being constructed // Set to null to signal to other tasks that the key is in the process // of being filled MaterialDataCache[texturePath] = null; var materialData = CubeBuilderHelpers.GetDefaultMaterialData( (int)textureCoordinates.x, (int)textureCoordinates.y, loadRequest.LodIndex, texturePath); _partiallyConstructedMaterialDatas[texturePath] = materialData; CacheWebRequest.GetBytes(texturePath, textureResponse => { CheckIfBackgroundThread(); if (textureResponse.Status == CacheWebRequest.CacheWebResponseStatus.Error) { Debug.LogError("Error getting texture [" + texturePath + "] " + textureResponse.ErrorMessage); FailGetMaterialDataRequest(loadRequest, texturePath); } else if (textureResponse.Status == CacheWebRequest.CacheWebResponseStatus.Cancelled) { lock (MaterialDataCache) { MaterialDataCache.Remove(texturePath); } } else { if (textureResponse.IsCacheHit) { //FileCacheHits++; } else { //FileCacheMisses++; } _texturesReadyForMaterialDataConstruction.ConcurrentEnqueue( new KeyValuePair <string, byte[]>(texturePath, textureResponse.Content)).Wait(); } }, DependentRequestsExistBlocking); } } } else // The material was in the cache { // Material data ready get it and move on //MaterialCacheHits++; loadRequest.MaterialData = MaterialDataCache[texturePath]; MaterialDataCache.AddRef(texturePath); MoveRequestForward(loadRequest); } Monitor.Exit(MaterialDataCache); }