private void ProcessWearable(string wearableId) { var wearable = ResolveWearable(wearableId); if (wearable == null) { return; } switch (wearable.category) { case WearableLiterals.Categories.EYES: eyesController = new FacialFeatureController(wearable, bodyShapeController.bodyShapeType); break; case WearableLiterals.Categories.EYEBROWS: eyebrowsController = new FacialFeatureController(wearable, bodyShapeController.bodyShapeType); break; case WearableLiterals.Categories.MOUTH: mouthController = new FacialFeatureController(wearable, bodyShapeController.bodyShapeType); break; case WearableLiterals.Categories.BODY_SHAPE: break; default: var wearableController = new WearableController(ResolveWearable(wearableId), bodyShapeController.id); wearablesController.Add(wearableId, wearableController); wearableController.Load(transform, OnWearableLoadingSuccess, OnWearableLoadingFail); break; } }
public IEnumerator FailsGracefully_EmptyContent() { //Arrange WearableItem fakeWearable = new WearableItem { category = WearableLiterals.Categories.EYES, baseUrl = "http://nothing_here.nope", representations = new [] { new WearableItem.Representation { bodyShapes = new [] { WearableLiterals.BodyShapes.FEMALE }, contents = new ContentServerUtils.MappingPair[0], } } }; FacialFeatureController controller = new FacialFeatureController(fakeWearable, new Material(Shader.Find("DCL/Toon Shader"))); //Act controller.Load(bodyShapeController, Color.red); yield return(new WaitUntil(() => controller.isReady)); //Assert Assert.Null(controller.mainTexture); Assert.Null(controller.maskTexture); }
public void CleanupAvatar() { StopLoadingCoroutines(); eyebrowsController?.CleanUp(); eyebrowsController = null; eyesController?.CleanUp(); eyesController = null; bodyShapeController?.CleanUp(); bodyShapeController = null; using (var iterator = wearableControllers.GetEnumerator()) { while (iterator.MoveNext()) { iterator.Current.Value.CleanUp(); } } wearableControllers.Clear(); model = null; isLoading = false; OnFailEvent = null; OnSuccessEvent = null; }
private void AddWearableController(WearableItem wearable) { if (wearable == null) { return; } switch (wearable.category) { case Categories.EYES: eyesController = new FacialFeatureController(wearable, eyeMaterial); break; case Categories.EYEBROWS: eyebrowsController = new FacialFeatureController(wearable, eyebrowMaterial); break; case Categories.MOUTH: mouthController = new FacialFeatureController(wearable, mouthMaterial); break; case Categories.BODY_SHAPE: break; default: var wearableController = new WearableController(wearable, bodyShapeController.id); wearableControllers.Add(wearable, wearableController); break; } }
//TODO: Remove/replace once the class is easily mockable. protected void CopyFrom(AvatarRenderer original) { this.wearableControllers = original.wearableControllers; this.mouthController = original.mouthController; this.bodyShapeController = original.bodyShapeController; this.eyebrowsController = original.eyebrowsController; this.eyesController = original.eyesController; }
public IEnumerator LoadProperly() { //Arrange FacialFeatureController controller = new FacialFeatureController(catalog.GetOrDefault(EYES_ID), new Material(Shader.Find("DCL/Toon Shader"))); //Act controller.Load(bodyShapeController, Color.red); yield return(new WaitUntil(() => controller.isReady)); //Assert Assert.NotNull(controller.mainTexture); Assert.NotNull(controller.maskTexture); }
public IEnumerator LoadMouthWithMaskProperly() { //Arrange FacialFeatureController controller = new FacialFeatureController(catalog.GetOrDefault(DRACULA_MOUTH_ID), new Material(Shader.Find("DCL/Unlit Cutout Tinted"))); //Act controller.Load(bodyShapeController, Color.red); yield return(new WaitUntil(() => controller.isReady)); //Assert Assert.NotNull(controller.mainTexture); Assert.NotNull(controller.maskTexture); }
public IEnumerator LoadProperly() { //Arrange catalog.TryGetValue(EYES_ID, out WearableItem wereableItem); FacialFeatureController controller = new FacialFeatureController(wereableItem, new Material(Shader.Find("DCL/Toon Shader"))); //Act controller.Load(bodyShapeController, Color.red); yield return(new WaitUntil(() => controller.isReady)); //Assert Assert.NotNull(controller.mainTexture); Assert.NotNull(controller.maskTexture); }
private void SetupDefaultFacialFeatures(string bodyShape) { string eyesDefaultId = WearableLiterals.DefaultWearables.GetDefaultWearable(bodyShape, WearableLiterals.Categories.EYES); eyesController = new FacialFeatureController(ResolveWearable(eyesDefaultId), bodyShapeController.bodyShapeType); string eyebrowsDefaultId = WearableLiterals.DefaultWearables.GetDefaultWearable(bodyShape, WearableLiterals.Categories.EYEBROWS); eyebrowsController = new FacialFeatureController(ResolveWearable(eyebrowsDefaultId), bodyShapeController.bodyShapeType); string mouthDefaultId = WearableLiterals.DefaultWearables.GetDefaultWearable(bodyShape, WearableLiterals.Categories.MOUTH); mouthController = new FacialFeatureController(ResolveWearable(mouthDefaultId), bodyShapeController.bodyShapeType); }
public void CleanupAvatar() { StopLoadingCoroutines(); eyebrowsController?.CleanUp(); eyebrowsController = null; eyesController?.CleanUp(); eyesController = null; mouthController?.CleanUp(); mouthController = null; bodyShapeController?.CleanUp(); bodyShapeController = null; using (var iterator = wearableControllers.GetEnumerator()) { while (iterator.MoveNext()) { iterator.Current.Value.CleanUp(); } } wearableControllers.Clear(); model = null; isLoading = false; OnFailEvent = null; OnSuccessEvent = null; if (lodController != null) { Environment.i.platform.avatarsLODController.RemoveAvatar(lodController); } if (bodySnapshotTexturePromise != null) { AssetPromiseKeeper_Texture.i.Forget(bodySnapshotTexturePromise); } CatalogController.RemoveWearablesInUse(wearablesInUse); wearablesInUse.Clear(); OnVisualCue?.Invoke(VisualCue.CleanedUp); }
public IEnumerator FailsGracefully_BadURL() { //Arrange WearableItem fakeWearable = new WearableItem { baseUrl = "http://nothing_here.nope", data = new WearableItem.Data() { category = WearableLiterals.Categories.EYES, representations = new [] { new WearableItem.Representation() { bodyShapes = new [] { WearableLiterals.BodyShapes.FEMALE }, contents = new [] { new WearableItem.MappingPair { key = "fake.png", hash = "nope" }, new WearableItem.MappingPair { key = "fake_mask.png", hash = "nope2" } }, } } } }; FacialFeatureController controller = new FacialFeatureController(fakeWearable, new Material(Shader.Find("DCL/Toon Shader"))); //Act controller.Load(bodyShapeController, Color.red); yield return(new WaitUntil(() => controller.isReady)); //Assert Assert.Null(controller.mainTexture); Assert.Null(controller.maskTexture); }
private IEnumerator LoadAvatar() { yield return(new WaitUntil(() => gameObject.activeSelf)); WearableItem resolvedBody = null; if (!string.IsNullOrEmpty(model.bodyShape) && !CatalogController.wearableCatalog.TryGetValue(model.bodyShape, out resolvedBody)) { Debug.LogError($"Bodyshape {model.bodyShape} not found in catalog"); } List <WearableItem> resolvedWearables = new List <WearableItem>(); if (model.wearables != null) { for (int i = 0; i < model.wearables.Count; i++) { if (!CatalogController.wearableCatalog.TryGetValue(model.wearables[i], out WearableItem item)) { Debug.LogError($"Wearable {model.wearables[i]} not found in catalog"); continue; } resolvedWearables.Add(item); } } if (resolvedBody == null) { isLoading = false; this.OnSuccessEvent?.Invoke(); yield break; } bool bodyIsDirty = false; if (bodyShapeController != null && bodyShapeController.id != model?.bodyShape) { bodyShapeController.CleanUp(); bodyShapeController = null; bodyIsDirty = true; } if (bodyShapeController == null) { HideAll(); bodyShapeController = new BodyShapeController(resolvedBody); eyesController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYES, eyeMaterial); eyebrowsController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYEBROWS, eyebrowMaterial); mouthController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.MOUTH, mouthMaterial); } else { //If bodyShape is downloading will call OnWearableLoadingSuccess (and therefore SetupDefaultMaterial) once ready if (bodyShapeController.isReady) { bodyShapeController.SetupDefaultMaterial(defaultMaterial, model.skinColor, model.hairColor); } } HashSet <string> unusedCategories = new HashSet <string>(Categories.ALL); int wearableCount = resolvedWearables.Count; for (int index = 0; index < wearableCount; index++) { WearableItem wearable = resolvedWearables[index]; if (wearable == null) { continue; } unusedCategories.Remove(wearable.category); if (wearableControllers.ContainsKey(wearable)) { UpdateWearableController(wearable); } else { AddWearableController(wearable); } } foreach (var category in unusedCategories) { switch (category) { case Categories.EYES: eyesController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYES, eyeMaterial); break; case Categories.MOUTH: mouthController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.MOUTH, mouthMaterial); break; case Categories.EYEBROWS: eyebrowsController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYEBROWS, eyebrowMaterial); break; } } CleanUpUnusedItems(); HashSet <string> hiddenList = WearableItem.CompoundHidesList(bodyShapeController.bodyShapeId, resolvedWearables); if (!bodyShapeController.isReady) { bodyShapeController.Load(transform, OnWearableLoadingSuccess, OnBodyShapeLoadingFail); } foreach (WearableController wearable in wearableControllers.Values) { if (bodyIsDirty) { wearable.boneRetargetingDirty = true; } wearable.Load(transform, OnWearableLoadingSuccess, x => OnWearableLoadingFail(x)); yield return(null); } yield return(new WaitUntil(() => bodyShapeController.isReady && wearableControllers.Values.All(x => x.isReady))); eyesController.Load(bodyShapeController, model.eyeColor); eyebrowsController.Load(bodyShapeController, model.hairColor); mouthController.Load(bodyShapeController, model.skinColor); yield return(new WaitUntil(() => eyebrowsController.isReady && eyesController.isReady && mouthController.isReady)); bodyShapeController.SetActiveParts(unusedCategories.Contains(Categories.LOWER_BODY), unusedCategories.Contains(Categories.UPPER_BODY), unusedCategories.Contains(Categories.FEET)); bodyShapeController.UpdateVisibility(hiddenList); foreach (WearableController wearableController in wearableControllers.Values) { wearableController.UpdateVisibility(hiddenList); } isLoading = false; SetWearableBones(); UpdateExpressions(model.expressionTriggerId, model.expressionTriggerTimestamp); OnSuccessEvent?.Invoke(); }
private IEnumerator LoadAvatar() { yield return(new WaitUntil(() => gameObject.activeSelf)); bool loadSoftFailed = false; WearableItem resolvedBody = null; Helpers.Promise <WearableItem> avatarBodyPromise = null; if (!string.IsNullOrEmpty(model.bodyShape)) { avatarBodyPromise = CatalogController.RequestWearable(model.bodyShape); } else { OnFailEvent?.Invoke(); yield break; } List <WearableItem> resolvedWearables = new List <WearableItem>(); List <Helpers.Promise <WearableItem> > avatarWearablePromises = new List <Helpers.Promise <WearableItem> >(); if (model.wearables != null) { for (int i = 0; i < model.wearables.Count; i++) { avatarWearablePromises.Add(CatalogController.RequestWearable(model.wearables[i])); } } // In this point, all the requests related to the avatar's wearables have been collected and sent to the CatalogController to be sent to kernel as a unique request. // From here we wait for the response of the requested wearables and process them. if (avatarBodyPromise != null) { yield return(avatarBodyPromise); if (!string.IsNullOrEmpty(avatarBodyPromise.error)) { Debug.LogError(avatarBodyPromise.error); loadSoftFailed = true; } else { resolvedBody = avatarBodyPromise.value; wearablesInUse.Add(avatarBodyPromise.value.id); } } foreach (var avatarWearablePromise in avatarWearablePromises) { yield return(avatarWearablePromise); if (!string.IsNullOrEmpty(avatarWearablePromise.error)) { Debug.LogError(avatarWearablePromise.error); loadSoftFailed = true; } else { resolvedWearables.Add(avatarWearablePromise.value); wearablesInUse.Add(avatarWearablePromise.value.id); } } if (resolvedBody == null) { isLoading = false; this.OnSuccessEvent?.Invoke(); yield break; } bool bodyIsDirty = false; if (bodyShapeController != null && bodyShapeController.id != model?.bodyShape) { bodyShapeController.CleanUp(); bodyShapeController = null; bodyIsDirty = true; } if (bodyShapeController == null) { HideAll(); bodyShapeController = new BodyShapeController(resolvedBody); eyesController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYES, eyeMaterial); eyebrowsController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYEBROWS, eyebrowMaterial); mouthController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.MOUTH, mouthMaterial); } else { //If bodyShape is downloading will call OnWearableLoadingSuccess (and therefore SetupDefaultMaterial) once ready if (bodyShapeController.isReady) { bodyShapeController.SetupDefaultMaterial(defaultMaterial, model.skinColor, model.hairColor); } } bool wearablesIsDirty = false; HashSet <string> unusedCategories = new HashSet <string>(Categories.ALL); int wearableCount = resolvedWearables.Count; for (int index = 0; index < wearableCount; index++) { WearableItem wearable = resolvedWearables[index]; if (wearable == null) { continue; } unusedCategories.Remove(wearable.category); if (wearableControllers.ContainsKey(wearable)) { if (wearableControllers[wearable].IsLoadedForBodyShape(bodyShapeController.bodyShapeId)) { UpdateWearableController(wearable); } else { wearableControllers[wearable].CleanUp(); } } else { AddWearableController(wearable); if (wearable.category != Categories.EYES && wearable.category != Categories.MOUTH && wearable.category != Categories.EYEBROWS) { wearablesIsDirty = true; } } } foreach (var category in unusedCategories) { switch (category) { case Categories.EYES: eyesController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYES, eyeMaterial); break; case Categories.MOUTH: mouthController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.MOUTH, mouthMaterial); break; case Categories.EYEBROWS: eyebrowsController = FacialFeatureController.CreateDefaultFacialFeature(bodyShapeController.bodyShapeId, Categories.EYEBROWS, eyebrowMaterial); break; } } CleanUpUnusedItems(); HashSet <string> hiddenList = WearableItem.CompoundHidesList(bodyShapeController.bodyShapeId, resolvedWearables); if (!bodyShapeController.isReady) { bodyShapeController.Load(bodyShapeController.bodyShapeId, transform, OnWearableLoadingSuccess, OnBodyShapeLoadingFail); } foreach (WearableController wearable in wearableControllers.Values) { if (bodyIsDirty) { wearable.boneRetargetingDirty = true; } wearable.Load(bodyShapeController.bodyShapeId, transform, OnWearableLoadingSuccess, x => OnWearableLoadingFail(x)); yield return(null); } yield return(new WaitUntil(() => bodyShapeController.isReady && wearableControllers.Values.All(x => x.isReady))); eyesController.Load(bodyShapeController, model.eyeColor); eyebrowsController.Load(bodyShapeController, model.hairColor); mouthController.Load(bodyShapeController, model.skinColor); yield return(new WaitUntil(() => eyebrowsController.isReady && eyesController.isReady && mouthController.isReady)); if (useFx && (bodyIsDirty || wearablesIsDirty)) { var particles = Instantiate(fxSpawnPrefab); var particlesFollow = particles.AddComponent <FollowObject>(); particles.transform.position += transform.position; particlesFollow.target = transform; particlesFollow.offset = fxSpawnPrefab.transform.position; } bodyShapeController.SetActiveParts(unusedCategories.Contains(Categories.LOWER_BODY), unusedCategories.Contains(Categories.UPPER_BODY), unusedCategories.Contains(Categories.FEET)); bodyShapeController.UpdateVisibility(hiddenList); foreach (WearableController wearableController in wearableControllers.Values) { wearableController.UpdateVisibility(hiddenList); } isLoading = false; SetWearableBones(); UpdateExpressions(model.expressionTriggerId, model.expressionTriggerTimestamp); if (loadSoftFailed) { OnFailEvent?.Invoke(); } else { OnSuccessEvent?.Invoke(); } }