コード例 #1
0
        /// <summary>
        /// StartAndAwaitAvatarCalculationAsync implementation
        /// </summary>
        private IEnumerator StartAndAwaitAvatarCalculationFunc(string avatarCode, AsyncRequest request)
        {
            var avatarRequest = GetAvatarAsync(avatarCode);

            yield return(avatarRequest.Await());

            if (avatarRequest.IsError)
            {
                request.SetError(avatarRequest.ErrorMessage);
                yield break;
            }

            var awaitCalculations = connection.AwaitAvatarCalculationsAsync(avatarRequest.Result);

            yield return(request.AwaitSubrequest(awaitCalculations, finalProgress: 1.0f));

            if (request.IsError)
            {
                yield break;
            }

            if (Strings.BadFinalStates.Contains(awaitCalculations.Result.status))
            {
                request.SetError(string.Format("Avatar {0} calculation finished with status: {1}", awaitCalculations.Result.code, awaitCalculations.Result.status));
                yield break;
            }

            request.IsDone = true;
        }
コード例 #2
0
    private static void ExecutePoolRequests()
    {
        double time  = EditorApplication.timeSinceStartup;
        int    count = Resources.instance.requests.Count;

        for (int i = 0; i < count; i++)
        {
            AsyncRequest request = Resources.instance.requests[i];
            switch (request.status)
            {
            case Status.NeedNewClipStatusRequest:
            case Status.WaitClipStatusRequest:
                if (time - request.lastStateTime > waitClipTimout)
                {
                    request.SetError(Error.Timeout);
                    continue;
                }
                else
                {
                    ExecuteRequest(time, request);
                    break;
                }

            case Status.Completed:
                if (time - request.lastStateTime > 2.0)
                {
                    Resources.instance.requests.RemoveAt(i);
                    EditorUtility.SetDirty(Resources.instance);
                    i--;
                    count--;
                }
                continue;

            case Status.Error:
                continue;

            default:
                if (time - request.lastStateTime > waitClipTimout)
                {
                    request.SetError(Error.Timeout);
                    continue;
                }
                break;
            }
            ExecuteRequest(time, Resources.instance.requests[i]);
        }

        if (Resources.instance.requests.Count == 0)
        {
            DisposeRefreshEvent();
        }
    }
コード例 #3
0
    private static void OnDownloaded(AsyncRequest request, byte[] data, Error error)
    {
        //Handle error
        if (error)
        {
            request.SetError(error);
            return;
        }

        //Download completed
        else
        {
            request.status = Status.WritingAsset;
        }

        //Write file
        string savePath = request.saveDirectory + "/" + request.fileName;

        File.WriteAllBytes(savePath, data);

        //Import asset
        savePath = Utils.LocalPath(savePath);
        AssetDatabase.ImportAsset(savePath, ImportAssetOptions.ForceUpdate);
        if (request.notificationLink == null)
        {
            request.notificationLink = AssetDatabase.LoadAssetAtPath <AudioClip>(savePath);
        }

        //Send notification
        NotificationsPopup.Add("Download completed\n" + request.requestName, MessageType.Info, request.notificationLink);

        //Delete clip if needed
        if (!request.deleteClipAtEnd)
        {
            request.status = Status.Completed;
        }
        else
        {
            request.status      = Status.SendRequestDeletion;
            request.currentTask = APIBridge.DeleteClip(request.clipUUID, (string content, Error deleteError) =>
            {
                if (deleteError)
                {
                    request.SetError(deleteError);
                }
                else
                {
                    request.status = Status.Completed;
                }
            });
        }
    }
