コード例 #1
0
 /// <summary>
 /// Checks if the asset has the contents of the format to import, fetching them if need be; then imports
 /// the asset.
 /// </summary>
 /// <param name="asset">The asset who's format is being imported.</param>
 /// <param name="format">The format to import.</param>
 /// <param name="options">The import options for this asset.</param>
 /// <param name="callback">The callback to call when this is finished.</param>
 private void FetchAndImportFormat(PolyAsset asset, PolyFormat format, PolyImportOptions options,
                                   PolyApi.ImportCallback callback = null)
 {
     if (format.root.contents != null)
     {
         // If asset already has the gltf package, proceed directly to importing it.
         ImportFormat(asset, format, options, callback);
     }
     else
     {
         // Otherwise, first fetch the package and then import the model.
         FetchFormatFiles(asset, format.formatType, (PolyAsset resultAsset, PolyStatus status) => {
             PolyFormat fetchedFormat = resultAsset.GetFormatIfExists(format.formatType);
             if (fetchedFormat != null)
             {
                 ImportFormat(asset, fetchedFormat, options, callback);
             }
             else
             {
                 if (callback != null)
                 {
                     callback(asset, new PolyStatusOr <PolyImportResult>(
                                  PolyStatus.Error("Could not fetch format files for asset")));
                 }
             }
         });
     }
 }
コード例 #2
0
        /// <summary>
        /// Processes the result of fetching an individual file.
        /// </summary>
        /// <param name="state">Indicates the state of the ongoing fetch operation (as set up in FetchObj).</param>
        /// <param name="index">If ROOT_FILE_INDEX, then this is a result for the main file; else this is a result for
        /// the resource file with that index.</param>
        /// <param name="status">The status indicating if the download succeed</param>
        /// <param name="data">The data that was downloaded.</param>
        private void ProcessFileFetchResult(FetchOperationState state, int index, PolyStatus status, byte[] data)
        {
            if (state.pendingFiles == 0)
            {
                // Another request for this format failed, so we ignore any further responses.
                return;
            }

            if (!status.ok)
            {
                // This request failed, so we set pendingFiles to 0 so we ignore any further responses, and callback with
                // an error message.
                state.pendingFiles = 0;
                state.completionCallback(state.asset, PolyStatus.Error(status, "Failed to fetch file #{0}", index));
                return;
            }

            PolyFormat package = state.packageBeingFetched;
            PolyFile   file    = index == ROOT_FILE_INDEX ? package.root : package.resources[index];

            file.contents = data;

            --state.pendingFiles;
            if (state.progressCallback != null)
            {
                state.progressCallback(state.asset, 1.0f - ((float)state.pendingFiles / state.totalFiles));
            }
            if (state.pendingFiles <= 0)
            {
                // All files done, call callback indicating success.
                state.completionCallback(state.asset, PolyStatus.Success());
            }
        }
コード例 #3
0
 /// <summary>
 /// Attempts to authenticate using the provided tokens.
 /// This will NOT launch a sign-in flow. It will use the given tokens directly.
 /// </summary>
 /// <param name="accessToken">The access token to use.</param>
 /// <param name="refreshToken">The refresh token to use.</param>
 /// <param name="callback">The callback to call when authentication completes.</param>
 public void Authenticate(string accessToken, string refreshToken, Action <PolyStatus> callback)
 {
     if (!instance.IsAuthenticationSupported)
     {
         callback(PolyStatus.Error("Authentication is not supported on this platform."));
     }
     oauth2Identity.LoginWithTokens(
         () => { callback(PolyStatus.Success()); },
         () => { callback(PolyStatus.Error("Authentication failed (with tokens).")); },
         accessToken, refreshToken);
 }
コード例 #4
0
 /// <summary>
 /// Attempts to authenticate.
 /// </summary>
 /// <param name="interactive">If true, launch the sign in flow (browser) if necessary. If false,
 /// attempt to authenticate silently.</param>
 /// <param name="callback">Callback to call when authentication completes.</param>
 public void Authenticate(bool interactive, Action <PolyStatus> callback)
 {
     if (!instance.IsAuthenticationSupported)
     {
         callback(PolyStatus.Error("Authentication is not supported on this platform."));
     }
     oauth2Identity.Login(
         () => { callback(PolyStatus.Success()); },
         () => { callback(PolyStatus.Error("Authentication failed.")); },
         interactive);
 }
