< Summary

Class:DCL.EmotesCustomization.EmotesCustomizationComponentController
Assembly:AvatarEditorHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs
Covered lines:0
Uncovered lines:188
Coverable lines:188
Total lines:420
Line coverage:0% (0 of 188)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:28
Method coverage:0% (0 of 28)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
EmotesCustomizationComponentController()0%2100%
EmotesCustomizationComponentController(...)0%2100%
Initialize(...)0%2100%
SetEmotes(...)0%20400%
SetEquippedBodyShape(...)0%12300%
RestoreEmoteSlots()0%2100%
Dispose()0%2100%
OnEquippedEmotesSet(...)0%2100%
ConfigureView(...)0%6200%
IsStarMenuOpenChanged(...)0%2100%
OnAvatarEditorVisibleChanged(...)0%2100%
AddEmote(...)0%42600%
RemoveEmote(...)0%2100%
OnAnimationAdded(...)0%2100%
RefreshEmoteLoadingState(...)0%12300%
ParseWearableItemIntoEmoteCardModel(...)0%12300%
UpdateEmoteSlots()0%56700%
StoreEquippedEmotes()0%20400%
OnEmoteEquipped(...)0%12300%
OnEmoteUnequipped(...)0%6200%
OnSellEmoteClicked(...)0%6200%
OnSlotSelected(...)0%12300%
ConfigureShortcuts()0%2100%
OnEquipInputActionTriggered(...)0%30500%
OnShowInfoInputActionTriggered(...)0%42600%
OnNumericShortcutInputActionTriggered(...)0%2101400%
CreateView(...)0%2100%

File(s)

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