コード例 #4
0
        private IEnumerator DownloadAvatarFunc(AvatarData avatar, PipelineType pipelineType, AsyncRequest request)
        {
            //Update avatar info
            int  retryCount = 3;
            bool gotAvatar  = false;

            while (!gotAvatar)
            {
                if (retryCount == 0)
                {
                    request.SetError("Unable to download avatar");
                    yield break;
                }

                var updateAvatar = connection.GetAvatarAsync(avatar.code);
                yield return(Await(updateAvatar, pipelineType));

                if (!updateAvatar.IsError)
                {
                    gotAvatar = true;
                    avatar    = updateAvatar.Result;
                }
                retryCount--;
            }

            // download avatar files
            retryCount = 3;
            bool isDownloaded = false;

            while (!isDownloaded)
            {
                if (retryCount == 0)
                {
                    request.SetError("Unable to download avatar");
                    yield break;
                }

                var downloadAvatar = avatarProvider.DownloadAndSaveAvatarModelAsync(avatar, pipelineType == PipelineType.FACE, true);
                yield return(Await(downloadAvatar, pipelineType));

                isDownloaded = !downloadAvatar.IsError;
                if (downloadAvatar.IsError)
                {
                    yield return(new WaitForSeconds(3));
                }

                retryCount--;
            }

            request.IsDone = true;
        }
コード例 #5
0
        /// <summary>
        /// AwaitAvatarCalculationsAsync implementation.
        /// </summary>
        private IEnumerator AwaitAvatarCalculationsLoop(AvatarData avatar, AsyncRequest <AvatarData> request)
        {
            while (!Strings.FinalStates.Contains(avatar.status))
            {
                yield return(new WaitForSeconds(4));

                var avatarStatusRequest = GetAvatarAsync(avatar.code);
                yield return(avatarStatusRequest);

                if (avatarStatusRequest.Status.Value == (long)StatusCode.Code.NOT_FOUND)
                {
                    Debug.LogWarning("404 error most likely means that avatar was deleted from the server");
                    request.SetError(string.Format("Avatar status response: {0}", avatarStatusRequest.ErrorMessage));
                    yield break;
                }

                if (avatarStatusRequest.Status.Value == (long)StatusCode.Code.TOO_MANY_REQUESTS_THROTTLING)
                {
                    Debug.LogWarning("Too many requests!");
                    yield return(new WaitForSeconds(10));
                }

                if (avatarStatusRequest.IsError)
                {
                    Debug.LogWarningFormat("Status polling error: {0}", avatarStatusRequest.ErrorMessage);
                    // Most likely this is a temporary issue. Keep polling.
                    continue;
                }

                avatar = avatarStatusRequest.Result;
                Debug.LogFormat("Status: {0}, progress: {1}%", avatar.status, avatar.progress);
                request.State = AvatarSdkMgr.Str(avatar.status);

                if (avatar.status == Strings.Computing)
                {
                    request.Progress = (float)avatar.progress / 100;
                }
            }

            if (Strings.GoodFinalStates.Contains(avatar.status))
            {
                request.Result = avatar;
                request.IsDone = true;
            }
            else
            {
                request.SetError(string.Format("Avatar calculations failed, status: {0}", avatar.status));
            }
        }
コード例 #6
0
        /// <summary>
        /// DeleteAvatarAsync implementation
        /// </summary>
        private IEnumerator DeleteAvatarFunc(string avatarCode, AsyncRequest request)
        {
            var avatarRequest = GetAvatarAsync(avatarCode);

            yield return(avatarRequest);

            if (avatarRequest.IsError)
            {
                request.SetError(avatarRequest.ErrorMessage);
                yield break;
            }

            var deleteRequest = connection.DeleteAvatarAsync(avatarRequest.Result);

            yield return(request.AwaitSubrequest(deleteRequest, 0.5f));

            if (request.IsError)
            {
                yield break;
            }

            CoreTools.DeleteAvatarFiles(avatarCode);

            request.IsDone = true;
        }
コード例 #7
0
        /// <summary>
        /// Loop until the desired number of pages is downloaded.
        /// </summary>
        public virtual IEnumerator AwaitMultiplePages <T> (string url, AsyncRequest <T[]> request, int maxItems = int.MaxValue)
        {
            List <T> items = new List <T> ();

            do
            {
                var pageRequest = AvatarJsonPageRequest <T> (url);
                yield return(pageRequest);

                if (pageRequest.IsError)
                {
                    request.SetError(string.Format("Page request failed. Error: {0}", pageRequest.ErrorMessage));
                    yield break;
                }

                // Debug.LogFormat ("Successfully loaded page {0}", url);
                var page = pageRequest.Result;

                for (int i = 0; i < page.content.Length && items.Count < maxItems; ++i)
                {
                    items.Add(page.content[i]);
                }

                url = page.nextPageUrl;
            } while (items.Count < maxItems && !string.IsNullOrEmpty(url));

            request.Result = items.ToArray();
            request.IsDone = true;
        }