コード例 #5
0
        /// <summary>
        ///   Refreshes an access token, if a given refresh token is valid, and then calls one of the given callbacks.
        /// </summary>
        public void Reauthorize(Action <PolyStatus> callback)
        {
            if (!instance.IsAuthenticationSupported)
            {
                callback(PolyStatus.Error("Authentication is not supported on this platform."));
            }

            CoroutineRunner.StartCoroutine(this, oauth2Identity.Reauthorize(
                                               successCallback: () => { callback(PolyStatus.Success()); },
                                               failureCallback: (string error) => { callback(PolyStatus.Error(error)); }
                                               ));
        }
コード例 #6
0
 /// <summary>
 /// As documented in PolyClient.ListUserAssets.
 /// </summary>
 public void ListLikedAssets(PolyListLikedAssetsRequest listLikedAssetsRequest, PolyApi.ListAssetsCallback callback)
 {
     polyClient.SendRequest(listLikedAssetsRequest, (PolyStatus status, PolyListAssetsResult polyListResult) => {
         if (status.ok)
         {
             ProcessRequestResult(polyListResult, callback);
         }
         else
         {
             callback(new PolyStatusOr <PolyListAssetsResult>(PolyStatus.Error(status, "Request failed")));
         }
     }, /*maxCacheAge*/ WebRequestManager.CACHE_NONE);
 }
コード例 #7
0
 /// <summary>
 /// Fetch a specific Poly asset.
 /// </summary>
 /// <param name="id">The ID of the sought asset.</param>
 /// <param name="callback">The callback.</param>
 public void GetAsset(string id, PolyApi.GetAssetCallback callback)
 {
     polyClient.GetAsset(id, (PolyStatus status, PolyAsset result) => {
         if (status.ok)
         {
             callback(new PolyStatusOr <PolyAsset>(result));
         }
         else
         {
             callback(new PolyStatusOr <PolyAsset>(PolyStatus.Error(status, "Failed to get asset {0}", id)));
         }
     });
 }
コード例 #8
0
 /// <summary>
 /// As documented in PolyClient.ListAssets.
 /// </summary>
 public void ListAssets(PolyListAssetsRequest listAssetsRequest, PolyApi.ListAssetsCallback callback)
 {
     polyClient.SendRequest(listAssetsRequest, (PolyStatus status, PolyListAssetsResult polyListResult) => {
         if (status.ok)
         {
             ProcessRequestResult(polyListResult, callback);
         }
         else
         {
             callback(new PolyStatusOr <PolyListAssetsResult>(PolyStatus.Error(status, "Request failed")));
         }
     });
 }
コード例 #9
0
 /// <summary>
 ///   Fetch a specific asset.
 /// </summary>
 /// <param name="assetId">The asset to be fetched.</param>
 /// <param name="callback">A callback to call with the result of the operation.</param>
 /// <param name="isRecursion">
 ///   If true, this is a recursive call to this function, and no further retries should be attempted.
 /// </param>
 public void GetAsset(string assetId, Action <PolyStatus, PolyAsset> callback, bool isRecursion = false)
 {
     // If the user passed in a raw asset ID (no "assets/" prefix), fix it.
     if (!assetId.StartsWith("assets/"))
     {
         assetId = "assets/" + assetId;
     }
     PolyMainInternal.Instance.webRequestManager.EnqueueRequest(
         () =>
     {
         string url = String.Format("{0}/v1/{1}?key={2}", BASE_URL, assetId, PolyMainInternal.Instance.apiKey);
         return(GetRequest(url, "text/text"));
     },
         (PolyStatus status, int responseCode, byte[] response) =>
     {
         if (responseCode == 401 || !status.ok)
         {
             if (isRecursion /* || !Authenticator.IsInitialized*/)
             {
                 callback(PolyStatus.Error("Get asset error ({0})", responseCode), null);
                 return;
             }
             //else
             //{
             //    Authenticator.Instance.Reauthorize((PolyStatus reauthStatus) =>
             //    {
             //        if (reauthStatus.ok)
             //        {
             //            GetAsset(assetId, callback, isRecursion: true);
             //        }
             //        else
             //        {
             //            callback(PolyStatus.Error(reauthStatus, "Failed to reauthenticate to get asset {0}", assetId), null);
             //        }
             //    });
             //}
         }
         else
         {
             string text = Encoding.UTF8.GetString(response);
             PolyStatus responseStatus = CheckResponseForError(text);
             if (!responseStatus.ok)
             {
                 callback(responseStatus, null);
                 return;
             }
             PolyMainInternal.Instance.DoBackgroundWork(new ParseAssetBackgroundWork(text,
                                                                                     callback));
         }
     }, DEFAULT_QUERY_CACHE_MAX_AGE_MILLIS);
 }
