/// <summary> /// Generates avatar with the selected set of resources and displayed it in AvatarViewer scene /// </summary> protected override IEnumerator GenerateAndDisplayHead(byte[] photoBytes, PipelineType pipeline) { //Get selected resources AvatarResources avatarResources = GetSelectedResources(); Debug.Log(CoreTools.GetAvatarCalculationParamsJson(avatarResources)); yield return(Await(null)); // generate avatar from the photo and get its code in the Result of request /* * var initializeRequest = avatarProvider.InitializeAvatarAsync(photoBytes, "name", "description", pipeline, avatarResources); * yield return Await(initializeRequest); * string avatarCode = initializeRequest.Result; * * StartCoroutine(SampleUtils.DisplayPhotoPreview(avatarCode, photoPreview)); * * var calculateRequest = avatarProvider.StartAndAwaitAvatarCalculationAsync(avatarCode); * yield return Await(calculateRequest); * * AvatarViewer.SetSceneParams(new AvatarViewer.SceneParams() * { * avatarCode = avatarCode, * showSettings = false, * sceneToReturn = SceneManager.GetActiveScene().name, * avatarProvider = avatarProvider, * useAnimations = false * }); * SceneManager.LoadScene(Scenes.GetSceneName(SceneType.AVATAR_VIEWER)); */ }
protected IEnumerator UpdateResources() { SetControlsInteractable(false); // Get all available resources var allResourcesRequest = avatarProvider.ResourceManager.GetResourcesAsync(AvatarResourcesSubset.ALL, pipelineType); // Get default resources var defaultResourcesRequest = avatarProvider.ResourceManager.GetResourcesAsync(AvatarResourcesSubset.DEFAULT, pipelineType); yield return(Await(allResourcesRequest, defaultResourcesRequest)); if (allResourcesRequest.IsError || defaultResourcesRequest.IsError) { Debug.LogError("Unable to get resources list"); haircutsSelectingView.InitItems(new List <string>()); blendshapesSelectingView.InitItems(new List <string>()); } else { AvatarResources allResources = allResourcesRequest.Result; AvatarResources defaultResources = defaultResourcesRequest.Result; haircutsSelectingView.InitItems(allResources.haircuts); haircutsSelectingView.Show(defaultResources.haircuts, null); blendshapesSelectingView.InitItems(allResources.blendshapes); blendshapesSelectingView.Show(defaultResources.blendshapes, null); } SetControlsInteractable(true); }
/// <summary> /// Initializes avatar and uploads photo to the server. /// </summary> /// <param name="photoBytes">Photo bytes (jpg or png encoded).</param> /// <param name="name">Name of the avatar</param> /// <param name="description">Description of the avatar</param> /// <param name="pipeline">Calculation pipeline to use</param> /// <returns>Avatar unique code</returns> public AsyncRequest <string> InitializeAvatarAsync(byte[] photoBytes, string name, string description, PipelineType pipeline = PipelineType.FACE, AvatarResources avatarResources = null) { var request = new AsyncRequest <string>(AvatarSdkMgr.Str(Strings.GeneratingAvatar)); AvatarSdkMgr.SpawnCoroutine(InitializeAvatarFunc(photoBytes, name, description, pipeline, avatarResources, request)); return(request); }
/// <summary> /// Forms selected resources lists /// </summary> protected AvatarResources GetSelectedResources() { AvatarResources resources = AvatarResources.Empty; resources.haircuts = haircutsSelectingView.CurrentSelection; resources.blendshapes = blendshapesSelectingView.CurrentSelection; return(resources); }
/// <summary> /// InitializeAvatarAsync implementation /// </summary> private IEnumerator InitializeAvatarFunc(byte[] photoBytes, string name, string description, PipelineType pipeline, AvatarResources resources, AsyncRequest <string> request) { // uploading photo and registering new avatar on the server var createAvatar = connection.CreateAvatarWithPhotoAsync(name, description, photoBytes, false, pipeline, resources); // Wait until async request is completed (without blocking the main thread). // Instead of using AwaitSubrequest we could just use `yield return createAvatar;` // AwaitSubrequest is a helper function that allows to track progress on composite // requests automatically. It also provides info for the caller about current subrequest // (and it's progress) and propagetes error from subrequest to the parent request. // finalProgress is a value between 0 and 1, a desired progress of parent request when given // subrequest is completed. yield return(request.AwaitSubrequest(createAvatar, finalProgress: 0.99f)); // must check whether request was successful before proceeding if (request.IsError) { yield break; } string avatarCode = createAvatar.Result.code; // save photo for later use var savePhoto = CoreTools.SaveAvatarFileAsync(photoBytes, avatarCode, AvatarFile.PHOTO); // save pipeline type var savePipeline = CoreTools.SaveAvatarFileAsync(Encoding.ASCII.GetBytes(pipeline.GetPipelineTypeName()), avatarCode, AvatarFile.PIPELINE_INFO); yield return(request.AwaitSubrequests(1.0f, savePhoto, savePipeline)); // again, must check for the error, there's no point in proceeding otherwise if (request.IsError) { yield break; } request.Result = avatarCode; request.IsDone = true; }
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; } }
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; }
void Start() { boxCollider2D = GetComponent <BoxCollider2D>(); avatarResources = avatar.GetComponent <AvatarResources>(); }
/// <summary> /// Upload photo and create avatar instance on the server. Calculations will start right away after the photo is uploaded. /// </summary> public virtual AsyncWebRequest <AvatarData> CreateAvatarWithPhotoAsync( string name, string description, byte[] photoBytes, bool forcePowerOfTwoTexture = false, PipelineType pipeline = PipelineType.FACE, AvatarResources resources = null ) { var request = new AsyncWebRequest <AvatarData> (AvatarSdkMgr.Str(Strings.UploadingPhoto), TrackProgress.UPLOAD); #if UNITY_2017_1_OR_NEWER Func <UnityWebRequest> webRequestFactory = () => { List <IMultipartFormSection> formData = new List <IMultipartFormSection>(); formData.Add(new MultipartFormDataSection("name", name)); if (!string.IsNullOrEmpty(description)) { formData.Add(new MultipartFormDataSection("description", description)); } formData.Add(new MultipartFormFileSection("photo", photoBytes, "photo.jpg", "application/octet-stream")); formData.Add(new MultipartFormDataSection("preserve_original_texture", (!forcePowerOfTwoTexture).ToString())); formData.Add(new MultipartFormDataSection("pipeline", pipeline.GetPipelineTypeName())); if (resources != null) { formData.Add(new MultipartFormDataSection("pipeline_subtype", pipeline_subtype)); formData.Add(new MultipartFormDataSection("resources", CoreTools.GetAvatarCalculationParamsJson(resources))); } var webRequest = UnityWebRequest.Post(GetUrl("avatars"), formData); webRequest.chunkedTransfer = false; SetAuthHeaders(webRequest); return(webRequest); }; Debug.LogFormat("Uploading photo..."); AvatarSdkMgr.SpawnCoroutine(AwaitJsonWebRequest(webRequestFactory, request)); return(request); #else // Unity 5.5.0 (and probably earlier versions) have a weird bug in default multipart form data // implementation, which causes incorrect boundaries between data fields. To work around this bug the // multipart request body is constructed manually, see below. byte[] requestBodyData = null; using (var requestBody = new MultipartBody()) { requestBody.WriteTextField("name", name); requestBody.WriteTextField("description", description); requestBody.WriteFileField("photo", "photo.jpg", photoBytes); requestBody.WriteTextField("preserve_original_texture", (!forcePowerOfTwoTexture).ToString()); requestBody.WriteTextField("pipeline", pipeline.GetPipelineTypeName()); if (resources != null) { requestBody.WriteTextField("pipeline_subtype", pipeline_subtype); requestBody.WriteTextField("resources", CoreTools.GetAvatarCalculationParamsJson(resources)); } requestBody.WriteFooter(); requestBodyData = requestBody.GetRequestBodyData(); Func <UnityWebRequest> webRequestFactory = () => { var webRequest = UnityWebRequest.Post(GetUrl("avatars"), " "); webRequest.uploadHandler = new UploadHandlerRaw(requestBodyData); webRequest.SetRequestHeader( "Content-Type", string.Format("multipart/form-data; boundary=\"{0}\"", requestBody.Boundary) ); webRequest.chunkedTransfer = false; SetAuthHeaders(webRequest); return(webRequest); }; Debug.LogFormat("Uploading photo..."); AvatarSdkMgr.SpawnCoroutine(AwaitJsonWebRequest(webRequestFactory, request)); return(request); } #endif }
void Start() { avatarResources = GetComponent <AvatarResources>(); avatarController = GetComponent <Avatar2DCharacterCTRL>(); isAvatarGrounded = avatarController.playerIsGrounded; }