コード例 #8
0
        /// <summary>
        /// GetAvatarAsync implementation
        /// </summary>
        private IEnumerator GetAvatarFunc(string avatarCode, AsyncRequest <AvatarData> request)
        {
            if (UseCache && avatarsDataCache.ContainsKey(avatarCode))
            {
                request.Result = avatarsDataCache[avatarCode];
                request.IsDone = true;
                yield break;
            }

            var avatarRequest = connection.GetAvatarAsync(avatarCode);

            yield return(avatarRequest);

            if (avatarRequest.IsError)
            {
                request.SetError(avatarRequest.ErrorMessage);
                yield break;
            }

            if (UseCache && string.Compare(avatarRequest.Result.status.ToLower(), "Completed") == 0)
            {
                avatarsDataCache[avatarCode] = avatarRequest.Result;
            }

            request.Result = avatarRequest.Result;
            request.IsDone = true;
        }
コード例 #9
0
    private static void ExecuteRequest(double time, AsyncRequest request)
    {
        //Do nothing if request is waiting for API response
        if (request.status == Status.WaitClipStatusRequest)
        {
            return;
        }

        //The next steps are only used to send status request
        if (request.status != Status.NeedNewClipStatusRequest)
        {
            return;
        }

        //Force a delay in requests to avoid flooding the api
        double delta = time - request.lastCheckTime;

        if (delta < 0.0f || delta > checkCooldown)
        {
            request.lastCheckTime = time;
        }
        else
        {
            return;
        }

        //Send GetClip request
        request.currentTask = APIBridge.GetClip(request.clipUUID, (ResembleClip clip, Error error) =>
        {
            //Error
            if (error)
            {
                request.SetError(error);
            }

            //Receive an response
            else
            {
                //Clip is ready - Start downloading
                if (clip.finished)
                {
                    DownloadClip(request, clip.link);

                    //Get phonemes
                    if (request.phonemeCallback != null)
                    {
                        request.phonemeCallback.Invoke(clip.phonemesRaw);
                    }
                }

                //Clip is not ready - Mark to create a request next time
                else
                {
                    request.status = Status.NeedNewClipStatusRequest;
                }
            }
        });
        request.status = Status.WaitClipStatusRequest;
    }
コード例 #10
0
        /// <summary>
        /// MoveToLocalStorageAvatarModelAsync implementation
        /// </summary>
        private IEnumerator MoveAvatarModelToLocalStorage(string avatarCode, bool withHaircutPointClouds, bool withBlendshapes, AsyncRequest request)
        {
            var avatarRequest = GetAvatarAsync(avatarCode);

            yield return(avatarRequest.Await());

            if (avatarRequest.IsError)
            {
                request.SetError(avatarRequest.ErrorMessage);
                yield break;
            }

            yield return(DownloadAndSaveAvatarModel(avatarRequest.Result, withHaircutPointClouds, withBlendshapes, request));
        }