コード例 #10
0
        /// <summary>
        /// Parses a single asset.
        /// </summary>
        public static PolyStatus ParseAsset(JObject asset, out PolyAsset polyAsset)
        {
            polyAsset = new PolyAsset();

            if (asset["visibility"] == null)
            {
                return(PolyStatus.Error("Asset has no visibility set."));
            }

            polyAsset.name       = asset["name"].ToString();
            polyAsset.authorName = asset["authorName"].ToString();
            if (asset["thumbnail"] != null)
            {
                var thumbnailElements = asset["thumbnail"].ToObject <JObject>();
                //IJEnumerable<JToken> thumbnailElements = asset["thumbnail"].AsJEnumerable();
                polyAsset.thumbnail = new PolyFile(thumbnailElements["relativePath"].ToString(),
                                                   thumbnailElements["url"].ToString(), thumbnailElements["contentType"].ToString());
            }

            if (asset["formats"] == null)
            {
                Debug.LogError("No formats found");
            }
            else
            {
                foreach (var format in asset["formats"].ToObject <List <JObject> >())
                //foreach (JToken format in asset["formats"])
                {
                    PolyFormat newFormat = ParseAssetsPackage(format);
                    newFormat.formatType = ParsePolyFormatType(format["formatType"]);
                    if (newFormat.formatType == PolyFormatType.UNKNOWN)
                    {
                        PtDebug.Log("Did not recognize format type: " + format["formatType"].ToString());
                    }
                    polyAsset.formats.Add(newFormat);
                }
            }
            polyAsset.displayName = asset["displayName"].ToString();
            polyAsset.createTime  = DateTime.Parse(asset["createTime"].ToString());
            polyAsset.updateTime  = DateTime.Parse(asset["updateTime"].ToString());
            polyAsset.visibility  = ParsePolyVisibility(asset["visibility"]);
            polyAsset.license     = ParsePolyAssetLicense(asset["license"]);
            if (asset["isCurated"] != null)
            {
                polyAsset.isCurated = bool.Parse(asset["isCurated"].ToString());
            }
            return(PolyStatus.Success());
        }
コード例 #11
0
 /// <summary>
 /// Gets raw file data from Poly given a data URL.
 /// </summary>
 /// <param name="dataUrl">Data URL to retrieve from.</param>
 /// <param name="accessToken">The access token to use for authentication.</param>
 /// <param name="callback">The callback to call when the download is complete.</param>
 /// <param name="maxCacheAgeMillis">Maximum age of the cached copy, in millis. See
 /// WebRequestManager for useful constants.</param>
 public static void GetRawFileBytes(string dataUrl, string accessToken,
                                    long maxCacheAgeMillis, GetRawFileDataBytesCallback callback)
 {
     PolyMainInternal.Instance.webRequestManager.EnqueueRequest(
         () => { return(MakeRawFileGetRequest(dataUrl, accessToken)); },
         (PolyStatus status, int responseCode, byte[] response) => {
         if (!status.ok)
         {
             callback(PolyStatus.Error(status, "Failed to get raw file bytes for {0}", dataUrl), null);
         }
         else
         {
             callback(PolyStatus.Success(), response);
         }
     }, maxCacheAgeMillis);
 }
コード例 #12
0
 /// <summary>
 /// As documented in PolyClient.ListUserAssets.
 /// </summary>
 public void ListUserAssets(PolyListUserAssetsRequest listUserAssetsRequest, PolyApi.ListAssetsCallback callback)
 {
     // Users expect their own private assets to update quickly once they make a change (one use case
     // being: I go to Blocks or Tilt Brush, modify my asset, come back to PolyToolkit, I expect it to be updated).
     // So we don't use caching for these.
     polyClient.SendRequest(listUserAssetsRequest, (PolyStatus status, PolyListAssetsResult polyListResult) => {
         if (status.ok)
         {
             ProcessRequestResult(polyListResult, callback);
         }
         else
         {
             callback(new PolyStatusOr <PolyListAssetsResult>(PolyStatus.Error(status, "Request failed")));
         }
     }, /*maxCacheAge*/ WebRequestManager.CACHE_NONE);
 }