#LineLine coverage
 1using AvatarSystem;
 2using Cysharp.Threading.Tasks;
 3using System;
 4using System.Collections.Generic;
 5using System.Linq;
 6using DCL.Emotes;
 7using DCL.Helpers;
 8using DCL.Tasks;
 9using System.Threading;
 10using UnityEngine;
 11
 12namespace DCL.EmotesCustomization
 13{
 14    public class EmotesCustomizationComponentController : IEmotesCustomizationComponentController
 15    {
 16        public event Action<string> onEmotePreviewed;
 17        public event Action<string> onEmoteEquipped;
 18        public event Action<string> onEmoteUnequipped;
 19        public event Action<string> onEmoteSell;
 20
 21        internal const int NUMBER_OF_SLOTS = 10;
 22        internal string bodyShapeId;
 23
 24        internal DataStore_EmotesCustomization emotesCustomizationDataStore;
 025        internal BaseDictionary<string, EmoteCardComponentView> emotesInLoadingState = new ();
 26        internal InputAction_Hold equipInputAction;
 27        internal DataStore_ExploreV2 exploreV2DataStore;
 28        internal DataStore_HUDs hudsDataStore;
 029        internal Dictionary<string, WearableItem> ownedEmotes = new ();
 30        // internal InputAction_Hold showInfoInputAction;
 31        internal InputAction_Trigger shortcut0InputAction;
 32        internal InputAction_Trigger shortcut1InputAction;
 33        internal InputAction_Trigger shortcut2InputAction;
 34        internal InputAction_Trigger shortcut3InputAction;
 35        internal InputAction_Trigger shortcut4InputAction;
 36        internal InputAction_Trigger shortcut5InputAction;
 37        internal InputAction_Trigger shortcut6InputAction;
 38        internal InputAction_Trigger shortcut7InputAction;
 39        internal InputAction_Trigger shortcut8InputAction;
 40        internal InputAction_Trigger shortcut9InputAction;
 41
 42        internal IEmotesCustomizationComponentView view;
 43
 044        internal bool isEmotesCustomizationSectionOpen => exploreV2DataStore.isOpen.Get() && view.isActive;
 45
 046        private CancellationTokenSource cts = new ();
 47        private IAvatarEmotesController emotesController;
 48
 049        public EmotesCustomizationComponentController() { }
 50
 051        public EmotesCustomizationComponentController(DataStore_EmotesCustomization emotesCustomizationDataStore,
 52            IAvatarEmotesController avatarEmotesController,
 53            DataStore_ExploreV2 exploreV2DataStore,
 54            DataStore_HUDs hudsDataStore,
 55            Transform parent,
 56            string viewPath = "EmotesCustomization/EmotesCustomizationSection")
 57        {
 058            Initialize(emotesCustomizationDataStore, avatarEmotesController, exploreV2DataStore, hudsDataStore, parent, 
 059        }
 60
 61        internal void Initialize(DataStore_EmotesCustomization emotesCustomizationDataStore,
 62            IAvatarEmotesController avatarEmotesController,
 63            DataStore_ExploreV2 exploreV2DataStore,
 64            DataStore_HUDs hudsDataStore,
 65            Transform parent,
 66            string viewPath = "EmotesCustomization/EmotesCustomizationSection")
 67        {
 068            this.emotesController = avatarEmotesController;
 069            this.emotesCustomizationDataStore = emotesCustomizationDataStore;
 070            this.exploreV2DataStore = exploreV2DataStore;
 071            this.hudsDataStore = hudsDataStore;
 72
 073            ConfigureView(parent, viewPath);
 074            ConfigureShortcuts();
 75
 076            emotesCustomizationDataStore.equippedEmotes.OnSet += OnEquippedEmotesSet;
 077            OnEquippedEmotesSet(emotesCustomizationDataStore.equippedEmotes.Get());
 78
 079            this.emotesController.OnEmoteEquipped += OnAnimationAdded;
 080        }
 81
 82        public void SetEmotes(WearableItem[] ownedEmotes)
 83        {
 84            //Find loaded emotes that are not contained in emotesToSet
 085            List<string> idsToRemove = emotesCustomizationDataStore.currentLoadedEmotes.Get().Where(x => ownedEmotes.All
 86
 087            foreach (string emoteId in idsToRemove)
 088                RemoveEmote(emoteId);
 89
 090            this.ownedEmotes.Clear();
 091            for (int i = 0; i < ownedEmotes.Length; i++)
 92            {
 093                WearableItem emote = ownedEmotes[i];
 94                //emotes owned multiple times will be received as separated entities, overriding by emote.id removes tha
 95                //if we want to show the amount of ocurrences we can modify this
 096                this.ownedEmotes[emote.id] = emote;
 97            }
 098            foreach (WearableItem emote in this.ownedEmotes.Values)
 099                AddEmote(emote);
 100
 0101            UpdateEmoteSlots();
 102
 0103            view.RefreshEmotesGrid();
 0104        }
 105
 106        public void SetEquippedBodyShape(string bodyShapeId)
 107        {
 0108            if (bodyShapeId == this.bodyShapeId)
 0109                return;
 110
 0111            this.bodyShapeId = bodyShapeId;
 0112            foreach (string emoteId in this.ownedEmotes.Keys)
 113            {
 0114                RefreshEmoteLoadingState(emoteId);
 115            }
 0116        }
 117
 118        public void RestoreEmoteSlots()
 119        {
 0120            emotesCustomizationDataStore.unsavedEquippedEmotes.Set(emotesCustomizationDataStore.equippedEmotes.Get());
 0121            UpdateEmoteSlots();
 0122        }
 123
 124        public void Dispose()
 125        {
 0126            cts.SafeCancelAndDispose();
 0127            view.onEmoteEquipped -= OnEmoteEquipped;
 0128            view.onEmoteUnequipped -= OnEmoteUnequipped;
 0129            view.onSellEmoteClicked -= OnSellEmoteClicked;
 0130            view.onSlotSelected -= OnSlotSelected;
 0131            exploreV2DataStore.isOpen.OnChange -= IsStarMenuOpenChanged;
 0132            hudsDataStore.avatarEditorVisible.OnChange -= OnAvatarEditorVisibleChanged;
 0133            emotesCustomizationDataStore.equippedEmotes.OnSet -= OnEquippedEmotesSet;
 0134            equipInputAction.OnFinished -= OnEquipInputActionTriggered;
 135            // showInfoInputAction.OnFinished -= OnShowInfoInputActionTriggered;
 0136            shortcut0InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0137            shortcut1InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0138            shortcut2InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0139            shortcut3InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0140            shortcut4InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0141            shortcut5InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0142            shortcut6InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0143            shortcut7InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0144            shortcut8InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0145            shortcut9InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered;
 0146        }
 147
 148        internal void OnEquippedEmotesSet(IEnumerable<EquippedEmoteData> equippedEmotes)
 149        {
 0150            emotesCustomizationDataStore.unsavedEquippedEmotes.Set(equippedEmotes);
 0151            UpdateEmoteSlots();
 0152        }
 153
 154        private void ConfigureView(Transform parent, string viewPath)
 155        {
 0156            view = CreateView(viewPath);
 157
 0158            if (view.viewTransform != null)
 159            {
 0160                view.viewTransform.SetParent(parent, false);
 0161                view.viewTransform.ResetLocalTRS();
 162            }
 0163            view.onEmoteEquipped += OnEmoteEquipped;
 0164            view.onEmoteUnequipped += OnEmoteUnequipped;
 0165            view.onSellEmoteClicked += OnSellEmoteClicked;
 0166            view.onSlotSelected += OnSlotSelected;
 0167            exploreV2DataStore.isOpen.OnChange += IsStarMenuOpenChanged;
 0168            hudsDataStore.avatarEditorVisible.OnChange += OnAvatarEditorVisibleChanged;
 0169        }
 170
 0171        internal void IsStarMenuOpenChanged(bool currentIsOpen, bool previousIsOpen) { view.SetEmoteInfoPanelActive(fals
 172
 0173        internal void OnAvatarEditorVisibleChanged(bool current, bool previous) { view.SetActive(current); }
 174
 175        internal void AddEmote(WearableItem emote)
 176        {
 0177            var emoteId = emote.id;
 0178            if (!emote.IsEmote() || emotesCustomizationDataStore.currentLoadedEmotes.Contains(emoteId))
 0179                return;
 180
 0181            emotesCustomizationDataStore.currentLoadedEmotes.Add(emoteId);
 182
 0183            if (!emote.ShowInBackpack())
 0184                return;
 185
 0186            EmoteCardComponentModel emoteToAdd = ParseWearableItemIntoEmoteCardModel(emote);
 0187            EmoteCardComponentView newEmote = view.AddEmote(emoteToAdd);
 188
 0189            if (newEmote != null)
 0190                newEmote.SetAsLoading(true);
 191
 0192            if (!emotesInLoadingState.ContainsKey(emoteId))
 0193                emotesInLoadingState.Add(emoteId, newEmote);
 194
 0195            RefreshEmoteLoadingState(emoteId);
 0196        }
 197
 198        internal void RemoveEmote(string emoteId)
 199        {
 0200            emotesCustomizationDataStore.currentLoadedEmotes.Remove(emoteId);
 0201            view.RemoveEmote(emoteId);
 0202            UpdateEmoteSlots();
 0203        }
 204
 205        private void OnAnimationAdded(string emoteId, IEmoteReference emoteClipData)
 206        {
 0207            RefreshEmoteLoadingState(emoteId);
 0208        }
 209
 210        internal void RefreshEmoteLoadingState(string emoteId)
 211        {
 0212            if (emotesController.TryGetEquippedEmote(bodyShapeId, emoteId, out IEmoteReference emoteReference))
 213            {
 0214                emotesInLoadingState.TryGetValue(emoteId, out EmoteCardComponentView emoteCard);
 0215                if (emoteCard != null)
 216                {
 0217                    emoteCard.SetAsLoading(false);
 0218                    emoteCard.SetSoundIcon(emoteReference.GetData().AudioSource != null);
 0219                    emotesInLoadingState.Remove(emoteId);
 220                }
 221            }
 0222        }
 223
 224        internal EmoteCardComponentModel ParseWearableItemIntoEmoteCardModel(WearableItem wearable)
 225        {
 0226            return new EmoteCardComponentModel
 227            {
 228                id = wearable.id,
 229                name = wearable.GetName(),
 230                amount = wearable.amount > 1 ? $"x{wearable.amount.ToString()}" : "",
 231                description = wearable.description,
 232                pictureUri = wearable.ComposeThumbnailUrl(),
 233                pictureSprite = wearable.thumbnailSprite,
 234                isAssignedInSelectedSlot = false,
 235                isSelected = false,
 236                assignedSlot = -1,
 237                rarity = wearable.rarity,
 238                isInL2 = wearable.IsInL2(),
 239                isLoading = false,
 240                isCollectible = wearable.IsCollectible()
 241            };
 242        }
 243
 244        internal void UpdateEmoteSlots()
 245        {
 0246            for (int i = 0; i < emotesCustomizationDataStore.unsavedEquippedEmotes.Count(); i++)
 247            {
 0248                if (i > NUMBER_OF_SLOTS)
 249                    break;
 250
 0251                if (emotesCustomizationDataStore.unsavedEquippedEmotes[i] == null) //empty slot
 252                {
 0253                    EmoteSlotCardComponentView existingEmoteIntoSlot = view.GetSlot(i);
 0254                    if (existingEmoteIntoSlot != null)
 0255                        view.UnequipEmote(existingEmoteIntoSlot.model.emoteId, i, false);
 256
 0257                    continue;
 258                }
 259
 0260                ownedEmotes.TryGetValue(emotesCustomizationDataStore.unsavedEquippedEmotes[i].id, out WearableItem emote
 0261                if (emoteItem != null && emotesCustomizationDataStore.currentLoadedEmotes.Contains(emoteItem.id))
 0262                    view.EquipEmote(emoteItem.id, emoteItem.GetName(), i, false, false);
 263            }
 0264        }
 265
 266        internal void StoreEquippedEmotes()
 267        {
 0268            List<EquippedEmoteData> newEquippedEmotesList = new List<EquippedEmoteData> { null, null, null, null, null, 
 269
 0270            if (view.currentSlots != null)
 271            {
 0272                foreach (EmoteSlotCardComponentView slot in view.currentSlots)
 273                {
 0274                    if (!string.IsNullOrEmpty(slot.model.emoteId))
 0275                        newEquippedEmotesList[slot.model.slotNumber] = new EquippedEmoteData
 276                        {
 277                            id = slot.model.emoteId,
 278                            cachedThumbnail = slot.model.pictureSprite
 279                        };
 280                }
 281            }
 282
 0283            emotesCustomizationDataStore.unsavedEquippedEmotes.Set(newEquippedEmotesList);
 0284        }
 285
 286        internal void OnEmoteEquipped(string emoteId, int slotNumber)
 287        {
 0288            StoreEquippedEmotes();
 0289            onEmotePreviewed?.Invoke(emoteId);
 0290            onEmoteEquipped?.Invoke(emoteId);
 0291        }
 292
 293        internal void OnEmoteUnequipped(string emoteId, int slotNumber)
 294        {
 0295            StoreEquippedEmotes();
 0296            onEmoteUnequipped?.Invoke(emoteId);
 0297        }
 298
 0299        internal void OnSellEmoteClicked(string emoteId) { onEmoteSell?.Invoke(emoteId); }
 300
 301        internal void OnSlotSelected(string emoteId, int slotNumber, bool playEmote)
 302        {
 0303            if (playEmote)
 0304                onEmotePreviewed?.Invoke(emoteId);
 0305        }
 306
 307        internal void ConfigureShortcuts()
 308        {
 0309            equipInputAction = Resources.Load<InputAction_Hold>("DefaultConfirmAction");
 0310            equipInputAction.OnFinished += OnEquipInputActionTriggered;
 311
 312            // showInfoInputAction = Resources.Load<InputAction_Hold>("ZoomIn");
 313            // showInfoInputAction.OnFinished += OnShowInfoInputActionTriggered;
 314
 0315            shortcut0InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut0");
 0316            shortcut0InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 317
 0318            shortcut1InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut1");
 0319            shortcut1InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 320
 0321            shortcut2InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut2");
 0322            shortcut2InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 323
 0324            shortcut3InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut3");
 0325            shortcut3InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 326
 0327            shortcut4InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut4");
 0328            shortcut4InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 329
 0330            shortcut5InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut5");
 0331            shortcut5InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 332
 0333            shortcut6InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut6");
 0334            shortcut6InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 335
 0336            shortcut7InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut7");
 0337            shortcut7InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 338
 0339            shortcut8InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut8");
 0340            shortcut8InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 341
 0342            shortcut9InputAction = Resources.Load<InputAction_Trigger>("ToggleShortcut9");
 0343            shortcut9InputAction.OnTriggered += OnNumericShortcutInputActionTriggered;
 0344        }
 345
 346        internal void OnEquipInputActionTriggered(DCLAction_Hold action)
 347        {
 0348            if (!isEmotesCustomizationSectionOpen || view.selectedCard == null || view.selectedCard.model.isLoading)
 0349                return;
 350
 0351            if (!view.selectedCard.model.isAssignedInSelectedSlot)
 352            {
 0353                view.EquipEmote(
 354                    view.selectedCard.model.id,
 355                    view.selectedCard.model.name,
 356                    view.selectedSlot);
 357            }
 358            else
 359            {
 0360                view.UnequipEmote(
 361                    view.selectedCard.model.id,
 362                    view.selectedSlot);
 363            }
 0364        }
 365
 366        internal void OnShowInfoInputActionTriggered(DCLAction_Hold action)
 367        {
 0368            if (!isEmotesCustomizationSectionOpen || view.selectedCard == null || !view.selectedCard.model.isCollectible
 0369                return;
 370
 0371            view.OpenEmoteInfoPanel(
 372                view.selectedCard.model,
 373                view.selectedCard.rarityMark.gameObject.activeSelf ? view.selectedCard.rarityMark.color : Color.grey,
 374                view.selectedCard.emoteInfoAnchor);
 0375        }
 376
 377        internal void OnNumericShortcutInputActionTriggered(DCLAction_Trigger action)
 378        {
 0379            if (!isEmotesCustomizationSectionOpen || view.selectedCard == null || view.selectedCard.model.isLoading)
 0380                return;
 381
 382            switch (action)
 383            {
 384                case DCLAction_Trigger.ToggleShortcut0:
 0385                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 0);
 0386                    break;
 387                case DCLAction_Trigger.ToggleShortcut1:
 0388                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 1);
 0389                    break;
 390                case DCLAction_Trigger.ToggleShortcut2:
 0391                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 2);
 0392                    break;
 393                case DCLAction_Trigger.ToggleShortcut3:
 0394                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 3);
 0395                    break;
 396                case DCLAction_Trigger.ToggleShortcut4:
 0397                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 4);
 0398                    break;
 399                case DCLAction_Trigger.ToggleShortcut5:
 0400                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 5);
 0401                    break;
 402                case DCLAction_Trigger.ToggleShortcut6:
 0403                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 6);
 0404                    break;
 405                case DCLAction_Trigger.ToggleShortcut7:
 0406                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 7);
 0407                    break;
 408                case DCLAction_Trigger.ToggleShortcut8:
 0409                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 8);
 0410                    break;
 411                case DCLAction_Trigger.ToggleShortcut9:
 0412                    view.EquipEmote(view.selectedCard.model.id, view.selectedCard.model.name, 9);
 413                    break;
 414            }
 0415        }
 416
 417        internal virtual IEmotesCustomizationComponentView CreateView(string path = "EmotesCustomization/EmotesCustomiza
 0418            EmotesCustomizationComponentView.Create(path);
 419    }
 420}