예제 #1
0
        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);
        }
예제 #3
0
        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;
        }
예제 #4
0
        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;
            }
        }
예제 #5
0
 //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);
        }
예제 #7
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #12
0
        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();
        }
예제 #13
0
        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();
            }
        }