public IEnumerator FetchTextures(TexturesFetched onTextureFetched)
    {
        if (texturesRetreived)
        {
            onTextureFetched?.Invoke(mainTexture, maskTexture);
            yield break;
        }

        var representation = wearable.GetRepresentation(bodyShapeType);

        string mainTextureName = representation.contents.FirstOrDefault(x => !x.file.ToLower().Contains("_mask.png"))?.hash;
        string maskName        = representation.contents.FirstOrDefault(x => x.file.ToLower().Contains("_mask.png"))?.hash;

        if (!string.IsNullOrEmpty(mainTextureName))
        {
            yield return(Utils.FetchTexture(wearable.baseUrl + mainTextureName, (tex) =>
            {
                tex.Compress(false);
                mainTexture = tex;
            }));
        }

        if (!string.IsNullOrEmpty(maskName))
        {
            yield return(Utils.FetchTexture(wearable.baseUrl + maskName, (tex) =>
            {
                tex.Compress(false);
                maskTexture = tex;
            }));
        }

        texturesRetreived = true;
        onTextureFetched?.Invoke(mainTexture, maskTexture);
    }
Example #2
0
    public virtual void Load(Transform parent, Action <WearableController> onSuccess, Action <WearableController> onFail)
    {
        bonesRetargeted = false;

        var representation = wearable.GetRepresentation(bodyShapeType);
        var provider       = wearable.GetContentProvider(bodyShapeType);

        loader = new RendereableAssetLoadHelper(provider, wearable.baseUrlBundles);

        loader.settings.forceNewInstance     = true;
        loader.settings.initialLocalPosition = Vector3.up * 0.75f;
        loader.settings.cachingFlags         = MaterialCachingHelper.Mode.CACHE_SHADERS;
        loader.settings.visibleFlags         = AssetPromiseSettings_Rendering.VisibleFlags.INVISIBLE;
        loader.settings.parent = parent;

        loader.OnSuccessEvent += (x) =>
        {
            PrepareWearable(x);
            onSuccess.Invoke(this);
        };

        loader.OnFailEvent += () => onFail.Invoke(this);

        loader.Load(representation.mainFile);
    }
    public virtual void Load(string bodyShapeId, Transform parent, Action <WearableController> onSuccess, Action <WearableController> onFail)
    {
        if (isReady)
        {
            return;
        }

        boneRetargetingDirty = true;

        var representation = wearable.GetRepresentation(bodyShapeId);

        if (representation == null)
        {
            onFail?.Invoke(this);
            return;
        }

        var provider = wearable.GetContentProvider(bodyShapeId);

        loader = new RendereableAssetLoadHelper(provider, wearable.baseUrlBundles);

        loader.settings.forceNewInstance     = false;
        loader.settings.initialLocalPosition = Vector3.up * 0.75f;
        loader.settings.cachingFlags         = MaterialCachingHelper.Mode.CACHE_SHADERS;
        loader.settings.visibleFlags         = AssetPromiseSettings_Rendering.VisibleFlags.INVISIBLE;
        loader.settings.parent = parent;

        assetRenderers = null;

        void OnSuccessWrapper(GameObject gameObject)
        {
            if (loader != null)
            {
                loader.OnSuccessEvent -= OnSuccessWrapper;
            }
            assetRenderers = gameObject.GetComponentsInChildren <Renderer>();
            PrepareWearable(gameObject);
            onSuccess?.Invoke(this);
        }

        loader.OnSuccessEvent += OnSuccessWrapper;

        void OnFailEventWrapper()
        {
            if (loader != null)
            {
                loader.OnFailEvent -= OnFailEventWrapper;
                loader.ClearEvents();
                lastMainFileLoaded = null;
                loader             = null;
            }
            onFail?.Invoke(this);
        }

        loader.OnFailEvent += OnFailEventWrapper;

        lastMainFileLoaded = representation.mainFile;
        loader.Load(representation.mainFile);
    }
    public IEnumerator FetchTextures()
    {
        if (mainTexturePromise != null)
        {
            AssetPromiseKeeper_Texture.i.Forget(mainTexturePromise);
        }

        if (maskTexturePromise != null)
        {
            AssetPromiseKeeper_Texture.i.Forget(maskTexturePromise);
        }

        mainTexture = null;
        maskTexture = null;

        var representation = wearableItem.GetRepresentation(bodyShape.bodyShapeId);

        string mainTextureHash = representation?.contents?.FirstOrDefault(x => x.key == representation?.mainFile)?.hash;

        if (mainTextureHash == null)
        {
            mainTextureHash = representation?.contents?.FirstOrDefault(x => !x.key.ToLower().Contains("_mask.png"))?.hash;
        }
        string maskhash = representation?.contents?.FirstOrDefault(x => x.key.ToLower().Contains("_mask.png"))?.hash;

        if (!string.IsNullOrEmpty(mainTextureHash))
        {
            mainTexturePromise = new AssetPromise_Texture(wearableItem.baseUrl + mainTextureHash);
            mainTexturePromise.OnSuccessEvent += (x) => mainTexture = x.texture;
            mainTexturePromise.OnFailEvent    += (x) => mainTexture = null;

            AssetPromiseKeeper_Texture.i.Keep(mainTexturePromise);
        }

        if (!string.IsNullOrEmpty(maskhash))
        {
            maskTexturePromise = new AssetPromise_Texture(wearableItem.baseUrl + maskhash);
            maskTexturePromise.OnSuccessEvent += (x) => maskTexture = x.texture;
            maskTexturePromise.OnFailEvent    += (x) => maskTexture = null;

            AssetPromiseKeeper_Texture.i.Keep(maskTexturePromise);
        }

        yield return(mainTexturePromise);

        yield return(maskTexturePromise);

        PrepareWearable();
    }
        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(true);
                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);
                }
            }

            if (resolvedBody == null)
            {
                isLoading = false;
                OnFailEvent?.Invoke(true);
                yield break;
            }

            List <Helpers.Promise <WearableItem> > replacementPromises = new List <Helpers.Promise <WearableItem> >();

            foreach (var avatarWearablePromise in avatarWearablePromises)
            {
                yield return(avatarWearablePromise);

                if (!string.IsNullOrEmpty(avatarWearablePromise.error))
                {
                    Debug.LogError(avatarWearablePromise.error);
                    loadSoftFailed = true;
                }
                else
                {
                    WearableItem wearableItem = avatarWearablePromise.value;
                    wearablesInUse.Add(wearableItem.id);
                    if (wearableItem.GetRepresentation(model.bodyShape) != null)
                    {
                        resolvedWearables.Add(wearableItem);
                    }
                    else
                    {
                        model.wearables.Remove(wearableItem.id);
                        string defaultReplacement = DefaultWearables.GetDefaultWearable(model.bodyShape, wearableItem.data.category);
                        if (!string.IsNullOrEmpty(defaultReplacement))
                        {
                            model.wearables.Add(defaultReplacement);
                            replacementPromises.Add(CatalogController.RequestWearable(defaultReplacement));
                        }
                    }
                }
            }

            foreach (var wearablePromise in replacementPromises)
            {
                yield return(wearablePromise);

                if (!string.IsNullOrEmpty(wearablePromise.error))
                {
                    Debug.LogError(wearablePromise.error);
                    loadSoftFailed = true;
                }
                else
                {
                    WearableItem wearableItem = wearablePromise.value;
                    wearablesInUse.Add(wearableItem.id);
                    resolvedWearables.Add(wearableItem);
                }
            }

            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.data.category);
                if (wearableControllers.ContainsKey(wearable))
                {
                    if (wearableControllers[wearable].IsLoadedForBodyShape(bodyShapeController.bodyShapeId))
                    {
                        UpdateWearableController(wearable);
                    }
                    else
                    {
                        wearableControllers[wearable].CleanUp();
                    }
                }
                else
                {
                    AddWearableController(wearable);
                    if (wearable.data.category != Categories.EYES && wearable.data.category != Categories.MOUTH && wearable.data.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;
                }
            }


            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 == null || (eyebrowsController != null && eyebrowsController.isReady)) &&
                                       (eyesController == null || (eyesController != null && eyesController.isReady)) &&
                                       (mouthController == null || (mouthController != null && mouthController.isReady))));

            if (bodyIsDirty || wearablesIsDirty)
            {
                OnVisualCue?.Invoke(VisualCue.Loaded);
            }

            bodyShapeController.SetActiveParts(unusedCategories.Contains(Categories.LOWER_BODY), unusedCategories.Contains(Categories.UPPER_BODY), unusedCategories.Contains(Categories.FEET));
            bodyShapeController.SetFacialFeaturesVisible(facialFeaturesVisible);
            bodyShapeController.UpdateVisibility(hiddenList);
            foreach (WearableController wearableController in wearableControllers.Values)
            {
                wearableController.UpdateVisibility(hiddenList);
            }

            CleanUpUnusedItems();

            isLoading = false;

            SetWearableBones();
            UpdateExpressions(model.expressionTriggerId, model.expressionTriggerTimestamp);
            if (lastStickerTimestamp != model.stickerTriggerTimestamp && model.stickerTriggerId != null)
            {
                lastStickerTimestamp = model.stickerTriggerTimestamp;
                stickersController?.PlayEmote(model.stickerTriggerId);
            }

            if (loadSoftFailed)
            {
                OnFailEvent?.Invoke(false);
            }
            else
            {
                OnSuccessEvent?.Invoke();
            }
        }