コード例 #11
0
        /// <summary>
        /// AuthorizeAsync implementation.
        /// </summary>
        private IEnumerator Authorize(AsyncRequest request)
        {
            var accessCredentials = AuthUtils.LoadCredentials();

            if (accessCredentials == null || string.IsNullOrEmpty(accessCredentials.clientSecret))
            {
                request.SetError("Could not find API keys! Please provide valid credentials via Window->ItSeez3D Avatar SDK");
                yield break;
            }

            var authRequest = AuthorizeClientCredentialsGrantTypeAsync(accessCredentials);

            yield return(request.AwaitSubrequest(authRequest, 0.5f));

            if (request.IsError)
            {
                yield break;
            }

            tokenType   = authRequest.Result.token_type;
            accessToken = authRequest.Result.access_token;
            Debug.LogFormat("Successful authentication!");

            // guarantees we re-register a Player if clientId changes
            var playerIdentifier = string.Format("player_uid_{0}", accessCredentials.clientId.Substring(0, accessCredentials.clientId.Length / 3));

            if (string.IsNullOrEmpty(playerUID))
            {
                playerUID = AvatarSdkMgr.Storage().LoadPlayerUID(playerIdentifier);
            }

            if (string.IsNullOrEmpty(playerUID))
            {
                Debug.Log("Registering new player UID");
                var playerRequest = RegisterPlayerAsync();
                yield return(request.AwaitSubrequest(playerRequest, 1));

                if (request.IsError)
                {
                    yield break;
                }

                playerUID = playerRequest.Result.code;
                AvatarSdkMgr.Storage().StorePlayerUID(playerIdentifier, playerUID);
            }

            request.IsDone = true;
        }
コード例 #12
0
        /// <summary>
        /// GetAllAvatarsAsync implementation
        /// </summary>
        private IEnumerator GetAllAvatarsFunc(int maxItems, AsyncRequest <string[]> request)
        {
            var avatarsRequest = connection.GetAvatarsAsync(maxItems);

            yield return(avatarsRequest);

            if (avatarsRequest.IsError)
            {
                request.SetError(avatarsRequest.ErrorMessage);
                yield break;
            }

            var avatarsData = avatarsRequest.Result.OrderBy(av => DateTime.Parse(av.created_on)).Reverse().ToArray();

            request.Result = avatarsData.Select(a => a.code).ToArray();
            request.IsDone = true;
        }
コード例 #13
0
        /// <summary>
        /// GetHaircutDataAsync implementation
        /// </summary>
        private IEnumerator GetHaircutDataFunc(string avatarCode, string haircutId, AsyncRequest <AvatarHaircutData> request)
        {
            bool takeFromCache = UseCache && haircutsDataCache.ContainsKey(avatarCode);

            if (takeFromCache)
            {
                request.Result = haircutsDataCache[avatarCode].FirstOrDefault(h => string.Compare(h.identity, haircutId) == 0);
            }
            else
            {
                // get AvatarData firstly.
                // If you would like to make multiple requests for getting haircut data, it is better to get AvatarData only once and store it somewhere
                var avatarRequest = GetAvatarAsync(avatarCode);
                yield return(avatarRequest.Await());

                if (avatarRequest.IsError)
                {
                    request.SetError(avatarRequest.ErrorMessage);
                    yield break;
                }

                var haircutInfoRequest = connection.GetHaircutsAsync(avatarRequest.Result);
                yield return(request.AwaitSubrequest(haircutInfoRequest, 0.9f));

                if (request.IsError)
                {
                    yield break;
                }

                if (UseCache)
                {
                    haircutsDataCache.Add(avatarCode, haircutInfoRequest.Result);
                }

                AvatarHaircutData haircutData = haircutInfoRequest.Result.FirstOrDefault(h => string.Compare(h.identity, haircutId) == 0);
                if (haircutData == null)
                {
                    Debug.LogErrorFormat("There is no {0} haircut for avatar with code: {1}", haircutId, avatarCode);
                    yield break;
                }
                request.Result = haircutData;
            }

            request.IsDone = true;
        }
コード例 #14
0
        /// <summary>
        /// GetHaircutsIdAsync implementation
        /// </summary>
        private IEnumerator GetHaircutsIdFunc(string avatarCode, AsyncRequest <string[]> request)
        {
            bool takeFromCache = UseCache && haircutsDataCache.ContainsKey(avatarCode);

            if (takeFromCache)
            {
                request.Result = haircutsDataCache[avatarCode].Select(h => h.identity).ToArray();
            }
            else
            {
                var avatarRequest = GetAvatarAsync(avatarCode);
                yield return(avatarRequest.Await());

                if (avatarRequest.IsError)
                {
                    request.SetError(avatarRequest.ErrorMessage);
                    yield break;
                }

                if (supportedHaircutsPipelines.Contains(avatarRequest.Result.pipeline))
                {
                    var haircutInfoRequest = connection.GetHaircutsAsync(avatarRequest.Result);
                    yield return(request.AwaitSubrequest(haircutInfoRequest, 0.9f));

                    if (request.IsError)
                    {
                        yield break;
                    }

                    request.Result = haircutInfoRequest.Result.Select(h => h.identity).ToArray();

                    if (UseCache)
                    {
                        haircutsDataCache.Add(avatarCode, haircutInfoRequest.Result);
                    }
                }
                else
                {
                    Debug.LogFormat("{0} doesn't support haircuts", avatarRequest.Result.pipeline);
                }
            }

            request.IsDone = true;
        }
