< Summary

Class:AvatarEditorHUDView
Assembly:AvatarEditorHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDView.cs
Covered lines:162
Uncovered lines:39
Coverable lines:201
Total lines:466
Line coverage:80.5% (162 of 201)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AvatarEditorHUDView()0%110100%
Initialize()0%110100%
AvatarEditorHUDView()0%110100%
Awake()0%220100%
Initialize(...)0%330100%
SetIsWeb3(...)0%110100%
InitializeNavigationEvents(...)0%330100%
InitializeNavigationInfo(...)0%550100%
InitializeNavigationInfo(...)0%110100%
InitializeWearableChangeEvents()0%220100%
Create(...)0%110100%
UpdateSelectedBody(...)0%330100%
EquipWearable(...)0%110100%
UnequipWearable(...)0%110100%
SetWearableLoadingSpinner(...)0%220100%
ClearWearablesLoadingSpinner()0%220100%
SelectHairColor(...)0%110100%
SelectSkinColor(...)0%110100%
SelectEyeColor(...)0%110100%
SetColors(...)0%110100%
UnselectAllWearables()0%330100%
UpdateAvatarPreview(...)0%4.074083.33%
AddWearable(...)0%4.594066.67%
RemoveWearable(...)0%20400%
RemoveAllWearables()0%220100%
OnRandomizeButton()0%12300%
OnDoneButton()0%2100%
OnSnapshotsReady(...)0%2100%
OnSnapshotsFailed()0%2100%
SetVisibility(...)0%770100%
CleanUp()0%10100100%
ShowCollectiblesLoadingSpinner(...)0%110100%
ShowCollectiblesLoadingRetry(...)0%110100%
SetAsFullScreenMenuMode(...)0%4.312016.67%
ShowSkinPopulatedList(...)0%2100%