コード例 #13
0
        public void Update()
        {
            // We process at most one import result per frame, to avoid doing too much work
            // in the main thread.
            ImportOperation operation;

            lock (finishedOperationsLock)
            {
                if (finishedOperations.Count == 0)
                {
                    return;
                }
                operation = finishedOperations.Dequeue();
            }

            if (!operation.status.ok)
            {
                // Import failed.
                operation.callback(operation.status, root: null, meshCreator: null);
                return;
            }

            try
            {
                IEnumerable meshCreator;
                ImportGltf.GltfImportResult result = ImportGltf.EndImport(operation.importState,
                                                                          operation.loader, out meshCreator);

                if (!operation.options.clientThrottledMainThread)
                {
                    // If we're not in throttled mode, create all the meshes immediately by exhausting
                    // the meshCreator enumeration. Otherwise, it's the caller's responsibility to
                    // do this.
                    foreach (var unused in meshCreator) /* empty */ } {
                    meshCreator = null;
            }
            // Success.
            operation.callback(PolyStatus.Success(), result.root, meshCreator);
        }
        catch (Exception ex)
        {
            // Import failed.
            Debug.LogException(ex);
            operation.callback(PolyStatus.Error("Failed to convert import to Unity objects.", ex),
                               root: null, meshCreator: null);
        }
    }
コード例 #14
0
        public void FetchFormatFiles(PolyAsset asset, PolyFormatType formatType,
                                     PolyApi.FetchFormatFilesCallback completionCallback, FetchProgressCallback progressCallback = null)
        {
            PolyUtils.AssertNotNull(asset, "Asset can't be null.");
            PolyUtils.AssertNotNull(formatType, "formatType can't be null.");
            PolyFormat packageToFetch = asset.GetFormatIfExists(formatType);

            if (packageToFetch == null)
            {
                if (completionCallback != null)
                {
                    completionCallback(asset, PolyStatus.Error("Format type not present in asset"));
                }
                return;
            }

            PolyUtils.AssertNotNull(packageToFetch.root, "packageToFetch.root can't be null.");
            PolyUtils.AssertNotNull(packageToFetch.root.url, "packageToFetch.root.url can't be null.");
            PolyUtils.AssertNotNull(packageToFetch.resources, "packageToFetch.resources can't be null.");

            string accessToken = GetAccessToken();

            FetchOperationState state = new FetchOperationState();

            state.asset = asset;
            state.completionCallback  = completionCallback;
            state.progressCallback    = progressCallback;
            state.packageBeingFetched = packageToFetch;

            // Indicates how many files are pending download (1 for main file + 1 for each resource).
            state.totalFiles = state.pendingFiles = 1 + packageToFetch.resources.Count;

            // Note that the callbacks are asynchronous so they may complete in any order.  What we do know is that they
            // will all be called on the main thread, so they won't be called concurrently.

            long maxCacheAge = asset.IsMutable ? MUTABLE_ASSET_MAX_CACHE_AGE : IMMUTABLE_ASSET_MAX_CACHE_AGE;

            PolyClientUtils.GetRawFileBytes(packageToFetch.root.url, accessToken, maxCacheAge,
                                            (PolyStatus status, byte[] data) => { ProcessFileFetchResult(state, ROOT_FILE_INDEX, status, data); });

            for (int i = 0; i < packageToFetch.resources.Count; i++)
            {
                int thisIndex = i; // copy of variable, for closure below.
                PolyClientUtils.GetRawFileBytes(packageToFetch.resources[i].url, accessToken, maxCacheAge,
                                                (status, data) => { ProcessFileFetchResult(state, thisIndex, status, data); });
            }
        }