コード例 #15
0
        private IEnumerator GetResourcesFunc(AvatarResourcesSubset resourcesSubset, PipelineType pipelineType, AsyncRequest <AvatarResources> request)
        {
            if (avatarResourcesCache[pipelineType].ContainsKey(resourcesSubset))
            {
                request.Result = avatarResourcesCache[pipelineType][resourcesSubset];
                request.IsDone = true;
            }
            else
            {
                var resourcesWebRequest = connection.GetResourcesAsync(pipelineType, resourcesSubset);
                yield return(resourcesWebRequest);

                if (resourcesWebRequest.IsError)
                {
                    Debug.LogError(resourcesWebRequest.ErrorMessage);
                    request.SetError(resourcesWebRequest.ErrorMessage);
                    yield break;
                }
                AvatarResources avatarResources = GetResourcesFromJson(resourcesWebRequest.Result);
                avatarResourcesCache[pipelineType].Add(resourcesSubset, avatarResources);
                request.IsDone = true;
                request.Result = avatarResources;
            }
        }
コード例 #16
0
    /// <summary> Build a async request for a clip. This request handles patching, downloading and notifications. </summary>
    public static AsyncRequest Make(Clip clip)
    {
        //Build request
        AsyncRequest request = new AsyncRequest();

        request.status = Status.BuildRequest;
        string savePath = clip.GetSavePath();

        request.saveDirectory    = Path.GetDirectoryName(savePath);
        request.fileName         = Path.GetFileName(savePath);
        request.requestName      = clip.speech.name + " > " + clip.clipName;
        request.clipUUID         = clip.uuid;
        request.notificationLink = clip;


        //Generate place holder
        request.status = Status.GeneratePlaceHolder;
        clip.clip      = request.GeneratePlaceHolder();


        //Phonemes stuff
        bool   includePhonemes = clip.speech.includePhonemes;
        string voiceUUID       = clip.speech.voiceUUID;

        if (includePhonemes)
        {
            request.phonemeCallback = clip.SetPhonemesRaw;
        }

        //No UUID - Create new clip
        request.status = Status.SendDataToAPI;
        if (string.IsNullOrEmpty(request.clipUUID))
        {
            //Create new clip
            ClipPatch.Data data = new ClipPatch.Data(clip.clipName, clip.text.BuildResembleString(), voiceUUID);
            request.currentTask = APIBridge.CreateClip(data, includePhonemes, (ClipStatus status, Error error) =>
                                                       { request.clipUUID = clip.uuid = status.id;  RegisterRequestToPool(request); });
        }
        else
        {
            ClipPatch patch = new ClipPatch(clip.clipName, clip.text.BuildResembleString(), voiceUUID, clip.speech.includePhonemes);

            //Bypass the api check for similarities.
            if (Settings.forceGeneration)
            {
                //Patch clip
                request.currentTask = APIBridge.UpdateClip(request.clipUUID, patch, (string content, Error patchError) =>
                                                           { RegisterRequestToPool(request); });
            }

            //Check the api for similarities
            else
            {
                //Get existing clip
                APIBridge.GetClip(clip.uuid, (ResembleClip apiClip, Error error) =>
                {
                    //Handle error
                    if (error)
                    {
                        request.SetError(error);
                    }

                    else
                    {
                        //No changes - Download existing clip
                        if (apiClip.finished && patch.CompareContent(apiClip))
                        {
                            APIBridge.DownloadClip(apiClip.link, (byte[] data, Error downloadError) =>
                                                   { OnDownloaded(request, data, downloadError); RegisterRequestToPool(request); });
                        }

                        //Changes - Patch existing clip
                        else
                        {
                            request.currentTask = APIBridge.UpdateClip(request.clipUUID, patch, (string content, Error patchError) =>
                                                                       { RegisterRequestToPool(request); });
                        }
                    }
                });
            }
        }

        //Return the request
        return(request);
    }
