< Summary

Class:AvatarEditorHUDController
Assembly:AvatarEditorHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDController.cs
Covered lines:255
Uncovered lines:74
Coverable lines:329
Total lines:660
Line coverage:77.5% (255 of 329)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AvatarEditorHUDController()0%110100%
AvatarEditorHUDController()0%110100%
Initialize(...)0%110100%
SetCatalog(...)0%2.062075%
LoadUserProfile(...)0%110100%
LoadOwnedWereables(...)0%440100%
QueryNftCollections(...)0%7.464040%
RetryLoadOwnedWearables()0%2100%
PlayerRendererLoaded(...)0%6.136084.62%
LoadUserProfile(...)0%11.4211084.85%
EnsureWearablesCategoriesNotEmpty()0%7.027092.86%
WearableClicked(...)0%7.197084.21%
HairColorClicked(...)0%110100%
SkinColorClicked(...)0%110100%
EyesColorClicked(...)0%110100%
UpdateAvatarPreview()0%220100%
EquipHairColor(...)0%220100%
EquipEyesColor(...)0%220100%
EquipSkinColor(...)0%220100%
EquipBodyShape(...)0%6.046089.47%
EquipWearable(...)0%5.055087.5%
UnequipWearable(...)0%220100%
UnequipAllWearables()0%220100%
ProcessCatalog(...)0%330100%
AddWearable(...)0%440100%
RemoveWearable(...)0%20400%
RandomizeWearables()0%44093.75%
GetWearablesReplacedBy(...)0%7.017093.33%
SetVisibility(...)0%110100%
OnAvatarEditorVisibleChanged(...)0%110100%
SetVisibility_Internal(...)0%8.028093.55%
Dispose()0%110100%
CleanUp()0%220100%
SetConfiguration(...)0%2100%
SaveAvatar(...)0%2.012085.71%
DiscardAndClose()0%12300%
GoToMarketplace()0%6200%
SellCollectible(...)0%12300%
ToggleVisibility()0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDController.cs