コード例 #15
0
        private static void BackgroundThreadProc(object userData)
        {
            ImportOperation operation = (ImportOperation)userData;

            try {
                using (TextReader reader = new StreamReader(new MemoryStream(operation.format.root.contents), Encoding.UTF8)) {
                    operation.importState = ImportGltf.BeginImport(
                        operation.format.formatType == PolyFormatType.GLTF ? GltfSchemaVersion.GLTF1 : GltfSchemaVersion.GLTF2,
                        reader, operation.loader, operation.options);
                }
            } catch (Exception ex) {
                Debug.LogException(ex);
                operation.status = PolyStatus.Error("Error importing asset.", ex);
            }
            // Done with background thread part, let's queue it so we can finish up on the main thread.
            operation.instance.EnqueueFinishedOperation(operation);
        }
コード例 #16
0
        /// <summary>
        /// Processes request results and delivers them to the callback.
        /// </summary>
        /// <param name="result">The result.</param>
        private void ProcessRequestResult(PolyListAssetsResult result, PolyApi.ListAssetsCallback callback)
        {
            if (result == null)
            {
                callback(new PolyStatusOr <PolyListAssetsResult>(PolyStatus.Error("No request result.")));
                return;
            }

            if (result.assets == null)
            {
                // Nothing wrong with the request, there were just no assets that matched those parameters.
                // Put an empty list in the result.
                result.assets = new List <PolyAsset>();
            }

            callback(new PolyStatusOr <PolyListAssetsResult>(result));
        }
コード例 #17
0
 /// <summary>
 /// Fetches a list of Poly assets together with metadata, using the given request params.
 /// </summary>
 /// <param name="request">The request to send; can be either a ListAssetsRequest, a ListUserAssetsRequest, or
 /// a ListLikedAssetsRequest.</param>
 /// <param name="callback">The callback to call when the request is complete.</param>
 /// <param name="maxCacheAge">The maximum cache age to use.</param>
 /// <param name="isRecursion"> If true, this is a recursive call to this function, and no
 /// further retries should be attempted.</param>
 public void SendRequest(PolyRequest request, Action <PolyStatus, PolyListAssetsResult> callback,
                         long maxCacheAge = DEFAULT_QUERY_CACHE_MAX_AGE_MILLIS, bool isRecursion = false)
 {
     PolyMainInternal.Instance.webRequestManager.EnqueueRequest(
         () => { return(GetRequest(MakeSearchUrl(request), "text/text")); },
         (PolyStatus status, int responseCode, byte[] response) =>
     {
         // Retry the request if this was the first failure. The failure may be a server blip, or may indicate
         // an authentication token has become stale and must be refreshed.
         if (responseCode == 401 || !status.ok)
         {
             if (isRecursion /* || !Authenticator.IsInitialized || !Authenticator.Instance.IsAuthenticated*/)
             {
                 callback(PolyStatus.Error(status, "Query error ({0})", responseCode), null);
                 return;
             }
             //else
             //{
             //    Authenticator.Instance.Reauthorize((PolyStatus reauthStatus) =>
             //    {
             //        if (reauthStatus.ok)
             //        {
             //            SendRequest(request, callback, maxCacheAge: maxCacheAge, isRecursion: true);
             //        }
             //        else
             //        {
             //            callback(PolyStatus.Error(reauthStatus, "Failed to reauthorize."), null);
             //        }
             //    });
             //}
         }
         else
         {
             string text = Encoding.UTF8.GetString(response);
             PolyStatus responseStatus = CheckResponseForError(text);
             if (!responseStatus.ok)
             {
                 callback(responseStatus, null);
                 return;
             }
             PolyMainInternal.Instance.DoBackgroundWork(new ParseAssetsBackgroundWork(
                                                            text, callback));
         }
     }, maxCacheAge);
 }
コード例 #18
0
        /// <summary>
        /// Verify if the response can be parsed as json and, if so, that it contains no error token.
        /// If either conditions are false return a PolyStatusError with relevant information.
        /// </summary>
        private PolyStatus CheckResponseForError(string response)
        {
            JObject results = new JObject();

            try {
                results = JObject.Parse(response);
            } catch (Exception ex) {
                return(PolyStatus.Error("Failed to parse Poly API response, encountered exception: {0}", ex.Message));
            }
            IJEnumerable <JToken> error = results["error"].AsJEnumerable();

            if (error == null)
            {
                return(PolyStatus.Success());
            }
            return(PolyStatus.Error("{0}: {1}", error["code"] != null ? error["code"].ToString() : "(no error code)",
                                    error["message"] != null ? error["message"].ToString() : "(no error message)"));
        }