コード例 #17
0
        private IEnumerator GenerateAvatarFunc(byte[] selectedImageBytes, PipelineType pipelineType, AsyncRequest <AvatarData> request)
        {
            UpdateAvatarState(WebglAvatarState.UPLOADING, pipelineType);

            var defaultResourcesRequest = avatarProvider.ResourceManager.GetResourcesAsync(AvatarResourcesSubset.DEFAULT, pipelineType);

            yield return(Await(defaultResourcesRequest, pipelineType));

            // Generate all haircuts and default blendshapes to play animations
            var allResourcesRequest = avatarProvider.ResourceManager.GetResourcesAsync(AvatarResourcesSubset.ALL, pipelineType);

            yield return(Await(allResourcesRequest, pipelineType));

            if (defaultResourcesRequest.IsError || allResourcesRequest.IsError)
            {
                string msg = "Unable to get resources list";
                Debug.LogError(msg);
                UpdateAvatarState(WebglAvatarState.FAILED, pipelineType);
                request.SetError(msg);
                yield break;
            }
            AvatarResources resources = allResourcesRequest.Result;

            resources.blendshapes = defaultResourcesRequest.Result.blendshapes;

            var createAvatar = connection.CreateAvatarWithPhotoAsync("test_avatar", "test_description", selectedImageBytes, false, pipelineType, resources);

            yield return(Await(createAvatar, pipelineType));

            if (createAvatar.IsError)
            {
                Debug.LogError(createAvatar.ErrorMessage);
                UpdateAvatarState(WebglAvatarState.FAILED, pipelineType);
                request.SetError(createAvatar.ErrorMessage);
                yield break;
            }

            var avatar    = createAvatar.Result;
            var savePhoto = CoreTools.SaveAvatarFileAsync(selectedImageBytes, avatar.code, AvatarFile.PHOTO);

            yield return(savePhoto);

            var savePipeline = CoreTools.SaveAvatarFileAsync(Encoding.ASCII.GetBytes(pipelineType.GetPipelineTypeName()), avatar.code, AvatarFile.PIPELINE_INFO);

            yield return(savePipeline);

            if (savePhoto.IsError)
            {
                Debug.LogError(savePhoto.ErrorMessage);
                UpdateAvatarState(WebglAvatarState.FAILED, pipelineType);
                request.SetError(savePhoto.ErrorMessage);
                yield break;
            }

            UpdateAvatarState(WebglAvatarState.CALCULATING_IN_CLOUD, pipelineType);

            var awaitCalculations = connection.AwaitAvatarCalculationsAsync(avatar);

            yield return(Await(awaitCalculations, pipelineType));

            if (awaitCalculations.IsError)
            {
                Debug.LogError(awaitCalculations.ErrorMessage);
                UpdateAvatarState(WebglAvatarState.FAILED, pipelineType);
                request.SetError(awaitCalculations.ErrorMessage);
                yield break;
            }

            AvatarData avatarData = awaitCalculations.Result;

            UpdateAvatarState(WebglAvatarState.DOWNLOADING, pipelineType);
            var downloadRequest = DownloadAvatarAsync(avatarData, pipelineType);

            yield return(downloadRequest);

            if (downloadRequest.IsError)
            {
                Debug.LogError(downloadRequest.ErrorMessage);
                UpdateAvatarState(WebglAvatarState.FAILED, pipelineType);
                request.SetError(downloadRequest.ErrorMessage);
                yield break;
            }

            UpdateAvatarState(WebglAvatarState.FINISHED, pipelineType);
            request.Result = avatarData;
            request.IsDone = true;
        }