#LineLine coverage
 1using DCL;
 2using DCL.Helpers;
 3using DCL.Interface;
 4using System;
 5using System.Collections.Generic;
 6using System.Linq;
 7using UnityEngine;
 8using UnityEngine.Rendering;
 9using UnityEngine.Rendering.Universal;
 10using Categories = WearableLiterals.Categories;
 11
 12public class AvatarEditorHUDController : IHUD
 13{
 14    private const int LOADING_OWNED_WEARABLES_RETRIES = 3;
 15    private const string LOADING_OWNED_WEARABLES_ERROR_MESSAGE = "There was a problem loading your wearables";
 16    private const string URL_MARKET_PLACE = "https://market.decentraland.org/browse?section=wearables";
 17    private const string URL_GET_A_WALLET = "https://docs.decentraland.org/get-a-wallet";
 18    private const string URL_SELL_COLLECTIBLE_GENERIC = "https://market.decentraland.org/account";
 19    private const string URL_SELL_SPECIFIC_COLLECTIBLE = "https://market.decentraland.org/contracts/{collectionId}/token
 20
 121    protected static readonly string[] categoriesThatMustHaveSelection = { Categories.BODY_SHAPE, Categories.UPPER_BODY,
 122    protected static readonly string[] categoriesToRandomize = { Categories.HAIR, Categories.EYES, Categories.EYEBROWS, 
 23
 24    [NonSerialized]
 25    public bool bypassUpdateAvatarPreview = false;
 26
 27    private UserProfile userProfile;
 28    private BaseDictionary<string, WearableItem> catalog;
 9829    bool renderingEnabled => CommonScriptableObjects.rendererState.Get();
 030    bool isPlayerRendererLoaded => DataStore.i.isPlayerRendererLoaded.Get();
 031    BaseVariable<bool> avatarEditorVisible => DataStore.i.HUDs.avatarEditorVisible;
 4632    private readonly Dictionary<string, List<WearableItem>> wearablesByCategory = new Dictionary<string, List<WearableIt
 4633    protected readonly AvatarEditorHUDModel model = new AvatarEditorHUDModel();
 34
 35    private ColorList skinColorList;
 36    private ColorList eyeColorList;
 37    private ColorList hairColorList;
 38    private bool prevMouseLockState = false;
 4639    private int ownedWearablesRemainingRequests = LOADING_OWNED_WEARABLES_RETRIES;
 40    private bool ownedWearablesAlreadyLoaded = false;
 4641    private List<Nft> ownedNftCollectionsL1 = new List<Nft>();
 4642    private List<Nft> ownedNftCollectionsL2 = new List<Nft>();
 43
 44    public AvatarEditorHUDView view;
 45
 46    public event Action OnOpen;
 47    public event Action OnClose;
 48
 9249    public AvatarEditorHUDController() { }
 50
 51    public void Initialize(UserProfile userProfile, BaseDictionary<string, WearableItem> catalog, bool bypassUpdateAvata
 52    {
 4453        this.userProfile = userProfile;
 4454        this.bypassUpdateAvatarPreview = bypassUpdateAvatarPreview;
 55
 4456        view = AvatarEditorHUDView.Create(this);
 57
 4458        avatarEditorVisible.OnChange += OnAvatarEditorVisibleChanged;
 4459        OnAvatarEditorVisibleChanged(avatarEditorVisible.Get(), false);
 4460        view.OnCloseActionTriggered += DiscardAndClose;
 61
 4462        skinColorList = Resources.Load<ColorList>("SkinTone");
 4463        hairColorList = Resources.Load<ColorList>("HairColor");
 4464        eyeColorList = Resources.Load<ColorList>("EyeColor");
 4465        view.SetColors(skinColorList.colors, hairColorList.colors, eyeColorList.colors);
 66
 4467        SetCatalog(catalog);
 68
 4469        LoadUserProfile(userProfile, true);
 4470        this.userProfile.OnUpdate += LoadUserProfile;
 4471    }
 72
 73    public void SetCatalog(BaseDictionary<string, WearableItem> catalog)
 74    {
 4475        if (this.catalog != null)
 76        {
 077            this.catalog.OnAdded -= AddWearable;
 078            this.catalog.OnRemoved -= RemoveWearable;
 79        }
 80
 4481        this.catalog = catalog;
 82
 4483        ProcessCatalog(this.catalog);
 4484        this.catalog.OnAdded += AddWearable;
 4485        this.catalog.OnRemoved += RemoveWearable;
 4486    }
 87
 88    private void LoadUserProfile(UserProfile userProfile)
 89    {
 4090        LoadUserProfile(userProfile, false);
 4091        QueryNftCollections(userProfile.userId);
 4092    }
 93
 94    private void LoadOwnedWereables(UserProfile userProfile)
 95    {
 3996        if (ownedWearablesAlreadyLoaded || ownedWearablesRemainingRequests <= 0 || string.IsNullOrEmpty(userProfile.user
 3897            return;
 98
 199        view.ShowCollectiblesLoadingSpinner(true);
 1100        view.ShowCollectiblesLoadingRetry(false);
 1101        CatalogController.RequestOwnedWearables(userProfile.userId)
 102            .Then((ownedWearables) =>
 103            {
 0104                ownedWearablesAlreadyLoaded = true;
 0105                this.userProfile.SetInventory(ownedWearables.Select(x => x.id).ToArray());
 0106                LoadUserProfile(userProfile, true);
 0107                view.ShowCollectiblesLoadingSpinner(false);
 0108            })
 109            .Catch((error) =>
 110            {
 0111                ownedWearablesRemainingRequests--;
 0112                if (ownedWearablesRemainingRequests > 0)
 113                {
 0114                    Debug.LogWarning("Retrying owned wereables loading...");
 0115                    LoadOwnedWereables(userProfile);
 0116                }
 117                else
 118                {
 0119                    NotificationsController.i.ShowNotification(new DCL.NotificationModel.Model
 120                    {
 121                        message = LOADING_OWNED_WEARABLES_ERROR_MESSAGE,
 122                        type = DCL.NotificationModel.Type.GENERIC,
 123                        timer = 10f,
 124                        destroyOnFinish = true
 125                    });
 126
 0127                    view.ShowCollectiblesLoadingSpinner(false);
 0128                    view.ShowCollectiblesLoadingRetry(true);
 0129                    Debug.LogError(error);
 130                }
 0131            });
 1132    }
 133
 134    private void QueryNftCollections(string userId)
 135    {
 40136        if (string.IsNullOrEmpty(userId))
 40137            return;
 138
 0139        DCL.Environment.i.platform.serviceProviders.theGraph.QueryNftCollections(userProfile.userId, NftCollectionsLayer
 0140            .Then((nfts) => ownedNftCollectionsL1 = nfts)
 0141            .Catch((error) => Debug.LogError(error));
 142
 0143        DCL.Environment.i.platform.serviceProviders.theGraph.QueryNftCollections(userProfile.userId, NftCollectionsLayer
 0144            .Then((nfts) => ownedNftCollectionsL2 = nfts)
 0145            .Catch((error) => Debug.LogError(error));
 0146    }
 147
 148    public void RetryLoadOwnedWearables()
 149    {
 0150        ownedWearablesRemainingRequests = LOADING_OWNED_WEARABLES_RETRIES;
 0151        LoadOwnedWereables(userProfile);
 0152    }
 153
 154    private void PlayerRendererLoaded(bool current, bool previous)
 155    {
 14156        if (!current)
 0157            return;
 158
 14159        if (!ownedWearablesAlreadyLoaded)
 160        {
 14161            List<string> equippedOwnedWearables = new List<string>();
 58162            for (int i = 0; i < userProfile.avatar.wearables.Count; i++)
 163            {
 15164                if (catalog.TryGetValue(userProfile.avatar.wearables[i], out WearableItem wearable) &&
 165                    !wearable.data.tags.Contains("base-wearable"))
 166                {
 0167                    equippedOwnedWearables.Add(userProfile.avatar.wearables[i]);
 168                }
 169            }
 170
 14171            userProfile.SetInventory(equippedOwnedWearables.ToArray());
 172        }
 173
 14174        LoadUserProfile(userProfile, true);
 14175        DataStore.i.isPlayerRendererLoaded.OnChange -= PlayerRendererLoaded;
 14176    }
 177
 178    public void LoadUserProfile(UserProfile userProfile, bool forceLoading)
 179    {
 98180        bool avatarEditorNotVisible = renderingEnabled && !view.isOpen;
 98181        bool isPlaying = !Application.isBatchMode;
 182
 98183        if (!forceLoading)
 184        {
 40185            if (isPlaying && avatarEditorNotVisible)
 0186                return;
 187        }
 188
 98189        if (userProfile == null)
 0190            return;
 191
 98192        if (userProfile.avatar == null || string.IsNullOrEmpty(userProfile.avatar.bodyShape))
 3193            return;
 194
 95195        CatalogController.wearableCatalog.TryGetValue(userProfile.avatar.bodyShape, out var bodyShape);
 196
 95197        if (bodyShape == null)
 198        {
 0199            return;
 200        }
 201
 95202        view.SetIsWeb3(userProfile.hasConnectedWeb3);
 203
 95204        ProcessCatalog(this.catalog);
 95205        EquipBodyShape(bodyShape);
 95206        EquipSkinColor(userProfile.avatar.skinColor);
 95207        EquipHairColor(userProfile.avatar.hairColor);
 95208        EquipEyesColor(userProfile.avatar.eyeColor);
 209
 95210        model.wearables.Clear();
 95211        view.UnselectAllWearables();
 212
 95213        int wearablesCount = userProfile.avatar.wearables.Count;
 214
 95215        if (isPlayerRendererLoaded)
 216        {
 158217            for (var i = 0; i < wearablesCount; i++)
 218            {
 46219                CatalogController.wearableCatalog.TryGetValue(userProfile.avatar.wearables[i], out var wearable);
 46220                if (wearable == null)
 221                {
 0222                    Debug.LogError($"Couldn't find wearable with ID {userProfile.avatar.wearables[i]}");
 0223                    continue;
 224                }
 225
 46226                EquipWearable(wearable);
 227            }
 228        }
 229
 95230        EnsureWearablesCategoriesNotEmpty();
 231
 95232        UpdateAvatarPreview();
 95233    }
 234
 235    private void EnsureWearablesCategoriesNotEmpty()
 236    {
 141237        var categoriesInUse = model.wearables.Select(x => x.data.category).ToArray();
 1520238        for (var i = 0; i < categoriesThatMustHaveSelection.Length; i++)
 239        {
 665240            var category = categoriesThatMustHaveSelection[i];
 665241            if (category != Categories.BODY_SHAPE && !(categoriesInUse.Contains(category)))
 242            {
 243                WearableItem wearable;
 534244                var defaultItemId = WearableLiterals.DefaultWearables.GetDefaultWearable(model.bodyShape.id, category);
 534245                if (defaultItemId != null)
 246                {
 534247                    CatalogController.wearableCatalog.TryGetValue(defaultItemId, out wearable);
 534248                }
 249                else
 250                {
 0251                    wearable = wearablesByCategory[category].FirstOrDefault(x => x.SupportsBodyShape(model.bodyShape.id)
 252                }
 253
 534254                if (wearable != null)
 255                {
 534256                    EquipWearable(wearable);
 257                }
 258            }
 259        }
 95260    }
 261
 262    public void WearableClicked(string wearableId)
 263    {
 20264        CatalogController.wearableCatalog.TryGetValue(wearableId, out var wearable);
 20265        if (wearable == null)
 3266            return;
 267
 17268        if (wearable.data.category == Categories.BODY_SHAPE)
 269        {
 3270            if (wearable.id == model.bodyShape.id)
 0271                return;
 3272            EquipBodyShape(wearable);
 3273        }
 274        else
 275        {
 14276            if (model.wearables.Contains(wearable))
 277            {
 2278                if (!categoriesThatMustHaveSelection.Contains(wearable.data.category))
 279                {
 0280                    UnequipWearable(wearable);
 0281                }
 282                else
 283                {
 2284                    return;
 285                }
 286            }
 287            else
 288            {
 91289                var sameCategoryEquipped = model.wearables.FirstOrDefault(x => x.data.category == wearable.data.category
 12290                if (sameCategoryEquipped != null)
 291                {
 2292                    UnequipWearable(sameCategoryEquipped);
 293                }
 294
 12295                EquipWearable(wearable);
 296            }
 297        }
 298
 15299        UpdateAvatarPreview();
 15300    }
 301
 302    public void HairColorClicked(Color color)
 303    {
 2304        EquipHairColor(color);
 2305        view.SelectHairColor(model.hairColor);
 2306        UpdateAvatarPreview();
 2307    }
 308
 309    public void SkinColorClicked(Color color)
 310    {
 2311        EquipSkinColor(color);
 2312        view.SelectSkinColor(model.skinColor);
 2313        UpdateAvatarPreview();
 2314    }
 315
 316    public void EyesColorClicked(Color color)
 317    {
 2318        EquipEyesColor(color);
 2319        view.SelectEyeColor(model.eyesColor);
 2320        UpdateAvatarPreview();
 2321    }
 322
 323    protected virtual void UpdateAvatarPreview()
 324    {
 117325        if (!bypassUpdateAvatarPreview)
 117326            view.UpdateAvatarPreview(model.ToAvatarModel());
 117327    }
 328
 329    private void EquipHairColor(Color color)
 330    {
 98331        var colorToSet = color;
 994332        if (!hairColorList.colors.Any(x => x.AproxComparison(colorToSet)))
 333        {
 88334            colorToSet = hairColorList.colors[hairColorList.defaultColor];
 335        }
 336
 98337        model.hairColor = colorToSet;
 98338        view.SelectHairColor(model.hairColor);
 98339    }
 340
 341    private void EquipEyesColor(Color color)
 342    {
 98343        var colorToSet = color;
 999344        if (!eyeColorList.colors.Any(x => x.AproxComparison(color)))
 345        {
 88346            colorToSet = eyeColorList.colors[eyeColorList.defaultColor];
 347        }
 348
 98349        model.eyesColor = colorToSet;
 98350        view.SelectEyeColor(model.eyesColor);
 98351    }
 352
 353    private void EquipSkinColor(Color color)
 354    {
 97355        var colorToSet = color;
 989356        if (!skinColorList.colors.Any(x => x.AproxComparison(colorToSet)))
 357        {
 88358            colorToSet = skinColorList.colors[skinColorList.defaultColor];
 359        }
 360
 97361        model.skinColor = colorToSet;
 97362        view.SelectSkinColor(model.skinColor);
 97363    }
 364
 365    private void EquipBodyShape(WearableItem bodyShape)
 366    {
 98367        if (bodyShape.data.category != Categories.BODY_SHAPE)
 368        {
 0369            Debug.LogError($"Item ({bodyShape.id} is not a body shape");
 0370            return;
 371        }
 372
 98373        if (model.bodyShape == bodyShape)
 50374            return;
 375
 48376        model.bodyShape = bodyShape;
 48377        view.UpdateSelectedBody(bodyShape);
 378
 48379        int wearablesCount = model.wearables.Count;
 136380        for (var i = wearablesCount - 1; i >= 0; i--)
 381        {
 20382            UnequipWearable(model.wearables[i]);
 383        }
 384
 48385        var defaultWearables = WearableLiterals.DefaultWearables.GetDefaultWearables(bodyShape.id);
 778386        for (var i = 0; i < defaultWearables.Length; i++)
 387        {
 341388            if (catalog.TryGetValue(defaultWearables[i], out var wearable))
 341389                EquipWearable(wearable);
 390        }
 48391    }
 392
 393    private void EquipWearable(WearableItem wearable)
 394    {
 940395        if (!wearablesByCategory.ContainsKey(wearable.data.category))
 0396            return;
 397
 940398        if (wearablesByCategory[wearable.data.category].Contains(wearable) && wearable.SupportsBodyShape(model.bodyShape
 399        {
 940400            var toReplace = GetWearablesReplacedBy(wearable);
 940401            toReplace.ForEach(UnequipWearable);
 940402            model.wearables.Add(wearable);
 940403            view.EquipWearable(wearable);
 404        }
 940405    }
 406
 407    private void UnequipWearable(WearableItem wearable)
 408    {
 24409        if (model.wearables.Contains(wearable))
 410        {
 24411            model.wearables.Remove(wearable);
 24412            view.UnequipWearable(wearable);
 413        }
 24414    }
 415
 416    public void UnequipAllWearables()
 417    {
 926418        foreach (var wearable in model.wearables)
 419        {
 395420            view.UnequipWearable(wearable);
 421        }
 422
 68423        model.wearables.Clear();
 68424    }
 425
 426    private void ProcessCatalog(BaseDictionary<string, WearableItem> catalog)
 427    {
 139428        wearablesByCategory.Clear();
 139429        view.RemoveAllWearables();
 139430        using (var iterator = catalog.Get().GetEnumerator())
 431        {
 5107432            while (iterator.MoveNext())
 433            {
 4968434                AddWearable(iterator.Current.Key, iterator.Current.Value);
 435            }
 139436        }
 139437    }
 438
 439    private void AddWearable(string id, WearableItem wearable)
 440    {
 4974441        if (!wearable.data.tags.Contains("base-wearable") && userProfile.GetItemAmount(id) == 0)
 442        {
 1094443            return;
 444        }
 445
 3880446        if (!wearablesByCategory.ContainsKey(wearable.data.category))
 447        {
 1518448            wearablesByCategory.Add(wearable.data.category, new List<WearableItem>());
 449        }
 450
 3880451        wearablesByCategory[wearable.data.category].Add(wearable);
 3880452        view.AddWearable(wearable, userProfile.GetItemAmount(id));
 3880453    }
 454
 455    private void RemoveWearable(string id, WearableItem wearable)
 456    {
 0457        if (wearablesByCategory.ContainsKey(wearable.data.category))
 458        {
 0459            if (wearablesByCategory[wearable.data.category].Remove(wearable))
 460            {
 0461                if (wearablesByCategory[wearable.data.category].Count == 0)
 462                {
 0463                    wearablesByCategory.Remove(wearable.data.category);
 464                }
 465            }
 466        }
 467
 0468        view.RemoveWearable(wearable);
 0469    }
 470
 471    public void RandomizeWearables()
 472    {
 1473        EquipHairColor(hairColorList.colors[UnityEngine.Random.Range(0, hairColorList.colors.Count)]);
 1474        EquipEyesColor(eyeColorList.colors[UnityEngine.Random.Range(0, eyeColorList.colors.Count)]);
 475
 1476        model.wearables.Clear();
 1477        view.UnselectAllWearables();
 1478        using (var iterator = wearablesByCategory.GetEnumerator())
 479        {
 12480            while (iterator.MoveNext())
 481            {
 11482                string category = iterator.Current.Key;
 11483                if (!categoriesToRandomize.Contains(category))
 484                {
 485                    continue;
 486                }
 487
 29488                var supportedWearables = iterator.Current.Value.Where(x => x.SupportsBodyShape(model.bodyShape.id)).ToAr
 7489                if (supportedWearables.Length == 0)
 490                {
 0491                    Debug.LogError($"Couldn't get any wearable for category {category} and bodyshape {model.bodyShape.id
 492                }
 493
 7494                var wearable = supportedWearables[UnityEngine.Random.Range(0, supportedWearables.Length - 1)];
 7495                EquipWearable(wearable);
 496            }
 1497        }
 498
 1499        UpdateAvatarPreview();
 1500    }
 501
 502    public List<WearableItem> GetWearablesReplacedBy(WearableItem wearableItem)
 503    {
 940504        List<WearableItem> wearablesToReplace = new List<WearableItem>();
 505
 940506        HashSet<string> categoriesToReplace = new HashSet<string>(wearableItem.GetReplacesList(model.bodyShape.id) ?? ne
 507
 940508        int wearableCount = model.wearables.Count;
 7140509        for (int i = 0; i < wearableCount; i++)
 510        {
 2630511            var wearable = model.wearables[i];
 2630512            if (wearable == null)
 513                continue;
 514
 2630515            if (categoriesToReplace.Contains(wearable.data.category))
 516            {
 2517                wearablesToReplace.Add(wearable);
 2518            }
 519            else
 520            {
 521                //For retrocompatibility's sake we check current wearables against new one (compatibility matrix is symm
 2628522                HashSet<string> replacesList = new HashSet<string>(wearable.GetReplacesList(model.bodyShape.id) ?? new s
 2628523                if (replacesList.Contains(wearableItem.data.category))
 524                {
 0525                    wearablesToReplace.Add(wearable);
 526                }
 527            }
 528        }
 529
 940530        return wearablesToReplace;
 531    }
 532
 46533    private float prevRenderScale = 1.0f;
 534    private Camera mainCamera;
 535
 80536    public void SetVisibility(bool visible) { avatarEditorVisible.Set(visible); }
 537
 168538    private void OnAvatarEditorVisibleChanged(bool current, bool previous) { SetVisibility_Internal(current); }
 539
 540    public void SetVisibility_Internal(bool visible)
 541    {
 84542        var currentRenderProfile = DCL.RenderProfileManifest.i.currentProfile;
 543
 84544        if (!visible && view.isOpen)
 545        {
 1546            DataStore.i.virtualAudioMixer.sceneSFXVolume.Set(1f);
 1547            DCL.Environment.i.messaging.manager.paused = false;
 1548            currentRenderProfile.avatarProfile.currentProfile = currentRenderProfile.avatarProfile.inWorld;
 1549            currentRenderProfile.avatarProfile.Apply();
 1550            if (prevMouseLockState)
 551            {
 0552                Utils.LockCursor();
 553            }
 554
 555            // NOTE(Brian): SSAO doesn't work correctly with the offseted avatar preview if the renderScale != 1.0
 1556            var asset = GraphicsSettings.renderPipelineAsset as UniversalRenderPipelineAsset;
 1557            asset.renderScale = prevRenderScale;
 558
 1559            CommonScriptableObjects.isFullscreenHUDOpen.Set(false);
 1560            DataStore.i.isPlayerRendererLoaded.OnChange -= PlayerRendererLoaded;
 561
 1562            OnClose?.Invoke();
 0563        }
 83564        else if (visible && !view.isOpen)
 565        {
 39566            DataStore.i.virtualAudioMixer.sceneSFXVolume.Set(0f);
 39567            LoadOwnedWereables(userProfile);
 39568            DCL.Environment.i.messaging.manager.paused = DataStore.i.isSignUpFlow.Get();
 39569            currentRenderProfile.avatarProfile.currentProfile = currentRenderProfile.avatarProfile.avatarEditor;
 39570            currentRenderProfile.avatarProfile.Apply();
 571
 39572            prevMouseLockState = Utils.isCursorLocked;
 39573            Utils.UnlockCursor();
 574
 575            // NOTE(Brian): SSAO doesn't work correctly with the offseted avatar preview if the renderScale != 1.0
 39576            var asset = GraphicsSettings.renderPipelineAsset as UniversalRenderPipelineAsset;
 39577            prevRenderScale = asset.renderScale;
 39578            asset.renderScale = 1.0f;
 579
 39580            CommonScriptableObjects.isFullscreenHUDOpen.Set(true);
 39581            DataStore.i.isPlayerRendererLoaded.OnChange += PlayerRendererLoaded;
 582
 39583            OnOpen?.Invoke();
 584        }
 585
 84586        currentRenderProfile.avatarProfile.Apply();
 84587        view.SetVisibility(visible);
 84588    }
 589
 590    public void Dispose()
 591    {
 39592        avatarEditorVisible.OnChange -= OnAvatarEditorVisibleChanged;
 39593        view.OnCloseActionTriggered -= DiscardAndClose;
 39594        DataStore.i.isPlayerRendererLoaded.OnChange -= PlayerRendererLoaded;
 595
 39596        CleanUp();
 39597    }
 598
 599    public void CleanUp()
 600    {
 44601        UnequipAllWearables();
 602
 44603        if (view != null)
 44604            view.CleanUp();
 605
 44606        this.userProfile.OnUpdate -= LoadUserProfile;
 44607        this.catalog.OnAdded -= AddWearable;
 44608        this.catalog.OnRemoved -= RemoveWearable;
 44609        DataStore.i.isPlayerRendererLoaded.OnChange -= PlayerRendererLoaded;
 44610    }
 611
 0612    public void SetConfiguration(HUDConfiguration configuration) { SetVisibility(configuration.active); }
 613
 614    public void SaveAvatar(Texture2D faceSnapshot, Texture2D face128Snapshot, Texture2D face256Snapshot, Texture2D bodyS
 615    {
 1616        var avatarModel = model.ToAvatarModel();
 617
 1618        WebInterface.SendSaveAvatar(avatarModel, faceSnapshot, face128Snapshot, face256Snapshot, bodySnapshot, DataStore
 1619        userProfile.OverrideAvatar(avatarModel, face256Snapshot);
 1620        if (DataStore.i.isSignUpFlow.Get())
 0621            DataStore.i.HUDs.signupVisible.Set(true);
 622
 1623        SetVisibility(false);
 1624    }
 625
 626    public void DiscardAndClose()
 627    {
 0628        if (!view.isOpen)
 0629            return;
 630
 0631        if (!DataStore.i.isSignUpFlow.Get())
 0632            LoadUserProfile(userProfile);
 633        else
 0634            WebInterface.SendCloseUserAvatar(true);
 635
 0636        SetVisibility(false);
 0637    }
 638
 639    public void GoToMarketplace()
 640    {
 0641        if (userProfile.hasConnectedWeb3)
 0642            WebInterface.OpenURL(URL_MARKET_PLACE);
 643        else
 0644            WebInterface.OpenURL(URL_GET_A_WALLET);
 0645    }
 646
 647    public void SellCollectible(string collectibleId)
 648    {
 0649        var ownedCollectible = ownedNftCollectionsL1.FirstOrDefault(nft => nft.urn == collectibleId);
 0650        if (ownedCollectible == null)
 0651            ownedCollectible = ownedNftCollectionsL2.FirstOrDefault(nft => nft.urn == collectibleId);
 652
 0653        if (ownedCollectible != null)
 0654            WebInterface.OpenURL(URL_SELL_SPECIFIC_COLLECTIBLE.Replace("{collectionId}", ownedCollectible.collectionId).
 655        else
 0656            WebInterface.OpenURL(URL_SELL_COLLECTIBLE_GENERIC);
 0657    }
 658
 0659    public void ToggleVisibility() { SetVisibility(!view.isOpen); }
 660}