コード例 #19
0
        /// <summary>
        /// Starts fetching the thumbnail (in the background).
        /// </summary>
        public void Fetch()
        {
            if (asset.thumbnail == null || string.IsNullOrEmpty(asset.thumbnail.url))
            {
                // Spoiler alert: if there's no thumbnail URL, our web request will fail, because
                // the URL is kind of an import part of a web request.
                // So fail early with a clear error message, rather than make a broken web request.
                if (callback != null)
                {
                    callback(asset, PolyStatus.Error("Thumbnail URL not available for asset: {0}", asset));
                }
                return;
            }
            // Only use cache if fetching the thumbnail for an immutable asset.
            long cacheAgeMaxMillis = asset.IsMutable ? 0 : CACHE_MAX_AGE_MILLIS;

            PolyMainInternal.Instance.webRequestManager.EnqueueRequest(MakeRequest, ProcessResponse, cacheAgeMaxMillis);
        }
コード例 #20
0
        public void Import(PolyAsset asset, PolyImportOptions options, PolyApi.ImportCallback callback = null)
        {
            PolyFormat gltfFormat  = asset.GetFormatIfExists(PolyFormatType.GLTF);
            PolyFormat gltf2Format = asset.GetFormatIfExists(PolyFormatType.GLTF_2);

            if (gltf2Format != null && gltfFormat == null)
            {
                FetchAndImportFormat(asset, gltf2Format, options, callback);
            }
            else if (gltfFormat != null)
            {
                FetchAndImportFormat(asset, gltfFormat, options, callback);
            }
            else
            {
                callback(asset, new PolyStatusOr <PolyImportResult>(
                             PolyStatus.Error("Neither glTF or glTF_2 format was present in asset")));
            }
        }
コード例 #21
0
ファイル: PolyClient.cs プロジェクト: bhaktavar/Eduthon
 public static PolyStatus ParseResponse(byte[] response, out JObject result)
 {
     try {
         result = JObject.Parse(Encoding.UTF8.GetString(response));
         JToken errorToken = result["error"];
         if (errorToken != null)
         {
             IJEnumerable <JToken> error = errorToken.AsJEnumerable();
             return(PolyStatus.Error("{0}: {1}", error["code"] != null ? error["code"].ToString() : "(no error code)",
                                     error["message"] != null ? error["message"].ToString() : "(no error message)"));
         }
         else
         {
             return(PolyStatus.Success());
         }
     } catch (Exception ex) {
         result = null;
         return(PolyStatus.Error("Failed to parse Poly API response, encountered exception: {0}", ex.Message));
     }
 }
コード例 #22
0
 private void ProcessResponse(PolyStatus status, int responseCode, byte[] data)
 {
     if (data == null || data.Length <= 0)
     {
         status = PolyStatus.Error("Thumbnail data was null or empty.");
     }
     if (status.ok)
     {
         asset.thumbnailTexture = new Texture2D(1, 1);
         asset.thumbnailTexture.LoadImage(data);
     }
     else
     {
         Debug.LogWarningFormat("Failed to fetch thumbnail for asset {0} ({1}): {2}",
                                asset.name, asset.displayName, status);
     }
     if (callback != null)
     {
         callback(asset, status);
     }
 }
コード例 #23
0
    // Searches directly by Poly URL.
    private void SearchByPolyUrl(string polyUrl, OnActorableSearchResult resultCallback, System.Action <bool> onComplete)
    {
        string[] parts   = polyUrl.Split('/');
        string   assetId = parts[parts.Length - 1];

        PolyApi.GetAsset(assetId, result =>
        {
            PolyListAssetsResult assetsResult;
            List <PolyAsset> assetList = new List <PolyAsset>();
            if (result.Ok)
            {
                // Successfully got the asset. This is good.
                // Is it acceptably licensed?
                if (result.Value.license == PolyAssetLicense.CREATIVE_COMMONS_BY)
                {
                    // Good license. We can use it.
                    assetList.Add(result.Value);
                    assetsResult = new PolyListAssetsResult(PolyStatus.Success(), 1, assetList);
                }
                else
                {
                    // Not CC-By. Can't use it.
                    Debug.LogError("This asset (" + assetId + ") is not licensed by CC-By. Try another asset.");
                    assetsResult = new PolyListAssetsResult(PolyStatus.Error("Asset " + assetId + " is not licensed as CC-By."), 0, assetList);
                }
            }
            else
            {
                // Failed to get the asset. This is bad.
                assetsResult = new PolyListAssetsResult(PolyStatus.Error("Failed to get asset " + assetId), 0, assetList);
            }
            PolySearchCallback(
                new PolyStatusOr <PolyListAssetsResult>(assetsResult), resultCallback, onComplete);
        });
        return;
    }