File(s)

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

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Runtime.CompilerServices;
 4using UnityEngine;
 5using UnityEngine.UI;
 6
 7[assembly: InternalsVisibleTo("AvatarEditorHUDTests")]
 8
 9public class AvatarEditorHUDView : MonoBehaviour
 10{
 111    private static readonly int RANDOMIZE_ANIMATOR_LOADING_BOOL = Animator.StringToHash("Loading");
 12    private const string VIEW_PATH = "AvatarEditorHUD";
 13    private const string VIEW_OBJECT_NAME = "_AvatarEditorHUD";
 14
 015    public bool isOpen { get; private set; }
 16
 17    internal bool arePanelsInitialized = false;
 18
 19    [Serializable]
 20    public class AvatarEditorNavigationInfo
 21    {
 22        public Toggle toggle;
 23        public Canvas canvas;
 24        public bool enabledByDefault;
 25        public CharacterPreviewController.CameraFocus focus = CharacterPreviewController.CameraFocus.DefaultEditing;
 26
 27        //To remove when we refactor this to avoid ToggleGroup issues when quitting application
 180028        public void Initialize() { Application.quitting += () => toggle.onValueChanged.RemoveAllListeners(); }
 29    }
 30
 31    [Serializable]
 32    public class AvatarEditorWearableFilter
 33    {
 34        public string categoryFilter;
 35        public ItemSelector selector;
 36    }
 37
 38    [SerializeField]
 39    internal Canvas avatarEditorCanvas;
 40
 41    [SerializeField]
 42    internal CanvasGroup avatarEditorCanvasGroup;
 43
 44    [SerializeField]
 45    internal AvatarEditorNavigationInfo[] navigationInfos;
 46
 47    [SerializeField]
 48    internal AvatarEditorWearableFilter[] wearableGridPairs;
 49
 50    [SerializeField]
 51    internal AvatarEditorNavigationInfo collectiblesNavigationInfo;
 52
 53    [SerializeField]
 54    internal ItemSelector collectiblesItemSelector;
 55
 56    [SerializeField]
 57    internal ColorSelector skinColorSelector;
 58
 59    [SerializeField]
 60    internal ColorSelector eyeColorSelector;
 61
 62    [SerializeField]
 63    internal ColorSelector hairColorSelector;
 64
 65    [SerializeField]
 66    internal GameObject characterPreviewPrefab;
 67
 68    [SerializeField]
 69    internal PreviewCameraRotation characterPreviewRotation;
 70
 71    [SerializeField]
 72    internal Button randomizeButton;
 73
 74    [SerializeField]
 75    internal Animator randomizeAnimator;
 76
 77    [SerializeField]
 78    internal Button doneButton;
 79
 80    [SerializeField] internal Button[] goToMarketplaceButtons;
 81
 82    [SerializeField] internal GameObject loadingSpinnerGameObject;
 83
 84    [Header("Collectibles")]
 85    [SerializeField]
 86    internal GameObject web3Container;
 87
 88    [SerializeField]
 89    internal GameObject noWeb3Container;
 90
 91    [Header("Skins")]
 92
 93    [SerializeField] internal GameObject skinsFeatureContainer;
 94
 95    [SerializeField] internal GameObject skinsWeb3Container;
 96
 97    [SerializeField] internal GameObject skinsMissingWeb3Container;
 98
 99    [SerializeField] internal GameObject skinsConnectWalletButtonContainer;
 100
 101    [SerializeField] private GameObject skinsPopulatedListContainer;
 102    [SerializeField] private GameObject skinsEmptyListContainer;
 103
 104    internal static CharacterPreviewController characterPreviewController;
 105    private AvatarEditorHUDController controller;
 47106    internal readonly Dictionary<string, ItemSelector> selectorsByCategory = new Dictionary<string, ItemSelector>();
 47107    private readonly HashSet<WearableItem> wearablesWithLoadingSpinner = new HashSet<WearableItem>();
 108
 109    public event Action<AvatarModel> OnAvatarAppear;
 110    public event Action<bool> OnSetVisibility;
 111    public event Action OnRandomize;
 112
 113    private void Awake()
 114    {
 46115        loadingSpinnerGameObject.SetActive(false);
 46116        doneButton.interactable = false; //the default state of the button should be disable until a profile has been lo
 46117        if (characterPreviewController == null)
 118        {
 46119            characterPreviewController = Instantiate(characterPreviewPrefab).GetComponent<CharacterPreviewController>();
 46120            characterPreviewController.name = "_CharacterPreviewController";
 121        }
 122
 46123        isOpen = false;
 46124        arePanelsInitialized = false;
 46125    }
 126
 127    private void Initialize(AvatarEditorHUDController controller)
 128    {
 46129        this.controller = controller;
 46130        gameObject.name = VIEW_OBJECT_NAME;
 131
 46132        randomizeButton.onClick.AddListener(OnRandomizeButton);
 46133        doneButton.onClick.AddListener(OnDoneButton);
 46134        InitializeWearableChangeEvents();
 135
 552136        foreach (var button in goToMarketplaceButtons)
 230137            button.onClick.RemoveAllListeners();
 552138        foreach (var button in goToMarketplaceButtons)
 230139            button.onClick.AddListener(controller.GoToMarketplaceOrConnectWallet);
 140
 46141        characterPreviewController.camera.enabled = false;
 46142    }
 143
 144    public void SetIsWeb3(bool isWeb3User)
 145    {
 99146        web3Container.SetActive(isWeb3User);
 99147        noWeb3Container.SetActive(!isWeb3User);
 99148        skinsWeb3Container.SetActive(isWeb3User);
 99149        skinsMissingWeb3Container.SetActive(!isWeb3User);
 99150    }
 151
 152    internal void InitializeNavigationEvents(bool isGuest)
 153    {
 99154        if (arePanelsInitialized)
 54155            return;
 156
 1800157        for (int i = 0; i < navigationInfos.Length; i++)
 158        {
 855159            InitializeNavigationInfo(navigationInfos[i]);
 160        }
 45161        InitializeNavigationInfo(collectiblesNavigationInfo, !isGuest);
 162
 45163        characterPreviewRotation.OnHorizontalRotation += characterPreviewController.Rotate;
 45164        arePanelsInitialized = true;
 45165    }
 166
 167    private void InitializeNavigationInfo(AvatarEditorNavigationInfo current, bool isActive)
 168    {
 900169        current.Initialize();
 170
 900171        current.toggle.isOn = isActive ? current.enabledByDefault : false;
 900172        current.canvas.gameObject.SetActive(isActive ? current.enabledByDefault : false);
 173
 900174        current.toggle.onValueChanged.AddListener((on) =>
 175        {
 45176            current.canvas.gameObject.SetActive(@on);
 45177            characterPreviewController.SetFocus(current.focus);
 45178        });
 900179    }
 180
 181    private void InitializeNavigationInfo(AvatarEditorNavigationInfo current)
 182    {
 855183        InitializeNavigationInfo(current, true);
 855184    }
 185
 186    private void InitializeWearableChangeEvents()
 187    {
 46188        int nPairs = wearableGridPairs.Length;
 1656189        for (int i = 0; i < nPairs; i++)
 190        {
 782191            wearableGridPairs[i].selector.OnItemClicked += controller.WearableClicked;
 782192            wearableGridPairs[i].selector.OnSellClicked += controller.SellCollectible;
 782193            selectorsByCategory.Add(wearableGridPairs[i].categoryFilter, wearableGridPairs[i].selector);
 194        }
 195
 46196        collectiblesItemSelector.OnItemClicked += controller.WearableClicked;
 46197        collectiblesItemSelector.OnSellClicked += controller.SellCollectible;
 46198        collectiblesItemSelector.OnRetryClicked += controller.RetryLoadOwnedWearables;
 199
 46200        skinColorSelector.OnColorChanged += controller.SkinColorClicked;
 46201        eyeColorSelector.OnColorChanged += controller.EyesColorClicked;
 46202        hairColorSelector.OnColorChanged += controller.HairColorClicked;
 46203    }
 204
 205    internal static AvatarEditorHUDView Create(AvatarEditorHUDController controller)
 206    {
 46207        var view = Instantiate(Resources.Load<GameObject>(VIEW_PATH)).GetComponent<AvatarEditorHUDView>();
 46208        view.Initialize(controller);
 46209        return view;
 210    }
 211
 212    public void UpdateSelectedBody(WearableItem bodyShape)
 213    {
 1800214        for (int i = 0; i < wearableGridPairs.Length; i++)
 215        {
 850216            if (wearableGridPairs[i].categoryFilter == WearableLiterals.Categories.BODY_SHAPE)
 217            {
 50218                wearableGridPairs[i].selector.UnselectAll();
 50219                wearableGridPairs[i].selector.Select(bodyShape.id);
 50220            }
 221            else
 222            {
 800223                wearableGridPairs[i].selector.SetBodyShape(bodyShape.id);
 224            }
 225        }
 226
 50227        collectiblesItemSelector.SetBodyShape(bodyShape.id);
 50228    }
 229
 230    public void EquipWearable(WearableItem wearable)
 231    {
 978232        selectorsByCategory[wearable.data.category].Select(wearable.id);
 978233        SetWearableLoadingSpinner(wearable, true);
 978234        collectiblesItemSelector.Select(wearable.id);
 978235    }
 236
 237    public void UnequipWearable(WearableItem wearable)
 238    {
 443239        selectorsByCategory[wearable.data.category].Unselect(wearable.id);
 443240        SetWearableLoadingSpinner(wearable, false);
 443241        collectiblesItemSelector.Unselect(wearable.id);
 443242    }
 243
 244    internal void SetWearableLoadingSpinner(WearableItem wearable, bool isActive)
 245    {
 1421246        selectorsByCategory[wearable.data.category].SetWearableLoadingSpinner(wearable.id, isActive);
 1421247        collectiblesItemSelector.SetWearableLoadingSpinner(wearable.id, isActive);
 1421248        if (isActive)
 978249            wearablesWithLoadingSpinner.Add(wearable);
 250        else
 443251            wearablesWithLoadingSpinner.Remove(wearable);
 443252    }
 253
 254    internal void ClearWearablesLoadingSpinner()
 255    {
 1126256        foreach (WearableItem wearable in wearablesWithLoadingSpinner)
 257        {
 442258            selectorsByCategory[wearable.data.category].SetWearableLoadingSpinner(wearable.id, false);
 442259            collectiblesItemSelector.SetWearableLoadingSpinner(wearable.id, false);
 260        }
 261
 121262        wearablesWithLoadingSpinner.Clear();
 121263    }
 264
 208265    public void SelectHairColor(Color hairColor) { hairColorSelector.Select(hairColor); }
 266
 206267    public void SelectSkinColor(Color skinColor) { skinColorSelector.Select(skinColor); }
 268
 208269    public void SelectEyeColor(Color eyesColor) { eyeColorSelector.Select(eyesColor); }
 270
 271    public void SetColors(List<Color> skinColors, List<Color> hairColors, List<Color> eyeColors)
 272    {
 46273        skinColorSelector.Populate(skinColors);
 46274        eyeColorSelector.Populate(eyeColors);
 46275        hairColorSelector.Populate(hairColors);
 46276    }
 277
 278    public void UnselectAllWearables()
 279    {
 3600280        for (int i = 0; i < wearableGridPairs.Length; i++)
 281        {
 1700282            if (wearableGridPairs[i].categoryFilter != WearableLiterals.Categories.BODY_SHAPE)
 283            {
 1600284                wearableGridPairs[i].selector.UnselectAll();
 285            }
 286        }
 287
 100288        collectiblesItemSelector.UnselectAll();
 100289    }
 290
 291    public void UpdateAvatarPreview(AvatarModel avatarModel)
 292    {
 121293        if (avatarModel?.wearables == null)
 0294            return;
 295
 121296        doneButton.interactable = false;
 121297        loadingSpinnerGameObject.SetActive(true);
 121298        characterPreviewController.UpdateModel(avatarModel,
 299            () =>
 300            {
 121301                if (doneButton != null)
 101302                    doneButton.interactable = true;
 303
 121304                loadingSpinnerGameObject?.SetActive(false);
 121305                OnAvatarAppear?.Invoke(avatarModel);
 121306                ClearWearablesLoadingSpinner();
 121307                randomizeAnimator?.SetBool(RANDOMIZE_ANIMATOR_LOADING_BOOL, false);
 101308            });
 121309    }
 310
 311    public void AddWearable(WearableItem wearableItem, int amount,
 312        Func<WearableItem, bool> hideOtherWearablesToastStrategy,
 313        Func<WearableItem, bool> replaceOtherWearablesToastStrategy)
 314    {
 4050315        if (wearableItem == null)
 0316            return;
 317
 4050318        if (!selectorsByCategory.ContainsKey(wearableItem.data.category))
 319        {
 0320            Debug.LogError($"Category couldn't find selector for category: {wearableItem.data.category} ");
 0321            return;
 322        }
 323
 4050324        selectorsByCategory[wearableItem.data.category].AddItemToggle(wearableItem, amount,
 325            hideOtherWearablesToastStrategy, replaceOtherWearablesToastStrategy);
 4050326        if (wearableItem.IsCollectible())
 327        {
 18328            collectiblesItemSelector.AddItemToggle(wearableItem, amount,
 329                hideOtherWearablesToastStrategy, replaceOtherWearablesToastStrategy);
 330        }
 4050331    }
 332
 333    public void RemoveWearable(WearableItem wearableItem)
 334    {
 0335        if (wearableItem == null)
 0336            return;
 337
 0338        if (!selectorsByCategory.ContainsKey(wearableItem.data.category))
 339        {
 0340            Debug.LogError($"Category couldn't find selector for category: {wearableItem.data.category} ");
 0341            return;
 342        }
 343
 0344        selectorsByCategory[wearableItem.data.category].RemoveItemToggle(wearableItem.id);
 0345        if (wearableItem.IsCollectible())
 0346            collectiblesItemSelector.RemoveItemToggle(wearableItem.id);
 0347    }
 348
 349    public void RemoveAllWearables()
 350    {
 145351        using (var enumerator = selectorsByCategory.GetEnumerator())
 352        {
 2610353            while (enumerator.MoveNext())
 354            {
 2465355                enumerator.Current.Value.RemoveAllItemToggle();
 356            }
 145357        }
 358
 145359        collectiblesItemSelector.RemoveAllItemToggle();
 145360    }
 361
 362    private void OnRandomizeButton()
 363    {
 0364        OnRandomize?.Invoke();
 0365        controller.RandomizeWearables();
 0366        randomizeAnimator?.SetBool(RANDOMIZE_ANIMATOR_LOADING_BOOL, true);
 0367    }
 368
 369    private void OnDoneButton()
 370    {
 0371        doneButton.interactable = false;
 0372        characterPreviewController.TakeSnapshots(OnSnapshotsReady, OnSnapshotsFailed);
 0373    }
 374
 375    private void OnSnapshotsReady(Texture2D face256, Texture2D body)
 376    {
 0377        doneButton.interactable = true;
 0378        controller.SaveAvatar(face256, body);
 0379    }
 380
 0381    private void OnSnapshotsFailed() { doneButton.interactable = true; }
 382
 383    public void SetVisibility(bool visible)
 384    {
 88385        characterPreviewController.camera.enabled = visible;
 88386        avatarEditorCanvas.enabled = visible;
 88387        avatarEditorCanvasGroup.blocksRaycasts = visible;
 388
 88389        if (visible && !isOpen)
 41390            OnSetVisibility?.Invoke(visible);
 47391        else if (!visible && isOpen)
 1392            OnSetVisibility?.Invoke(visible);
 393
 88394        isOpen = visible;
 88395    }
 396
 397    public void CleanUp()
 398    {
 46399        loadingSpinnerGameObject = null;
 46400        randomizeAnimator = null;
 46401        if (wearableGridPairs != null)
 402        {
 46403            int nPairs = wearableGridPairs.Length;
 1656404            for (int i = 0; i < nPairs; i++)
 405            {
 782406                var itemSelector = wearableGridPairs[i].selector;
 782407                if (itemSelector != null)
 408                {
 782409                    itemSelector.OnItemClicked -= controller.WearableClicked;
 782410                    itemSelector.OnSellClicked -= controller.SellCollectible;
 411                }
 412            }
 413        }
 414
 46415        if (collectiblesItemSelector != null)
 416        {
 46417            collectiblesItemSelector.OnItemClicked -= controller.WearableClicked;
 46418            collectiblesItemSelector.OnSellClicked -= controller.SellCollectible;
 46419            collectiblesItemSelector.OnRetryClicked -= controller.RetryLoadOwnedWearables;
 420        }
 421
 46422        if (skinColorSelector != null)
 46423            skinColorSelector.OnColorChanged -= controller.SkinColorClicked;
 46424        if (eyeColorSelector != null)
 46425            eyeColorSelector.OnColorChanged -= controller.EyesColorClicked;
 46426        if (hairColorSelector != null)
 46427            hairColorSelector.OnColorChanged -= controller.HairColorClicked;
 428
 46429        if (this != null)
 46430            Destroy(gameObject);
 431
 46432        if (characterPreviewController != null)
 433        {
 46434            Destroy(characterPreviewController.gameObject);
 46435            characterPreviewController = null;
 436        }
 46437    }
 438
 2439    public void ShowCollectiblesLoadingSpinner(bool isActive) { collectiblesItemSelector.ShowLoading(isActive); }
 440
 2441    public void ShowCollectiblesLoadingRetry(bool isActive) { collectiblesItemSelector.ShowRetryLoading(isActive); }
 442
 443    public void SetAsFullScreenMenuMode(Transform parentTransform)
 444    {
 46445        if (parentTransform == null)
 46446            return;
 447
 0448        transform.SetParent(parentTransform);
 0449        transform.localScale = Vector3.one;
 450
 0451        RectTransform rectTransform = transform as RectTransform;
 0452        rectTransform.anchorMin = Vector2.zero;
 0453        rectTransform.anchorMax = Vector2.one;
 0454        rectTransform.pivot = new Vector2(0.5f, 0.5f);
 0455        rectTransform.localPosition = Vector2.zero;
 0456        rectTransform.offsetMax = new Vector2(0f, 50f);
 0457        rectTransform.offsetMin = Vector2.zero;
 0458    }
 459
 460    public void ShowSkinPopulatedList(bool show)
 461    {
 0462        skinsPopulatedListContainer.SetActive(show);
 0463        skinsEmptyListContainer.SetActive(!show);
 0464        skinsConnectWalletButtonContainer.SetActive(show);
 0465    }
 466}