コード例 #24
0
        /// <summary>
        /// Co-routine that services one PendingRequest. This method must be called with StartCoroutine.
        /// </summary>
        /// <param name="request">The request to service.</param>
        private IEnumerator HandleWebRequest(PendingRequest request, BufferHolder bufferHolder)
        {
            // NOTE: This method runs on the main thread, but never blocks -- the blocking part of the work is
            // done by yielding the UnityWebRequest, which releases the main thread for other tasks while we
            // are waiting for the web request to complete (by the miracle of coroutines).

            // Let the caller create the UnityWebRequest, configuring it as they want. The caller can set the URL,
            // method, headers, anything they want. The only thing they can't do is call Send(), as we're in charge
            // of doing that.
            UnityWebRequest webRequest = request.creationCallback();

            PtDebug.LogVerboseFormat("Web request: {0} {1}", webRequest.method, webRequest.url);

            bool cacheAllowed = cache != null && webRequest.method == "GET" && request.maxAgeMillis != CACHE_NONE;

            // Check the cache (if it's a GET request and cache is enabled).
            if (cacheAllowed)
            {
                bool   cacheHit      = false;
                byte[] cacheData     = null;
                bool   cacheReadDone = false;
                cache.RequestRead(webRequest.url, request.maxAgeMillis, (bool success, byte[] data) =>
                {
                    cacheHit      = success;
                    cacheData     = data;
                    cacheReadDone = true;
                });
                while (!cacheReadDone)
                {
                    yield return(null);
                }
                if (cacheHit)
                {
                    PtDebug.LogVerboseFormat("Web request CACHE HIT: {0}, response: {1} bytes",
                                             webRequest.url, cacheData.Length);
                    request.completionCallback(PolyStatus.Success(), /* responseCode */ 200, cacheData);

                    // Return the buffer to the pool for reuse.
                    CleanUpAfterWebRequest(bufferHolder);

                    yield break;
                }
                else
                {
                    PtDebug.LogVerboseFormat("Web request CACHE MISS: {0}.", webRequest.url);
                }
            }

            DownloadHandlerBuffer handler = new DownloadHandlerBuffer();

            webRequest.downloadHandler = handler;

            // We need to asset that we actually succeeded in setting the download handler, because this can fail
            // if, for example, the creation callback mistakenly called Send().
            PolyUtils.AssertTrue(webRequest.downloadHandler == handler,
                                 "Couldn't set download handler. It's either disposed of, or the creation callback mistakenly called Send().");

            // Start the web request. This will suspend this coroutine until the request is done.
            PtDebug.LogVerboseFormat("Sending web request: {0}", webRequest.url);
            yield return(UnityCompat.SendWebRequest(webRequest));

            // Request is finished. Call user-supplied callback.
            PtDebug.LogVerboseFormat("Web request finished: {0}, HTTP response code {1}, response: {2}",
                                     webRequest.url, webRequest.responseCode, webRequest.downloadHandler.text);
            PolyStatus status = UnityCompat.IsNetworkError(webRequest) ? PolyStatus.Error(webRequest.error) : PolyStatus.Success();

            request.completionCallback(status, (int)webRequest.responseCode, webRequest.downloadHandler.data);

            // Cache the result, if applicable.
            if (!UnityCompat.IsNetworkError(webRequest) && cacheAllowed)
            {
                byte[] data = webRequest.downloadHandler.data;
                if (data != null && data.Length > 0)
                {
                    byte[] copy = new byte[data.Length];
                    Buffer.BlockCopy(data, 0, copy, 0, data.Length);
                    cache.RequestWrite(webRequest.url, copy);
                }
            }

            // Clean up.
            webRequest.Dispose();
            CleanUpAfterWebRequest(bufferHolder);
        }