From cec3e0dd48abf0a01ddbad67d89f809a84162bc7 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Thu, 24 Aug 2023 16:53:56 -0300 Subject: [PATCH 01/35] Emotes extra content is now being loaded --- .../EmoteAnimations/EmoteAnimationLoader.cs | 13 ++- .../EmoteAnimations/EmoteAnimationsTracker.cs | 69 ++++++--------- .../EmoteAnimations/IEmoteAnimationLoader.cs | 6 +- .../Tests/EmoteAnimationsTrackerShould.cs | 8 +- .../Components/Avatar/AvatarAnimatorLegacy.cs | 64 ++++++++++---- .../EmotesCustomizationComponentController.cs | 2 +- .../DCL/Models/AvatarAssets/EmoteClipData.cs | 85 ++++++++++++++++--- 7 files changed, 169 insertions(+), 78 deletions(-) diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs index f2e3a2f644..5976d6451c 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs @@ -10,15 +10,17 @@ public class EmoteAnimationLoader : IEmoteAnimationLoader { private readonly IWearableRetriever retriever; public AnimationClip loadedAnimationClip { get; internal set; } + public GameObject container { get; private set; } + public AudioClip audioClip { get; private set; } public EmoteAnimationLoader(IWearableRetriever retriever) { this.retriever = retriever; } - public async UniTask LoadEmote(GameObject container, WearableItem emote, string bodyShapeId, CancellationToken ct = default) + public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default) { - if (container == null) + if (targetContainer == null) throw new NullReferenceException("Container cannot be null"); if (emote == null) @@ -29,7 +31,7 @@ public async UniTask LoadEmote(GameObject container, WearableItem emote, string ct.ThrowIfCancellationRequested(); - Rendereable rendereable = await retriever.Retrieve(container, emote, bodyShapeId, ct); + Rendereable rendereable = await retriever.Retrieve(targetContainer, emote, bodyShapeId, ct); var animation = rendereable.container.GetComponentInChildren(); @@ -39,6 +41,11 @@ public async UniTask LoadEmote(GameObject container, WearableItem emote, string return; } + if (animation.GetClipCount() > 1) + { + this.container = rendereable.container; + } + animation.enabled = false; var animationClip = animation.clip; diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs index fc45292341..57413df70c 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs +++ b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs @@ -14,15 +14,20 @@ namespace DCL.Emotes { public class EmoteAnimationsTracker : IDisposable { + //To avoid circular references in assemblies we hardcode this here instead of using WearableLiterals + //Embedded Emotes are only temporary until they can be retrieved from the content server + private const string FEMALE = "urn:decentraland:off-chain:base-avatars:BaseFemale"; + private const string MALE = "urn:decentraland:off-chain:base-avatars:BaseMale"; + internal readonly DataStore_Emotes dataStore; internal readonly EmoteAnimationLoaderFactory emoteAnimationLoaderFactory; private readonly IEmotesCatalogService emotesCatalogService; private readonly IWearablesCatalogService wearablesCatalogService; private readonly ICatalyst catalyst; - internal Dictionary<(string bodyshapeId, string emoteId), IEmoteAnimationLoader> loaders = new Dictionary<(string bodyshapeId, string emoteId), IEmoteAnimationLoader>(); + internal Dictionary<(string bodyshapeId, string emoteId), IEmoteAnimationLoader> loaders = new (); - private CancellationTokenSource cts = new CancellationTokenSource(); + private CancellationTokenSource cts = new (); internal GameObject animationsModelsContainer; @@ -47,36 +52,15 @@ public EmoteAnimationsTracker( private async UniTaskVoid AsyncInitialization() { - //To avoid circular references in assemblies we hardcode this here instead of using WearableLiterals - //Embedded Emotes are only temporary until they can be retrieved from the content server - const string FEMALE = "urn:decentraland:off-chain:base-avatars:BaseFemale"; - const string MALE = "urn:decentraland:off-chain:base-avatars:BaseMale"; - EmbeddedEmotesSO embeddedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); foreach (EmbeddedEmote embeddedEmote in embeddedEmotes.emotes) { if (embeddedEmote.maleAnimation != null) - { - //We match the animation id with its name due to performance reasons - //Unity's Animation uses the name to play the clips. - embeddedEmote.maleAnimation.name = embeddedEmote.id; - dataStore.emotesOnUse.SetRefCount((MALE, embeddedEmote.id), 5000); - var clipData = new EmoteClipData(embeddedEmote.maleAnimation, embeddedEmote.emoteDataV0); - dataStore.animations.Add((MALE, embeddedEmote.id), clipData); - loaders.Add((MALE, embeddedEmote.id), emoteAnimationLoaderFactory.Get()); - } + SetupEmbeddedClip(embeddedEmote, embeddedEmote.maleAnimation, MALE); if (embeddedEmote.femaleAnimation != null) - { - //We match the animation id with its name due to performance reasons - //Unity's Animation uses the name to play the clips. - embeddedEmote.femaleAnimation.name = embeddedEmote.id; - dataStore.emotesOnUse.SetRefCount((FEMALE, embeddedEmote.id), 5000); - var emoteClipData = new EmoteClipData(embeddedEmote.femaleAnimation, embeddedEmote.emoteDataV0); - dataStore.animations.Add((FEMALE, embeddedEmote.id), emoteClipData); - loaders.Add((FEMALE, embeddedEmote.id), emoteAnimationLoaderFactory.Get()); - } + SetupEmbeddedClip(embeddedEmote, embeddedEmote.femaleAnimation, FEMALE); } wearablesCatalogService.EmbedWearables(embeddedEmotes.emotes); @@ -84,6 +68,17 @@ private async UniTaskVoid AsyncInitialization() this.dataStore.emotesOnUse.OnRefCountUpdated += OnRefCountUpdated; } + private void SetupEmbeddedClip(EmbeddedEmote embeddedEmote, AnimationClip clip, string urn) + { + //We match the animation id with its name due to performance reasons + //Unity's Animation uses the name to play the clips. + clip.name = embeddedEmote.id; + dataStore.emotesOnUse.SetRefCount((urn, embeddedEmote.id), 5000); + var clipData = new EmoteClipData(clip, embeddedEmote.emoteDataV0?.loop ?? false); + dataStore.animations.Add((urn, embeddedEmote.id), clipData); + loaders.Add((urn, embeddedEmote.id), emoteAnimationLoaderFactory.Get()); + } + private void OnRefCountUpdated((string bodyshapeId, string emoteId) value, int refCount) { if (refCount > 0) @@ -94,10 +89,7 @@ private void OnRefCountUpdated((string bodyshapeId, string emoteId) value, int r private void InitializeEmotes(IEnumerable> refCounts) { - foreach (KeyValuePair<(string bodyshapeId, string emoteId), int> keyValuePair in refCounts) - { - LoadEmote(keyValuePair.Key.bodyshapeId, keyValuePair.Key.emoteId, cts.Token); - } + foreach (KeyValuePair<(string bodyshapeId, string emoteId), int> keyValuePair in refCounts) { LoadEmote(keyValuePair.Key.bodyshapeId, keyValuePair.Key.emoteId, cts.Token); } } private async UniTaskVoid LoadEmote(string bodyShapeId, string emoteId, CancellationToken ct) @@ -124,14 +116,13 @@ private async UniTaskVoid LoadEmote(string bodyShapeId, string emoteId, Cancella if (emote is EmoteItem newEmoteItem) emoteClipData = new EmoteClipData(animationLoader.loadedAnimationClip, newEmoteItem.data.loop); else - emoteClipData = new EmoteClipData(animationLoader.loadedAnimationClip, emote.emoteDataV0); + emoteClipData = new EmoteClipData(animationLoader.loadedAnimationClip, emote.emoteDataV0?.loop ?? false); + + emoteClipData.LoadExtraContent(animationLoader.container, animationLoader.audioClip); dataStore.animations.Add((bodyShapeId, emoteId), emoteClipData); - if (animationLoader.loadedAnimationClip == null) - { - Debug.LogError("Emote animation failed to load for emote " + emote.id); - } + if (animationLoader.loadedAnimationClip == null) { Debug.LogError("Emote animation failed to load for emote " + emote.id); } } catch (Exception e) { @@ -158,10 +149,7 @@ public void Dispose() dataStore.emotesOnUse.OnRefCountUpdated -= OnRefCountUpdated; (string bodyshapeId, string emoteId)[] keys = loaders.Keys.ToArray(); - foreach ((string bodyshapeId, string emoteId) in keys) - { - UnloadEmote(bodyshapeId, emoteId); - } + foreach ((string bodyshapeId, string emoteId) in keys) { UnloadEmote(bodyshapeId, emoteId); } loaders.Clear(); cts.Cancel(); @@ -181,10 +169,7 @@ private UniTask RequestEmote(string bodyShapeId, string emoteId, C private static WearableItem GenerateSceneEmoteItem(string bodyShapeId, string emoteId, string contentLambdaUrl) { - if (!SceneEmoteHelper.TryGetDataFromEmoteId(emoteId, out string emoteHash, out bool loop)) - { - return null; - } + if (!SceneEmoteHelper.TryGetDataFromEmoteId(emoteId, out string emoteHash, out bool loop)) { return null; } return new EmoteItem() { diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs index 6ca1f0e008..8326283085 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs @@ -8,6 +8,8 @@ namespace DCL.Emotes public interface IEmoteAnimationLoader : IDisposable { AnimationClip loadedAnimationClip { get; } - UniTask LoadEmote(GameObject container, WearableItem emote, string bodyShapeId, CancellationToken ct = default); + GameObject container { get; } + AudioClip audioClip { get; } + UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default); } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs index 6c217c2b2c..d481c376dd 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs +++ b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs @@ -51,8 +51,8 @@ public IEnumerator InitializeEmbeddedEmotesOnConstructor() foreach (EmbeddedEmote emote in embeddedEmotesSo.emotes) { - Assert.AreEqual(dataStore.animations[(WearableLiterals.BodyShapes.FEMALE, emote.id)]?.clip, emote.femaleAnimation); - Assert.AreEqual(dataStore.animations[(WearableLiterals.BodyShapes.MALE, emote.id)]?.clip, emote.maleAnimation); + Assert.AreEqual(dataStore.animations[(WearableLiterals.BodyShapes.FEMALE, emote.id)]?.AvatarClip, emote.femaleAnimation); + Assert.AreEqual(dataStore.animations[(WearableLiterals.BodyShapes.MALE, emote.id)]?.AvatarClip, emote.maleAnimation); Assert.IsTrue(tracker.loaders.ContainsKey((WearableLiterals.BodyShapes.MALE, emote.id))); } @@ -76,7 +76,7 @@ public void ReactToEquipEmotesIncreasingReference() emoteCatalog.Received(1).RequestEmoteAsync(EMOTE_ID, Arg.Any()); loader.Received(1).LoadEmote(tracker.animationsModelsContainer, emote, WearableLiterals.BodyShapes.FEMALE, Arg.Any()); var animKey = (WearableLiterals.BodyShapes.FEMALE, EMOTE_ID); - Assert.AreEqual(animClip, dataStore.animations[animKey]?.clip); + Assert.AreEqual(animClip, dataStore.animations[animKey]?.AvatarClip); } [Test] @@ -139,7 +139,7 @@ async UniTask GetDelayedEmoteItem() emoteCatalog.Received(1).RequestEmoteAsync(EMOTE_ID, Arg.Any()); loader.Received(1).LoadEmote(tracker.animationsModelsContainer, emote, WearableLiterals.BodyShapes.FEMALE, Arg.Any()); var animKey = (WearableLiterals.BodyShapes.FEMALE, EMOTE_ID); - Assert.AreEqual(animClip, dataStore.animations[animKey]?.clip); + Assert.AreEqual(animClip, dataStore.animations[animKey]?.AvatarClip); }); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 94415d9384..de8836d0eb 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -109,6 +109,7 @@ public class BlackBoard private Ray rayCache; private bool hasTarget; + private EmoteClipData lastExtendedEmoteData; private void Awake() { @@ -367,13 +368,7 @@ private void State_Expression(BlackBoard bb) } if (exitTransitionStarted) - { - animation.Blend(bb.expressionTriggerId, 0, EXPRESSION_EXIT_TRANSITION_TIME); - - bb.expressionTriggerId = null; - bb.shouldLoop = false; - OnUpdateWithDeltaTime(bb.deltaTime); - } + StopEmote(bb); else if (prevAnimation != AvatarAnimation.EMOTE) // this condition makes Blend be called only in first frame of the state { animation.wrapMode = bb.shouldLoop ? WrapMode.Loop : WrapMode.Once; @@ -392,6 +387,16 @@ bool ExpressionGroundTransitionCondition(AnimationState animationState) } } + private void StopEmote(BlackBoard bb) + { + animation.Blend(bb.expressionTriggerId, 0, EXPRESSION_EXIT_TRANSITION_TIME); + bb.expressionTriggerId = null; + bb.shouldLoop = false; + OnUpdateWithDeltaTime(bb.deltaTime); + + lastExtendedEmoteData?.StopAllAnimations(); + } + private void SetExpressionValues(string expressionTriggerId, long expressionTriggerTimestamp) { if (animation == null) @@ -416,8 +421,7 @@ private void SetExpressionValues(string expressionTriggerId, long expressionTrig latestAnimation = AvatarAnimation.IDLE; } - blackboard.shouldLoop = emoteClipDataMap.TryGetValue(expressionTriggerId, out var clipData) - && clipData.loop; + blackboard.shouldLoop = emoteClipDataMap.TryGetValue(expressionTriggerId, out var clipData) && clipData.Loop; currentState = State_Expression; OnUpdateWithDeltaTime(Time.deltaTime); @@ -438,6 +442,21 @@ public void Reset() public void PlayEmote(string emoteId, long timestamps) { SetExpressionValues(emoteId, timestamps); + + if (!string.IsNullOrEmpty(emoteId)) + { + lastExtendedEmoteData?.StopAllAnimations(); + + if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) + { + lastExtendedEmoteData = emoteClipData; + emoteClipData.PlayAllAnimations(); + } + } + else + { + lastExtendedEmoteData?.StopAllAnimations(); + } } public void EquipBaseClip(AnimationClip clip) @@ -457,18 +476,22 @@ public void EquipEmote(string emoteId, EmoteClipData emoteClipData) if (animation == null) return; - if (emoteClipData.clip == null) - { - Debug.LogError("Can't equip null animation clip for emote " + emoteId); - return; - } - if (animation.GetClip(emoteId) != null) animation.RemoveClip(emoteId); emoteClipDataMap[emoteId] = emoteClipData; - animation.AddClip(emoteClipData.clip, emoteId); + animation.AddClip(emoteClipData.AvatarClip, emoteId); + + // Enhanced emotes setup + + if (emoteClipData.ExtraContent != null) + { + emoteClipData.ExtraContent.transform.SetParent(animation.transform, false); + emoteClipData.ExtraContent.transform.ResetLocalTRS(); + } + + // TODO: Setup sound clip for this emote } public void UnequipEmote(string emoteId) @@ -480,6 +503,15 @@ public void UnequipEmote(string emoteId) return; animation.RemoveClip(emoteId); + + if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) + { + // Enhanced emotes setup + if (emoteClipData.ExtraContent != null) + emoteClipData.ExtraContent.transform.SetParent(null, false); + + // TODO: Setup sound clip for this emote + } } private void InitializeAvatarAudioAndParticleHandlers(Animation createdAnimation) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs index 2ffe3e61e2..726e9b67e0 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs @@ -201,7 +201,7 @@ internal void RemoveEmote(string emoteId) internal void OnAnimationAdded((string bodyshapeId, string emoteId) values, EmoteClipData emoteClipData) { - if(emoteClipData.clip != null) + if(emoteClipData.AvatarClip != null) RefreshEmoteLoadingState(values.emoteId); else { diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index cdf6d623e1..8893b8aa49 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -1,22 +1,87 @@ -using UnityEngine; +using JetBrains.Annotations; +using System; +using UnityEngine; namespace DCL.Emotes { public class EmoteClipData { - public readonly AnimationClip clip; - public readonly bool loop; + public AnimationClip AvatarClip { get; } + public bool Loop { get; } - public EmoteClipData(AnimationClip clip, bool loop = false) + [CanBeNull] private Animation animation; + [CanBeNull] public GameObject ExtraContent { get; private set; } + [CanBeNull] public AudioClip AudioClip { get; private set; } + + [CanBeNull] private Renderer[] renderers; + + public EmoteClipData(AnimationClip avatarClip, bool loop = false) + { + this.AvatarClip = avatarClip; + this.Loop = loop; + } + + public void LoadExtraContent(GameObject extraContent, AudioClip audioClip) + { + this.ExtraContent = extraContent; + this.AudioClip = audioClip; + + if (extraContent != null) + { + animation = extraContent.GetComponentInChildren(); + + if (animation == null) + Debug.LogError($"Animation {AvatarClip.name} extra content does not have an animation"); + + renderers = extraContent.GetComponentsInChildren(); + } + } + + public void PlayAllAnimations() { - this.clip = clip; - this.loop = loop; + if (renderers != null) + { + foreach (Renderer renderer in renderers) + { + renderer.enabled = true; + } + } + + if (animation != null) + { + var layer = 0; + + foreach (AnimationState state in animation) + { + if (state.clip == AvatarClip) continue; + state.layer = layer++; + animation.Play(state.clip.name); + } + + animation.enabled = true; + } } - public EmoteClipData(AnimationClip clip, EmoteDataV0 emoteDataV0) + public void StopAllAnimations() { - this.clip = clip; - loop = emoteDataV0?.loop ?? false; + if (renderers != null) + { + foreach (Renderer renderer in renderers) + { + renderer.enabled = false; + } + } + + if (animation != null) + { + foreach (AnimationState state in animation) + { + if (state.clip == AvatarClip) continue; + animation.Stop(state.clip.name); + } + + animation.enabled = false; + } } } -} \ No newline at end of file +} From 3f987217d64d981e7a1df4d73f83e87c3f78fa65 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Tue, 29 Aug 2023 18:47:34 -0300 Subject: [PATCH 02/35] Big refactor --- .../ECSComponents/AvatarShape/AvatarShape.cs | 2 +- .../DCL.ECSComponents.AvatarShape.asmdef | 3 +- .../AvatarShape/Tests/AvatarShapeShould.cs | 26 +- ...DCL.ECSComponents.AvatarShape.Tests.asmdef | 11 +- .../Assets/DCLPlugins/EmoteAnimations.meta | 13 - .../EmoteAnimations/AssemblyInfo.cs.meta | 3 - .../EmoteAnimations/EmoteAnimationsPlugin.cs | 25 -- .../EmoteAnimationsPlugin.cs.meta | 15 - .../EmoteAnimations/EmoteAnimationsTracker.cs | 201 ---------- .../EmoteAnimationsTracker.cs.meta | 3 - .../Tests/EmoteAnimationLoaderShould.cs | 93 ----- .../Tests/EmoteAnimationLoaderShould.cs.meta | 3 - .../Tests/EmoteAnimationsPluginTests.asmdef | 44 --- .../Tests/EmoteAnimationsTrackerShould.cs | 145 ------- .../EmoteAnimationsTrackerShould.cs.meta | 11 - .../Assets/DCLServices/EmotesService.meta | 3 + .../EmotesService}/Addressables.meta | 0 .../Addressables/EmbeddedEmotes.asset | 0 .../Addressables/EmbeddedEmotes.asset.meta | 0 .../EmotesService}/EmoteAnimationLoader.cs | 8 +- .../EmoteAnimationLoader.cs.meta | 0 .../EmoteAnimationLoaderFactory.cs | 0 .../EmoteAnimationLoaderFactory.cs.meta | 0 .../EmotesService/EmotesService.asmdef} | 23 +- .../EmotesService/EmotesService.asmdef.meta} | 2 +- .../EmotesService/EmotesService.cs | 122 ++++++ .../EmotesService/EmotesService.cs.meta | 3 + .../DCLServices/EmotesService/Interfaces.meta | 3 + .../Interfaces/EmbedEmoteReference.cs | 27 ++ .../Interfaces/EmbedEmoteReference.cs.meta | 3 + .../EmotesServiceDefinitions.asmdef | 18 + .../EmotesServiceDefinitions.asmdef.meta} | 2 +- .../Interfaces}/IEmoteAnimationLoader.cs | 2 +- .../Interfaces}/IEmoteAnimationLoader.cs.meta | 0 .../Interfaces/IEmoteReference.cs | 10 + .../Interfaces/IEmoteReference.cs.meta | 3 + .../Interfaces/IEmotesService.cs | 10 + .../Interfaces/IEmotesService.cs.meta | 3 + .../Interfaces/NftEmoteReference.cs | 27 ++ .../Interfaces/NftEmoteReference.cs.meta | 3 + .../IWearablesCatalogService.cs | 2 +- .../LambdasWearablesCatalogService.cs | 2 +- .../LambdasWearablesCatalogServiceShould.cs | 2 +- .../WearablesCatalogServiceProxy.cs | 4 +- .../WebInterfaceWearablesCatalogService.cs | 2 +- .../GPUSkinning/Tests/GPUSkinningTests.asmdef | 3 +- .../MainScripts/DCL/AvatarSystem/Avatar.cs | 24 +- .../AvatarSystem/AvatarEmotesController.cs | 114 ++++++ ...cs.meta => AvatarEmotesController.cs.meta} | 0 .../DCL/AvatarSystem/AvatarFactory.cs | 5 +- .../DCL/AvatarSystem/AvatarSystem.asmdef | 7 +- .../DCL/AvatarSystem/AvatarWithHologram.cs | 4 +- .../AvatarSystemDefinitions.asmdef | 3 +- .../DCL/AvatarSystem/Definitions/IAnimator.cs | 3 +- .../DCL/AvatarSystem/Definitions/IAvatar.cs | 5 +- .../Definitions/IAvatarEmotesController.cs | 22 ++ ...s.meta => IAvatarEmotesController.cs.meta} | 0 .../Definitions/IEmoteAnimationEquipper.cs | 10 - .../AvatarSystem/EmoteAnimationEquipper.cs | 76 ---- .../DCL/AvatarSystem/Loader}/AssemblyInfo.cs | 4 +- .../AvatarSystem/Loader/AssemblyInfo.cs.meta | 3 + .../Loader/AvatarSystemLoaders.asmdef | 34 ++ .../Loader/AvatarSystemLoaders.asmdef.meta} | 5 +- .../{ => Loader}/AvatarSystemUtils.cs | 0 .../{ => Loader}/AvatarSystemUtils.cs.meta | 0 .../AvatarSystem/Loader/BodyShapeLoader.cs | 5 +- .../DCL/AvatarSystem/Loader/Loader.cs | 39 +- .../AvatarSystem/Loader/SceneEmoteHelper.cs | 97 ----- .../{ => Loader}/WearableItemResolver.cs | 0 .../{ => Loader}/WearableItemResolver.cs.meta | 0 .../DCL/AvatarSystem/Loader/WearableLoader.cs | 5 +- .../AvatarSystem/Loader/WearableRetriever.cs | 2 +- .../DCL/AvatarSystem/Tests/AvatarShould.cs | 4 +- .../Tests/AvatarSystemTests.asmdef | 3 +- .../Tests/AvatarWithHologramShould.cs | 4 +- .../Tests/EmoteAnimationEquipperShould.cs | 146 ------- .../EmoteAnimationEquipperShould.cs.meta | 3 - .../Tests/SceneEmoteHelperShould.cs | 189 --------- .../Components/Avatar/AvatarAnimatorLegacy.cs | 2 +- .../Avatar/AvatarSceneEmoteHandler.cs | 87 ++--- .../DCL/Components/Avatar/AvatarShape.asmdef | 5 +- .../DCL/Components/Avatar/AvatarShape.cs | 6 +- .../Tests/AvatarSceneEmoteHandlerShould.cs | 148 +++----- .../Avatar/Tests/AvatarShapeTests.asmdef | 12 +- .../AvatarEditorHUD/AvatarEditorHUD.asmdef | 3 +- .../Scripts/AvatarEditorHUDController.cs | 2 +- .../Scripts/AvatarEditorHUDPlugin.cs | 5 +- .../EmotesCustomizationComponentController.cs | 67 ++-- .../EmotesWheelUIPlugin.cs | 3 +- .../Tests/AvatarEditorHUDControllerShould.cs | 80 ++-- .../Tests/AvatarEditorHUDTests.asmdef | 16 +- .../Tests/AvatarEditorHUDTests.cs | 6 +- .../Tests/AvatarEditorHUDViewShould.cs | 143 ++++--- .../EmoteCardComponentViewTests.cs | 9 +- .../EmoteSlotCardComponentViewTests.cs | 9 +- .../EmoteSlotSelectorComponentViewTests.cs | 9 +- ...esCustomizationComponentControllerTests.cs | 122 +++--- .../EmotesCustomizationComponentViewTests.cs | 9 +- .../BackpackEditorHUDV2.asmdef | 3 +- .../BackpackEditorHUDV2ComponentView.cs | 2 + .../BackpackEditorV2Plugin.cs | 18 +- .../BackpackEmotesSectionController.cs | 10 +- .../BackpackPreviewPanel.cs | 4 +- .../WearableGridController.cs | 9 +- .../CharacterPreview/CharacterPreview.asmdef | 3 +- .../CharacterPreviewController.cs | 13 +- .../ICharacterPreviewController.cs | 4 + .../EmotesWheelHUD/EmotesWheelController.cs | 112 ++++-- .../HUD/EmotesWheelHUD/EmotesWheelHUD.asmdef | 5 +- .../HUD/EmotesWheelHUD/EmotesWheelView.cs | 74 ++-- .../Test/EmotesWheelHUDTests.asmdef | 3 +- .../HUD/Passport/PassportHUD.asmdef | 3 +- .../PlayerAvatarController.asmdef | 5 +- .../PlayerAvatarController.cs | 4 +- .../PluginSystem/PluginSystemFactory.cs | 1 - .../MainScripts/DCL/DataStore/DataStore.cs | 1 - .../DCL/DataStore/DataStore_Emotes.cs | 14 - .../DCL/DataStore/DataStore_Emotes.cs.meta | 3 - .../DataStore_EmotesCustomization.cs | 14 +- .../ServiceLocatorFactory.asmdef | 2 + .../ServiceLocatorFactory.cs | 8 + .../DCL/FeatureFlags/FeatureFlagController.cs | 5 +- .../Models/AvatarAssets/AvatarAssets.asmdef | 3 +- .../DCL/Models/AvatarAssets/EmoteClipData.cs | 23 +- .../Models/AvatarAssets/SceneEmoteHelper.cs | 51 +++ .../AvatarAssets}/SceneEmoteHelper.cs.meta | 0 .../Tests/AvatarAssetsTest.asmdef | 26 +- .../Tests/SceneEmoteHelperShould.cs | 58 +++ .../Tests/SceneEmoteHelperShould.cs.meta | 0 .../DCL/Models/AvatarAssets/WearableItem.cs | 43 ++- .../EmotesRendererServiceImpl.cs | 92 ++--- .../EmotesService/RPC.Service.Emotes.asmdef | 3 +- .../Tests/RPC.Services.Emotes.Tests.asmdef | 7 +- .../Tests/TriggerSceneExpressionShould.cs | 358 ++++++++---------- .../DCL/WorldRuntime/SceneController.cs | 4 +- .../Tests/IntegrationTestSuite_Legacy.cs | 5 +- 136 files changed, 1433 insertions(+), 2004 deletions(-) delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations.meta delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/AssemblyInfo.cs.meta delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs.meta delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs.meta delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs.meta delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs delete mode 100644 unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs.meta create mode 100644 unity-renderer/Assets/DCLServices/EmotesService.meta rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService}/Addressables.meta (100%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService}/Addressables/EmbeddedEmotes.asset (100%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService}/Addressables/EmbeddedEmotes.asset.meta (100%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService}/EmoteAnimationLoader.cs (92%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService}/EmoteAnimationLoader.cs.meta (100%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService}/EmoteAnimationLoaderFactory.cs (100%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService}/EmoteAnimationLoaderFactory.cs.meta (100%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef => DCLServices/EmotesService/EmotesService.asmdef} (61%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef.meta => DCLServices/EmotesService/EmotesService.asmdef.meta} (76%) create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs.meta create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces.meta create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs.meta create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef.meta => DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef.meta} (76%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService/Interfaces}/IEmoteAnimationLoader.cs (88%) rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => DCLServices/EmotesService/Interfaces}/IEmoteAnimationLoader.cs.meta (100%) create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs.meta create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs.meta create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs.meta create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs rename unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/{EmoteAnimationEquipper.cs.meta => AvatarEmotesController.cs.meta} (100%) create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs rename unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/{IEmoteAnimationEquipper.cs.meta => IAvatarEmotesController.cs.meta} (100%) delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IEmoteAnimationEquipper.cs delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/EmoteAnimationEquipper.cs rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations => Scripts/MainScripts/DCL/AvatarSystem/Loader}/AssemblyInfo.cs (57%) create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AssemblyInfo.cs.meta create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef rename unity-renderer/Assets/{DCLPlugins/EmoteAnimations/Tests.meta => Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef.meta} (57%) rename unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/{ => Loader}/AvatarSystemUtils.cs (100%) rename unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/{ => Loader}/AvatarSystemUtils.cs.meta (100%) delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/SceneEmoteHelper.cs rename unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/{ => Loader}/WearableItemResolver.cs (100%) rename unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/{ => Loader}/WearableItemResolver.cs.meta (100%) delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs.meta delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/SceneEmoteHelperShould.cs delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs.meta create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/SceneEmoteHelper.cs rename unity-renderer/Assets/Scripts/MainScripts/DCL/{AvatarSystem/Loader => Models/AvatarAssets}/SceneEmoteHelper.cs.meta (100%) create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/SceneEmoteHelperShould.cs rename unity-renderer/Assets/Scripts/MainScripts/DCL/{AvatarSystem => Models/AvatarAssets}/Tests/SceneEmoteHelperShould.cs.meta (100%) diff --git a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/AvatarShape.cs b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/AvatarShape.cs index 5ffaddb6a9..3e7df139d2 100644 --- a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/AvatarShape.cs +++ b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/AvatarShape.cs @@ -204,7 +204,7 @@ public async void ApplyModel(IParcelScene scene, IDCLEntity entity, PBAvatarShap // If the model contains a value for expressionTriggerId then we try it, if value doesn't exist, we skip if(model.HasExpressionTriggerId) - avatar.PlayEmote(model.ExpressionTriggerId, model.GetExpressionTriggerTimestamp()); + avatar.GetEmotesController().PlayEmote(model.ExpressionTriggerId, model.GetExpressionTriggerTimestamp()); UpdatePlayerStatus(entity, model); diff --git a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/DCL.ECSComponents.AvatarShape.asmdef b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/DCL.ECSComponents.AvatarShape.asmdef index 47deeb1688..d5536fd6b0 100644 --- a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/DCL.ECSComponents.AvatarShape.asmdef +++ b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/DCL.ECSComponents.AvatarShape.asmdef @@ -48,7 +48,8 @@ "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", "GUID:6c1761dc8f737004198eb333521bd665", "GUID:c8ea72e806cd2ab47b539b37895b86b7", - "GUID:9cccce9925d3495d8a5e4fa5b25f54a5" + "GUID:9cccce9925d3495d8a5e4fa5b25f54a5", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/AvatarShapeShould.cs b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/AvatarShapeShould.cs index b97a1e1c95..7f58e969cf 100644 --- a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/AvatarShapeShould.cs +++ b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/AvatarShapeShould.cs @@ -2,7 +2,6 @@ using Cysharp.Threading.Tasks; using DCL.Controllers; using DCL.Emotes; -using DCL.Helpers; using DCL.Models; using DCLServices.MapRendererV2; using NSubstitute; @@ -21,6 +20,7 @@ public class AvatarShapeShould private IParcelScene scene; private AvatarShape avatarShape; private GameObject gameObject; + private IAvatarEmotesController emotesController; [SetUp] public void SetUp() @@ -29,13 +29,15 @@ public void SetUp() entity = Substitute.For(); scene = Substitute.For(); avatar = Substitute.For(); + emotesController = Substitute.For(); + avatar.GetEmotesController().Returns(emotesController); avatarReporterController = Substitute.For(); movementController = Substitute.For(); Environment.Setup(InitializeServiceLocator()); AvatarShape avatarShapePrefab = Resources.Load("NewAvatarShape"); - avatarShape = GameObject.Instantiate(avatarShapePrefab); + avatarShape = Object.Instantiate(avatarShapePrefab); avatarShape.OnPoolGet(); avatarShape.avatar = avatar; avatarShape.avatarReporterController = avatarReporterController; @@ -70,8 +72,8 @@ private async UniTask GetEmbeddedEmotesSO() [TearDown] protected void TearDown() { - GameObject.Destroy(gameObject); - GameObject.Destroy(avatarShape.gameObject); + Helpers.Utils.SafeDestroy(gameObject); + Helpers.Utils.SafeDestroy(avatarShape.gameObject); } [Test] @@ -84,11 +86,11 @@ public void ApplyModelCorrectly() avatarShape.ApplyModel(scene, entity, model); // Assert - Assert.AreEqual(entity,avatarShape.entity); + Assert.AreEqual(entity, avatarShape.entity); Assert.IsTrue(avatarShape.initializedPosition); - avatar.Received(1).PlayEmote(model.ExpressionTriggerId, model.ExpressionTriggerTimestamp); - movementController.Received(1).OnTransformChanged(Arg.Any(), Arg.Any(), Arg.Any()); + emotesController.Received(1).PlayEmote(model.ExpressionTriggerId, model.ExpressionTriggerTimestamp); + movementController.Received(1).OnTransformChanged(Arg.Any(), Arg.Any(), Arg.Any()); } [Test] @@ -101,12 +103,12 @@ public void UpdatePlayerStatusCorrectly() avatarShape.UpdatePlayerStatus(entity, model); // Assert - Assert.AreEqual(model.Id,avatarShape.player.id); - Assert.AreEqual(model.Name,avatarShape.player.name); - Assert.AreEqual(model.Talking,avatarShape.player.isTalking); - Assert.AreEqual(avatar,avatarShape.player.avatar); + Assert.AreEqual(model.Id, avatarShape.player.id); + Assert.AreEqual(model.Name, avatarShape.player.name); + Assert.AreEqual(model.Talking, avatarShape.player.isTalking); + Assert.AreEqual(avatar, avatarShape.player.avatar); Assert.AreEqual(avatarShape.avatarCollider, avatarShape.player.collider); - Assert.AreEqual(avatarShape.onPointerDown,avatarShape.player.onPointerDownCollider); + Assert.AreEqual(avatarShape.onPointerDown, avatarShape.player.onPointerDownCollider); } [Test] diff --git a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/DCL.ECSComponents.AvatarShape.Tests.asmdef b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/DCL.ECSComponents.AvatarShape.Tests.asmdef index ce6f752d10..7a5fcb7596 100644 --- a/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/DCL.ECSComponents.AvatarShape.Tests.asmdef +++ b/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AvatarShape/Tests/DCL.ECSComponents.AvatarShape.Tests.asmdef @@ -11,11 +11,9 @@ "GUID:0acc523941302664db1f4e527237feb3", "GUID:a3ceb534947fac14da25035bc5c24788", "GUID:b308ae946900fa04080222d7daf47d9a", - "GUID:bf449696eeb8a48adb5d063bf6fb0d91", "GUID:97d8897529779cb49bebd400c7f402a6", "GUID:a881b57670b1d2747a6d7f9e32b63230", "GUID:1dd0780aa6be12b428c8005d0bee46b8", - "GUID:3c42479e53c24ab098ea7aa54c818b2e", "GUID:3f9bd7dfada994a3ca114055e53e2c1f", "GUID:f8a3a0af3ed28474c885e04c605a7962", "GUID:37d2c04574c1d480d8c817e2a7c578e7", @@ -45,20 +43,19 @@ "GUID:a871c50d0a774d2b8594d36cb4766e5e", "GUID:8796c22c84974ce385f8d79b1ae08e1b" ], - "includePlatforms": [], + "includePlatforms": [ + "Editor" + ], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": true, "precompiledReferences": [ "nunit.framework.dll", "NSubstitute.dll", - "System.Threading.Tasks.Extensions.dll", "Google.Protobuf.dll" ], "autoReferenced": false, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], + "defineConstraints": [], "versionDefines": [], "noEngineReferences": false } \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations.meta b/unity-renderer/Assets/DCLPlugins/EmoteAnimations.meta deleted file mode 100644 index bd72c99906..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -<<<<<<< HEAD:unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/InputController/Resources/ToggleEmoteShortcut1.asset.meta -guid: 4c5b99b745b1fe9428ad685203b89c97 -NativeFormatImporter: -======= -guid: ddee3b1fb70a62d4eabc77062775da1b -folderAsset: yes -DefaultImporter: ->>>>>>> master:unity-renderer/Assets/Scripts/MainScripts/DCL/EmoteAnimationsPlugin.meta - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/AssemblyInfo.cs.meta b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/AssemblyInfo.cs.meta deleted file mode 100644 index d74a304cc7..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/AssemblyInfo.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2447cfc0839b4f718f0003edacfacccb -timeCreated: 1647859070 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs deleted file mode 100644 index 9eefe0bf89..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs +++ /dev/null @@ -1,25 +0,0 @@ -using DCLServices.WearablesCatalogService; - -namespace DCL.Emotes -{ - // [ADR 66 - https://github.com/decentraland/adr] - public class EmoteAnimationsPlugin : IPlugin - { - private readonly EmoteAnimationsTracker emotesAnimationTracker; - - public EmoteAnimationsPlugin() - { - var wearablesCatalogService = Environment.i.serviceLocator.Get(); - var catalyst = Environment.i.serviceLocator.Get().catalyst; - - emotesAnimationTracker = new EmoteAnimationsTracker( - DataStore.i.emotes, - new EmoteAnimationLoaderFactory(), - Environment.i.serviceLocator.Get(), - wearablesCatalogService, - catalyst); - } - - public void Dispose() { emotesAnimationTracker?.Dispose(); } - } -} diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs.meta b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs.meta deleted file mode 100644 index 3f8c5b203f..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.cs.meta +++ /dev/null @@ -1,15 +0,0 @@ -fileFormatVersion: 2 -<<<<<<< HEAD:unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentModel.cs.meta -guid: 84218ef6e26f397429e51f04aa0b5e15 -======= -guid: cce32c8e11d86e44f940734b0f3af10d ->>>>>>> master:unity-renderer/Assets/Scripts/MainScripts/DCL/EmoteAnimationsPlugin/EmoteAnimationsPlugin.cs.meta -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs deleted file mode 100644 index 57413df70c..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs +++ /dev/null @@ -1,201 +0,0 @@ -using AvatarSystem; -using Cysharp.Threading.Tasks; -using DCL.Configuration; -using DCLServices.WearablesCatalogService; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.ExceptionServices; -using System.Threading; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace DCL.Emotes -{ - public class EmoteAnimationsTracker : IDisposable - { - //To avoid circular references in assemblies we hardcode this here instead of using WearableLiterals - //Embedded Emotes are only temporary until they can be retrieved from the content server - private const string FEMALE = "urn:decentraland:off-chain:base-avatars:BaseFemale"; - private const string MALE = "urn:decentraland:off-chain:base-avatars:BaseMale"; - - internal readonly DataStore_Emotes dataStore; - internal readonly EmoteAnimationLoaderFactory emoteAnimationLoaderFactory; - private readonly IEmotesCatalogService emotesCatalogService; - private readonly IWearablesCatalogService wearablesCatalogService; - private readonly ICatalyst catalyst; - - internal Dictionary<(string bodyshapeId, string emoteId), IEmoteAnimationLoader> loaders = new (); - - private CancellationTokenSource cts = new (); - - internal GameObject animationsModelsContainer; - - public EmoteAnimationsTracker( - DataStore_Emotes dataStore, - EmoteAnimationLoaderFactory emoteAnimationLoaderFactory, - IEmotesCatalogService emotesCatalogService, - IWearablesCatalogService wearablesCatalogService, - ICatalyst catalyst) - { - animationsModelsContainer = new GameObject("_EmoteAnimationsHolder"); - animationsModelsContainer.transform.position = EnvironmentSettings.MORDOR; - this.dataStore = dataStore; - this.emoteAnimationLoaderFactory = emoteAnimationLoaderFactory; - this.emotesCatalogService = emotesCatalogService; - this.wearablesCatalogService = wearablesCatalogService; - this.dataStore.animations.Clear(); - this.catalyst = catalyst; - - AsyncInitialization(); - } - - private async UniTaskVoid AsyncInitialization() - { - EmbeddedEmotesSO embeddedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); - - foreach (EmbeddedEmote embeddedEmote in embeddedEmotes.emotes) - { - if (embeddedEmote.maleAnimation != null) - SetupEmbeddedClip(embeddedEmote, embeddedEmote.maleAnimation, MALE); - - if (embeddedEmote.femaleAnimation != null) - SetupEmbeddedClip(embeddedEmote, embeddedEmote.femaleAnimation, FEMALE); - } - - wearablesCatalogService.EmbedWearables(embeddedEmotes.emotes); - InitializeEmotes(this.dataStore.emotesOnUse.GetAllRefCounts()); - this.dataStore.emotesOnUse.OnRefCountUpdated += OnRefCountUpdated; - } - - private void SetupEmbeddedClip(EmbeddedEmote embeddedEmote, AnimationClip clip, string urn) - { - //We match the animation id with its name due to performance reasons - //Unity's Animation uses the name to play the clips. - clip.name = embeddedEmote.id; - dataStore.emotesOnUse.SetRefCount((urn, embeddedEmote.id), 5000); - var clipData = new EmoteClipData(clip, embeddedEmote.emoteDataV0?.loop ?? false); - dataStore.animations.Add((urn, embeddedEmote.id), clipData); - loaders.Add((urn, embeddedEmote.id), emoteAnimationLoaderFactory.Get()); - } - - private void OnRefCountUpdated((string bodyshapeId, string emoteId) value, int refCount) - { - if (refCount > 0) - LoadEmote(value.bodyshapeId, value.emoteId, cts.Token); - else - UnloadEmote(value.bodyshapeId, value.emoteId); - } - - private void InitializeEmotes(IEnumerable> refCounts) - { - foreach (KeyValuePair<(string bodyshapeId, string emoteId), int> keyValuePair in refCounts) { LoadEmote(keyValuePair.Key.bodyshapeId, keyValuePair.Key.emoteId, cts.Token); } - } - - private async UniTaskVoid LoadEmote(string bodyShapeId, string emoteId, CancellationToken ct) - { - ct.ThrowIfCancellationRequested(); - - if (loaders.ContainsKey((bodyShapeId, emoteId))) - return; - - try - { - loaders.Add((bodyShapeId, emoteId), null); - var emote = await RequestEmote(bodyShapeId, emoteId, ct); - - if (emote == null) - return; - - IEmoteAnimationLoader animationLoader = emoteAnimationLoaderFactory.Get(); - loaders[(bodyShapeId, emoteId)] = animationLoader; - await animationLoader.LoadEmote(animationsModelsContainer, emote, bodyShapeId, ct); - - EmoteClipData emoteClipData; - - if (emote is EmoteItem newEmoteItem) - emoteClipData = new EmoteClipData(animationLoader.loadedAnimationClip, newEmoteItem.data.loop); - else - emoteClipData = new EmoteClipData(animationLoader.loadedAnimationClip, emote.emoteDataV0?.loop ?? false); - - emoteClipData.LoadExtraContent(animationLoader.container, animationLoader.audioClip); - - dataStore.animations.Add((bodyShapeId, emoteId), emoteClipData); - - if (animationLoader.loadedAnimationClip == null) { Debug.LogError("Emote animation failed to load for emote " + emote.id); } - } - catch (Exception e) - { - loaders.Remove((bodyShapeId, emoteId)); - dataStore.animations.Remove((bodyShapeId, emoteId)); - ExceptionDispatchInfo.Capture(e).Throw(); - throw; - } - } - - private void UnloadEmote(string bodyShapeId, string emoteId) - { - dataStore.animations.Remove((bodyShapeId, emoteId)); - - if (!loaders.TryGetValue((bodyShapeId, emoteId), out IEmoteAnimationLoader loader)) - return; - - loaders.Remove((bodyShapeId, emoteId)); - loader?.Dispose(); - } - - public void Dispose() - { - dataStore.emotesOnUse.OnRefCountUpdated -= OnRefCountUpdated; - (string bodyshapeId, string emoteId)[] keys = loaders.Keys.ToArray(); - - foreach ((string bodyshapeId, string emoteId) in keys) { UnloadEmote(bodyshapeId, emoteId); } - - loaders.Clear(); - cts.Cancel(); - Object.Destroy(animationsModelsContainer); - } - - private UniTask RequestEmote(string bodyShapeId, string emoteId, CancellationToken ct) - { - if (SceneEmoteHelper.IsSceneEmote(emoteId)) - return new UniTask(GenerateSceneEmoteItem(bodyShapeId, emoteId, catalyst.contentUrl)); - - if (!emoteId.StartsWith("urn")) - return emotesCatalogService.RequestEmoteFromBuilderAsync(emoteId, ct); - - return emotesCatalogService.RequestEmoteAsync(emoteId, ct); - } - - private static WearableItem GenerateSceneEmoteItem(string bodyShapeId, string emoteId, string contentLambdaUrl) - { - if (!SceneEmoteHelper.TryGetDataFromEmoteId(emoteId, out string emoteHash, out bool loop)) { return null; } - - return new EmoteItem() - { - data = new WearableItem.Data() - { - representations = new[] - { - new WearableItem.Representation() - { - bodyShapes = new[] { bodyShapeId }, - contents = new[] - { - new WearableItem.MappingPair() - { - hash = emoteHash, key = emoteHash - } - }, - mainFile = emoteHash, - } - }, - loop = loop - }, - emoteDataV0 = new EmoteDataV0() { loop = loop }, - id = emoteId, - baseUrl = $"{contentLambdaUrl}contents/" - }; - } - } -} diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs.meta b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs.meta deleted file mode 100644 index b577df8edb..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d2f7ef313b7d427899a3ddf4227c48db -timeCreated: 1648460490 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs deleted file mode 100644 index 20b874df59..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections; -using System.Threading; -using AvatarSystem; -using Cysharp.Threading.Tasks; -using DCL.Helpers; -using DCL.Providers; -using NSubstitute; -using NSubstitute.Core.Arguments; -using NUnit.Framework; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace DCL.Emotes -{ - public class EmoteAnimationLoaderShould - { - private EmoteAnimationLoader loader; - private IWearableRetriever retriever; - private GameObject container; - - [SetUp] - public void SetUp() - { - container = new GameObject("_Container"); - retriever = Substitute.For(); - loader = new EmoteAnimationLoader(retriever); - } - - [TearDown] - public void TearDown() { Object.Destroy(container); } - - [UnityTest] - public IEnumerator ThrowIfNullContainer() => UniTask.ToCoroutine(async () => await TestUtils.ThrowsAsync(loader.LoadEmote(null, new WearableItem(), "female"))); - - [UnityTest] - public IEnumerator ThrowIfNullEmote() => UniTask.ToCoroutine(async () => await TestUtils.ThrowsAsync(loader.LoadEmote(container, null, "female"))); - - [UnityTest] - public IEnumerator ThrowIfNullBodyShape() => UniTask.ToCoroutine(async () => await TestUtils.ThrowsAsync(loader.LoadEmote(container, new WearableItem(), null))); - - [UnityTest] - public IEnumerator ThrowIfEmptyBodyShape() => UniTask.ToCoroutine(async () => await TestUtils.ThrowsAsync(loader.LoadEmote(container, new WearableItem(), ""))); - - [UnityTest] - public IEnumerator ThrowIfNoRepresentationForBodyShape() => UniTask.ToCoroutine(async () => await TestUtils.ThrowsAsync(loader.LoadEmote(container, new WearableItem { id = "emote0" }, "female"), $"No representation for female of emote: emote0")); - - [UnityTest] - public IEnumerator ThrowIfCancelledTokenProvided() => UniTask.ToCoroutine(async () => - { - CancellationTokenSource cts = new CancellationTokenSource(); - cts.Cancel(); - - await TestUtils.ThrowsAsync(loader.LoadEmote(container, new WearableItem(), "female", cts.Token)); - }); - - [UnityTest] - public IEnumerator ProvideTheRetrieverAnimation() => UniTask.ToCoroutine(async () => - { - Animation animation = container.AddComponent(); - AnimationClip clip = await new AddressableResourceProvider().GetAddressable("tik.anim"); - animation.clip = clip; - Rendereable rendereable = new Rendereable { container = container, }; - retriever.Retrieve( - Arg.Any(), - Arg.Any(), - Arg.Any(), - Arg.Any()) - .Returns(new UniTask(rendereable)); - retriever.rendereable.Returns(rendereable); - - await loader.LoadEmote(container, new WearableItem - { - id = "emote", - data = new WearableItem.Data - { - representations = new [] - { - new WearableItem.Representation - { - bodyShapes = new [] { "female" }, - contents = new [] { new WearableItem.MappingPair { key = "key", hash = "hash" } } - } - } - } - }, - "female"); - - Assert.AreEqual(clip, loader.loadedAnimationClip); - }); - } -} diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs.meta b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs.meta deleted file mode 100644 index 82a5dd8869..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationLoaderShould.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 1217321afbf94a3b8a49d4c00c0e4120 -timeCreated: 1647345829 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef deleted file mode 100644 index 5de8cc6869..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "EmoteAnimationsPluginTests", - "rootNamespace": "", - "references": [ - "GUID:b1087c5731ff68448a0a9c625bb7e52d", - "GUID:ef84d7ce90ba34f07be26ace428e9bc8", - "GUID:27619889b8ba8c24980f49ee34dbb44a", - "GUID:a1e1473c53889c2489c0822a9dd5fa33", - "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", - "GUID:f51ebe6a0ceec4240a699833d6309b23", - "GUID:8af21c3a612af2645a9953d4b9b3f6d5", - "GUID:b24824f3bc2a60641a01e2083614f802", - "GUID:59a84c943ce672c4695df742fcdd6d20", - "GUID:f070f44586498a44c9e6d2ea3e166379", - "GUID:e65144cdbd5b744238fa03c40df6cd71", - "GUID:28f74c468a54948bfa9f625c5d428f56", - "GUID:81fbd0260d07a69449fb0fc6ed29d254", - "GUID:49176a91bbf7f8a4aaf35f6df0643d1a", - "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", - "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", - "GUID:6c1761dc8f737004198eb333521bd665", - "GUID:3b80b0b562b1cbc489513f09fc1b8f69", - "GUID:a3ceb534947fac14da25035bc5c24788", - "GUID:f342ce4813b58d84586a4577257fc0b9", - "GUID:c8ea72e806cd2ab47b539b37895b86b7", - "GUID:a4bf61c057a098f4ca05b539a6d8c0fe" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": true, - "precompiledReferences": [ - "nunit.framework.dll", - "Newtonsoft.Json.dll", - "NSubstitute.dll", - "System.Threading.Tasks.Extensions.dll" - ], - "autoReferenced": false, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs deleted file mode 100644 index d481c376dd..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System.Threading; -using AvatarSystem; -using Cysharp.Threading.Tasks; -using DCLServices.WearablesCatalogService; -using NSubstitute; -using NSubstitute.Extensions; -using NUnit.Framework; -using System.Collections; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using UnityEngine.TestTools; - -namespace DCL.Emotes -{ - public class EmoteAnimationsTrackerShould - { - private EmoteAnimationsTracker tracker; - private DataStore_Emotes dataStore; - private EmoteAnimationLoaderFactory loaderFactory; - private IEmotesCatalogService emoteCatalog; - private IWearablesCatalogService wearablesCatalogService; - - [SetUp] - public void SetUp() - { - wearablesCatalogService = Substitute.For(); - dataStore = new DataStore_Emotes(); - loaderFactory = Substitute.ForPartsOf(); - loaderFactory.Get().Returns(Substitute.For()); - - emoteCatalog = Substitute.For(); - emoteCatalog.GetEmbeddedEmotes().Returns(GetEmbeddedEmotesSO()); - - tracker = new EmoteAnimationsTracker(dataStore, loaderFactory, emoteCatalog, wearablesCatalogService, Substitute.For()); - } - - private async UniTask GetEmbeddedEmotesSO() - { - EmbeddedEmotesSO embeddedEmotes = ScriptableObject.CreateInstance(); - embeddedEmotes.emotes = new EmbeddedEmote[] { }; - return embeddedEmotes; - } - - [UnityTest] - public IEnumerator InitializeEmbeddedEmotesOnConstructor() - { - UniTask.Awaiter embeddedEmotesTask = GetEmbeddedEmotesSO().GetAwaiter(); - yield return new WaitUntil(() => embeddedEmotesTask.IsCompleted); - EmbeddedEmotesSO embeddedEmotesSo = embeddedEmotesTask.GetResult(); - - foreach (EmbeddedEmote emote in embeddedEmotesSo.emotes) - { - Assert.AreEqual(dataStore.animations[(WearableLiterals.BodyShapes.FEMALE, emote.id)]?.AvatarClip, emote.femaleAnimation); - Assert.AreEqual(dataStore.animations[(WearableLiterals.BodyShapes.MALE, emote.id)]?.AvatarClip, emote.maleAnimation); - Assert.IsTrue(tracker.loaders.ContainsKey((WearableLiterals.BodyShapes.MALE, emote.id))); - } - - wearablesCatalogService.Received(1).EmbedWearables(Arg.Any()); - } - - [Test] - public void ReactToEquipEmotesIncreasingReference() - { - const string EMOTE_ID = "urn:emote0"; - AnimationClip animClip = new AnimationClip(); - EmoteItem emote = new EmoteItem() { id = EMOTE_ID, data = new WearableItem.Data() }; - emoteCatalog.RequestEmoteAsync(Arg.Any(), Arg.Any()).Returns(new UniTask(emote)); - IEmoteAnimationLoader loader = Substitute.For(); - loader.loadedAnimationClip.Returns(animClip); - loaderFactory.Get().Returns(loader); - - dataStore.emotesOnUse.IncreaseRefCount((WearableLiterals.BodyShapes.FEMALE, EMOTE_ID)); - - loaderFactory.Received(1).Get(); - emoteCatalog.Received(1).RequestEmoteAsync(EMOTE_ID, Arg.Any()); - loader.Received(1).LoadEmote(tracker.animationsModelsContainer, emote, WearableLiterals.BodyShapes.FEMALE, Arg.Any()); - var animKey = (WearableLiterals.BodyShapes.FEMALE, EMOTE_ID); - Assert.AreEqual(animClip, dataStore.animations[animKey]?.AvatarClip); - } - - [Test] - public void ReactToEquipEmotesIncreasingReferenceWithExistentLoader() - { - loaderFactory.ClearReceivedCalls(); - tracker.loaders.Add((WearableLiterals.BodyShapes.FEMALE, "emote0"), Substitute.For()); - - dataStore.emotesOnUse.IncreaseRefCount((WearableLiterals.BodyShapes.FEMALE, "emote0")); - - loaderFactory.DidNotReceive().Get(); - } - - [Test] - public void ReactToEquipEmotesReferenceSetTo0() - { - string bodyshapeId = WearableLiterals.BodyShapes.FEMALE; - - var tikAnim = AssetDatabase.LoadAssetAtPath("Assets/Scripts/MainScripts/DCL/Components/Avatar/Animations/Addressables/tik.anim"); - dataStore.animations.Add((bodyshapeId, "emote0"), new EmoteClipData(tikAnim)); - IEmoteAnimationLoader loader = Substitute.For(); - tracker.loaders.Add((bodyshapeId, "emote0"), loader); - - dataStore.emotesOnUse.SetRefCount((bodyshapeId, "emote0"), 0); - - Assert.IsFalse(tracker.loaders.ContainsKey((bodyshapeId, "emote0"))); - loader.Received().Dispose(); - Assert.IsFalse(dataStore.animations.ContainsKey((bodyshapeId, "emote0"))); - } - - [UnityTest] - public IEnumerator HandleMultipleLoadEmoteCallsGracefully() => - UniTask.ToCoroutine(async () => - { - // Arrange - const string EMOTE_ID = "urn:emote0"; - - EmoteItem emote = new EmoteItem - { id = EMOTE_ID, data = new WearableItem.Data() }; - - async UniTask GetDelayedEmoteItem() - { - await UniTask.DelayFrame(1); - return emote; - } - - AnimationClip animClip = new AnimationClip(); - emoteCatalog.RequestEmoteAsync(Arg.Any(), Arg.Any()).Returns((x) => GetDelayedEmoteItem()); - IEmoteAnimationLoader loader = Substitute.For(); - loader.loadedAnimationClip.Returns(animClip); - loaderFactory.Configure().Get().Returns(loader); - - // Act - dataStore.emotesOnUse.IncreaseRefCount((WearableLiterals.BodyShapes.FEMALE, EMOTE_ID)); - dataStore.emotesOnUse.IncreaseRefCount((WearableLiterals.BodyShapes.FEMALE, EMOTE_ID)); - await UniTask.DelayFrame(2); // Give time for GetDelayedEmoteItem to be performed. - - // Assert - loaderFactory.Received(1).Get(); - emoteCatalog.Received(1).RequestEmoteAsync(EMOTE_ID, Arg.Any()); - loader.Received(1).LoadEmote(tracker.animationsModelsContainer, emote, WearableLiterals.BodyShapes.FEMALE, Arg.Any()); - var animKey = (WearableLiterals.BodyShapes.FEMALE, EMOTE_ID); - Assert.AreEqual(animClip, dataStore.animations[animKey]?.AvatarClip); - }); - } -} diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs.meta b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs.meta deleted file mode 100644 index fd57502625..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsTrackerShould.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7bdee358e4836504189a1ccf3f2f3527 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/unity-renderer/Assets/DCLServices/EmotesService.meta b/unity-renderer/Assets/DCLServices/EmotesService.meta new file mode 100644 index 0000000000..38ae231ee2 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6e226da51ecb46149f69bf458040c172 +timeCreated: 1693233907 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Addressables.meta b/unity-renderer/Assets/DCLServices/EmotesService/Addressables.meta similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/Addressables.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Addressables.meta diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Addressables/EmbeddedEmotes.asset b/unity-renderer/Assets/DCLServices/EmotesService/Addressables/EmbeddedEmotes.asset similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/Addressables/EmbeddedEmotes.asset rename to unity-renderer/Assets/DCLServices/EmotesService/Addressables/EmbeddedEmotes.asset diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Addressables/EmbeddedEmotes.asset.meta b/unity-renderer/Assets/DCLServices/EmotesService/Addressables/EmbeddedEmotes.asset.meta similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/Addressables/EmbeddedEmotes.asset.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Addressables/EmbeddedEmotes.asset.meta diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs similarity index 92% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs rename to unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index 5976d6451c..cbdf051d6c 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -1,6 +1,6 @@ -using System; +using AvatarSystem; +using System; using System.Threading; -using AvatarSystem; using Cysharp.Threading.Tasks; using UnityEngine; @@ -9,7 +9,7 @@ namespace DCL.Emotes public class EmoteAnimationLoader : IEmoteAnimationLoader { private readonly IWearableRetriever retriever; - public AnimationClip loadedAnimationClip { get; internal set; } + public AnimationClip mainClip { get; internal set; } public GameObject container { get; private set; } public AudioClip audioClip { get; private set; } @@ -56,7 +56,7 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s } //Setting animation name equal to emote id to avoid unity animation clip duplication on Animation.AddClip() - this.loadedAnimationClip = animationClip; + this.mainClip = animationClip; animationClip.name = emote.id; } diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs.meta diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoaderFactory.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoaderFactory.cs rename to unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoaderFactory.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoaderFactory.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs.meta diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef similarity index 61% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef rename to unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef index 1902a4472b..183dc7d251 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef @@ -1,25 +1,18 @@ { - "name": "EmoteAnimationsPlugin", + "name": "EmotesService", "rootNamespace": "", "references": [ - "GUID:7fe146b43e76fe745aeaf2020feb54b7", - "GUID:28f74c468a54948bfa9f625c5d428f56", - "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", - "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", - "GUID:a1e1473c53889c2489c0822a9dd5fa33", + "GUID:0c0c18c12967b3944b844b79c47c2320", "GUID:f51ebe6a0ceec4240a699833d6309b23", - "GUID:b24824f3bc2a60641a01e2083614f802", - "GUID:8af21c3a612af2645a9953d4b9b3f6d5", - "GUID:24ec3d5b95972d44394d682772ea3db1", - "GUID:49176a91bbf7f8a4aaf35f6df0643d1a", - "GUID:cc6bfabbfe87b7949aa248893f89ce37", - "GUID:fbcc413e192ef9048811d47ab0aca0c0", - "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", "GUID:3b80b0b562b1cbc489513f09fc1b8f69", + "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", "GUID:c8ea72e806cd2ab47b539b37895b86b7", - "GUID:6c1761dc8f737004198eb333521bd665", "GUID:a4bf61c057a098f4ca05b539a6d8c0fe", - "GUID:dffbb581f2650ea4990781f603ac258a" + "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", + "GUID:cc6bfabbfe87b7949aa248893f89ce37", + "GUID:8af21c3a612af2645a9953d4b9b3f6d5", + "GUID:49176a91bbf7f8a4aaf35f6df0643d1a", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef.meta b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef.meta similarity index 76% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef.meta rename to unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef.meta index ab3bfe7dfc..f1432b7f51 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef.meta +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 81fbd0260d07a69449fb0fc6ed29d254 +guid: 687884b2e72b39a439951d6db2e2c7ee AssemblyDefinitionImporter: externalObjects: {} userData: diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs new file mode 100644 index 0000000000..7cb70565cf --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs @@ -0,0 +1,122 @@ +using AvatarAssets; +using Cysharp.Threading.Tasks; +using DCL.Configuration; +using DCLServices.WearablesCatalogService; +using System; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; +using System.Threading; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace DCL.Emotes +{ + public class EmotesService : IEmotesService + { + //To avoid circular references in assemblies we hardcode this here instead of using WearableLiterals + //Embedded Emotes are only temporary until they can be retrieved from the content server + private const string FEMALE = "urn:decentraland:off-chain:base-avatars:BaseFemale"; + private const string MALE = "urn:decentraland:off-chain:base-avatars:BaseMale"; + + private readonly EmoteAnimationLoaderFactory emoteAnimationLoaderFactory; + private readonly IEmotesCatalogService emotesCatalogService; + private readonly IWearablesCatalogService wearablesCatalogService; + private readonly ICatalyst catalyst; + private GameObject animationsModelsContainer; + + private readonly Dictionary<(string, string), IEmoteReference> embeddedEmotes = new (); + + public EmotesService( + EmoteAnimationLoaderFactory emoteAnimationLoaderFactory, + IEmotesCatalogService emotesCatalogService, + IWearablesCatalogService wearablesCatalogService, + ICatalyst catalyst) + { + this.emoteAnimationLoaderFactory = emoteAnimationLoaderFactory; + this.emotesCatalogService = emotesCatalogService; + this.wearablesCatalogService = wearablesCatalogService; + this.catalyst = catalyst; + } + + public void Initialize() + { + animationsModelsContainer = new GameObject("_EmotesAnimationContainer") + { + transform = + { + position = EnvironmentSettings.MORDOR, + }, + }; + } + + public async UniTask InitializeAsync(CancellationToken cancellationToken) + { + EmbeddedEmotesSO embeddedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); + + foreach (EmbeddedEmote embeddedEmote in embeddedEmotes.emotes) + { + if (embeddedEmote.maleAnimation != null) + SetupEmbeddedClip(embeddedEmote, embeddedEmote.maleAnimation, MALE); + + if (embeddedEmote.femaleAnimation != null) + SetupEmbeddedClip(embeddedEmote, embeddedEmote.femaleAnimation, FEMALE); + } + + wearablesCatalogService.AddEmbeddedWearablesToCatalog(embeddedEmotes.emotes); + } + + private void SetupEmbeddedClip(EmbeddedEmote embeddedEmote, AnimationClip clip, string urnPrefix) + { + clip.name = embeddedEmote.id; + var clipData = new EmoteClipData(clip, embeddedEmote.emoteDataV0?.loop ?? false); + embeddedEmotes.Add((urnPrefix, embeddedEmote.id), new EmbedEmoteReference(embeddedEmote, clipData)); + } + + public async UniTask RequestEmote(string bodyShapeId, string emoteId, CancellationToken cancellationToken = default) + { + if (embeddedEmotes.ContainsKey((bodyShapeId, emoteId))) + return embeddedEmotes[(bodyShapeId, emoteId)]; + + try + { + var emote = await FetchEmote(bodyShapeId, emoteId, cancellationToken); + + if (emote == null) + { + Debug.LogError($"Unexpected null emote when requesting {bodyShapeId} {emoteId}"); + return null; + } + + IEmoteAnimationLoader animationLoader = emoteAnimationLoaderFactory.Get(); + await animationLoader.LoadEmote(animationsModelsContainer, emote, bodyShapeId, cancellationToken); + + if (animationLoader.mainClip == null) + Debug.LogError("Emote animation failed to load for emote " + emote.id); + + bool loop = emote is EmoteItem newEmoteItem ? newEmoteItem.data.loop : emote.emoteDataV0?.loop ?? false; + IEmoteReference emoteReference = new NftEmoteReference(emote, animationLoader, loop); + return emoteReference; + } + catch (Exception e) + { + ExceptionDispatchInfo.Capture(e).Throw(); + throw; + } + } + + private UniTask FetchEmote(string bodyShapeId, string emoteId, CancellationToken ct) + { + if (!SceneEmoteHelper.IsSceneEmote(emoteId)) + return emotesCatalogService.RequestEmoteAsync(emoteId, ct); + + WearableItem emoteItem = SceneEmoteHelper.TryGetDataFromEmoteId(emoteId, out string emoteHash, out bool loop) ? new EmoteItem(bodyShapeId, emoteId, emoteHash, catalyst.contentUrl, loop) : null; + + return new UniTask(emoteItem); + } + + public void Dispose() + { + Object.Destroy(animationsModelsContainer); + } + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs.meta new file mode 100644 index 0000000000..10bccffc3b --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6cdb84bcbac84808aabf1eeb42223369 +timeCreated: 1693233916 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces.meta b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces.meta new file mode 100644 index 0000000000..5de69e56bc --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d061cdb2071249ffb491eab63c1d7fa7 +timeCreated: 1693241917 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs new file mode 100644 index 0000000000..adc08e5538 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs @@ -0,0 +1,27 @@ +using System; + +namespace DCL.Emotes +{ + public class EmbedEmoteReference : IEmoteReference + { + private readonly WearableItem emoteItem; + private readonly EmoteClipData clipData; + + public EmbedEmoteReference(WearableItem emoteItem, EmoteClipData clipData) + { + this.emoteItem = emoteItem; + this.clipData = clipData; + } + + public WearableItem GetEntity() => + emoteItem; + + public EmoteClipData GetData() => + clipData; + + public void Dispose() + { + + } + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs.meta new file mode 100644 index 0000000000..4a27cc2b4d --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bca4973385bb42c7b3529598f5e3aff7 +timeCreated: 1693235003 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef new file mode 100644 index 0000000000..4b2b4ba166 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef @@ -0,0 +1,18 @@ +{ + "name": "EmotesServiceDefinitions", + "rootNamespace": "", + "references": [ + "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", + "GUID:3b80b0b562b1cbc489513f09fc1b8f69", + "GUID:f51ebe6a0ceec4240a699833d6309b23" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef.meta b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef.meta similarity index 76% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef.meta index b64fa3ecf4..a10d65aa3d 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef.meta +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c6c6ea0310ce27d4bb0af5d6dc0205d1 +guid: 0c0c18c12967b3944b844b79c47c2320 AssemblyDefinitionImporter: externalObjects: {} userData: diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs similarity index 88% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs rename to unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs index 8326283085..6331ee6e2d 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs @@ -7,7 +7,7 @@ namespace DCL.Emotes { public interface IEmoteAnimationLoader : IDisposable { - AnimationClip loadedAnimationClip { get; } + AnimationClip mainClip { get; } GameObject container { get; } AudioClip audioClip { get; } UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default); diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs new file mode 100644 index 0000000000..dd1c46f28c --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs @@ -0,0 +1,10 @@ +using System; + +namespace DCL.Emotes +{ + public interface IEmoteReference : IDisposable + { + WearableItem GetEntity(); + EmoteClipData GetData(); + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs.meta new file mode 100644 index 0000000000..ee3167b5a3 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7270d7888ef4409aa8caca7559e9ee88 +timeCreated: 1693234668 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs new file mode 100644 index 0000000000..66df709240 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs @@ -0,0 +1,10 @@ +using Cysharp.Threading.Tasks; +using System.Threading; + +namespace DCL.Emotes +{ + public interface IEmotesService : IService + { + UniTask RequestEmote(string bodyShapeId, string emoteId, CancellationToken cancellationToken); + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs.meta new file mode 100644 index 0000000000..29da9ed18f --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bbde70bc520847e3b30c46b84b757217 +timeCreated: 1693234066 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs new file mode 100644 index 0000000000..5ac38e7621 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs @@ -0,0 +1,27 @@ +namespace DCL.Emotes +{ + public class NftEmoteReference : IEmoteReference + { + private readonly WearableItem emoteItem; + private readonly IEmoteAnimationLoader loader; + private readonly EmoteClipData emoteClipData; + + public NftEmoteReference(WearableItem emoteItem, IEmoteAnimationLoader loader, bool loop) + { + this.emoteItem = emoteItem; + this.loader = loader; + emoteClipData = new EmoteClipData(loader.mainClip, loader.container, loader.audioClip, loop); + } + + public WearableItem GetEntity() => + emoteItem; + + public EmoteClipData GetData() => + emoteClipData; + + public void Dispose() + { + loader.Dispose(); + } + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs.meta new file mode 100644 index 0000000000..5f13b88d18 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f667fa1c2f15436aa8c91e87eac75d81 +timeCreated: 1693240259 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/WearablesCatalogService/IWearablesCatalogService.cs b/unity-renderer/Assets/DCLServices/WearablesCatalogService/IWearablesCatalogService.cs index f28d7281c1..38fd46916e 100644 --- a/unity-renderer/Assets/DCLServices/WearablesCatalogService/IWearablesCatalogService.cs +++ b/unity-renderer/Assets/DCLServices/WearablesCatalogService/IWearablesCatalogService.cs @@ -33,7 +33,7 @@ public interface IWearablesCatalogService : IService void RemoveWearableFromCatalog(string wearableId); void RemoveWearablesInUse(IEnumerable wearablesInUseToRemove); [Obsolete("Will be removed in the future, when emotes are in the content server.")] - void EmbedWearables(IEnumerable wearables); + void AddEmbeddedWearablesToCatalog(IEnumerable wearables); void Clear(); bool IsValidWearable(string wearableId); } diff --git a/unity-renderer/Assets/DCLServices/WearablesCatalogService/LambdasWearablesCatalogService.cs b/unity-renderer/Assets/DCLServices/WearablesCatalogService/LambdasWearablesCatalogService.cs index 27aef8cedc..966f9a0972 100644 --- a/unity-renderer/Assets/DCLServices/WearablesCatalogService/LambdasWearablesCatalogService.cs +++ b/unity-renderer/Assets/DCLServices/WearablesCatalogService/LambdasWearablesCatalogService.cs @@ -435,7 +435,7 @@ public void RemoveWearablesInUse(IEnumerable wearablesInUseToRemove) } } - public void EmbedWearables(IEnumerable wearables) + public void AddEmbeddedWearablesToCatalog(IEnumerable wearables) { foreach (WearableItem wearableItem in wearables) { diff --git a/unity-renderer/Assets/DCLServices/WearablesCatalogService/Tests/LambdasWearablesCatalogServiceShould.cs b/unity-renderer/Assets/DCLServices/WearablesCatalogService/Tests/LambdasWearablesCatalogServiceShould.cs index 96da5e7e42..ba9e8b1040 100644 --- a/unity-renderer/Assets/DCLServices/WearablesCatalogService/Tests/LambdasWearablesCatalogServiceShould.cs +++ b/unity-renderer/Assets/DCLServices/WearablesCatalogService/Tests/LambdasWearablesCatalogServiceShould.cs @@ -398,7 +398,7 @@ public void RemoveWearables() [Test] public void RemoveWearablesInUse() { - service.EmbedWearables(new[] { GivenValidWearableItem(VALID_WEARABLE_ID, "baseurl/thumbnail") }); + service.AddEmbeddedWearablesToCatalog(new[] { GivenValidWearableItem(VALID_WEARABLE_ID, "baseurl/thumbnail") }); service.AddWearablesToCatalog(new[] { GivenValidWearableItem(WEARABLE_WITHOUT_THUMBNAIL, null) }); service.RemoveWearablesInUse(new[] { VALID_WEARABLE_ID, WEARABLE_WITHOUT_THUMBNAIL }); diff --git a/unity-renderer/Assets/DCLServices/WearablesCatalogService/WearablesCatalogServiceProxy.cs b/unity-renderer/Assets/DCLServices/WearablesCatalogService/WearablesCatalogServiceProxy.cs index 837be001ee..acc61b1db4 100644 --- a/unity-renderer/Assets/DCLServices/WearablesCatalogService/WearablesCatalogServiceProxy.cs +++ b/unity-renderer/Assets/DCLServices/WearablesCatalogService/WearablesCatalogServiceProxy.cs @@ -145,8 +145,8 @@ public void RemoveWearableFromCatalog(string wearableId) => public void RemoveWearablesInUse(IEnumerable wearablesInUseToRemove) => wearablesCatalogServiceInUse?.RemoveWearablesInUse(wearablesInUseToRemove); - public void EmbedWearables(IEnumerable wearables) => - wearablesCatalogServiceInUse?.EmbedWearables(wearables); + public void AddEmbeddedWearablesToCatalog(IEnumerable wearables) => + wearablesCatalogServiceInUse?.AddEmbeddedWearablesToCatalog(wearables); public void Clear() => wearablesCatalogServiceInUse?.Clear(); diff --git a/unity-renderer/Assets/DCLServices/WearablesCatalogService/WebInterfaceWearablesCatalogService.cs b/unity-renderer/Assets/DCLServices/WearablesCatalogService/WebInterfaceWearablesCatalogService.cs index 3e351d4da3..e86f7b51a9 100644 --- a/unity-renderer/Assets/DCLServices/WearablesCatalogService/WebInterfaceWearablesCatalogService.cs +++ b/unity-renderer/Assets/DCLServices/WearablesCatalogService/WebInterfaceWearablesCatalogService.cs @@ -255,7 +255,7 @@ public void RemoveWearablesInUse(IEnumerable wearablesInUseToRemove) } } - public void EmbedWearables(IEnumerable wearables) + public void AddEmbeddedWearablesToCatalog(IEnumerable wearables) { foreach (WearableItem wearableItem in wearables) { diff --git a/unity-renderer/Assets/Rendering/Utils/GPUSkinning/Tests/GPUSkinningTests.asmdef b/unity-renderer/Assets/Rendering/Utils/GPUSkinning/Tests/GPUSkinningTests.asmdef index cfaec6591a..d1f9aa92d6 100644 --- a/unity-renderer/Assets/Rendering/Utils/GPUSkinning/Tests/GPUSkinningTests.asmdef +++ b/unity-renderer/Assets/Rendering/Utils/GPUSkinning/Tests/GPUSkinningTests.asmdef @@ -22,7 +22,8 @@ "GUID:a3ceb534947fac14da25035bc5c24788", "GUID:c8ea72e806cd2ab47b539b37895b86b7", "GUID:3b80b0b562b1cbc489513f09fc1b8f69", - "GUID:68069f49d86442cd9618861b4d74b1aa" + "GUID:68069f49d86442cd9618861b4d74b1aa", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Avatar.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Avatar.cs index 1b6c33d229..7f8b563b85 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Avatar.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Avatar.cs @@ -27,10 +27,9 @@ public class Avatar : IAvatar private readonly ILOD lod; private readonly IGPUSkinning gpuSkinning; private readonly IGPUSkinningThrottlerService gpuSkinningThrottlerService; - private readonly IEmoteAnimationEquipper emoteAnimationEquipper; + private readonly IAvatarEmotesController emotesController; private CancellationTokenSource loadCancellationToken; - public IAvatar.Status status { get; private set; } = IAvatar.Status.Idle; public Vector3 extents { get; private set; } public int lodLevel => lod?.lodIndex ?? 0; @@ -39,7 +38,7 @@ public class Avatar : IAvatar internal Avatar(IAvatarCurator avatarCurator, ILoader loader, IAnimator animator, IVisibility visibility, ILOD lod, IGPUSkinning gpuSkinning, IGPUSkinningThrottlerService gpuSkinningThrottlerService, - IEmoteAnimationEquipper emoteAnimationEquipper) + IAvatarEmotesController emotesController) { this.avatarCurator = avatarCurator; this.loader = loader; @@ -48,7 +47,7 @@ internal Avatar(IAvatarCurator avatarCurator, ILoader loader, IAnimator animator this.lod = lod; this.gpuSkinning = gpuSkinning; this.gpuSkinningThrottlerService = gpuSkinningThrottlerService; - this.emoteAnimationEquipper = emoteAnimationEquipper; + this.emotesController = emotesController; } /// @@ -64,10 +63,7 @@ public async UniTask Load(List wearablesIds, List emotesIds, Ava loadCancellationToken = loadCancellationToken.SafeRestart(); CancellationToken linkedCt = CancellationTokenSource.CreateLinkedTokenSource(ct, loadCancellationToken.Token).Token; - try - { - await LoadTry(wearablesIds, emotesIds, settings, linkedCt); - } + try { await LoadTry(wearablesIds, emotesIds, settings, linkedCt); } catch (OperationCanceledException) { // Cancel any ongoing process except the current loadCancellationToken @@ -86,6 +82,7 @@ public async UniTask Load(List wearablesIds, List emotesIds, Ava Debug.Log($"Avatar.Load failed with wearables:[{string.Join(",", wearablesIds)}] " + $"for bodyshape:{settings.bodyshapeId} and player {settings.playerName}"); + if (e.InnerException != null) ExceptionDispatchInfo.Capture(e.InnerException).Throw(); else @@ -150,7 +147,7 @@ protected void Prepare(AvatarSettings settings, List emotes, GameO //Scale the bounds due to the giant avatar not being skinned yet extents = loader.combinedRenderer.localBounds.extents * 2f / RESCALING_BOUNDS_FACTOR; - emoteAnimationEquipper.SetEquippedEmotes(settings.bodyshapeId, emotes); + emotesController.LoadEmotes(settings.bodyshapeId, emotes); gpuSkinning.Prepare(loader.combinedRenderer); gpuSkinningThrottlerService.Register(gpuSkinning); } @@ -176,14 +173,7 @@ public virtual void AddVisibilityConstraint(string key) public void RemoveVisibilityConstrain(string key) => visibility.RemoveGlobalConstrain(key); - public void PlayEmote(string emoteId, long timestamps) => - animator?.PlayEmote(emoteId, timestamps); - - public void EquipEmote(string emoteId, EmoteClipData emoteClipData) => - animator?.EquipEmote(emoteId, emoteClipData); - - public void UnequipEmote(string emoteId) => - animator?.UnequipEmote(emoteId); + public IAvatarEmotesController GetEmotesController() => emotesController; public void SetLODLevel(int lodIndex) => lod.SetLodIndex(lodIndex); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs new file mode 100644 index 0000000000..8f4a11a390 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -0,0 +1,114 @@ +using Cysharp.Threading.Tasks; +using System.Collections.Generic; +using DCL.Emotes; +using DCL.Tasks; +using System; +using System.Threading; +using UnityEngine; + +namespace AvatarSystem +{ + public class AvatarEmotesController : IAvatarEmotesController + { + public event Action OnEmoteEquipped; + public event Action OnEmoteUnequipped; + + + private string bodyShapeId = ""; + private readonly IAnimator animator; + private readonly IEmotesService emotesService; + private readonly Dictionary<(string, string), IEmoteReference> emotes = new (); + private readonly CancellationTokenSource cts = new (); + + public AvatarEmotesController(IAnimator animator, IEmotesService emotesService) + { + this.animator = animator; + this.emotesService = emotesService; + } + + public bool TryGetEquippedEmote(string bodyShape, string emoteId, out IEmoteReference emoteReference) => + emotes.TryGetValue((bodyShape, emoteId), out emoteReference); + + // ReSharper disable once PossibleMultipleEnumeration (its intended) + public void LoadEmotes(string bodyShapeId, IEnumerable newEmotes) + { + this.bodyShapeId = bodyShapeId; + + foreach (WearableItem emote in newEmotes) + LoadEmote(bodyShapeId, emote); + } + + private void LoadEmote(string bodyShapeId, WearableItem emote) + { + (string bodyShapeId, string id) emoteKey = (bodyShapeId, emote.id); + if (emotes.ContainsKey(emoteKey)) return; + emotes.Add(emoteKey, null); + AsyncEmoteLoad(bodyShapeId, emote.id).Forget(); + } + + private async UniTask AsyncEmoteLoad(string bodyShapeId, string emoteId) + { + (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); + + try + { + IEmoteReference emoteReference = await emotesService.RequestEmote(bodyShapeId, emoteId, cts.Token); + animator.EquipEmote(emoteId, emoteReference.GetData()); + emotes[emoteKey] = emoteReference; + OnEmoteEquipped?.Invoke(emoteId, emoteReference); + } + catch (OperationCanceledException) { } + catch (Exception e) + { + Debug.LogException(e); + } + } + + public void PlayEmote(string emoteId, long timestamps) + { + if (string.IsNullOrEmpty(emoteId)) return; + + (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); + + if (emotes.ContainsKey(emoteKey)) + animator.PlayEmote(emoteId, timestamps); + } + + public void EquipEmote(string emoteId, IEmoteReference emoteReference) + { + if (emotes.ContainsKey((bodyShapeId, emoteId))) + { + // we avoid dangling references in case an emote was loaded twice + emoteReference.Dispose(); + return; + } + + emotes.Add((bodyShapeId, emoteId), emoteReference); + animator.EquipEmote(emoteId, emoteReference.GetData()); + OnEmoteEquipped?.Invoke(emoteId, emoteReference); + } + + public void UnEquipEmote(string emoteId) + { + (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); + + if (emotes.ContainsKey(emoteKey)) + { + animator.UnequipEmote(emoteId); + emotes[emoteKey].Dispose(); + emotes.Remove(emoteKey); + } + } + + + public void Dispose() + { + cts.SafeCancelAndDispose(); + + foreach (var kvp in emotes) + kvp.Value.Dispose(); + + emotes.Clear(); + } + } +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/EmoteAnimationEquipper.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs.meta similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/EmoteAnimationEquipper.cs.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs.meta diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarFactory.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarFactory.cs index d9effe7621..48b5dc71ca 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarFactory.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarFactory.cs @@ -1,4 +1,5 @@ using DCL; +using DCL.Emotes; using DCLServices.WearablesCatalogService; using GPUSkinning; using UnityEngine; @@ -23,7 +24,7 @@ public IAvatar CreateAvatar(GameObject avatarContainer, IAnimator animator, ILOD lod, new SimpleGPUSkinning(), serviceLocator.Get(), - new EmoteAnimationEquipper(animator, DataStore.i.emotes) + new AvatarEmotesController(animator, serviceLocator.Get()) ); public IAvatar CreateAvatarWithHologram( @@ -42,7 +43,7 @@ IVisibility visibility lod, new SimpleGPUSkinning(), serviceLocator.Get(), - new EmoteAnimationEquipper(animator, DataStore.i.emotes) + new AvatarEmotesController(animator, serviceLocator.Get()) ); private Loader CreateLoader(GameObject avatarContainer) => diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef index 8f39887a13..dc2a39cd19 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef @@ -10,10 +10,8 @@ "GUID:28f74c468a54948bfa9f625c5d428f56", "GUID:2995626b54c60644988f134a69a77450", "GUID:b24824f3bc2a60641a01e2083614f802", - "GUID:2fe41b558b0755a499a0dae91e369bc7", "GUID:8af21c3a612af2645a9953d4b9b3f6d5", "GUID:1de3566cccb280f4a982c59ad0d08c96", - "GUID:a1e1473c53889c2489c0822a9dd5fa33", "GUID:43315b150e1df4592868fc0fe58b3429", "GUID:e99faafecbf8dd74d8130597511b9b27", "GUID:59a84c943ce672c4695df742fcdd6d20", @@ -23,7 +21,6 @@ "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", "GUID:f070f44586498a44c9e6d2ea3e166379", "GUID:4720e174f2805c74bb7aa94cc8bb5bf8", - "GUID:188b4f4962395428c9eaf195f971521d", "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", "GUID:3b80b0b562b1cbc489513f09fc1b8f69", "GUID:fbcc413e192ef9048811d47ab0aca0c0", @@ -35,7 +32,9 @@ "GUID:26861d1714ac819459758e0b653efd06", "GUID:97d8897529779cb49bebd400c7f402a6", "GUID:a881b57670b1d2747a6d7f9e32b63230", - "GUID:4d3366a36e77f41cfb7436340334e236" + "GUID:4d3366a36e77f41cfb7436340334e236", + "GUID:0c0c18c12967b3944b844b79c47c2320", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarWithHologram.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarWithHologram.cs index ff7c62cc95..d861aff4f5 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarWithHologram.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarWithHologram.cs @@ -14,8 +14,8 @@ public class AvatarWithHologram : Avatar private readonly IBaseAvatar baseAvatar; internal AvatarWithHologram(IBaseAvatar baseAvatar, IAvatarCurator avatarCurator, ILoader loader, IAnimator animator, IVisibility visibility, - ILOD lod, IGPUSkinning gpuSkinning, IGPUSkinningThrottlerService gpuSkinningThrottlerService, IEmoteAnimationEquipper emoteAnimationEquipper) - : base(avatarCurator, loader, animator, visibility, lod, gpuSkinning, gpuSkinningThrottlerService, emoteAnimationEquipper) + ILOD lod, IGPUSkinning gpuSkinning, IGPUSkinningThrottlerService gpuSkinningThrottlerService, IAvatarEmotesController emotesController) + : base(avatarCurator, loader, animator, visibility, lod, gpuSkinning, gpuSkinningThrottlerService, emotesController) { this.baseAvatar = baseAvatar; } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/AvatarSystemDefinitions.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/AvatarSystemDefinitions.asmdef index a7beaa9d32..c6fe96acae 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/AvatarSystemDefinitions.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/AvatarSystemDefinitions.asmdef @@ -5,7 +5,8 @@ "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", "GUID:8af21c3a612af2645a9953d4b9b3f6d5", "GUID:f51ebe6a0ceec4240a699833d6309b23", - "GUID:b24824f3bc2a60641a01e2083614f802" + "GUID:b24824f3bc2a60641a01e2083614f802", + "GUID:0c0c18c12967b3944b844b79c47c2320" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs index 350a0ae37e..e7b3acd1ed 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs @@ -1,4 +1,3 @@ -using DCL; using DCL.Emotes; using UnityEngine; @@ -11,4 +10,4 @@ public interface IAnimator void EquipEmote(string emoteId, EmoteClipData emoteClipData); void UnequipEmote(string emoteId); } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatar.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatar.cs index cf169abc8e..a0d3d28bbe 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatar.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatar.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading; using Cysharp.Threading.Tasks; -using DCL.Emotes; using UnityEngine; namespace AvatarSystem @@ -22,9 +21,7 @@ public enum Status UniTask Load(List wearablesIds, List emotesIds, AvatarSettings settings, CancellationToken ct = default); void AddVisibilityConstraint(string key); void RemoveVisibilityConstrain(string key); - void PlayEmote(string emoteId, long timestamps); - void EquipEmote(string emoteId, EmoteClipData emoteClipData); - void UnequipEmote(string emoteId); + IAvatarEmotesController GetEmotesController(); void SetLODLevel(int lodIndex); void SetAnimationThrottling(int framesBetweenUpdate); void SetImpostorTexture(Texture2D impostorTexture); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs new file mode 100644 index 0000000000..728d1bf673 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs @@ -0,0 +1,22 @@ +using DCL.Emotes; +using System; +using System.Collections.Generic; + +namespace AvatarSystem +{ + public interface IAvatarEmotesController : IDisposable + { + void LoadEmotes(string bodyShapeId, IEnumerable emotes); + + void PlayEmote(string emoteId, long timestamps); + + void EquipEmote(string emoteId, IEmoteReference emoteReference); + + void UnEquipEmote(string emoteId); + + event Action OnEmoteEquipped; + event Action OnEmoteUnequipped; + + bool TryGetEquippedEmote(string bodyShape, string emoteId, out IEmoteReference emoteReference); + } +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IEmoteAnimationEquipper.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs.meta similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IEmoteAnimationEquipper.cs.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs.meta diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IEmoteAnimationEquipper.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IEmoteAnimationEquipper.cs deleted file mode 100644 index 51d83965b4..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IEmoteAnimationEquipper.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace AvatarSystem -{ - public interface IEmoteAnimationEquipper : IDisposable - { - void SetEquippedEmotes( string bodyShapeId, IEnumerable emotes); - } -} \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/EmoteAnimationEquipper.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/EmoteAnimationEquipper.cs deleted file mode 100644 index cfae074f71..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/EmoteAnimationEquipper.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using DCL; -using DCL.Emotes; -using UnityEngine; - -namespace AvatarSystem -{ - public class EmoteAnimationEquipper : IEmoteAnimationEquipper - { - internal readonly IAnimator animator; - internal readonly DataStore_Emotes dataStoreEmotes; - - internal string bodyShapeId = ""; - internal readonly List emotes = new List(); - - public EmoteAnimationEquipper(IAnimator animator, DataStore_Emotes dataStoreEmotes) - { - this.animator = animator; - this.dataStoreEmotes = dataStoreEmotes; - this.dataStoreEmotes.animations.OnAdded += OnAnimationAdded; - this.dataStoreEmotes.animations.OnRemoved += OnAnimationRemoved; - } - - private void OnAnimationAdded((string bodyshapeId, string emoteId) values, EmoteClipData emoteClipData) - { - if (bodyShapeId != values.bodyshapeId) - return; - - if (!emotes.Contains(values.emoteId)) - return; - animator.EquipEmote(values.emoteId, emoteClipData); - } - - private void OnAnimationRemoved((string bodyshapeId, string emoteId) values, EmoteClipData emoteClipData) - { - if (bodyShapeId != values.bodyshapeId) - return; - - animator.UnequipEmote(values.emoteId); - } - - public void SetEquippedEmotes(string bodyShapeId, IEnumerable newEmotes) - { - this.bodyShapeId = bodyShapeId; - foreach (WearableItem emote in newEmotes) - { - dataStoreEmotes.emotesOnUse.IncreaseRefCount((bodyShapeId, emote.id)); - - //If the clip is not ready by the time we equip it - //we will receive it once its added to the collection in the DataStore - if (dataStoreEmotes.animations.TryGetValue((this.bodyShapeId, emote.id), - out EmoteClipData emoteClipData)) - animator.EquipEmote(emote.id, emoteClipData); - } - - foreach (string emoteId in this.emotes) - { - dataStoreEmotes.emotesOnUse.DecreaseRefCount((this.bodyShapeId, emoteId)); - } - this.emotes.Clear(); - this.emotes.AddRange(newEmotes.Select(e => e.id)); - } - - public void Dispose() - { - dataStoreEmotes.animations.OnAdded -= OnAnimationAdded; - dataStoreEmotes.animations.OnRemoved -= OnAnimationRemoved; - foreach (string emoteId in this.emotes) - { - dataStoreEmotes.emotesOnUse.DecreaseRefCount((bodyShapeId, emoteId)); - } - emotes.Clear(); - } - } -} \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/AssemblyInfo.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AssemblyInfo.cs similarity index 57% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/AssemblyInfo.cs rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AssemblyInfo.cs index d50a7686f9..1d1de9ca4d 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/AssemblyInfo.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AssemblyInfo.cs @@ -1,4 +1,4 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("EmoteAnimationsPluginTests")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] //Needed for nsubstitute \ No newline at end of file +[assembly: InternalsVisibleTo("AvatarSystemTests")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] //Needed for nsubstitute diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AssemblyInfo.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AssemblyInfo.cs.meta new file mode 100644 index 0000000000..0cc1488861 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AssemblyInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d47c6de8fb8a47fc8556a049d02db8db +timeCreated: 1693328276 \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef new file mode 100644 index 0000000000..791a7ea713 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef @@ -0,0 +1,34 @@ +{ + "name": "AvatarSystemLoaders", + "rootNamespace": "", + "references": [ + "GUID:49176a91bbf7f8a4aaf35f6df0643d1a", + "GUID:8af21c3a612af2645a9953d4b9b3f6d5", + "GUID:50ec9ad5165784219ba1b15ab4e77d65", + "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", + "GUID:a3ceb534947fac14da25035bc5c24788", + "GUID:f51ebe6a0ceec4240a699833d6309b23", + "GUID:28f74c468a54948bfa9f625c5d428f56", + "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", + "GUID:08b2edf8f14cdd3408988fd7746b749c", + "GUID:c8ea72e806cd2ab47b539b37895b86b7", + "GUID:e99faafecbf8dd74d8130597511b9b27", + "GUID:b24824f3bc2a60641a01e2083614f802", + "GUID:bab23c9e6b4c4da469d4688d16c1ee9b", + "GUID:26861d1714ac819459758e0b653efd06", + "GUID:59a84c943ce672c4695df742fcdd6d20", + "GUID:fbcc413e192ef9048811d47ab0aca0c0", + "GUID:b1087c5731ff68448a0a9c625bb7e52d", + "GUID:2995626b54c60644988f134a69a77450", + "GUID:3b80b0b562b1cbc489513f09fc1b8f69" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef.meta similarity index 57% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef.meta index 1ec06465b9..6d32b93b7b 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests.meta +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemLoaders.asmdef.meta @@ -1,7 +1,6 @@ fileFormatVersion: 2 -guid: 4f6ab5f9e4fa4b04c86d8a12843a9ced -folderAsset: yes -DefaultImporter: +guid: 2d39cc535b437e749965d4a8258f0c13 +AssemblyDefinitionImporter: externalObjects: {} userData: assetBundleName: diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystemUtils.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemUtils.cs similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystemUtils.cs rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemUtils.cs diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystemUtils.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemUtils.cs.meta similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystemUtils.cs.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/AvatarSystemUtils.cs.meta diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/BodyShapeLoader.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/BodyShapeLoader.cs index f8cc40a9ef..1e9baaf009 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/BodyShapeLoader.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/BodyShapeLoader.cs @@ -1,12 +1,11 @@ +using Cysharp.Threading.Tasks; using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using Cysharp.Threading.Tasks; using DCL; -using DCL.Helpers; -using UnityEngine; using DCL.Shaders; +using UnityEngine; using Object = UnityEngine.Object; namespace AvatarSystem diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/Loader.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/Loader.cs index 0650a48749..b8aed7dee1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/Loader.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/Loader.cs @@ -13,8 +13,8 @@ public class Loader : ILoader { public GameObject bodyshapeContainer => bodyshapeLoader?.rendereable?.container; public SkinnedMeshRenderer combinedRenderer { get; private set; } - public IReadOnlyList originalVisibleRenderers => originalVisibleRenderersValue; - public List originalVisibleRenderersValue { get; private set; } = new List(); + public IReadOnlyList originalVisibleRenderers => originalVisibleRenderersValue; + public List originalVisibleRenderersValue { get; private set; } = new (); public List facialFeaturesRenderers { get; private set; } public ILoader.Status status { get; private set; } = ILoader.Status.Idle; @@ -22,7 +22,7 @@ public class Loader : ILoader private readonly GameObject container; internal IBodyshapeLoader bodyshapeLoader; - internal readonly Dictionary loaders = new Dictionary(); + internal readonly Dictionary loaders = new (); private readonly IAvatarMeshCombinerHelper avatarMeshCombiner; public Loader(IWearableLoaderFactory wearableLoaderFactory, GameObject container, IAvatarMeshCombinerHelper avatarMeshCombiner) @@ -40,27 +40,23 @@ public async UniTask Load(BodyWearables bodyWearables, List wearab cancellationToken.ThrowIfCancellationRequested(); List toCleanUp = new List(); + try { status = ILoader.Status.Loading; await LoadBodyshape(settings, bodyWearables, toCleanUp, cancellationToken); await LoadWearables(wearables, settings, toCleanUp, cancellationToken); SkinnedMeshRenderer skinnedContainer = bonesContainer == null ? bodyshapeLoader.upperBodyRenderer : bonesContainer; + // Update Status accordingly status = ComposeStatus(loaders); + if (status == ILoader.Status.Failed_Major) throw new Exception($"Couldnt load (nor fallback) wearables with required category: {string.Join(", ", ConstructRequiredFailedWearablesList(loaders.Values))}"); + foreach (IWearableLoader wearableLoader in loaders.Values) { wearableLoader.SetBones(skinnedContainer.rootBone, skinnedContainer.bones); } - foreach (IWearableLoader wearableLoader in loaders.Values) - { - wearableLoader.SetBones(skinnedContainer.rootBone, skinnedContainer.bones); - } - - if (bodyshapeLoader.rendereable != null) - { - bodyshapeLoader.SetBones(skinnedContainer.rootBone, skinnedContainer.bones); - } + if (bodyshapeLoader.rendereable != null) { bodyshapeLoader.SetBones(skinnedContainer.rootBone, skinnedContainer.bones); } var activeBodyParts = AvatarSystemUtils.GetActiveBodyPartsRenderers(bodyshapeLoader, settings.bodyshapeId, wearables); originalVisibleRenderersValue = activeBodyParts.Union(loaders.Values.SelectMany(x => x.rendereable.renderers.OfType())).ToList(); @@ -74,11 +70,13 @@ public async UniTask Load(BodyWearables bodyWearables, List wearab facialFeaturesRenderers.Add(bodyshapeLoader.eyesRenderer); originalVisibleRenderersValue.Add(bodyshapeLoader.eyesRenderer); } + if (bodyWearables.Eyebrows != null) { facialFeaturesRenderers.Add(bodyshapeLoader.eyebrowsRenderer); originalVisibleRenderersValue.Add(bodyshapeLoader.eyebrowsRenderer); } + if (bodyWearables.Mouth != null) { facialFeaturesRenderers.Add(bodyshapeLoader.mouthRenderer); @@ -87,7 +85,7 @@ public async UniTask Load(BodyWearables bodyWearables, List wearab } else { - if(bodyshapeLoader != null) + if (bodyshapeLoader != null) bodyshapeLoader.DisableFacialRenderers(); } } @@ -108,6 +106,7 @@ public async UniTask Load(BodyWearables bodyWearables, List wearab { if (toCleanUp[i] == null) continue; + toCleanUp[i].Dispose(); } } @@ -143,6 +142,7 @@ private async UniTask LoadWearables(List wearables, AvatarSettings (List notReusableLoaders, List newLoaders) = GetNewLoaders(wearables, loaders, wearableLoaderFactory); loadersToCleanUp.AddRange(notReusableLoaders); loaders.Clear(); + for (int i = 0; i < newLoaders.Count; i++) { IWearableLoader loader = newLoaders[i]; @@ -172,6 +172,7 @@ internal static (List notReusableLoaders, List continue; } } + newLoaders.Add(wearableLoaderFactory.GetWearableLoader(wearable)); } @@ -194,11 +195,13 @@ private async UniTask MergeAvatar(List avatarMeshCombiner.useCullOpaqueHeuristic = true; avatarMeshCombiner.enableCombinedMesh = false; bool success = avatarMeshCombiner.Combine(bonesContainer, renderers); + if (!success) { status = ILoader.Status.Failed_Major; throw new Exception("Couldnt merge avatar"); } + avatarMeshCombiner.container.transform.SetParent(container.transform, true); avatarMeshCombiner.container.transform.localPosition = Vector3.zero; avatarMeshCombiner.container.transform.localScale = Vector3.one; @@ -208,6 +211,7 @@ private async UniTask MergeAvatar(List internal static ILoader.Status ComposeStatus(Dictionary loaders) { ILoader.Status composedStatus = ILoader.Status.Succeeded; + foreach ((string category, IWearableLoader loader) in loaders) { if (loader.status == IWearableLoader.Status.Defaulted) @@ -216,19 +220,20 @@ internal static ILoader.Status ComposeStatus(Dictionary { if (AvatarSystemUtils.IsCategoryRequired(category)) return ILoader.Status.Failed_Major; + composedStatus = ILoader.Status.Failed_Minor; } } + return composedStatus; } private void ClearLoaders() { bodyshapeLoader?.Dispose(); - foreach (IWearableLoader wearableLoader in loaders.Values) - { - wearableLoader.Dispose(); - } + + foreach (IWearableLoader wearableLoader in loaders.Values) { wearableLoader.Dispose(); } + loaders.Clear(); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/SceneEmoteHelper.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/SceneEmoteHelper.cs deleted file mode 100644 index 769064d38f..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/SceneEmoteHelper.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Cysharp.Threading.Tasks; -using DCL.Controllers; -using DCL.Emotes; -using System; -using System.Collections.Generic; -using System.Threading; - -namespace AvatarSystem -{ - public static class SceneEmoteHelper - { - public const string SCENE_EMOTE_PREFIX = "urn:decentraland:off-chain:scene-emote:"; - - public static bool TryGenerateEmoteId(IParcelScene scene, string emoteFilePath, bool loop, out string emoteId) - { - if (scene.contentProvider.TryGetContentHash(emoteFilePath, out string emoteHash)) - { - emoteId = $"{SCENE_EMOTE_PREFIX}{emoteHash}-{(loop ? "true" : "false")}"; - return true; - } - - emoteId = string.Empty; - return false; - } - - public static bool TryGetDataFromEmoteId(string emoteId, out string emoteHash, out bool loop) - { - try - { - ReadOnlySpan prefixRemoved = emoteId.AsSpan().Slice(SCENE_EMOTE_PREFIX.Length, emoteId.Length - SCENE_EMOTE_PREFIX.Length); - int loopSeparator = prefixRemoved.LastIndexOf('-'); - emoteHash = prefixRemoved.Slice(0, loopSeparator).ToString(); - - var loopSpan = prefixRemoved.Slice(loopSeparator + 1, 4); - loop = loopSpan.Equals("true", StringComparison.InvariantCultureIgnoreCase); - - return true; - } - catch (Exception _) - { - emoteHash = string.Empty; - loop = false; - } - - return false; - } - - public static bool IsSceneEmote(string emoteId) - { - return emoteId.StartsWith(SCENE_EMOTE_PREFIX); - } - - public static async UniTask RequestLoadSceneEmote( - string bodyShapeId, - string emoteId, - IBaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animations, - BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesInUse, - HashSet<(string bodyshapeId, string emoteId)> currentScenePendingSceneEmotes, - HashSet<(string bodyshapeId, string emoteId)> currentSceneEquippedEmotes, - CancellationToken ct) - { - var emoteData = (bodyShapeId, emoteId); - - // check if already loaded - if (currentSceneEquippedEmotes.Contains(emoteData)) - { - return; - } - - // if emote it's not pending to be resolved, we add it to the pending list - if (!currentScenePendingSceneEmotes.Contains(emoteData)) - { - currentScenePendingSceneEmotes.Add(emoteData); - emotesInUse.IncreaseRefCount(emoteData); - } - - try - { - // wait until emote is loaded - while (!animations.ContainsKey(emoteData)) - { - await UniTask.Yield(ct); - } - } - catch (OperationCanceledException e) - { - currentScenePendingSceneEmotes.Remove(emoteData); - emotesInUse.DecreaseRefCount(emoteData); - throw e; - } - - // flag it as equipped - currentSceneEquippedEmotes.Add(emoteData); - currentScenePendingSceneEmotes.Remove(emoteData); - } - } -} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/WearableItemResolver.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableItemResolver.cs similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/WearableItemResolver.cs rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableItemResolver.cs diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/WearableItemResolver.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableItemResolver.cs.meta similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/WearableItemResolver.cs.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableItemResolver.cs.meta diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableLoader.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableLoader.cs index ebdef0acfd..bc5239b96f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableLoader.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableLoader.cs @@ -1,17 +1,18 @@ -using System; using System.Linq; using System.Threading; using Cysharp.Threading.Tasks; using DCL; using DCLServices.WearablesCatalogService; +using System; using UnityEngine; +using Environment = DCL.Environment; namespace AvatarSystem { public class WearableLoader : IWearableLoader { // TODO: This should be a service - internal static IWearableItemResolver defaultWearablesResolver = new WearableItemResolver(DCL.Environment.i.serviceLocator.Get()); + internal static IWearableItemResolver defaultWearablesResolver = new WearableItemResolver(Environment.i.serviceLocator.Get()); static WearableLoader() { // Prewarm default wearables diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableRetriever.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableRetriever.cs index 7bf8a709cc..d0cd26fc66 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableRetriever.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableRetriever.cs @@ -39,7 +39,7 @@ public async UniTask Retrieve(GameObject container, WearableItem we if (IsNewAssetBundleFlagEnabled()) { if (string.IsNullOrEmpty(wearable.entityId)) - Debug.LogError(mainFile + " has no entity ID, check where this wearable was loaded from"); + Debug.LogWarning(mainFile + " has no entity ID, ignore this message if you are on a testnet"); else { var sceneAb = await FetchSceneAssetBundles(wearable.entityId, contentProvider.assetBundlesBaseUrl); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarShould.cs index 4766ca2b09..dfd512347b 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarShould.cs @@ -28,7 +28,7 @@ public class AvatarShould private ILOD lod; private IGPUSkinning gpuSkinning; private IGPUSkinningThrottlerService gpuSkinningThrottlerService; - private IEmoteAnimationEquipper emoteAnimationEquipper; + private IAvatarEmotesController emoteAnimationEquipper; [SetUp] public void SetUp() @@ -42,7 +42,7 @@ public void SetUp() lod = Substitute.For(); gpuSkinning = Substitute.For(); gpuSkinningThrottlerService = Substitute.For(); - emoteAnimationEquipper = Substitute.For(); + emoteAnimationEquipper = Substitute.For(); avatar = new Avatar( curator, diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarSystemTests.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarSystemTests.asmdef index 361bcfbb08..6011161c07 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarSystemTests.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarSystemTests.asmdef @@ -25,7 +25,8 @@ "GUID:3b80b0b562b1cbc489513f09fc1b8f69", "GUID:68069f49d86442cd9618861b4d74b1aa", "GUID:97d8897529779cb49bebd400c7f402a6", - "GUID:6e6a87f97192ec947993f360104e75b7" + "GUID:6e6a87f97192ec947993f360104e75b7", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [ "Editor" diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarWithHologramShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarWithHologramShould.cs index 8a71dcfb52..198e9126f1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarWithHologramShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/AvatarWithHologramShould.cs @@ -28,7 +28,7 @@ public class AvatarWithHologramShould private ILOD lod; private IGPUSkinning gpuSkinning; private IGPUSkinningThrottlerService gpuSkinningThrottlerService; - private IEmoteAnimationEquipper emoteAnimationEquipper; + private IAvatarEmotesController emoteAnimationEquipper; private IBaseAvatar baseAvatar; [SetUp] @@ -43,7 +43,7 @@ public void SetUp() lod = Substitute.For(); gpuSkinning = Substitute.For(); gpuSkinningThrottlerService = Substitute.For(); - emoteAnimationEquipper = Substitute.For(); + emoteAnimationEquipper = Substitute.For(); baseAvatar = Substitute.For(); avatar = new AvatarWithHologram( diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs deleted file mode 100644 index 4bd9631f41..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs +++ /dev/null @@ -1,146 +0,0 @@ -using AvatarSystem; -using DCL; -using DCL.Emotes; -using NSubstitute; -using NUnit.Framework; -using UnityEditor; -using UnityEngine; - -namespace Test.AvatarSystem -{ - public class EmoteAnimationEquipperShould - { - private EmoteAnimationEquipper equipper; - private IAnimator animator; - private DataStore_Emotes dataStore; - private AnimationClip tikAnim; - private AnimationClip discoAnim; - - [SetUp] - public void SetUp() - { - tikAnim = AssetDatabase.LoadAssetAtPath("Assets/Scripts/MainScripts/DCL/Components/Avatar/Animations/Addressables/tik.anim"); - discoAnim = AssetDatabase.LoadAssetAtPath("Assets/Scripts/MainScripts/DCL/Components/Avatar/Animations/Addressables/disco.anim"); - - animator = Substitute.For(); - dataStore = new DataStore_Emotes(); - equipper = new EmoteAnimationEquipper(animator, dataStore); - } - - [TearDown] - public void TearDown() { equipper.Dispose(); } - - [Test] - public void AssignReferencesOnConstruction() - { - Assert.AreEqual(animator, equipper.animator); - Assert.AreEqual(dataStore, equipper.dataStoreEmotes); - Assert.AreEqual(0, equipper.emotes.Count); - } - - [Test] - public void SetEmoteListAndUpdateUses() - { - dataStore.emotesOnUse.SetRefCount(("female", "emote0"), 0); - dataStore.emotesOnUse.SetRefCount(("female", "emote1"), 1); - dataStore.emotesOnUse.SetRefCount(("female", "emote2"), 2); - - equipper.SetEquippedEmotes("female", new [] - { - new WearableItem { id = "emote0" }, - new WearableItem { id = "emote1" }, - new WearableItem { id = "emote2" }, - }); - - Assert.AreEqual("female", equipper.bodyShapeId); - Assert.AreEqual("emote0" , equipper.emotes[0]); - Assert.AreEqual("emote1" , equipper.emotes[1]); - Assert.AreEqual("emote2" , equipper.emotes[2]); - Assert.AreEqual(1, dataStore.emotesOnUse.GetRefCount(("female", "emote0"))); - Assert.AreEqual(2, dataStore.emotesOnUse.GetRefCount(("female", "emote1"))); - Assert.AreEqual(3, dataStore.emotesOnUse.GetRefCount(("female", "emote2"))); - } - - [Test] - public void NotEquipNotReadyEmotesOnSet() - { - equipper.SetEquippedEmotes("", new [] - { - new WearableItem { id = "emote0" }, - new WearableItem { id = "emote1" }, - new WearableItem { id = "emote2" }, - }); - - animator.DidNotReceive().EquipEmote(Arg.Any(), Arg.Any()); - } - - [Test] - public void EquipReadyEmotes() - { - var tikEmoteData = new EmoteClipData(tikAnim); - var discoEmoteData = new EmoteClipData(discoAnim); - dataStore.animations.Add(("female", "emote0"), tikEmoteData); - dataStore.animations.Add(("female", "emote1"), discoEmoteData); - equipper.SetEquippedEmotes("female", new [] - { - new WearableItem { id = "emote0" }, - new WearableItem { id = "emote1" }, - new WearableItem { id = "emote2" }, - }); - - animator.Received().EquipEmote("emote0", tikEmoteData); - animator.Received().EquipEmote("emote1", discoEmoteData); - animator.DidNotReceive().EquipEmote("emote2", Arg.Any()); - } - - [Test] - public void DecreaseRefCountOfPrevEmotes() - { - dataStore.emotesOnUse.SetRefCount(("female", "old0"), 10); - dataStore.emotesOnUse.SetRefCount(("female", "old1"), 11); - dataStore.emotesOnUse.SetRefCount(("female", "old2"), 12); - equipper.bodyShapeId = "female"; - equipper.emotes.AddRange(new [] { "old0", "old1", "old2" }); - - equipper.SetEquippedEmotes("male", new [] - { - new WearableItem { id = "new0" }, - new WearableItem { id = "new1" }, - new WearableItem { id = "new2" }, - }); - - Assert.AreEqual(10, dataStore.emotesOnUse.GetRefCount(("female", "old0"))); - Assert.AreEqual(11, dataStore.emotesOnUse.GetRefCount(("female", "old1"))); - Assert.AreEqual(12, dataStore.emotesOnUse.GetRefCount(("female", "old2"))); - Assert.AreEqual(1, dataStore.emotesOnUse.GetRefCount(("male", "new0"))); - Assert.AreEqual(1, dataStore.emotesOnUse.GetRefCount(("male", "new1"))); - Assert.AreEqual(1, dataStore.emotesOnUse.GetRefCount(("male", "new2"))); - } - - [Test] - public void EquipEmoteWhenAnimationReadyForCurrentBodyshape() - { - equipper.bodyShapeId = "female"; - equipper.emotes.AddRange(new [] { "old0", "old1", "old2" }); - - var emoteClipData = new EmoteClipData(tikAnim); - - dataStore.animations.Add(("female", "old0"), emoteClipData); - - animator.Received().EquipEmote("old0", emoteClipData); - } - - [Test] - public void NotEquipEmoteWhenAnimationReadyForOtherBodyshape() - { - equipper.bodyShapeId = "female"; - equipper.emotes.AddRange(new [] { "old0", "old1", "old2" }); - - var emoteClipData = new EmoteClipData(tikAnim); - - dataStore.animations.Add(("male", "old0"), emoteClipData); - - animator.DidNotReceive().EquipEmote(Arg.Any(), Arg.Any()); - } - } -} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs.meta deleted file mode 100644 index e51e92d44f..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/EmoteAnimationEquipperShould.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 64d32c939d254dff97ad86a9e89400b6 -timeCreated: 1646927251 \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/SceneEmoteHelperShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/SceneEmoteHelperShould.cs deleted file mode 100644 index 2d95419341..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/SceneEmoteHelperShould.cs +++ /dev/null @@ -1,189 +0,0 @@ -using AvatarSystem; -using Cysharp.Threading.Tasks; -using DCL; -using DCL.Controllers; -using DCL.Emotes; -using NSubstitute; -using NUnit.Framework; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Test.AvatarSystem -{ - public class SceneEmoteHelperShould - { - [Test] - public void TryGenerateEmoteId() - { - const string HASH = "00172"; - const string FILE = "test"; - IParcelScene scene = Substitute.For(); - - var contentProvider = new ContentProvider() - { - contents = - { - new ContentServerUtils.MappingPair() { file = FILE, hash = HASH } - } - }; - - contentProvider.BakeHashes(); - scene.contentProvider.Returns(contentProvider); - - string emoteIdResult; - Assert.IsTrue(SceneEmoteHelper.TryGenerateEmoteId(scene, FILE, true, out emoteIdResult)); - Assert.AreEqual($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-true", emoteIdResult); - - Assert.IsTrue(SceneEmoteHelper.TryGenerateEmoteId(scene, FILE, false, out emoteIdResult)); - Assert.AreEqual($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-false", emoteIdResult); - } - - [Test] - public void TryGetDataFromEmoteId() - { - const string HASH = "00172"; - Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-true", out string hash, out bool loop)); - Assert.AreEqual(HASH, hash); - Assert.IsTrue(loop); - - Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-false", out hash, out loop)); - Assert.AreEqual(HASH, hash); - Assert.IsFalse(loop); - - Assert.IsFalse(SceneEmoteHelper.TryGetDataFromEmoteId($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}", out hash, out loop)); - } - - [Test] - public void IsSceneEmote() - { - Assert.IsTrue(SceneEmoteHelper.IsSceneEmote($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}0-false")); - Assert.IsFalse(SceneEmoteHelper.IsSceneEmote($"otherstring")); - } - - [UnityTest] - public IEnumerator RequestLoadSceneEmote_Success() - { - const string BODY_SHAPE = "nogender"; - const string EMOTE_ID = "emoteId"; - - BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesOnUse = new BaseRefCountedCollection<(string bodyshapeId, string emoteId)>(); - BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animations = new BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData>(); - HashSet<(string bodyshapeId, string emoteId)> currentScenePendingSceneEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - HashSet<(string bodyshapeId, string emoteId)> currentSceneEquippedEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - - yield return UniTask.ToCoroutine(async () => - { - emotesOnUse.OnRefCountUpdated += (tuple, i) => animations[tuple] = new EmoteClipData(new AnimationClip(), false); - - await SceneEmoteHelper.RequestLoadSceneEmote( - BODY_SHAPE, - EMOTE_ID, - animations, - emotesOnUse, - currentScenePendingSceneEmotes, - currentSceneEquippedEmotes, - default - ); - - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - Assert.IsTrue(currentSceneEquippedEmotes.Contains(emoteData)); - Assert.IsTrue(animations.ContainsKey(emoteData)); - }); - } - - [UnityTest] - public IEnumerator RequestLoadSceneEmote_Cancelled() - { - const string BODY_SHAPE = "nogender"; - const string EMOTE_ID = "emoteId"; - - BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesOnUse = new BaseRefCountedCollection<(string bodyshapeId, string emoteId)>(); - BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animations = new BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData>(); - HashSet<(string bodyshapeId, string emoteId)> currentScenePendingSceneEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - HashSet<(string bodyshapeId, string emoteId)> currentSceneEquippedEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - - yield return UniTask.ToCoroutine(async () => - { - try - { - // schedule cancellation after request starts - UniTask.Create(async () => - { - await UniTask.Yield(); - cancellationTokenSource.Cancel(); - }); - - await SceneEmoteHelper.RequestLoadSceneEmote( - BODY_SHAPE, - EMOTE_ID, - animations, - emotesOnUse, - currentScenePendingSceneEmotes, - currentSceneEquippedEmotes, - cancellationTokenSource.Token - ); - } - catch (OperationCanceledException _) - { - // Ignored - } - - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - Assert.IsFalse(currentSceneEquippedEmotes.Contains(emoteData)); - Assert.IsFalse(currentScenePendingSceneEmotes.Contains(emoteData)); - Assert.IsFalse(animations.ContainsKey(emoteData)); - Assert.AreEqual(0, emotesOnUse.GetRefCount(emoteData)); - }); - } - - [UnityTest] - public IEnumerator RequestLoadSceneEmote_LoadedTwice() - { - const string BODY_SHAPE = "nogender"; - const string EMOTE_ID = "emoteId"; - - BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesOnUse = new BaseRefCountedCollection<(string bodyshapeId, string emoteId)>(); - BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animations = new BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData>(); - HashSet<(string bodyshapeId, string emoteId)> currentScenePendingSceneEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - HashSet<(string bodyshapeId, string emoteId)> currentSceneEquippedEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - - yield return UniTask.ToCoroutine(async () => - { - emotesOnUse.OnRefCountUpdated += (tuple, i) => animations[tuple] = new EmoteClipData(new AnimationClip(), false); - - var load1 = SceneEmoteHelper.RequestLoadSceneEmote( - BODY_SHAPE, - EMOTE_ID, - animations, - emotesOnUse, - currentScenePendingSceneEmotes, - currentSceneEquippedEmotes, - default - ); - - var load2 = SceneEmoteHelper.RequestLoadSceneEmote( - BODY_SHAPE, - EMOTE_ID, - animations, - emotesOnUse, - currentScenePendingSceneEmotes, - currentSceneEquippedEmotes, - default - ); - - await UniTask.WhenAll(load1, load2); - - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - Assert.IsTrue(currentSceneEquippedEmotes.Contains(emoteData)); - Assert.IsFalse(currentScenePendingSceneEmotes.Contains(emoteData)); - Assert.IsTrue(animations.ContainsKey(emoteData)); - Assert.AreEqual(1, emotesOnUse.GetRefCount(emoteData)); - }); - } - } -} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index de8836d0eb..0da4d77f73 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -450,7 +450,7 @@ public void PlayEmote(string emoteId, long timestamps) if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) { lastExtendedEmoteData = emoteClipData; - emoteClipData.PlayAllAnimations(); + emoteClipData.PlayAllAnimations(gameObject.layer); } } else diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs index 06bce53289..74ce44db38 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs @@ -1,6 +1,8 @@ +using AvatarAssets; using AvatarSystem; using Cysharp.Threading.Tasks; using DCL.Emotes; +using DCL.Tasks; using System; using System.Collections.Generic; using System.Threading; @@ -10,30 +12,22 @@ namespace DCL { public class AvatarSceneEmoteHandler { - private readonly IAvatar avatar; - private readonly IBaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> alreadyLoadedEmotes; - private readonly BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesInUse; - private readonly HashSet<(string bodyshapeId, string emoteId)> pendingEmotesByScene; - private readonly HashSet<(string bodyshapeId, string emoteId)> equippedEmotesByScene; + private readonly IAvatarEmotesController emotesController; + private readonly IEmotesService emotesService; + private readonly HashSet<(string bodyshapeId, string emoteId)> equippedEmotes; - private long lamportTimestamp = 0; - internal CancellationTokenSource cancellationTokenSource = null; + private long lamportTimestamp; + internal CancellationTokenSource cts; - public AvatarSceneEmoteHandler(IAvatar avatar, - IBaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> alreadyLoadedEmotes, - BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesInUse) + public AvatarSceneEmoteHandler(IAvatarEmotesController emotesController, IEmotesService emotesService) { - this.avatar = avatar; - this.alreadyLoadedEmotes = alreadyLoadedEmotes; - this.emotesInUse = emotesInUse; - this.equippedEmotesByScene = new HashSet<(string bodyshapeId, string emoteId)>(); - this.pendingEmotesByScene = new HashSet<(string bodyshapeId, string emoteId)>(); + this.emotesController = emotesController; + this.emotesService = emotesService; + this.equippedEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); } - public bool IsSceneEmote(string emoteId) - { - return SceneEmoteHelper.IsSceneEmote(emoteId); - } + public bool IsSceneEmote(string emoteId) => + SceneEmoteHelper.IsSceneEmote(emoteId); public void SetExpressionLamportTimestamp(long timestamp) { @@ -43,60 +37,35 @@ public void SetExpressionLamportTimestamp(long timestamp) public async UniTask LoadAndPlayEmote(string bodyShapeId, string emoteId) { long timestamp = lamportTimestamp; - cancellationTokenSource ??= new CancellationTokenSource(); + cts ??= new CancellationTokenSource(); + + (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); try { - await SceneEmoteHelper.RequestLoadSceneEmote( - bodyShapeId, - emoteId, - alreadyLoadedEmotes, - emotesInUse, - pendingEmotesByScene, - equippedEmotesByScene, - cancellationTokenSource.Token - ); + var loadedEmote = await emotesService.RequestEmote(bodyShapeId, emoteId, cts.Token); + + emotesController.EquipEmote(emoteId, loadedEmote); + equippedEmotes.Add(emoteKey); //avoid playing emote if timestamp has change, //meaning a new emote was trigger while this one was loading if (timestamp == lamportTimestamp) - { - avatar.EquipEmote(emoteId, alreadyLoadedEmotes[(bodyShapeId, emoteId)]); - avatar.PlayEmote(emoteId, lamportTimestamp); - } - } - catch (OperationCanceledException _) - { - // Ignored - } - catch (Exception e) - { - Debug.LogException(e); + emotesController.PlayEmote(emoteId, lamportTimestamp); } + catch (OperationCanceledException) { } + catch (Exception e) { Debug.LogException(e); } } public void CleanUp() { - if (cancellationTokenSource != null) - { - cancellationTokenSource.Cancel(); - cancellationTokenSource.Dispose(); - cancellationTokenSource = null; - } + cts?.SafeCancelAndDispose(); + cts = null; - foreach (var emoteData in equippedEmotesByScene) - { - avatar?.UnequipEmote(emoteData.emoteId); - emotesInUse.DecreaseRefCount(emoteData); - } - - foreach (var emoteData in pendingEmotesByScene) - { - emotesInUse.DecreaseRefCount(emoteData); - } + foreach (var emoteData in equippedEmotes) + emotesController?.UnEquipEmote(emoteData.emoteId); - equippedEmotesByScene.Clear(); - pendingEmotesByScene.Clear(); + equippedEmotes.Clear(); } } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.asmdef index e869bd7bf2..e9c4a26b71 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.asmdef @@ -74,7 +74,10 @@ "GUID:af7c0aba882f460ea6413f87a04b1ae5", "GUID:8d76e605759c3f64a957d63ef96ada7c", "GUID:05dd262a0c0a2f841b8252c8c3815582", - "GUID:da3e51d19d51a544fa14d43fee843098" + "GUID:da3e51d19d51a544fa14d43fee843098", + "GUID:0c0c18c12967b3944b844b79c47c2320", + "GUID:4d3366a36e77f41cfb7436340334e236", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs index 0007edf018..3b035aa75f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs @@ -59,6 +59,7 @@ public class AvatarShape : BaseComponent, IHideAvatarAreaHandler, IHidePassportA private Service emotesCatalogService; public override string componentName => "avatarShape"; private AvatarSceneEmoteHandler sceneEmoteHandler; + private IAvatarEmotesController emotesController; private void Awake() { @@ -73,7 +74,8 @@ private void Awake() else avatar = GetStandardAvatar(); - sceneEmoteHandler = new AvatarSceneEmoteHandler(avatar, DataStore.i.emotes.animations, DataStore.i.emotes.emotesOnUse); + emotesController = avatar.GetEmotesController(); + sceneEmoteHandler = new AvatarSceneEmoteHandler(emotesController, Environment.i.serviceLocator.Get()); if (avatarReporterController == null) { @@ -242,7 +244,7 @@ public override IEnumerator ApplyChanges(BaseModel newModel) } else { - avatar.PlayEmote(model.expressionTriggerId, model.expressionTriggerTimestamp); + emotesController.PlayEmote(model.expressionTriggerId, model.expressionTriggerTimestamp); } onPointerDown.OnPointerDownReport -= PlayerClicked; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs index 7a83560de8..141f8b0c20 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs @@ -3,139 +3,117 @@ using DCL; using DCL.Emotes; using NSubstitute; +using NSubstitute.ExceptionExtensions; using NUnit.Framework; -using System.Collections; -using UnityEngine; -using UnityEngine.TestTools; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Tests { public class AvatarSceneEmoteHandlerShould { - private BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesOnUse; - private BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animations; private AvatarSceneEmoteHandler handler; - private IAvatar avatar; + private IAvatarEmotesController emotesController; + private IEmotesService emotesService; [SetUp] public void SetUp() { - emotesOnUse = new BaseRefCountedCollection<(string bodyshapeId, string emoteId)>(); - animations = new BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData>(); - avatar = Substitute.For(); - handler = new AvatarSceneEmoteHandler(avatar, animations, emotesOnUse); + emotesService = Substitute.For(); + emotesController = Substitute.For(); + handler = new AvatarSceneEmoteHandler(emotesController, emotesService); } - [UnityTest] - public IEnumerator LoadAndPlayEmote_Success() + [Test] + public async Task LoadAndPlayEmote_Success() { const string BODY_SHAPE = "nogender"; const string EMOTE_ID = "emoteId"; - yield return UniTask.ToCoroutine(async () => - { - emotesOnUse.OnRefCountUpdated += (tuple, i) => animations[tuple] = new EmoteClipData(new AnimationClip()); + var emote = SetupEmoteService(BODY_SHAPE, EMOTE_ID); - await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); + await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - Assert.IsTrue(animations.ContainsKey(emoteData)); - Assert.AreEqual(1, emotesOnUse.GetRefCount(emoteData)); - avatar.Received(1).EquipEmote(EMOTE_ID, animations[emoteData]); - avatar.Received(1).PlayEmote(EMOTE_ID, 0); - }); + var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); + emotesService.Received(1).RequestEmote(emoteData.bodyshapeId, emoteData.emoteId, Arg.Any()); + emotesController.Received(1).EquipEmote(EMOTE_ID, emote); + emotesController.Received(1).PlayEmote(EMOTE_ID, 0); } - [UnityTest] - public IEnumerator LoadAndPlayEmote_Cancelled() + [Test] + public async Task LoadAndPlayEmote_Cancelled() { const string BODY_SHAPE = "nogender"; const string EMOTE_ID = "emoteId"; - yield return UniTask.ToCoroutine(async () => - { - var task = handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); - handler.cancellationTokenSource.Cancel(); - await task; - - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - Assert.IsFalse(animations.ContainsKey(emoteData)); - Assert.AreEqual(0, emotesOnUse.GetRefCount(emoteData)); - avatar.DidNotReceive().EquipEmote(Arg.Any(), Arg.Any()); - avatar.DidNotReceive().PlayEmote(Arg.Any(), Arg.Any()); - }); + emotesService.RequestEmote(BODY_SHAPE, EMOTE_ID, Arg.Any()).Throws(new OperationCanceledException()); + + await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); + + var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); + emotesService.Received(1).RequestEmote(emoteData.bodyshapeId, emoteData.emoteId, Arg.Any()); + emotesController.DidNotReceive().EquipEmote(Arg.Any(), Arg.Any()); + emotesController.DidNotReceive().PlayEmote(Arg.Any(), Arg.Any()); } - [UnityTest] - public IEnumerator LoadAndPlayEmote_LoadTwice() + [Test] + public async Task LoadAndPlayEmote_LoadTwice() { const string BODY_SHAPE = "nogender"; const string EMOTE_ID1 = "emoteId"; const string EMOTE_ID2 = "emoteId2"; - yield return UniTask.ToCoroutine(async () => - { - BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animationsToAdd = new (); - emotesOnUse.OnRefCountUpdated += (tuple, i) => animationsToAdd[tuple] = new EmoteClipData(new AnimationClip()); - - handler.SetExpressionLamportTimestamp(0); - var load1 = handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID1); - handler.SetExpressionLamportTimestamp(1); - var load2 = handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID2); + var emote1 = SetupEmoteService(BODY_SHAPE, EMOTE_ID1); + var emote2 = SetupEmoteService(BODY_SHAPE, EMOTE_ID2); - foreach (var toAdd in animationsToAdd) - { - animations[toAdd.Key] = toAdd.Value; - } + handler.SetExpressionLamportTimestamp(0); + var load1 = handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID1); + handler.SetExpressionLamportTimestamp(1); + var load2 = handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID2); - await UniTask.WhenAll(load1, load2); + await UniTask.WhenAll(load1, load2); - avatar.DidNotReceive().EquipEmote(EMOTE_ID1, animations[(bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID1)]); - avatar.DidNotReceive().PlayEmote(EMOTE_ID1, 0); - avatar.Received(1).EquipEmote(EMOTE_ID2, animations[(bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID2)]); - avatar.Received(1).PlayEmote(EMOTE_ID2, 1); - }); + // first emote is equipped + emotesController.Received(1).EquipEmote(EMOTE_ID1, emote1); + // but not played + emotesController.DidNotReceive().PlayEmote(EMOTE_ID1, 0); + // second emote is equipped + emotesController.Received(1).EquipEmote(EMOTE_ID2, emote2); + // and played + emotesController.Received(1).PlayEmote(EMOTE_ID2, 1); } - [UnityTest] - public IEnumerator CleanUp() + [Test] + public async Task CleanUp() { const string BODY_SHAPE = "nogender"; const string EMOTE_ID = "emoteId"; - yield return UniTask.ToCoroutine(async () => - { - emotesOnUse.OnRefCountUpdated += (tuple, i) => animations[tuple] = new EmoteClipData(new AnimationClip()); + var emote = SetupEmoteService(BODY_SHAPE, EMOTE_ID); - await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); + await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - Assert.IsTrue(animations.ContainsKey(emoteData)); - Assert.AreEqual(1, emotesOnUse.GetRefCount(emoteData)); - avatar.Received(1).EquipEmote(EMOTE_ID, animations[emoteData]); - avatar.Received(1).PlayEmote(EMOTE_ID, 0); + emotesController.Received(1).EquipEmote(EMOTE_ID, emote); + emotesController.Received(1).PlayEmote(EMOTE_ID, 0); - handler.CleanUp(); - Assert.AreEqual(0, emotesOnUse.GetRefCount(emoteData)); - }); + handler.CleanUp(); + + emotesController.Received(1).UnEquipEmote(EMOTE_ID); } - [UnityTest] - public IEnumerator CleanUp_WhileLoadingEmote() + private IEmoteReference SetupEmoteService(string bodyShape, string emoteId) { - const string BODY_SHAPE = "nogender"; - const string EMOTE_ID = "emoteId"; - - yield return UniTask.ToCoroutine(async () => - { - handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID).Forget(); - - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - Assert.AreEqual(1, emotesOnUse.GetRefCount(emoteData)); + var emote = Substitute.For(); + emotesService.RequestEmote(bodyShape, emoteId, Arg.Any()).Returns(_ => GetResult(emote)); + return emote; + } - handler.CleanUp(); - Assert.AreEqual(0, emotesOnUse.GetRefCount(emoteData)); - }); + // the yield hack was used for the test LoadAndPlayEmote_LoadTwice in order to simulate that the emotes are not loaded yet + private async UniTask GetResult(IEmoteReference emote) + { + await UniTask.Yield(); + return emote; } } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarShapeTests.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarShapeTests.asmdef index b67cc70185..b8c7ef1114 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarShapeTests.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarShapeTests.asmdef @@ -2,7 +2,6 @@ "name": "AvatarShapeTests", "rootNamespace": "", "references": [ - "GUID:54b09a4a10c111e46a817873fcea53fe", "GUID:e65144cdbd5b744238fa03c40df6cd71", "GUID:b1087c5731ff68448a0a9c625bb7e52d", "GUID:760a1d365aad58044916992b072cf2a6", @@ -40,9 +39,12 @@ "GUID:3b80b0b562b1cbc489513f09fc1b8f69", "GUID:68069f49d86442cd9618861b4d74b1aa", "GUID:fbcc413e192ef9048811d47ab0aca0c0", - "GUID:f51ebe6a0ceec4240a699833d6309b23" + "GUID:f51ebe6a0ceec4240a699833d6309b23", + "GUID:0c0c18c12967b3944b844b79c47c2320" + ], + "includePlatforms": [ + "Editor" ], - "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": true, @@ -52,9 +54,7 @@ "NSubstitute.dll" ], "autoReferenced": false, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], + "defineConstraints": [], "versionDefines": [], "noEngineReferences": false } \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/AvatarEditorHUD.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/AvatarEditorHUD.asmdef index 07cdd4f925..8953925786 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/AvatarEditorHUD.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/AvatarEditorHUD.asmdef @@ -62,7 +62,8 @@ "GUID:8aa60ff897c74401cb96cdbc583fed0d", "GUID:4d3366a36e77f41cfb7436340334e236", "GUID:bab23c9e6b4c4da469d4688d16c1ee9b", - "GUID:1a2f349ffd2464ef8a6a7c0615f79b0f" + "GUID:1a2f349ffd2464ef8a6a7c0615f79b0f", + "GUID:0c0c18c12967b3944b844b79c47c2320" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDController.cs index 6e0b6d0ae2..897bdef65a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDController.cs @@ -134,7 +134,7 @@ private async void InitializeAsyncEmoteController() emotesCustomizationComponentController = new EmotesCustomizationComponentController( DataStore.i.emotesCustomization, - DataStore.i.emotes, + view.CharacterPreview.GetEmotesController(), DataStore.i.exploreV2, DataStore.i.HUDs, view.emotesSection.transform); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDPlugin.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDPlugin.cs index 4db4094898..fcf967db76 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDPlugin.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDPlugin.cs @@ -1,3 +1,4 @@ +using DCL.Emotes; using DCLServices.WearablesCatalogService; using MainScripts.DCL.Controllers.HUD.CharacterPreview; @@ -9,10 +10,12 @@ public class AvatarEditorHUDPlugin : IPlugin public AvatarEditorHUDPlugin() { + ServiceLocator serviceLocator = Environment.i.serviceLocator; + hudController = new AvatarEditorHUDController( DataStore.i.featureFlags, Environment.i.platform.serviceProviders.analytics, - Environment.i.serviceLocator.Get(), + serviceLocator.Get(), new UserProfileWebInterfaceBridge()); // there could be a race condition going on if we initialize the avatar editor before the feature flags are set diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs index 726e9b67e0..2401cb6d5c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs @@ -1,23 +1,31 @@ +using AvatarSystem; +using Cysharp.Threading.Tasks; using System; using System.Collections.Generic; using System.Linq; using DCL.Emotes; +using DCL.Tasks; +using System.Threading; using UnityEngine; namespace DCL.EmotesCustomization { public class EmotesCustomizationComponentController : IEmotesCustomizationComponentController { + public event Action onEmotePreviewed; + public event Action onEmoteEquipped; + public event Action onEmoteUnequipped; + public event Action onEmoteSell; + internal const int NUMBER_OF_SLOTS = 10; internal string bodyShapeId; internal DataStore_EmotesCustomization emotesCustomizationDataStore; - internal DataStore_Emotes emotesDataStore; - internal BaseDictionary emotesInLoadingState = new BaseDictionary(); + internal BaseDictionary emotesInLoadingState = new (); internal InputAction_Hold equipInputAction; internal DataStore_ExploreV2 exploreV2DataStore; internal DataStore_HUDs hudsDataStore; - internal Dictionary ownedEmotes = new Dictionary(); + internal Dictionary ownedEmotes = new (); // internal InputAction_Hold showInfoInputAction; internal InputAction_Trigger shortcut0InputAction; internal InputAction_Trigger shortcut1InputAction; @@ -34,34 +42,30 @@ public class EmotesCustomizationComponentController : IEmotesCustomizationCompon internal bool isEmotesCustomizationSectionOpen => exploreV2DataStore.isOpen.Get() && view.isActive; - public event Action onEmotePreviewed; - public event Action onEmoteEquipped; - public event Action onEmoteUnequipped; - public event Action onEmoteSell; + private CancellationTokenSource cts = new (); + private IAvatarEmotesController emotesController; public EmotesCustomizationComponentController() { } - public EmotesCustomizationComponentController( - DataStore_EmotesCustomization emotesCustomizationDataStore, - DataStore_Emotes emotesDataStore, + public EmotesCustomizationComponentController(DataStore_EmotesCustomization emotesCustomizationDataStore, + IAvatarEmotesController avatarEmotesController, DataStore_ExploreV2 exploreV2DataStore, DataStore_HUDs hudsDataStore, Transform parent, string viewPath = "EmotesCustomization/EmotesCustomizationSection") { - Initialize(emotesCustomizationDataStore, emotesDataStore, exploreV2DataStore, hudsDataStore, parent, viewPath); + Initialize(emotesCustomizationDataStore, avatarEmotesController, exploreV2DataStore, hudsDataStore, parent, viewPath); } - internal void Initialize( - DataStore_EmotesCustomization emotesCustomizationDataStore, - DataStore_Emotes emotesDataStore, + internal void Initialize(DataStore_EmotesCustomization emotesCustomizationDataStore, + IAvatarEmotesController avatarEmotesController, DataStore_ExploreV2 exploreV2DataStore, DataStore_HUDs hudsDataStore, Transform parent, string viewPath = "EmotesCustomization/EmotesCustomizationSection") { + this.emotesController = avatarEmotesController; this.emotesCustomizationDataStore = emotesCustomizationDataStore; - this.emotesDataStore = emotesDataStore; this.exploreV2DataStore = exploreV2DataStore; this.hudsDataStore = hudsDataStore; @@ -71,8 +75,7 @@ internal void Initialize( emotesCustomizationDataStore.equippedEmotes.OnSet += OnEquippedEmotesSet; OnEquippedEmotesSet(emotesCustomizationDataStore.equippedEmotes.Get()); - emotesDataStore.animations.OnAdded -= OnAnimationAdded; - emotesDataStore.animations.OnAdded += OnAnimationAdded; + this.emotesController.OnEmoteEquipped += OnAnimationAdded; } public void SetEmotes(WearableItem[] ownedEmotes) @@ -81,9 +84,7 @@ public void SetEmotes(WearableItem[] ownedEmotes) List idsToRemove = emotesCustomizationDataStore.currentLoadedEmotes.Get().Where(x => ownedEmotes.All(y => x != y.id)).ToList(); foreach (string emoteId in idsToRemove) - { RemoveEmote(emoteId); - } this.ownedEmotes.Clear(); for (int i = 0; i < ownedEmotes.Length; i++) @@ -94,9 +95,8 @@ public void SetEmotes(WearableItem[] ownedEmotes) this.ownedEmotes[emote.id] = emote; } foreach (WearableItem emote in this.ownedEmotes.Values) - { AddEmote(emote); - } + UpdateEmoteSlots(); } @@ -120,6 +120,7 @@ public void RestoreEmoteSlots() public void Dispose() { + cts.SafeCancelAndDispose(); view.onEmoteEquipped -= OnEmoteEquipped; view.onEmoteUnequipped -= OnEmoteUnequipped; view.onSellEmoteClicked -= OnSellEmoteClicked; @@ -127,7 +128,6 @@ public void Dispose() exploreV2DataStore.isOpen.OnChange -= IsStarMenuOpenChanged; hudsDataStore.avatarEditorVisible.OnChange -= OnAvatarEditorVisibleChanged; emotesCustomizationDataStore.equippedEmotes.OnSet -= OnEquippedEmotesSet; - emotesDataStore.animations.OnAdded -= OnAnimationAdded; equipInputAction.OnFinished -= OnEquipInputActionTriggered; // showInfoInputAction.OnFinished -= OnShowInfoInputActionTriggered; shortcut0InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; @@ -172,8 +172,6 @@ internal void AddEmote(WearableItem emote) return; emotesCustomizationDataStore.currentLoadedEmotes.Add(emoteId); - emotesDataStore.emotesOnUse.IncreaseRefCount((WearableLiterals.BodyShapes.FEMALE, emoteId)); - emotesDataStore.emotesOnUse.IncreaseRefCount((WearableLiterals.BodyShapes.MALE, emoteId)); if (!emote.ShowInBackpack()) return; @@ -192,33 +190,24 @@ internal void AddEmote(WearableItem emote) internal void RemoveEmote(string emoteId) { - emotesDataStore.emotesOnUse.DecreaseRefCount((WearableLiterals.BodyShapes.FEMALE, emoteId)); - emotesDataStore.emotesOnUse.DecreaseRefCount((WearableLiterals.BodyShapes.MALE, emoteId)); emotesCustomizationDataStore.currentLoadedEmotes.Remove(emoteId); view.RemoveEmote(emoteId); UpdateEmoteSlots(); } - internal void OnAnimationAdded((string bodyshapeId, string emoteId) values, EmoteClipData emoteClipData) + private void OnAnimationAdded(string emoteId, IEmoteReference emoteClipData) { - if(emoteClipData.AvatarClip != null) - RefreshEmoteLoadingState(values.emoteId); - else - { - var emoteId = values.emoteId; - RemoveEmote(emoteId); - Debug.LogError("Emote " + emoteId + " was not found in emotes data store"); - } + RefreshEmoteLoadingState(emoteId); } internal void RefreshEmoteLoadingState(string emoteId) { - if (emotesDataStore.animations.ContainsKey((bodyShapeId, emoteId))) + if (emotesController.TryGetEquippedEmote(bodyShapeId, emoteId, out IEmoteReference _)) { - emotesInLoadingState.TryGetValue(emoteId, out EmoteCardComponentView emote); - if (emote != null) + emotesInLoadingState.TryGetValue(emoteId, out EmoteCardComponentView emoteCard); + if (emoteCard != null) { - emote.SetAsLoading(false); + emoteCard.SetAsLoading(false); emotesInLoadingState.Remove(emoteId); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesWheelUIPlugin.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesWheelUIPlugin.cs index 7753c756a9..6fec8770d0 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesWheelUIPlugin.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesWheelUIPlugin.cs @@ -1,3 +1,4 @@ +using DCL.Emotes; using DCLServices.WearablesCatalogService; namespace DCL.EmotesWheel @@ -13,7 +14,7 @@ public EmotesWheelUIPlugin() { emotesWheelController = new EmotesWheelController( UserProfile.GetOwnUserProfile(), - Environment.i.serviceLocator.Get(), + Environment.i.serviceLocator.Get(), Environment.i.serviceLocator.Get()); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDControllerShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDControllerShould.cs index 5b2516420f..78b2f47c94 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDControllerShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDControllerShould.cs @@ -1,4 +1,5 @@ using DCL; +using DCL.Emotes; using DCLServices.WearablesCatalogService; using MainScripts.DCL.Controllers.HUD.CharacterPreview; using MainScripts.DCL.Models.AvatarAssets.Tests.Helpers; @@ -15,7 +16,7 @@ namespace AvatarEditorHUD_Tests public class AvatarEditorHUDControllerShould : IntegrationTestSuite_Legacy { private const string EYEBROWS_ID = "urn:decentraland:off-chain:base-avatars:f_eyebrows_01"; - private const string FEMALE_CATGLASSES_ID = "urn:decentraland:off-chain:base-avatars:f_glasses_cat_style"; + private const string FEMALE_CAT_GLASSES_ID = "urn:decentraland:off-chain:base-avatars:f_glasses_cat_style"; private UserProfile userProfile; private AvatarEditorHUDController_Mock controller; @@ -24,6 +25,7 @@ public class AvatarEditorHUDControllerShould : IntegrationTestSuite_Legacy private ColorList hairColorList; private ColorList eyeColorList; private IAnalytics analytics; + private IEmotesService emotesService; [UnitySetUp] protected override IEnumerator SetUp() @@ -44,6 +46,8 @@ protected override IEnumerator SetUp() IUserProfileBridge userProfileBridge = Substitute.For(); userProfileBridge.GetOwn().Returns(userProfile); + emotesService = Substitute.For(); + controller = new AvatarEditorHUDController_Mock(DataStore.i.featureFlags, analytics, wearablesCatalogService, userProfileBridge); @@ -55,15 +59,15 @@ protected override IEnumerator SetUp() controller.SetVisibility(true); DataStore.i.common.isPlayerRendererLoaded.Set(true); - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); controller.avatarIsDirty = false; @@ -80,15 +84,15 @@ protected override IEnumerator TearDown() [Test] public void AutofillMandatoryCategoriesIfNotProvided() { - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); var categoriesEquiped = controller.myModel.wearables.Select(x => x.data.category).ToArray(); @@ -102,36 +106,36 @@ public void AutofillMandatoryCategoriesIfNotProvided() [Test] public void ReplaceNotSupportedWearablesWhenChangingBodyShape() { - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() + wearables = new List { - FEMALE_CATGLASSES_ID + FEMALE_CAT_GLASSES_ID, }, - } + }, }); controller.WearableClicked(WearableLiterals.BodyShapes.MALE); - Assert.False(controller.myModel.wearables.Any(x => x.id == FEMALE_CATGLASSES_ID)); + Assert.False(controller.myModel.wearables.Any(x => x.id == FEMALE_CAT_GLASSES_ID)); } [Test] public void LoadUserProfileByConstructor() { - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() + wearables = new List { EYEBROWS_ID, "urn:decentraland:off-chain:base-avatars:f_eyes_00", @@ -139,12 +143,12 @@ public void LoadUserProfileByConstructor() "urn:decentraland:off-chain:base-avatars:f_african_leggins", "urn:decentraland:off-chain:base-avatars:f_mouth_00", "urn:decentraland:off-chain:base-avatars:blue_bandana", - "urn:decentraland:off-chain:base-avatars:bee_t_shirt" + "urn:decentraland:off-chain:base-avatars:bee_t_shirt", }, skinColor = skinColorList.colors[0], hairColor = hairColorList.colors[0], eyeColor = eyeColorList.colors[0], - } + }, }); AssertAvatarModelAgainstAvatarEditorHUDModel(userProfile.avatar, controller.myModel); @@ -153,14 +157,14 @@ public void LoadUserProfileByConstructor() [Test] public void ReactToUserProfileUpdate() { - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() + wearables = new List { EYEBROWS_ID, "urn:decentraland:off-chain:base-avatars:f_eyes_00", @@ -168,12 +172,12 @@ public void ReactToUserProfileUpdate() "urn:decentraland:off-chain:base-avatars:f_african_leggins", "urn:decentraland:off-chain:base-avatars:f_mouth_00", "urn:decentraland:off-chain:base-avatars:blue_bandana", - "urn:decentraland:off-chain:base-avatars:bee_t_shirt" + "urn:decentraland:off-chain:base-avatars:bee_t_shirt", }, skinColor = skinColorList.colors[0], hairColor = hairColorList.colors[0], eyeColor = eyeColorList.colors[0], - } + }, }); AssertAvatarModelAgainstAvatarEditorHUDModel(userProfile.avatar, controller.myModel); @@ -260,14 +264,14 @@ public void RandomizeOnlyTheSelectedSetOfWearables() [Test] public void SaveAvatarProperly() { - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() + wearables = new List { EYEBROWS_ID, "urn:decentraland:off-chain:base-avatars:f_eyes_00", @@ -275,12 +279,12 @@ public void SaveAvatarProperly() "urn:decentraland:off-chain:base-avatars:f_african_leggins", "urn:decentraland:off-chain:base-avatars:f_mouth_00", "urn:decentraland:off-chain:base-avatars:blue_bandana", - "urn:decentraland:off-chain:base-avatars:bee_t_shirt" + "urn:decentraland:off-chain:base-avatars:bee_t_shirt", }, skinColor = skinColorList.colors[0], hairColor = hairColorList.colors[0], eyeColor = eyeColorList.colors[0], - } + }, }); controller.WearableClicked(WearableLiterals.BodyShapes.MALE); @@ -309,9 +313,9 @@ public void SendNewEquippedWearablesAnalyticsProperly() { category = WearableLiterals.Categories.EYES, tags = new[] { WearableLiterals.Tags.BASE_WEARABLE }, - representations = new WearableItem.Representation[] { } + representations = new WearableItem.Representation[] { }, }, - i18n = new i18n[] { new i18n { code = "en", text = "testWearableId1" } } + i18n = new i18n[] { new i18n { code = "en", text = "testWearableId1" } }, }; WearableItem newTestWearableequipped1 = new WearableItem @@ -322,9 +326,9 @@ public void SendNewEquippedWearablesAnalyticsProperly() { category = WearableLiterals.Categories.FEET, tags = new[] { WearableLiterals.Tags.BASE_WEARABLE }, - representations = new WearableItem.Representation[] { } + representations = new WearableItem.Representation[] { }, }, - i18n = new i18n[] { new i18n { code = "en", text = "testWearableIdEquipped1" } } + i18n = new i18n[] { new i18n { code = "en", text = "testWearableIdEquipped1" } }, }; WearableItem newTestWearableequipped2 = new WearableItem @@ -335,9 +339,9 @@ public void SendNewEquippedWearablesAnalyticsProperly() { category = WearableLiterals.Categories.FEET, tags = new[] { WearableLiterals.Tags.BASE_WEARABLE }, - representations = new WearableItem.Representation[] { } + representations = new WearableItem.Representation[] { }, }, - i18n = new i18n[] { new i18n { code = "en", text = "testWearableIdEquipped2" } } + i18n = new i18n[] { new i18n { code = "en", text = "testWearableIdEquipped2" } }, }; wearablesCatalogService.WearablesCatalog.Add(alreadyExistingTestWearable.id, alreadyExistingTestWearable); @@ -346,14 +350,14 @@ public void SendNewEquippedWearablesAnalyticsProperly() List oldWearables = new List { - alreadyExistingTestWearable.id + alreadyExistingTestWearable.id, }; List newWearables = new List { alreadyExistingTestWearable.id, newTestWearableequipped1.id, - newTestWearableequipped2.id + newTestWearableequipped2.id, }; // Act diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.asmdef index f6aa65c2ec..8d95500913 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.asmdef @@ -32,21 +32,23 @@ "GUID:c8ea72e806cd2ab47b539b37895b86b7", "GUID:3b80b0b562b1cbc489513f09fc1b8f69", "GUID:68069f49d86442cd9618861b4d74b1aa", - "GUID:f51ebe6a0ceec4240a699833d6309b23" + "GUID:f51ebe6a0ceec4240a699833d6309b23", + "GUID:0c0c18c12967b3944b844b79c47c2320", + "GUID:b1087c5731ff68448a0a9c625bb7e52d", + "GUID:49176a91bbf7f8a4aaf35f6df0643d1a" + ], + "includePlatforms": [ + "Editor" ], - "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": true, "precompiledReferences": [ "nunit.framework.dll", - "NSubstitute.dll", - "System.Threading.Tasks.Extensions.dll" + "NSubstitute.dll" ], "autoReferenced": false, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], + "defineConstraints": [], "versionDefines": [], "noEngineReferences": false } \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.cs index 6488b1e2ab..113c521803 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDTests.cs @@ -1,4 +1,5 @@ using DCL; +using DCL.Emotes; using DCLServices.WearablesCatalogService; using MainScripts.DCL.Controllers.HUD.CharacterPreview; using MainScripts.DCL.Models.AvatarAssets.Tests.Helpers; @@ -39,15 +40,14 @@ protected override IEnumerator SetUp() userProfile = ScriptableObject.CreateInstance(); - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, wearables = new List() - { } } }); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDViewShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDViewShould.cs index 75cb735bae..a6e0768c5b 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDViewShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/AvatarEditorHUDViewShould.cs @@ -1,4 +1,5 @@ using DCL; +using DCL.Emotes; using DCLServices.WearablesCatalogService; using MainScripts.DCL.Controllers.HUD.CharacterPreview; using MainScripts.DCL.Models.AvatarAssets.Tests.Helpers; @@ -18,6 +19,7 @@ public class AvatarEditorHUDViewShould : IntegrationTestSuite_Legacy private AvatarEditorHUDController_Mock controller; private IAnalytics analytics; private IWearablesCatalogService wearablesCatalogService; + private IEmotesService emotesService; [UnitySetUp] protected override IEnumerator SetUp() @@ -42,15 +44,16 @@ protected override IEnumerator TearDown() private void Setup_AvatarEditorHUDController() { userProfile = ScriptableObject.CreateInstance(); - userProfile.UpdateData(new UserProfileModel() + + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); analytics = Substitute.For(); @@ -59,8 +62,11 @@ private void Setup_AvatarEditorHUDController() IUserProfileBridge userProfileBridge = Substitute.For(); userProfileBridge.GetOwn().Returns(userProfile); + emotesService = Substitute.For(); + controller = new AvatarEditorHUDController_Mock(DataStore.i.featureFlags, analytics, wearablesCatalogService, userProfileBridge); + controller.collectionsAlreadyLoaded = true; controller.Initialize(false, Substitute.For()); } @@ -70,16 +76,17 @@ private void Setup_AvatarEditorHUDController() [TestCase("urn:decentraland:off-chain:base-avatars:eyebrows_02", WearableLiterals.BodyShapes.MALE)] public void Activate_CompatibleWithBodyShape_ItemToggle(string wearableId, string bodyShape) { - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = bodyShape, - wearables = new List() { }, - } + wearables = new List(), + }, }); + var category = wearablesCatalogService.WearablesCatalog.Get(wearableId).data.category; Assert.IsTrue(controller.myView.selectorsByCategory.ContainsKey(category)); @@ -98,15 +105,15 @@ public void Activate_CompatibleWithBodyShape_ItemToggle(string wearableId, strin [TestCase("urn:decentraland:off-chain:base-avatars:eyebrows_02", WearableLiterals.BodyShapes.FEMALE)] public void IncompatibleWithBodyShape_ItemToggle(string wearableId, string bodyShape) { - userProfile.UpdateData(new UserProfileModel() + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = bodyShape, - wearables = new List() { }, - } + wearables = new List(), + }, }); var category = wearablesCatalogService.WearablesCatalog.Get(wearableId).data.category; @@ -132,16 +139,17 @@ public void NotAdd_BaseWearables_ToCollectibles(string wearableId) [TestCase("urn:decentraland:off-chain:halloween_2019:sad_clown_upper_body")] public void Add_Exclusives_ToCollectibles(string wearableId) { - userProfile.SetInventory(new[] {wearableId}); - userProfile.UpdateData(new UserProfileModel() + userProfile.SetInventory(new[] { wearableId }); + + userProfile.UpdateData(new UserProfileModel { name = "name", email = "email", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); // changed from itemToggles from totalWearables since this wearable cant be used by the test avatar ( female ) @@ -161,11 +169,11 @@ public void CreateNFTsButtonsByRarityCorrectly(string rarity) var selector = controller.myView.selectorsByCategory[dummyItem.data.category]; var itemToggleObject = selector.currentItemToggles[dummyItem.id].gameObject; - var originalName = "";//selector.itemToggleFactory.nftDictionary[rarity].prefab.name; + var originalName = ""; //selector.itemToggleFactory.nftDictionary[rarity].prefab.name; Assert.IsTrue( itemToggleObject.name - .Contains(originalName)); //Comparing names because PrefabUtility.GetOutermostPrefabInstanceRoot(itemToggleObject) is returning null + .Contains(originalName)); //Comparing names because PrefabUtility.GetOutermostPrefabInstanceRoot(itemToggleObject) is returning null } [Test] @@ -179,6 +187,7 @@ public void FillNFTInfoPanelCorrectly() Assert.NotNull(nftInfo); Assert.AreEqual(dummyItem.GetName(), nftInfo.name.text); Assert.AreEqual(dummyItem.description, nftInfo.description.text); + Assert.AreEqual($"{dummyItem.issuedId} / {dummyItem.GetIssuedCountFromRarity(dummyItem.rarity)}", nftInfo.minted.text); } @@ -187,20 +196,22 @@ public void FillNFTInfoPanelCorrectly() public void NotShowAmmountIfOnlyOneItemIsPossesed() { var wearableId = "urn:decentraland:off-chain:halloween_2019:sad_clown_upper_body"; - userProfile.SetInventory(new[] {wearableId}); - userProfile.UpdateData(new UserProfileModel() + userProfile.SetInventory(new[] { wearableId }); + + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.MALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); - Assert.IsFalse(controller.myView.collectiblesItemSelector.currentItemToggles[wearableId].amountContainer.gameObject - .activeSelf); + Assert.IsFalse(controller.myView.collectiblesItemSelector.currentItemToggles[wearableId] + .amountContainer.gameObject + .activeSelf); } [Test] @@ -212,19 +223,20 @@ public void ShowAndUpdateAmount(int amount) { var wearableId = "urn:decentraland:off-chain:halloween_2019:sad_clown_upper_body"; userProfile.SetInventory(Enumerable.Repeat(wearableId, amount)); - userProfile.UpdateData(new UserProfileModel() + + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.MALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); var itemToggle = controller.myView.selectorsByCategory[WearableLiterals.Categories.UPPER_BODY] - .currentItemToggles[wearableId]; + .currentItemToggles[wearableId]; Assert.IsTrue(itemToggle.amountContainer.gameObject.activeSelf); Assert.AreEqual($"x{amount}", itemToggle.amountText.text); @@ -239,15 +251,16 @@ public void ShowAndUpdateAmountInCollectibleTab(int amount) { var wearableId = "urn:decentraland:off-chain:halloween_2019:sad_clown_upper_body"; userProfile.SetInventory(Enumerable.Repeat(wearableId, amount)); - userProfile.UpdateData(new UserProfileModel() + + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.MALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); var itemToggle = controller.myView.collectiblesItemSelector.currentItemToggles[wearableId]; @@ -262,9 +275,9 @@ public void MarkNFTAsSmart() var smartNft = CreateSmartNFT(); var selector = controller.myView.selectorsByCategory[smartNft.data.category]; - var itemToggleObject = (NFTItemToggle) selector.currentItemToggles[smartNft.id]; + var itemToggleObject = (NFTItemToggle)selector.currentItemToggles[smartNft.id]; - Assert.IsTrue( itemToggleObject.smartItemBadge.activeSelf); + Assert.IsTrue(itemToggleObject.smartItemBadge.activeSelf); } [Test] @@ -273,9 +286,9 @@ public void HideSmartIconWhenIsNormalNFT() var smartNft = CreateDummyNFT("rare"); var selector = controller.myView.selectorsByCategory[smartNft.data.category]; - var itemToggleObject = (NFTItemToggle) selector.currentItemToggles[smartNft.id]; + var itemToggleObject = (NFTItemToggle)selector.currentItemToggles[smartNft.id]; - Assert.IsFalse( itemToggleObject.smartItemBadge.activeSelf); + Assert.IsFalse(itemToggleObject.smartItemBadge.activeSelf); } [Test] @@ -287,37 +300,42 @@ public void ShowWarningWhenNoLinkedWearableAvailable() private WearableItem CreateDummyNFT(string rarity) { - var dummyItem = new WearableItem() + var dummyItem = new WearableItem { id = "dummyItem", rarity = rarity, description = "My Description", issuedId = 1, - data = new WearableItem.Data() + data = new WearableItem.Data { category = WearableLiterals.Categories.EYES, - tags = new[] {WearableLiterals.Tags.EXCLUSIVE}, + tags = new[] { WearableLiterals.Tags.EXCLUSIVE }, representations = new[] { - new WearableItem.Representation() + new WearableItem.Representation { - bodyShapes = new[] {WearableLiterals.BodyShapes.FEMALE, WearableLiterals.BodyShapes.MALE}, - } - } + bodyShapes = new[] { WearableLiterals.BodyShapes.FEMALE, WearableLiterals.BodyShapes.MALE }, + }, + }, + }, + i18n = new[] + { + new i18n + { code = "en", text = "Dummy Item" }, }, - i18n = new[] {new i18n() {code = "en", text = "Dummy Item"}} }; - userProfile.SetInventory(new[] {dummyItem.id}); - userProfile.UpdateData(new UserProfileModel() + userProfile.SetInventory(new[] { dummyItem.id }); + + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() { }, - } + wearables = new List(), + }, }); wearablesCatalogService.WearablesCatalog.Remove(dummyItem.id); @@ -336,29 +354,30 @@ private WearableItem CreateSmartNFT() data = new WearableItem.Data { category = WearableLiterals.Categories.EYES, - tags = new[] {WearableLiterals.Tags.EXCLUSIVE}, + tags = new[] { WearableLiterals.Tags.EXCLUSIVE }, representations = new[] { new WearableItem.Representation { - bodyShapes = new[] {WearableLiterals.BodyShapes.FEMALE, WearableLiterals.BodyShapes.MALE}, - contents = new[] {new WearableItem.MappingPair {key = "game.js", hash = "hash"}} - } - } + bodyShapes = new[] { WearableLiterals.BodyShapes.FEMALE, WearableLiterals.BodyShapes.MALE }, + contents = new[] { new WearableItem.MappingPair { key = "game.js", hash = "hash" } }, + }, + }, }, - i18n = new[] {new i18n {code = "en", text = "Smart Item"}} + i18n = new[] { new i18n { code = "en", text = "Smart Item" } }, }; - userProfile.SetInventory(new[] {dummyItem.id}); + userProfile.SetInventory(new[] { dummyItem.id }); + userProfile.UpdateData(new UserProfileModel { name = "name", email = "mail", - avatar = new AvatarModel() + avatar = new AvatarModel { bodyShape = WearableLiterals.BodyShapes.FEMALE, - wearables = new List() - } + wearables = new List(), + }, }); wearablesCatalogService.WearablesCatalog.Remove(dummyItem.id); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteCardComponentViewTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteCardComponentViewTests.cs index 84d39fc179..0872564c6b 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteCardComponentViewTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteCardComponentViewTests.cs @@ -1,8 +1,11 @@ +using DCL.Helpers; using NUnit.Framework; using UnityEngine; +using UnityEngine.TestTools; namespace DCL.EmotesCustomization.Tests { + [TestFixture, RequiresPlayMode] public class EmoteCardComponentViewTests { private EmoteCardComponentView emoteCardComponent; @@ -21,8 +24,8 @@ public void SetUp() public void TearDown() { emoteCardComponent.Dispose(); - GameObject.Destroy(testTexture); - GameObject.Destroy(testSprite); + Utils.SafeDestroy(testTexture); + Utils.SafeDestroy(testSprite); } [Test] @@ -323,4 +326,4 @@ public void RaiseOnEmoteImageLoadedCorrectly(bool useNullSprite) Assert.AreEqual(testSprite, emoteCardComponent.model.pictureSprite, "The pciture sprite does not match in the model."); } } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotCardComponentViewTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotCardComponentViewTests.cs index e521500d51..d6470d16f0 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotCardComponentViewTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotCardComponentViewTests.cs @@ -1,8 +1,11 @@ +using DCL.Helpers; using NUnit.Framework; using UnityEngine; +using UnityEngine.TestTools; namespace DCL.EmotesCustomization.Tests { + [TestFixture, RequiresPlayMode] public class EmoteSlotCardComponentViewTests { private EmoteSlotCardComponentView emoteSlotCardComponent; @@ -21,8 +24,8 @@ public void SetUp() public void TearDown() { emoteSlotCardComponent.Dispose(); - GameObject.Destroy(testTexture); - GameObject.Destroy(testSprite); + Utils.SafeDestroy(testTexture); + Utils.SafeDestroy(testSprite); } [Test] @@ -277,4 +280,4 @@ private void SetSelectedVisualsForHoveringAssert(bool isSelected) Assert.AreEqual(isSelected, emoteSlotCardComponent.slotViewerImage.gameObject.activeSelf); } } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs index efea27602f..0857367707 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs @@ -1,9 +1,12 @@ +using DCL.Helpers; using NUnit.Framework; using System.Collections.Generic; using UnityEngine; +using UnityEngine.TestTools; namespace DCL.EmotesCustomization.Tests { + [TestFixture, RequiresPlayMode] public class EmoteSlotSelectorComponentViewTests { private EmoteSlotSelectorComponentView emoteSlotSelectorComponent; @@ -22,8 +25,8 @@ public void SetUp() public void TearDown() { emoteSlotSelectorComponent.Dispose(); - GameObject.Destroy(testTexture); - GameObject.Destroy(testSprite); + Utils.SafeDestroy(testTexture); + Utils.SafeDestroy(testSprite); } [Test] @@ -144,4 +147,4 @@ public void UnsubscribeSlotButtonsCorrectly(int slotIndex) Assert.IsFalse(clickedResponse); } } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs index e8986f8ed0..28f6eef8c1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs @@ -1,10 +1,10 @@ +using AvatarSystem; using NSubstitute; using NSubstitute.Extensions; using NUnit.Framework; using System.Collections.Generic; using System.Linq; using DCL.Emotes; -using UnityEngine; namespace DCL.EmotesCustomization.Tests { @@ -12,30 +12,34 @@ public class EmotesCustomizationComponentControllerTests { private EmotesCustomizationComponentController emotesCustomizationComponentController; private DataStore_EmotesCustomization emotesCustomizationDataStore; - private DataStore_Emotes emotesDataStore; private DataStore_ExploreV2 exploreV2DataStore; private DataStore_HUDs hudsDataStore; private IEmotesCustomizationComponentView emotesCustomizationComponentView; + private IAvatarEmotesController emotesController; [SetUp] public void SetUp() { emotesCustomizationDataStore = new DataStore_EmotesCustomization(); - emotesDataStore = new DataStore_Emotes(); exploreV2DataStore = new DataStore_ExploreV2(); hudsDataStore = new DataStore_HUDs(); emotesCustomizationComponentView = Substitute.For(); emotesCustomizationComponentController = Substitute.ForPartsOf(); + emotesController = Substitute.For(); emotesCustomizationComponentController.Configure().CreateView().Returns(info => emotesCustomizationComponentView); + emotesCustomizationComponentController.Initialize(emotesCustomizationDataStore, - emotesDataStore, + emotesController, exploreV2DataStore, hudsDataStore, null); } [TearDown] - public void TearDown() { emotesCustomizationComponentController.Dispose(); } + public void TearDown() + { + emotesCustomizationComponentController.Dispose(); + } [Test] public void InitializeCorrectly() @@ -49,10 +53,11 @@ public void RestoreEmoteSlotsCorrectly() { // Arrange emotesCustomizationDataStore.unsavedEquippedEmotes.Set(new List()); + emotesCustomizationDataStore.equippedEmotes.Set(new List { - new EquippedEmoteData { id = "TestId1", cachedThumbnail = null }, - new EquippedEmoteData { id = "TestId2", cachedThumbnail = null } + new () { id = "TestId1", cachedThumbnail = null }, + new () { id = "TestId2", cachedThumbnail = null }, }); // Act @@ -68,8 +73,8 @@ public void RaiseOnEquippedEmotesSetCorrectly() // Arrange List testEquippedEmotes = new List { - new EquippedEmoteData { id = "TestId1", cachedThumbnail = null }, - new EquippedEmoteData { id = "TestId2", cachedThumbnail = null } + new () { id = "TestId1", cachedThumbnail = null }, + new () { id = "TestId2", cachedThumbnail = null }, }; // Act @@ -106,24 +111,25 @@ public void ProcessCatalogCorrectly() { // Arrange emotesCustomizationComponentController.emotesCustomizationDataStore.currentLoadedEmotes.Set(new List()); - string testId1 = "TestId1"; - string testId2 = "TestId2"; - WearableItem[] emotes = new [] + var testId1 = "TestId1"; + var testId2 = "TestId2"; + + WearableItem[] emotes = { - new WearableItem + new () { id = testId1, - emoteDataV0 = new Emotes.EmoteDataV0 { loop = false }, - data = new WearableItem.Data { tags = new string[] { WearableLiterals.Tags.BASE_WEARABLE } }, - i18n = new i18n[] { new i18n { code = "en", text = testId1 } } + emoteDataV0 = new EmoteDataV0 { loop = false }, + data = new WearableItem.Data { tags = new[] { WearableLiterals.Tags.BASE_WEARABLE } }, + i18n = new[] { new i18n { code = "en", text = testId1 } }, }, - new WearableItem + new () { id = testId2, - emoteDataV0 = new Emotes.EmoteDataV0 { loop = false }, - data = new WearableItem.Data { tags = new string[] { WearableLiterals.Tags.BASE_WEARABLE } }, - i18n = new i18n[] { new i18n { code = "en", text = testId2 } } - } + emoteDataV0 = new EmoteDataV0 { loop = false }, + data = new WearableItem.Data { tags = new[] { WearableLiterals.Tags.BASE_WEARABLE } }, + i18n = new[] { new i18n { code = "en", text = testId2 } }, + }, }; // Act @@ -135,28 +141,6 @@ public void ProcessCatalogCorrectly() Assert.AreEqual(testId2, emotesCustomizationComponentController.emotesCustomizationDataStore.currentLoadedEmotes.Get().ToList()[1]); } - [Test] - public void RefreshEmoteLoadingStateCorrectly() - { - // Arrange - string emoteId = "TestId"; - EmoteCardComponentView testEmoteCard = new GameObject().AddComponent(); - emotesCustomizationComponentController.SetEquippedBodyShape("bodyShapeId"); - - emotesCustomizationComponentController.emotesDataStore.animations - .Add(("bodyShapeId", emoteId), new EmoteClipData(new AnimationClip())); - - testEmoteCard.model = new EmoteCardComponentModel { isLoading = true }; - emotesCustomizationComponentController.emotesInLoadingState.Add(emoteId, testEmoteCard); - - // Act - emotesCustomizationComponentController.RefreshEmoteLoadingState(emoteId); - - // Assert - Assert.IsFalse(testEmoteCard.model.isLoading); - Assert.AreEqual(0, emotesCustomizationComponentController.emotesInLoadingState.Count()); - } - [Test] public void ParseWearableItemIntoEmoteCardModelCorrectly() { @@ -164,12 +148,12 @@ public void ParseWearableItemIntoEmoteCardModelCorrectly() WearableItem testWearableItem = new WearableItem { id = "TestId", - i18n = new i18n[] { new i18n { code = "en", text = "Test Name" } }, + i18n = new[] { new i18n { code = "en", text = "Test Name" } }, description = "Test Desc", baseUrl = "", thumbnail = "", thumbnailSprite = null, - rarity = "Epic" + rarity = "Epic", }; // Act @@ -190,31 +174,29 @@ public void ParseWearableItemIntoEmoteCardModelCorrectly() Assert.AreEqual(true, result.isCollectible); } - [Test] public void UpdateEmoteSlotsCorrectly() { // Arrange - string testId1 = "TestId1"; - string testId2 = "TestId2"; + var testId1 = "TestId1"; + var testId2 = "TestId2"; - WearableItem[] emotes = new [] + WearableItem[] emotes = { - - new WearableItem + new () { id = testId1, - emoteDataV0 = new Emotes.EmoteDataV0 { loop = false }, - data = new WearableItem.Data { tags = new string[] { WearableLiterals.Tags.BASE_WEARABLE } }, - i18n = new i18n[] { new i18n { code = "en", text = testId1 } } + emoteDataV0 = new EmoteDataV0 { loop = false }, + data = new WearableItem.Data { tags = new[] { WearableLiterals.Tags.BASE_WEARABLE } }, + i18n = new[] { new i18n { code = "en", text = testId1 } }, }, - new WearableItem + new () { id = testId2, - emoteDataV0 = new Emotes.EmoteDataV0 { loop = false }, - data = new WearableItem.Data { tags = new string[] { WearableLiterals.Tags.BASE_WEARABLE } }, - i18n = new i18n[] { new i18n { code = "en", text = testId2 } } - } + emoteDataV0 = new EmoteDataV0 { loop = false }, + data = new WearableItem.Data { tags = new[] { WearableLiterals.Tags.BASE_WEARABLE } }, + i18n = new[] { new i18n { code = "en", text = testId2 } }, + }, }; emotesCustomizationComponentController.ownedEmotes = emotes.ToDictionary(x => x.id, x => x); @@ -222,8 +204,8 @@ public void UpdateEmoteSlotsCorrectly() emotesCustomizationDataStore.unsavedEquippedEmotes.Set(new List { - new EquippedEmoteData { id = testId1, cachedThumbnail = null }, - new EquippedEmoteData { id = testId2, cachedThumbnail = null } + new () { id = testId1, cachedThumbnail = null }, + new () { id = testId2, cachedThumbnail = null }, }); // Act @@ -237,11 +219,11 @@ public void UpdateEmoteSlotsCorrectly() public void RaiseOnEmoteEquippedCorrectly() { // Arrange - string emoteId = "TestId"; - string receivedId1 = ""; + var emoteId = "TestId"; + var receivedId1 = ""; emotesCustomizationComponentController.onEmotePreviewed += (id) => { receivedId1 = id; }; - string receivedId2 = ""; + var receivedId2 = ""; emotesCustomizationComponentController.onEmoteEquipped += (id) => { receivedId2 = id; }; // Act @@ -256,8 +238,8 @@ public void RaiseOnEmoteEquippedCorrectly() public void RaiseOnEmoteUnequippedCorrectly() { // Arrange - string emoteId = "TestId"; - string receivedId = ""; + var emoteId = "TestId"; + var receivedId = ""; emotesCustomizationComponentController.onEmoteUnequipped += (id) => { receivedId = id; }; // Act @@ -271,8 +253,8 @@ public void RaiseOnEmoteUnequippedCorrectly() public void RaiseOnSellEmoteClickedCorrectly() { // Arrange - string emoteId = "TestId"; - string receivedId = ""; + var emoteId = "TestId"; + var receivedId = ""; emotesCustomizationComponentController.onEmoteSell += (id) => { receivedId = id; }; // Act @@ -286,8 +268,8 @@ public void RaiseOnSellEmoteClickedCorrectly() public void RaiseOnSlotSelectedCorrectly() { // Arrange - string emoteId = "TestId"; - string receivedId = ""; + var emoteId = "TestId"; + var receivedId = ""; emotesCustomizationComponentController.onEmotePreviewed += (id) => { receivedId = id; }; // Act diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs index 087bf0bed8..5afda170bb 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs @@ -1,9 +1,12 @@ +using DCL.Helpers; using NUnit.Framework; using System.Collections.Generic; using UnityEngine; +using UnityEngine.TestTools; namespace DCL.EmotesCustomization.Tests { + [TestFixture, RequiresPlayMode] public class EmotesCustomizationComponentViewTests { private EmotesCustomizationComponentView emotesCustomizationComponent; @@ -25,8 +28,8 @@ public void TearDown() { testEmoteSlotCard.Dispose(); emotesCustomizationComponent.Dispose(); - GameObject.Destroy(testTexture); - GameObject.Destroy(testSprite); + Utils.SafeDestroy(testTexture); + Utils.SafeDestroy(testSprite); } [Test] @@ -353,4 +356,4 @@ private EmoteCardComponentModel GetTestEmoteCardModel() }; } } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2.asmdef index 5357f11478..9071b9576c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2.asmdef @@ -70,7 +70,8 @@ "GUID:a4bf61c057a098f4ca05b539a6d8c0fe", "GUID:5ec801bb410ed4adf91f82aa97aaf380", "GUID:4ad87ae8afda2df4d897ad1a3527cd1d", - "GUID:d6fe1b5729e3405d98cf8ff2035d9542" + "GUID:d6fe1b5729e3405d98cf8ff2035d9542", + "GUID:0c0c18c12967b3944b844b79c47c2320" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs index c09cde1470..f7c14e6d32 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs @@ -1,3 +1,4 @@ +using AvatarSystem; using Cysharp.Threading.Tasks; using DCL.Tasks; using MainScripts.DCL.Controllers.HUD.CharacterPreview; @@ -46,6 +47,7 @@ public class BackpackEditorHUDV2ComponentView : BaseComponentView originalVisibleRenderers => backpackPreviewPanel?.originalVisibleRenderers; + public IAvatarEmotesController EmotesController => backpackPreviewPanel?.EmotesController; public override bool isVisible => gameObject.activeInHierarchy; public Transform EmotesSectionTransform => emotesSection.transform; public WearableGridComponentView WearableGridComponentView => wearableGridComponentView; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorV2Plugin.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorV2Plugin.cs index e3bc6303eb..90521c2026 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorV2Plugin.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorV2Plugin.cs @@ -1,5 +1,6 @@ using Cysharp.Threading.Tasks; using DCL.Browser; +using DCL.Emotes; using DCL.Providers; using DCLServices.CustomNftCollection; using DCLServices.DCLFileBrowser; @@ -24,7 +25,8 @@ private async UniTaskVoid Initialize() var assetsProvider = Environment.i.platform.serviceLocator.Get(); var vrmExporterReferences = await assetsProvider.Instantiate("VRMExporter", "_VRMExporter"); - IWearablesCatalogService wearablesCatalogService = Environment.i.serviceLocator.Get(); + ServiceLocator serviceLocator = Environment.i.serviceLocator; + IWearablesCatalogService wearablesCatalogService = serviceLocator.Get(); var userProfileBridge = new UserProfileWebInterfaceBridge(); DataStore dataStore = DataStore.i; @@ -32,7 +34,7 @@ private async UniTaskVoid Initialize() var view = BackpackEditorHUDV2ComponentView.Create(); view.Initialize( - Environment.i.serviceLocator.Get(), + serviceLocator.Get(), new PreviewCameraRotationController(), new PreviewCameraPanningController(), new PreviewCameraZoomController()); @@ -41,13 +43,13 @@ private async UniTaskVoid Initialize() Environment.i.platform.serviceProviders.analytics, new NewUserExperienceAnalytics(Environment.i.platform.serviceProviders.analytics)); - view.OutfitsSectionComponentView.Initialize(Environment.i.serviceLocator.Get()); + view.OutfitsSectionComponentView.Initialize(serviceLocator.Get()); var outfitsController = new OutfitsController( view.OutfitsSectionComponentView, new LambdaOutfitsService( - Environment.i.serviceLocator.Get(), - Environment.i.serviceLocator.Get()), + serviceLocator.Get(), + serviceLocator.Get()), userProfileBridge, dataStore, backpackAnalyticsService); @@ -56,8 +58,10 @@ private async UniTaskVoid Initialize() dataStore, view.EmotesSectionTransform, userProfileBridge, - Environment.i.serviceLocator.Get(), - Environment.i.serviceLocator.Get()); + serviceLocator.Get(), + view.EmotesController, + Environment.i.serviceLocator.Get() + ); var backpackFiltersController = new BackpackFiltersController(view.BackpackFiltersComponentView, wearablesCatalogService); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEmotesSectionController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEmotesSectionController.cs index c73fe8feb6..4c82f73fd8 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEmotesSectionController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEmotesSectionController.cs @@ -1,4 +1,5 @@ -using Cysharp.Threading.Tasks; +using AvatarSystem; +using Cysharp.Threading.Tasks; using DCL.Emotes; using DCL.EmotesCustomization; using DCL.Interface; @@ -37,6 +38,7 @@ public BackpackEmotesSectionController( Transform emotesSectionTransform, IUserProfileBridge userProfileBridge, IEmotesCatalogService emotesCatalogService, + IAvatarEmotesController emotesController, ICustomNftCollectionService customNftCollectionService) { this.dataStore = dataStore; @@ -46,7 +48,7 @@ public BackpackEmotesSectionController( emotesCustomizationComponentController = new EmotesCustomizationComponentController( dataStore.emotesCustomization, - dataStore.emotes, + emotesController, dataStore.exploreV2, dataStore.HUDs, emotesSectionTransform, @@ -127,15 +129,19 @@ public void RestoreEmoteSlots() => public void SetEquippedBodyShape(string bodyShapeId) => emotesCustomizationComponentController.SetEquippedBodyShape(bodyShapeId); + // TODO: Delete? private void NewEmoteAdded(string emoteId) => OnNewEmoteAdded?.Invoke(emoteId); + // TODO: Delete? private void EmotePreviewed(string emoteId) => OnEmotePreviewed?.Invoke(emoteId); + // TODO: Delete? private void EmoteEquipped(string emoteId) => OnEmoteEquipped?.Invoke(emoteId); + // TODO: Delete? private void EmoteUnEquipped(string emoteId) => OnEmoteUnEquipped?.Invoke(emoteId); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs index b7524dbbac..0e9f81e9d3 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs @@ -1,4 +1,5 @@ -using Cysharp.Threading.Tasks; +using AvatarSystem; +using Cysharp.Threading.Tasks; using MainScripts.DCL.Controllers.HUD.CharacterPreview; using System; using System.Collections.Generic; @@ -50,6 +51,7 @@ public class BackpackPreviewPanel : BaseComponentView public delegate void OnSnapshotsReady(Texture2D face256, Texture2D body); public IReadOnlyList originalVisibleRenderers => characterPreviewController?.originalVisibleRenderers; + public IAvatarEmotesController EmotesController => characterPreviewController.GetEmotesController(); private ICharacterPreviewController characterPreviewController; private IPreviewCameraRotationController avatarPreviewRotationController; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/WearableGridController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/WearableGridController.cs index 776f256689..3470661744 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/WearableGridController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/WearableGridController.cs @@ -349,11 +349,18 @@ await UniTask.WhenAll(wearablesCatalogService.RequestWearableCollection(publishe private WearableGridItemModel ToWearableGridModel(WearableItem wearable) { - if (!Enum.TryParse(wearable.rarity, true, out NftRarity rarity)) + NftRarity rarity; + + if (string.IsNullOrEmpty(wearable.rarity)) + rarity = NftRarity.None; + else + if (!Enum.TryParse(wearable.rarity, true, out NftRarity result)) { rarity = NftRarity.None; Debug.LogWarning($"Could not parse the rarity \"{wearable.rarity}\" of the wearable '{wearable.id}'. Fallback to common."); } + else + rarity = result; string currentBodyShapeId = dataStoreBackpackV2.previewBodyShape.Get(); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreview.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreview.asmdef index 5954f0a26d..2a60146c00 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreview.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreview.asmdef @@ -18,7 +18,8 @@ "GUID:4720e174f2805c74bb7aa94cc8bb5bf8", "GUID:99cea83ca76dcd846abed7e61a8c90bd", "GUID:4d3366a36e77f41cfb7436340334e236", - "GUID:98bf3bf29030cbf4092d89a7cc28b7fb" + "GUID:98bf3bf29030cbf4092d89a7cc28b7fb", + "GUID:0c0c18c12967b3944b844b79c47c2320" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs index c90a8b8f33..0e6518a97e 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs @@ -1,12 +1,14 @@ using AvatarSystem; using Cysharp.Threading.Tasks; using DCL; +using DCL.Emotes; using MainScripts.DCL.Components.Avatar.VRMExporter; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; +using Environment = DCL.Environment; namespace MainScripts.DCL.Controllers.HUD.CharacterPreview { @@ -220,8 +222,15 @@ public void ConfigureZoom(float verticalCenterRef, float bottomMaxOffset, float public void SetCharacterShadowActive(bool isActive) => avatarShadow.SetActive(isActive); - public void PlayEmote(string emoteId, long timestamp) => - avatar.PlayEmote(emoteId, timestamp); + public IAvatarEmotesController GetEmotesController() => + avatar.GetEmotesController(); + + public void PlayEmote(string emoteId, long timestamp) + { + Debug.Log("[Character Preview] Playing emote " + emoteId); + avatar.GetEmotesController().PlayEmote(emoteId, timestamp); + } + public void Dispose() => Destroy(gameObject); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs index f3128df606..c0a7c4eafa 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs @@ -1,4 +1,6 @@ +using AvatarSystem; using Cysharp.Threading.Tasks; +using DCL.Emotes; using System; using System.Collections.Generic; using System.Threading; @@ -22,5 +24,7 @@ public interface ICharacterPreviewController : IDisposable void SetCameraLimits(Bounds limits); void ConfigureZoom(float verticalCenterRef, float bottomMaxOffset, float topMaxOffset); void SetCharacterShadowActive(bool isActive); + + IAvatarEmotesController GetEmotesController(); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs index 843378b4fe..de26f3c0e5 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs @@ -1,11 +1,15 @@ +using AvatarSystem; using Cysharp.Threading.Tasks; using System.Collections.Generic; using DCL.Emotes; using DCLServices.WearablesCatalogService; +using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using UnityEngine; using UnityEngine.Pool; +using Object = UnityEngine.Object; namespace DCL.EmotesWheel { @@ -19,7 +23,6 @@ public class EmotesWheelController : IHUD private BaseVariable canStartMenuBeOpened => DataStore.i.exploreV2.isSomeModalOpen; private bool shortcutsCanBeUsed => !isStartMenuOpen.Get(); private DataStore_EmotesCustomization emotesCustomizationDataStore => DataStore.i.emotesCustomization; - private BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> emoteAnimations => DataStore.i.emotes.animations; private UserProfile ownUserProfile => UserProfile.GetOwnUserProfile(); private InputAction_Trigger closeWindow; @@ -44,18 +47,22 @@ public class EmotesWheelController : IHUD private InputAction_Trigger auxShortcut7InputAction; private InputAction_Trigger auxShortcut8InputAction; private InputAction_Trigger auxShortcut9InputAction; - private UserProfile userProfile; - private readonly IEmotesCatalogService emoteCatalog; + private readonly UserProfile userProfile; private readonly IWearablesCatalogService wearablesCatalogService; - private bool ownedWearablesAlreadyRequested = false; - private BaseDictionary slotsInLoadingState = new BaseDictionary(); - private CancellationTokenSource loadOwnedWearablesCTS = new CancellationTokenSource(); + private bool ownedWearablesAlreadyRequested; + private readonly BaseDictionary slotsInLoadingState = new (); + private CancellationTokenSource cts = new (); + private readonly IEmotesCatalogService emoteCatalog; + private readonly IEmotesService emotesService; + private IAvatar avatar; + private IAvatarEmotesController emotesController; public EmotesWheelController( UserProfile userProfile, - IEmotesCatalogService emoteCatalog, + IEmotesService emotesService, IWearablesCatalogService wearablesCatalogService) { + this.emotesService = emotesService; closeWindow = Resources.Load("CloseWindow"); closeWindow.OnTriggered += OnCloseWindowPressed; @@ -71,15 +78,33 @@ public EmotesWheelController( isStartMenuOpen.OnChange += IsStartMenuOpenChanged; this.userProfile = userProfile; - this.emoteCatalog = emoteCatalog; this.wearablesCatalogService = wearablesCatalogService; emotesCustomizationDataStore.equippedEmotes.OnSet += OnEquippedEmotesSet; - OnEquippedEmotesSet(emotesCustomizationDataStore.equippedEmotes.Get()); - emoteAnimations.OnAdded += OnAnimationAdded; ConfigureShortcuts(); emotesCustomizationDataStore.isWheelInitialized.Set(true); + + DataStore.i.player.ownPlayer.OnChange += OnPlayerSet; + } + + private void OnPlayerSet(Player current, Player previous) + { + emotesController = current.avatar.GetEmotesController(); + emotesController.OnEmoteEquipped += OnEmoteEquipped; + emotesController.OnEmoteUnequipped += OnEmoteUnequipped; + UpdateEmoteSlots(); + } + + private void OnEmoteEquipped(string emoteId, IEmoteReference emoteReference) + { + Debug.Log($"[EMOTE WHEEL] emote equipped {emoteId}"); + RefreshSlotLoadingState(emoteId); + } + + private void OnEmoteUnequipped(string emoteId) + { + Debug.Log($"[EMOTE WHEEL] emote UNequipped {emoteId} :("); } public void SetVisibility(bool visible) @@ -102,6 +127,7 @@ private void IsStartMenuOpenChanged(bool current, bool previous) private void UpdateEmoteSlots() { + if (emotesController == null) return; List emotesToSet = new List(); var equippedEmotes = ListPool.Get(); @@ -111,25 +137,26 @@ private void UpdateEmoteSlots() { if (equippedEmoteData != null) { - emoteCatalog.TryGetLoadedEmote(equippedEmoteData.id, out var emoteItem); - - if (emoteItem != null) + if (emotesController.TryGetEquippedEmote(userProfile.avatar.bodyShape, equippedEmoteData.id, out var emote)) { + var entity = emote.GetEntity(); + emotesToSet.Add(new EmotesWheelView.EmoteSlotData { - emoteItem = emoteItem, - thumbnailSprite = emoteItem.thumbnailSprite != null ? emoteItem.thumbnailSprite : equippedEmoteData.cachedThumbnail + emoteId = equippedEmoteData.id, + emoteItem = entity, + thumbnailSprite = entity.thumbnailSprite != null ? entity.thumbnailSprite : equippedEmoteData.cachedThumbnail, }); } else - { - emotesToSet.Add(null); - } - } - else - { - emotesToSet.Add(null); - } + emotesToSet.Add(new EmotesWheelView.EmoteSlotData + { + emoteId = equippedEmoteData.id, + emoteItem = null, + thumbnailSprite = equippedEmoteData.cachedThumbnail, + }); + } else + equippedEmotes.Add(null); } ListPool.Release(equippedEmotes); @@ -151,18 +178,21 @@ private void UpdateEmoteSlots() } } - private void OnAnimationAdded((string bodyshapeId, string emoteId) values, EmoteClipData emoteClipData) { RefreshSlotLoadingState(values.emoteId); } - private void RefreshSlotLoadingState(string emoteId) { - if (emoteAnimations.ContainsKey((userProfile.avatar.bodyShape, emoteId))) + if (emotesController.TryGetEquippedEmote(userProfile.avatar.bodyShape, emoteId, out var emote)) { slotsInLoadingState.TryGetValue(emoteId, out EmoteWheelSlot slot); - if (slot != null) + if (slot == null) return; + var entity = emote.GetEntity(); + view.SetupEmoteWheelSlot(slot, new EmotesWheelView.EmoteSlotData { - slot.SetAsLoading(false); - slotsInLoadingState.Remove(emoteId); - } + emoteId = emoteId, + emoteItem = entity, + thumbnailSprite = entity.thumbnailSprite, + }); + slot.SetAsLoading(false); + slotsInLoadingState.Remove(emoteId); } } @@ -195,16 +225,16 @@ async UniTaskVoid RequestOwnedWearablesAsync(CancellationToken ct) if (visible) { - DCL.Helpers.Utils.UnlockCursor(); + Helpers.Utils.UnlockCursor(); if (userProfile != null && !string.IsNullOrEmpty(userProfile.userId) && !ownedWearablesAlreadyRequested) { - loadOwnedWearablesCTS?.Cancel(); - loadOwnedWearablesCTS?.Dispose(); - loadOwnedWearablesCTS = new CancellationTokenSource(); - RequestOwnedWearablesAsync(loadOwnedWearablesCTS.Token).Forget(); + cts?.Cancel(); + cts?.Dispose(); + cts = new CancellationTokenSource(); + RequestOwnedWearablesAsync(cts.Token).Forget(); } } @@ -220,7 +250,6 @@ public void Dispose() ownUserProfile.OnAvatarEmoteSet -= OnAvatarEmoteSet; emotesVisible.OnChange -= OnEmoteVisibleChanged; emotesCustomizationDataStore.equippedEmotes.OnSet -= OnEquippedEmotesSet; - emoteAnimations.OnAdded -= OnAnimationAdded; shortcut0InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; shortcut1InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; shortcut2InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; @@ -241,15 +270,16 @@ public void Dispose() auxShortcut7InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; auxShortcut8InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; auxShortcut9InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; - - loadOwnedWearablesCTS?.Cancel(); - loadOwnedWearablesCTS?.Dispose(); - loadOwnedWearablesCTS = null; + emotesController.OnEmoteEquipped -= OnEmoteEquipped; + emotesController.OnEmoteUnequipped -= OnEmoteUnequipped; + cts?.Cancel(); + cts?.Dispose(); + cts = null; if (view != null) { view.CleanUp(); - UnityEngine.Object.Destroy(view.gameObject); + Object.Destroy(view.gameObject); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelHUD.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelHUD.asmdef index d45f201b74..7b9db3b91c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelHUD.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelHUD.asmdef @@ -24,7 +24,10 @@ "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", "GUID:3b80b0b562b1cbc489513f09fc1b8f69", "GUID:c8ea72e806cd2ab47b539b37895b86b7", - "GUID:f51ebe6a0ceec4240a699833d6309b23" + "GUID:f51ebe6a0ceec4240a699833d6309b23", + "GUID:0c0c18c12967b3944b844b79c47c2320", + "GUID:c34e38f41494f834abff029ddf82af43", + "GUID:49176a91bbf7f8a4aaf35f6df0643d1a" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs index 0b1aa79724..fde648dfd3 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs @@ -10,6 +10,7 @@ public class EmotesWheelView : MonoBehaviour { public class EmoteSlotData { + public string emoteId; public WearableItem emoteItem; public Sprite thumbnailSprite; } @@ -22,7 +23,7 @@ internal class RarityColor } private const string PATH = "EmotesWheelHUD"; - + public event Action onEmoteClicked; public event Action OnClose; @@ -37,7 +38,7 @@ internal class RarityColor [SerializeField] internal GameObject customizeTitle; private HUDCanvasCameraModeController hudCanvasCameraModeController; - + public static EmotesWheelView Create() { return Instantiate(Resources.Load(PATH)).GetComponent(); } private void Awake() @@ -78,42 +79,47 @@ public List SetEmotes(List emotes) { EmoteSlotData equippedEmote = emotes[i]; - if (i < emoteButtons.Length) - { - emoteButtons[i].button.onClick.RemoveAllListeners(); - emoteButtons[i].onSlotHover -= OnSlotHover; - emoteButtons[i].onSlotHover += OnSlotHover; - - if (equippedEmote != null) - { - emoteButtons[i].button.onClick.AddListener(() => onEmoteClicked?.Invoke(equippedEmote.emoteItem.id)); - - if (equippedEmote.thumbnailSprite != null) - emoteButtons[i].SetImage(equippedEmote.thumbnailSprite); - else - emoteButtons[i].SetImage(equippedEmote.emoteItem.ComposeThumbnailUrl()); - - emoteButtons[i].SetId(equippedEmote.emoteItem.id); - emoteButtons[i].SetName(equippedEmote.emoteItem.GetName()); - - RarityColor rarityColor = rarityColors.FirstOrDefault(x => x.rarity == equippedEmote.emoteItem.rarity); - emoteButtons[i].SetRarity( - rarityColor != null, - rarityColor != null ? rarityColor.markColor : Color.white); - } - else - { - emoteButtons[i].SetImage(nonAssignedEmoteSprite); - emoteButtons[i].SetId(string.Empty); - emoteButtons[i].SetName(string.Empty); - emoteButtons[i].SetRarity(false, Color.white); - } - } + if (i >= emoteButtons.Length) continue; + + EmoteWheelSlot emoteWheelSlot = emoteButtons[i]; + SetupEmoteWheelSlot(emoteWheelSlot, equippedEmote); } return emoteButtons.ToList(); } + public void SetupEmoteWheelSlot(EmoteWheelSlot emoteWheelSlot, EmoteSlotData slotData) + { + emoteWheelSlot.button.onClick.RemoveAllListeners(); + emoteWheelSlot.onSlotHover -= OnSlotHover; + emoteWheelSlot.onSlotHover += OnSlotHover; + + if (slotData != null) + { + emoteWheelSlot.button.onClick.AddListener(() => onEmoteClicked?.Invoke(slotData.emoteItem.id)); + + if (slotData.thumbnailSprite != null) + emoteWheelSlot.SetImage(slotData.thumbnailSprite); + else + emoteWheelSlot.SetImage(slotData.emoteItem.ComposeThumbnailUrl()); + + emoteWheelSlot.SetId(slotData.emoteItem.id); + emoteWheelSlot.SetName(slotData.emoteItem.GetName()); + + RarityColor rarityColor = rarityColors.FirstOrDefault(x => x.rarity == slotData.emoteItem.rarity); + emoteWheelSlot.SetRarity( + rarityColor != null, + rarityColor != null ? rarityColor.markColor : Color.white); + } + else + { + emoteWheelSlot.SetImage(nonAssignedEmoteSprite); + emoteWheelSlot.SetId(string.Empty); + emoteWheelSlot.SetName(string.Empty); + emoteWheelSlot.SetRarity(false, Color.white); + } + } + private void OnSlotHover(string emoteName) { selectedEmoteName.text = emoteName; } private void Close() { OnClose?.Invoke(); } @@ -134,4 +140,4 @@ public void CleanUp() openCustomizeButton.onClick.RemoveAllListeners(); } } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/Test/EmotesWheelHUDTests.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/Test/EmotesWheelHUDTests.asmdef index 15ac9ac490..34d095aa8a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/Test/EmotesWheelHUDTests.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/Test/EmotesWheelHUDTests.asmdef @@ -15,7 +15,8 @@ "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", - "GUID:c8ea72e806cd2ab47b539b37895b86b7" + "GUID:c8ea72e806cd2ab47b539b37895b86b7", + "GUID:0c0c18c12967b3944b844b79c47c2320" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/Passport/PassportHUD.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/Passport/PassportHUD.asmdef index d694b569af..baa32ae431 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/Passport/PassportHUD.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/Passport/PassportHUD.asmdef @@ -52,7 +52,8 @@ "GUID:70aa308435753374584c7061e4b89ef2", "GUID:029e05fd02d6c49d5ac9dd7e3725a35b", "GUID:2ce94b4811f2a4b9b8dfd650158f7796", - "GUID:70263d10ecfb462ba0f6762dda35634b" + "GUID:70263d10ecfb462ba0f6762dda35634b", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.asmdef index 601b43375d..8ec958e316 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.asmdef @@ -35,19 +35,18 @@ "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", "GUID:c82a7bd4346dd3d4c9334dbf01ab9a87", "GUID:55b66aa56b81d2d4cafb4a5f02bc90ca", - "GUID:a1e1473c53889c2489c0822a9dd5fa33", "GUID:4016c129fc7e2bd4eba9d6ee09f42a69", "GUID:c2159e5e82608e6469313e7118f72718", "GUID:bf7bc5cfaf25db643b5b7e691a83390c", "GUID:ce5ce184029b7f34c9188d4ae2aeb3d7", - "GUID:c073232dc37f7254ebc6c5dda74c99cb", "GUID:6c1761dc8f737004198eb333521bd665", "GUID:c8ea72e806cd2ab47b539b37895b86b7", "GUID:44002c75b9995c34d97b8afc551d32eb", "GUID:97d8897529779cb49bebd400c7f402a6", "GUID:44a9db8f655ab05409802e5476cf9dd3", "GUID:1dd0780aa6be12b428c8005d0bee46b8", - "GUID:2995626b54c60644988f134a69a77450" + "GUID:2995626b54c60644988f134a69a77450", + "GUID:2d39cc535b437e749965d4a8258f0c13" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.cs index 054bff3e66..05d2309515 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.cs @@ -160,7 +160,7 @@ private void OnEnable() private void OnAvatarEmote(string id, long timestamp, UserProfile.EmoteSource source) { - avatar.PlayEmote(id, timestamp); + avatar.GetEmotesController().PlayEmote(id, timestamp); bool found = DataStore.i.common.wearables.TryGetValue(id, out WearableItem emoteItem); @@ -228,7 +228,7 @@ private async UniTaskVoid LoadingAvatarRoutine(UserProfile profile, Cancellation if (avatar.lodLevel <= 1) AvatarSystemUtils.SpawnAvatarLoadedParticles(avatarContainer.transform, loadingParticlesPrefab); - avatar.PlayEmote(profile.avatar.expressionTriggerId, profile.avatar.expressionTriggerTimestamp); + avatar.GetEmotesController().PlayEmote(profile.avatar.expressionTriggerId, profile.avatar.expressionTriggerTimestamp); } } catch (Exception e) when (e is not OperationCanceledException) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PluginSystem/PluginSystemFactory.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PluginSystem/PluginSystemFactory.cs index e57077f5b6..b0c766f877 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PluginSystem/PluginSystemFactory.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PluginSystem/PluginSystemFactory.cs @@ -48,7 +48,6 @@ public static PluginSystem Create() pluginSystem.Register(() => new SkyboxController(DataStore.i)); pluginSystem.Register(() => new ExperiencesViewerPlugin()); pluginSystem.RegisterWithFlag(() => new ExperiencesConfirmationPlugin(), "px_confirm_enabled"); - pluginSystem.Register(() => new EmoteAnimationsPlugin()); pluginSystem.Register(() => new TeleportHUDPlugin()); pluginSystem.Register(() => new EquippedEmotesInitializerPlugin()); pluginSystem.Register(() => new EmotesWheelUIPlugin()); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore.cs index 69809bf922..98540a0457 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore.cs @@ -55,7 +55,6 @@ public static void Clear() => public WorldTimer worldTimer => i.Get(); public DataStore_Performance performance => i.Get(); public DataStore_ExperiencesViewer experiencesViewer => i.Get(); - public DataStore_Emotes emotes => i.Get(); public DataStore_EmotesCustomization emotesCustomization => i.Get(); public DataStore_SceneBoundariesChecker sceneBoundariesChecker => i.Get(); public DataStore_ECS7 ecs7 => i.Get(); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs deleted file mode 100644 index 8d1afefab9..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using DCL.Emotes; -using UnityEngine; - -namespace DCL -{ - public class DataStore_Emotes - { - public readonly BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesOnUse = new BaseRefCountedCollection<(string bodyshapeId, string emoteId)>(); - public readonly BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animations = new BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData>(); - - - } -} \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs.meta deleted file mode 100644 index 3b642d708b..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_Emotes.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 0f0af4cbcc304e0ea56522692bb85893 -timeCreated: 1645124065 \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_EmotesCustomization.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_EmotesCustomization.cs index ccc775b5a2..542354e4f1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_EmotesCustomization.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_EmotesCustomization.cs @@ -12,18 +12,18 @@ public class EquippedEmoteData public class DataStore_EmotesCustomization { - public readonly BaseVariable isWheelInitialized = new BaseVariable(false); - public readonly BaseCollection unsavedEquippedEmotes = new BaseCollection(new List { null, null, null, null, null, null, null, null, null, null }); - public readonly BaseCollection equippedEmotes = new BaseCollection(new List { null, null, null, null, null, null, null, null, null, null }); - public readonly BaseVariable isEmotesCustomizationSelected = new BaseVariable(false); - public readonly BaseCollection currentLoadedEmotes = new BaseCollection(); + public readonly BaseVariable isWheelInitialized = new (false); + public readonly BaseCollection unsavedEquippedEmotes = new (new List { null, null, null, null, null, null, null, null, null, null }); + public readonly BaseCollection equippedEmotes = new (new List { null, null, null, null, null, null, null, null, null, null }); + public readonly BaseVariable isEmotesCustomizationSelected = new (false); + public readonly BaseCollection currentLoadedEmotes = new (); public void UnequipMissingEmotes(IEnumerable emotes) { var setOfIds = new HashSet(); foreach (var emote in emotes) setOfIds.Add(emote.id); - + for (int i = 0; i < equippedEmotes.Count(); i++) { if (equippedEmotes[i] != null && !setOfIds.Contains(equippedEmotes[i].id)) @@ -31,4 +31,4 @@ public void UnequipMissingEmotes(IEnumerable emotes) } } } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.asmdef index 69fcba5ab6..3666f3cab9 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.asmdef @@ -87,6 +87,8 @@ "GUID:70263d10ecfb462ba0f6762dda35634b", "GUID:4da9df9a132541f2a0ce3fc6f0578851", "GUID:a385efcc15091954c9f00857801f60b3", + "GUID:687884b2e72b39a439951d6db2e2c7ee", + "GUID:0c0c18c12967b3944b844b79c47c2320", "GUID:d6fe1b5729e3405d98cf8ff2035d9542", "GUID:a4bf61c057a098f4ca05b539a6d8c0fe" ], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs index cc193f1ff7..6e2a653992 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs @@ -2,6 +2,7 @@ using DCL.Chat; using DCL.Chat.Channels; using DCL.Controllers; +using DCL.Emotes; using DCL.Helpers; using DCL.ProfanityFiltering; using DCL.Providers; @@ -79,6 +80,7 @@ public static ServiceLocator CreateDefault() new DeleteWebRequestFactory(), new RPCSignRequest(irpc) ); + result.Register(() => webRequestController); result.Register(() => new ServiceProviders()); @@ -130,6 +132,7 @@ public static ServiceLocator CreateDefault() result.Get(), result.Get(), featureFlagsDataStore); + var lambdasEmotesCatalogService = new LambdasEmotesCatalogService(emotesRequest, addressableResourceProvider, result.Get().catalyst, result.Get(), DataStore.i); var webInterfaceEmotesCatalogService = new WebInterfaceEmotesCatalogService(EmotesCatalogBridge.GetOrCreate(), addressableResourceProvider); @@ -156,6 +159,11 @@ public static ServiceLocator CreateDefault() result.Register(WebInterfaceCustomNftCatalogBridge.GetOrCreate); + result.Register(() => new EmotesService(new EmoteAnimationLoaderFactory(), + result.Get(), + result.Get(), + result.Get().catalyst)); + result.Register(() => new ThrottledRegexProfanityFilter( new ProfanityWordProviderFromResourcesJson("Profanity/badwords"), 20)); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/FeatureFlags/FeatureFlagController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/FeatureFlags/FeatureFlagController.cs index ef1b69354a..ce701d9f8c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/FeatureFlags/FeatureFlagController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/FeatureFlags/FeatureFlagController.cs @@ -1,4 +1,5 @@ using DCL; +using DCL.Helpers; using UnityEngine; public class FeatureFlagController : IFeatureFlagController @@ -35,7 +36,7 @@ public void AddBridgeComponent(GameObject gameObjectToAddBridge) public void Dispose() { - Object.Destroy(bridgeGameObject); + Utils.SafeDestroy(bridgeGameObject); bridgeGameObject = null; featureFlagBridgeComponent = null; } @@ -43,4 +44,4 @@ public void Dispose() public void Initialize() { } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/AvatarAssets.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/AvatarAssets.asmdef index 67c0b0544a..f44cf287b4 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/AvatarAssets.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/AvatarAssets.asmdef @@ -6,7 +6,8 @@ "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", "GUID:b24824f3bc2a60641a01e2083614f802", "GUID:6e6a87f97192ec947993f360104e75b7", - "GUID:f51ebe6a0ceec4240a699833d6309b23" + "GUID:f51ebe6a0ceec4240a699833d6309b23", + "GUID:97d8897529779cb49bebd400c7f402a6" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index 8893b8aa49..771929bb70 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -21,29 +21,32 @@ public EmoteClipData(AnimationClip avatarClip, bool loop = false) this.Loop = loop; } - public void LoadExtraContent(GameObject extraContent, AudioClip audioClip) + public EmoteClipData(AnimationClip mainClip, GameObject container, AudioClip audioClip, bool loop = false) { - this.ExtraContent = extraContent; + this.AvatarClip = mainClip; + this.Loop = loop; + this.ExtraContent = container; this.AudioClip = audioClip; - if (extraContent != null) - { - animation = extraContent.GetComponentInChildren(); + if (ExtraContent == null) return; - if (animation == null) - Debug.LogError($"Animation {AvatarClip.name} extra content does not have an animation"); + animation = ExtraContent.GetComponentInChildren(); - renderers = extraContent.GetComponentsInChildren(); - } + if (animation == null) + Debug.LogError($"Animation {AvatarClip.name} extra content does not have an animation"); + + renderers = ExtraContent.GetComponentsInChildren(); } - public void PlayAllAnimations() + + public void PlayAllAnimations(int gameObjectLayer) { if (renderers != null) { foreach (Renderer renderer in renderers) { renderer.enabled = true; + renderer.gameObject.layer = gameObjectLayer; } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/SceneEmoteHelper.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/SceneEmoteHelper.cs new file mode 100644 index 0000000000..1eaa5b8e3e --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/SceneEmoteHelper.cs @@ -0,0 +1,51 @@ +using Cysharp.Threading.Tasks; +using DCL.Controllers; +using DCL.Emotes; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace AvatarAssets +{ + public static class SceneEmoteHelper + { + public const string SCENE_EMOTE_PREFIX = "urn:decentraland:off-chain:scene-emote:"; + + public static bool TryGenerateEmoteId(IParcelScene scene, string emoteFilePath, bool loop, out string emoteId) + { + if (scene.contentProvider.TryGetContentHash(emoteFilePath, out string emoteHash)) + { + emoteId = $"{SCENE_EMOTE_PREFIX}{emoteHash}-{(loop ? "true" : "false")}"; + return true; + } + + emoteId = string.Empty; + return false; + } + + public static bool TryGetDataFromEmoteId(string emoteId, out string emoteHash, out bool loop) + { + try + { + ReadOnlySpan prefixRemoved = emoteId.AsSpan().Slice(SCENE_EMOTE_PREFIX.Length, emoteId.Length - SCENE_EMOTE_PREFIX.Length); + int loopSeparator = prefixRemoved.LastIndexOf('-'); + emoteHash = prefixRemoved.Slice(0, loopSeparator).ToString(); + + var loopSpan = prefixRemoved.Slice(loopSeparator + 1, 4); + loop = loopSpan.Equals("true", StringComparison.InvariantCultureIgnoreCase); + + return true; + } + catch (Exception _) + { + emoteHash = string.Empty; + loop = false; + } + + return false; + } + + public static bool IsSceneEmote(string emoteId) => + emoteId.StartsWith(SCENE_EMOTE_PREFIX); + } +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/SceneEmoteHelper.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/SceneEmoteHelper.cs.meta similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/SceneEmoteHelper.cs.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/SceneEmoteHelper.cs.meta diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/AvatarAssetsTest.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/AvatarAssetsTest.asmdef index 8472da0fd4..c9f0238d3c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/AvatarAssetsTest.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/AvatarAssetsTest.asmdef @@ -1,19 +1,29 @@ { "name": "AvatarAssetsTest", + "rootNamespace": "", "references": [ "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", "GUID:e555144732b726c4cba5b0f6337fea75", - "GUID:ef84d7ce90ba34f07be26ace428e9bc8" + "GUID:ef84d7ce90ba34f07be26ace428e9bc8", + "GUID:97d8897529779cb49bebd400c7f402a6", + "GUID:b24824f3bc2a60641a01e2083614f802", + "GUID:6e6a87f97192ec947993f360104e75b7", + "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", + "GUID:27619889b8ba8c24980f49ee34dbb44a", + "GUID:0acc523941302664db1f4e527237feb3" ], - "optionalUnityReferences": [ - "TestAssemblies" + "includePlatforms": [ + "Editor" ], - "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll", + "NSubstitute.dll" + ], + "autoReferenced": false, "defineConstraints": [], - "versionDefines": [] + "versionDefines": [], + "noEngineReferences": false } \ No newline at end of file diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/SceneEmoteHelperShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/SceneEmoteHelperShould.cs new file mode 100644 index 0000000000..73dfdfd12a --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/SceneEmoteHelperShould.cs @@ -0,0 +1,58 @@ +using DCL; +using DCL.Controllers; +using NSubstitute; +using NUnit.Framework; + +namespace AvatarAssets.Tests +{ + public class SceneEmoteHelperShould + { + [Test] + public void TryGenerateEmoteId() + { + const string HASH = "00172"; + const string FILE = "test"; + IParcelScene scene = Substitute.For(); + + var contentProvider = new ContentProvider() + { + contents = + { + new ContentServerUtils.MappingPair() { file = FILE, hash = HASH } + } + }; + + contentProvider.BakeHashes(); + scene.contentProvider.Returns(contentProvider); + + string emoteIdResult; + Assert.IsTrue(SceneEmoteHelper.TryGenerateEmoteId(scene, FILE, true, out emoteIdResult)); + Assert.AreEqual($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-true", emoteIdResult); + + Assert.IsTrue(SceneEmoteHelper.TryGenerateEmoteId(scene, FILE, false, out emoteIdResult)); + Assert.AreEqual($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-false", emoteIdResult); + } + + [Test] + public void TryGetDataFromEmoteId() + { + const string HASH = "00172"; + Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-true", out string hash, out bool loop)); + Assert.AreEqual(HASH, hash); + Assert.IsTrue(loop); + + Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}-false", out hash, out loop)); + Assert.AreEqual(HASH, hash); + Assert.IsFalse(loop); + + Assert.IsFalse(SceneEmoteHelper.TryGetDataFromEmoteId($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}{HASH}", out hash, out loop)); + } + + [Test] + public void IsSceneEmote() + { + Assert.IsTrue(SceneEmoteHelper.IsSceneEmote($"{SceneEmoteHelper.SCENE_EMOTE_PREFIX}0-false")); + Assert.IsFalse(SceneEmoteHelper.IsSceneEmote($"otherstring")); + } + } +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/SceneEmoteHelperShould.cs.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/SceneEmoteHelperShould.cs.meta similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Tests/SceneEmoteHelperShould.cs.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/Tests/SceneEmoteHelperShould.cs.meta diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/WearableItem.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/WearableItem.cs index 4389cbc2dc..99ea572036 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/WearableItem.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/WearableItem.cs @@ -146,8 +146,8 @@ public string ThirdPartyCollectionId public string description; public int issuedId; - private readonly Dictionary cachedI18n = new (); - private readonly Dictionary cachedContentProviers = new (); + private Dictionary cachedI18n = new (); + private Dictionary cachedContentProviers = new (); public bool TryGetRepresentation(string bodyshapeId, out Representation representation) { @@ -175,6 +175,8 @@ public ContentProvider GetContentProvider(string bodyShapeType) if (representation == null) return null; + cachedContentProviers ??= new Dictionary(); + if (!cachedContentProviers.ContainsKey(bodyShapeType)) { var contentProvider = CreateContentProvider(baseUrl, representation.contents); @@ -236,8 +238,10 @@ public string[] GetHidesList(string bodyShapeType) // we apply this rule to hide the hands by default if the wearable is an upper body or hides the upper body bool isOrHidesUpperBody = hides.Contains(Categories.UPPER_BODY) || data.category == Categories.UPPER_BODY; + // the rule is ignored if the wearable contains the removal of this default rule (newer upper bodies since the release of hands) bool removesHandDefault = data.removesDefaultHiding?.Contains(Categories.HANDS) ?? false; + // why we do this? because old upper bodies contains the base hand mesh, and they might clip with the new handwear items if (isOrHidesUpperBody && !removesHandDefault) hides.UnionWith(UPPER_BODY_DEFAULT_HIDES); @@ -301,8 +305,8 @@ public bool IsSmart() public string GetName(string langCode = "en") { - if (!cachedI18n.ContainsKey(langCode)) { cachedI18n.Add(langCode, i18n.FirstOrDefault(x => x.code == langCode)?.text); } - + cachedI18n ??= new Dictionary(); + cachedI18n.TryAdd(langCode, i18n.FirstOrDefault(x => x.code == langCode)?.text); return cachedI18n[langCode]; } @@ -427,7 +431,36 @@ public string GetMarketplaceLink() } [Serializable] -public class EmoteItem : WearableItem { } +public class EmoteItem : WearableItem +{ + public EmoteItem(string bodyShapeId, string emoteId, string emoteHash, string contentUrl, bool loop) + { + data = new Data + { + representations = new[] + { + new Representation + { + bodyShapes = new[] { bodyShapeId }, + contents = new[] + { + new MappingPair + { + hash = emoteHash, key = emoteHash + }, + }, + mainFile = emoteHash, + }, + }, + loop = loop, + }; + + emoteDataV0 = new EmoteDataV0 { loop = loop }; + + id = emoteId; + baseUrl = $"{contentUrl}contents/"; + } +} [Serializable] public class WearablesRequestResponse diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs index 755f39b6a7..3fe93cb140 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs @@ -1,4 +1,5 @@ -using AvatarSystem; +using AvatarAssets; +using AvatarSystem; using Cysharp.Threading.Tasks; using DCL; using DCL.Controllers; @@ -15,20 +16,19 @@ namespace RPC.Services { public class EmotesRendererServiceImpl : IEmotesRendererService { - private static readonly SuccessResponse FAILURE_RESPONSE = new SuccessResponse() { Success = false }; - private static readonly SuccessResponse SUCCESS_RESPONSE = new SuccessResponse() { Success = true }; + private static readonly SuccessResponse FAILURE_RESPONSE = new () { Success = false }; + private static readonly SuccessResponse SUCCESS_RESPONSE = new () { Success = true }; private readonly IWorldState worldState; private readonly ISceneController sceneController; private readonly UserProfile userProfile; private readonly BaseVariable ownPlayer; - private readonly IBaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> alreadyLoadedEmotes; - private readonly BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesInUse; - private readonly IDictionary> pendingEmotesByScene; - private readonly IDictionary> equippedEmotesByScene; + private readonly IEmotesService emotesService; + + private readonly IDictionary> emotesByScene; private readonly IDictionary cancellationTokenSources; - private IAvatar avatarData; + private IAvatarEmotesController emotesController; public static void RegisterService(RpcServerPort port) { @@ -40,10 +40,8 @@ public static void RegisterService(RpcServerPort port) sceneController: Environment.i.world.sceneController, userProfile: UserProfile.GetOwnUserProfile(), ownPlayer: DataStore.i.player.ownPlayer, - alreadyLoadedEmotes: DataStore.i.emotes.animations, - emotesInUse: DataStore.i.emotes.emotesOnUse, - pendingEmotesByScene: new Dictionary>(), - equippedEmotesByScene: new Dictionary>(), + emotesService: Environment.i.serviceLocator.Get(), + emotesByScene: new Dictionary>(), cancellationTokenSources: new Dictionary() )); } @@ -54,10 +52,8 @@ public EmotesRendererServiceImpl( ISceneController sceneController, UserProfile userProfile, BaseVariable ownPlayer, - IBaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> alreadyLoadedEmotes, - BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesInUse, - IDictionary> pendingEmotesByScene, - IDictionary> equippedEmotesByScene, + IEmotesService emotesService, + IDictionary> emotesByScene, IDictionary cancellationTokenSources ) { @@ -65,10 +61,8 @@ IDictionary cancellationTokenSources this.sceneController = sceneController; this.userProfile = userProfile; this.ownPlayer = ownPlayer; - this.alreadyLoadedEmotes = alreadyLoadedEmotes; - this.pendingEmotesByScene = pendingEmotesByScene; - this.equippedEmotesByScene = equippedEmotesByScene; - this.emotesInUse = emotesInUse; + this.emotesService = emotesService; + this.emotesByScene = emotesByScene; this.cancellationTokenSources = cancellationTokenSources; port.OnClose += OnPortClosed; @@ -99,25 +93,18 @@ public async UniTask TriggerSceneExpression(TriggerSceneExpress if (!SceneEmoteHelper.TryGenerateEmoteId(scene, request.Path, request.Loop, out string emoteId)) return FAILURE_RESPONSE; - avatarData ??= ownPlayer.Get()?.avatar; + emotesController ??= ownPlayer.Get()?.avatar.GetEmotesController(); - if (avatarData == null) + if (emotesController == null) return FAILURE_RESPONSE; string userBodyShape = userProfile.avatar.bodyShape; - // get hashset for scene emotes that are currently loading or create one if none - if (!pendingEmotesByScene.TryGetValue(scene, out HashSet<(string bodyshapeId, string emoteId)> scenePendingEmotes)) - { - scenePendingEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - pendingEmotesByScene.Add(scene, scenePendingEmotes); - } - // get hashset for scene emotes that are already equipped - if (!equippedEmotesByScene.TryGetValue(scene, out HashSet<(string bodyshapeId, string emoteId)> sceneEquippedEmotes)) + if (!emotesByScene.TryGetValue(scene, out HashSet<(string bodyShape, string emoteId)> sceneEquippedEmotes)) { - sceneEquippedEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - equippedEmotesByScene.Add(scene, sceneEquippedEmotes); + sceneEquippedEmotes = new HashSet<(string bodyShape, string emoteId)>(); + emotesByScene.Add(scene, sceneEquippedEmotes); } // get / create cancellation source for scene @@ -134,20 +121,15 @@ public async UniTask TriggerSceneExpression(TriggerSceneExpress { await UniTask.SwitchToMainThread(ct); - // request emote to load using DataStore::emotes which will make `EmoteAnimationsTracker` plugin to load the emote - await SceneEmoteHelper.RequestLoadSceneEmote( - userBodyShape, - emoteId, - alreadyLoadedEmotes, - emotesInUse, - scenePendingEmotes, - sceneEquippedEmotes, - cancellationTokenSource.Token); - - // make emote play - avatarData.EquipEmote(emoteId, alreadyLoadedEmotes[(userBodyShape, emoteId)]); + if (!emotesByScene[scene].Contains((userBodyShape, emoteId))) + { + var result = await emotesService.RequestEmote(userBodyShape, emoteId, cancellationTokenSource.Token); + emotesController.EquipEmote(emoteId, result); + emotesByScene[scene].Add((userBodyShape, emoteId)); + } userProfile.SetAvatarExpression(emoteId, UserProfile.EmoteSource.Command); + return SUCCESS_RESPONSE; } catch (OperationCanceledException _) @@ -170,26 +152,12 @@ private void OnSceneRemoved(IParcelScene scene) cancellationTokenSources.Remove(scene); } - if (equippedEmotesByScene.TryGetValue(scene, out var equippedEmotes)) - { - foreach (var emoteData in equippedEmotes) - { - avatarData?.UnequipEmote(emoteData.emoteId); - emotesInUse.DecreaseRefCount(emoteData); - } - - equippedEmotesByScene.Remove(scene); - } + if (!emotesByScene.TryGetValue(scene, out var equippedEmotes)) return; - if (pendingEmotesByScene.TryGetValue(scene, out var pendingEmotes)) - { - foreach (var emoteData in pendingEmotes) - { - emotesInUse.DecreaseRefCount((bodyshapeId: emoteData.bodyshapeId, emoteId: emoteData.emoteId)); - } + foreach (var emoteData in equippedEmotes) + emotesController?.UnEquipEmote(emoteData.emoteId); - pendingEmotesByScene.Remove(scene); - } + emotesByScene.Remove(scene); } } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/RPC.Service.Emotes.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/RPC.Service.Emotes.asmdef index 06a6028bad..22d12db045 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/RPC.Service.Emotes.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/RPC.Service.Emotes.asmdef @@ -19,7 +19,8 @@ "GUID:c34e38f41494f834abff029ddf82af43", "GUID:49176a91bbf7f8a4aaf35f6df0643d1a", "GUID:24ec3d5b95972d44394d682772ea3db1", - "GUID:3047fd2f05bcaae498a99a3f9321f9a8" + "GUID:3047fd2f05bcaae498a99a3f9321f9a8", + "GUID:0c0c18c12967b3944b844b79c47c2320" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/RPC.Services.Emotes.Tests.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/RPC.Services.Emotes.Tests.asmdef index 6f909a2f3d..505b7dd28f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/RPC.Services.Emotes.Tests.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/RPC.Services.Emotes.Tests.asmdef @@ -23,9 +23,12 @@ "GUID:24ec3d5b95972d44394d682772ea3db1", "GUID:fbcc413e192ef9048811d47ab0aca0c0", "GUID:5db7e9d450464b96bfddf316690db751", - "GUID:3047fd2f05bcaae498a99a3f9321f9a8" + "GUID:3047fd2f05bcaae498a99a3f9321f9a8", + "GUID:0c0c18c12967b3944b844b79c47c2320" + ], + "includePlatforms": [ + "Editor" ], - "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": true, diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs index ae35e1c363..2bcd4ed389 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs @@ -1,3 +1,4 @@ +using AvatarAssets; using AvatarSystem; using Cysharp.Threading.Tasks; using DCL; @@ -14,6 +15,7 @@ using System.Collections; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using UnityEngine; using UnityEngine.TestTools; using Environment = DCL.Environment; @@ -26,33 +28,28 @@ public class TriggerSceneExpressionShould private ISceneController sceneController; private UserProfile userProfile; private BaseVariable ownPlayer; - private IBaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData> animations; - private BaseRefCountedCollection<(string bodyshapeId, string emoteId)> emotesInUse; - private IDictionary> pendingEmotesByScene; - private IDictionary> equippedEmotesByScene; + + private IDictionary> equippedEmotesByScene; private IDictionary cancellationTokenSources; private IClientEmotesRendererService client; + private IEmotesService emotesService; + private EmotesRendererServiceImpl emotesRendererServiceImpl; + private IEmoteReference emoteReference; + private IAvatarEmotesController avatar => ownPlayer.Get().avatar.GetEmotesController(); - [UnitySetUp] - public IEnumerator SetUp() + [SetUp] + public async Task SetUp() { worldState = Substitute.For(); sceneController = Substitute.For(); + emotesService = Substitute.For(); userProfile = UserProfile.GetOwnUserProfile(); ownPlayer = new BaseVariable(); - animations = new BaseDictionary<(string bodyshapeId, string emoteId), EmoteClipData>(); - emotesInUse = new BaseRefCountedCollection<(string bodyshapeId, string emoteId)>(); - pendingEmotesByScene = new Dictionary>(); - equippedEmotesByScene = new Dictionary>(); + equippedEmotesByScene = new Dictionary>(); cancellationTokenSources = new Dictionary(); - Environment.i.serviceLocator.Register(() => Substitute.For()); - - yield return UniTask.ToCoroutine(async () => - { - client = await CreateRpcClient(); - await Environment.i.serviceLocator.Initialize(); - }); + client = await CreateRpcClient(); + await Environment.i.serviceLocator.Initialize(); } [TearDown] @@ -61,31 +58,29 @@ public void TearDown() Resources.UnloadAsset(userProfile); } - [UnityTest] - public IEnumerator Fail_When_SceneNotLoaded() + [Test] + public async Task Fail_When_SceneNotLoaded() { - yield return UniTask.ToCoroutine(async () => - { - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = "local/emote", - SceneNumber = 666 - }); - - Assert.IsFalse(result.Success); - }); + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = "local/emote", + SceneNumber = 666, + }); + + Assert.IsFalse(result.Success); } - [UnityTest] - public IEnumerator Fail_When_EmoteNotPresentInSceneMapping() + [Test] + public async Task Fail_When_EmoteNotPresentInSceneMapping() { - var contentProvider = new ContentProvider() + var contentProvider = new ContentProvider { contents = { - new ContentServerUtils.MappingPair() { file = "theEmote", hash = "0066688" } - } + new ContentServerUtils.MappingPair + { file = "theEmote", hash = "0066688" }, + }, }; contentProvider.BakeHashes(); @@ -100,28 +95,26 @@ public IEnumerator Fail_When_EmoteNotPresentInSceneMapping() return true; }); - yield return UniTask.ToCoroutine(async () => - { - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = "NOT_THE_EMOTE", - SceneNumber = 666 - }); - - Assert.IsFalse(result.Success); - }); + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = "NOT_THE_EMOTE", + SceneNumber = 666, + }); + + Assert.IsFalse(result.Success); } - [UnityTest] - public IEnumerator Fail_When_NoUserAvatarSet() + [Test] + public async Task Fail_When_NoUserAvatarSet() { - var contentProvider = new ContentProvider() + var contentProvider = new ContentProvider { contents = { - new ContentServerUtils.MappingPair() { file = "theEmote", hash = "0066688" } - } + new ContentServerUtils.MappingPair + { file = "theEmote", hash = "0066688" }, + }, }; contentProvider.BakeHashes(); @@ -136,201 +129,158 @@ public IEnumerator Fail_When_NoUserAvatarSet() return true; }); - yield return UniTask.ToCoroutine(async () => - { - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = "theEmote", - SceneNumber = 666 - }); - - Assert.IsFalse(result.Success); - }); + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = "theEmote", + SceneNumber = 666, + }); + + Assert.IsFalse(result.Success); } - [UnityTest] - public IEnumerator Success_LoadingAndPlayingEmote() + [Test] + public async Task Success_LoadingAndPlayingEmote_Twice() { const string EMOTE_PATH = "theEmote"; const int SCENE_NUMBER = 666; var (emoteData, scene) = SetUpWorkingEnvironment(SCENE_NUMBER, EMOTE_PATH); - emotesInUse.OnRefCountUpdated += (tuple, i) => animations[tuple] = new EmoteClipData(new AnimationClip()); + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = EMOTE_PATH, + SceneNumber = SCENE_NUMBER, + }); - yield return UniTask.ToCoroutine(async () => - { - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = EMOTE_PATH, - SceneNumber = SCENE_NUMBER - }); - - Assert.IsTrue(result.Success); - Assert.AreEqual(1, emotesInUse.GetRefCount(emoteData)); - var avatar = ownPlayer.Get().avatar; - avatar.Received(1).EquipEmote(emoteData.emoteId, animations[emoteData]); - Assert.AreEqual(emoteData.emoteId, userProfile.avatar.expressionTriggerId); - Assert.IsTrue(equippedEmotesByScene[scene].Contains(emoteData)); - Assert.IsTrue(pendingEmotesByScene[scene].Count == 0); - }); + result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = EMOTE_PATH, + SceneNumber = SCENE_NUMBER, + }); + + Assert.IsTrue(result.Success); + + avatar.Received(1).EquipEmote(emoteData.emoteId, emoteReference); + Assert.AreEqual(userProfile.avatar.expressionTriggerId, emoteData.emoteId); } - [UnityTest] - public IEnumerator Success_LoadingAndPlayingEmote_Twice() + [Test] + public async Task Success_LoadingAndPlayingEmote() { const string EMOTE_PATH = "theEmote"; const int SCENE_NUMBER = 666; var (emoteData, scene) = SetUpWorkingEnvironment(SCENE_NUMBER, EMOTE_PATH); - emotesInUse.OnRefCountUpdated += (tuple, i) => animations[tuple] = new EmoteClipData(new AnimationClip()); + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = EMOTE_PATH, + SceneNumber = SCENE_NUMBER, + }); - yield return UniTask.ToCoroutine(async () => - { - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = EMOTE_PATH, - SceneNumber = SCENE_NUMBER - }); - - result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = EMOTE_PATH, - SceneNumber = SCENE_NUMBER - }); - - Assert.IsTrue(result.Success); - Assert.AreEqual(1, emotesInUse.GetRefCount(emoteData)); - Assert.IsTrue(equippedEmotesByScene[scene].Contains(emoteData)); - Assert.IsTrue(pendingEmotesByScene[scene].Count == 0); - }); + Assert.IsTrue(result.Success); + avatar.Received(1).EquipEmote(emoteData.emoteId, emoteReference); + Assert.AreEqual(emoteData.emoteId, userProfile.avatar.expressionTriggerId); + Assert.IsTrue(equippedEmotesByScene[scene].Contains(emoteData)); } - [UnityTest] - public IEnumerator Cancelled_When_SceneRemovedWhileLoading() + [Test] + public async Task Cancelled_When_SceneRemovedWhileLoading() { const string EMOTE_PATH = "theEmote"; const int SCENE_NUMBER = 666; var (emoteData, scene) = SetUpWorkingEnvironment(SCENE_NUMBER, EMOTE_PATH); - yield return UniTask.ToCoroutine(async () => - { - UniTask.Create(async () => + await UniTask.Yield(); + cancellationTokenSources[scene].Cancel(); + + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest { - await UniTask.Yield(); - cancellationTokenSources[scene].Cancel(); + Path = EMOTE_PATH, + SceneNumber = SCENE_NUMBER, }); - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = EMOTE_PATH, - SceneNumber = SCENE_NUMBER - }); - - Assert.IsFalse(result.Success); - Assert.AreEqual(0, emotesInUse.GetRefCount(emoteData)); - Assert.IsTrue(equippedEmotesByScene[scene].Count == 0); - Assert.IsTrue(pendingEmotesByScene[scene].Count == 0); - }); + Assert.IsFalse(result.Success); + Assert.IsTrue(equippedEmotesByScene[scene].Count == 0); + avatar.Received(1).EquipEmote(emoteData.emoteId, emoteReference); } - [UnityTest] - public IEnumerator CleanUp_When_SceneIsUnloaded() + [Test] + public async Task CleanUp_When_SceneIsUnloaded() { const string EMOTE_PATH = "theEmote"; const int SCENE_NUMBER = 666; var (emoteData, scene) = SetUpWorkingEnvironment(SCENE_NUMBER, EMOTE_PATH); - emotesInUse.OnRefCountUpdated += (tuple, i) => - { - if (i == 0) - animations.Remove(tuple); - else - animations[tuple] = new EmoteClipData(new AnimationClip()); - }; + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = EMOTE_PATH, + SceneNumber = SCENE_NUMBER, + }); - yield return UniTask.ToCoroutine(async () => - { - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = EMOTE_PATH, - SceneNumber = SCENE_NUMBER - }); - - Assert.IsTrue(result.Success); - Assert.AreEqual(1, emotesInUse.GetRefCount(emoteData)); - Assert.IsTrue(animations.ContainsKey(emoteData)); - Assert.IsTrue(equippedEmotesByScene[scene].Count == 1); - Assert.IsTrue(equippedEmotesByScene[scene].Count == 1); - }); + Assert.IsTrue(result.Success); + Assert.IsTrue(equippedEmotesByScene[scene].Count == 1); sceneController.OnSceneRemoved += Raise.Event>(scene); - Assert.AreEqual(0, emotesInUse.GetRefCount(emoteData)); - Assert.IsFalse(animations.ContainsKey(emoteData)); Assert.IsFalse(equippedEmotesByScene.ContainsKey(scene)); - Assert.IsFalse(pendingEmotesByScene.ContainsKey(scene)); + emoteReference.Received(1).Dispose(); } - [UnityTest] - public IEnumerator GenerateEmoteId_Correctly() + [Test] + public async Task GenerateEmoteId_Correctly() { const string EMOTE_PATH = "theEmote"; const int SCENE_NUMBER = 666; var (emoteData, scene) = SetUpWorkingEnvironment(SCENE_NUMBER, EMOTE_PATH); - emotesInUse.OnRefCountUpdated += (tuple, i) => animations[tuple] = new EmoteClipData(new AnimationClip()); + var result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = EMOTE_PATH, + SceneNumber = SCENE_NUMBER, + Loop = true, + }); - yield return UniTask.ToCoroutine(async () => - { - var result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = EMOTE_PATH, - SceneNumber = SCENE_NUMBER, - Loop = true - }); - - Assert.IsTrue(result.Success); - Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId(userProfile.avatar.expressionTriggerId, out string hash, out bool loop)); - Assert.IsTrue(loop); - Assert.AreEqual(scene.contentProvider.contents[0].hash, hash); - - result = await client.TriggerSceneExpression( - new TriggerSceneExpressionRequest() - { - Path = EMOTE_PATH, - SceneNumber = SCENE_NUMBER, - Loop = false - }); - - Assert.IsTrue(result.Success); - Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId(userProfile.avatar.expressionTriggerId, out hash, out loop)); - Assert.IsFalse(loop); - Assert.AreEqual(scene.contentProvider.contents[0].hash, hash); - }); + Assert.IsTrue(result.Success); + Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId(userProfile.avatar.expressionTriggerId, out string hash, out bool loop)); + Assert.IsTrue(loop); + Assert.AreEqual(scene.contentProvider.contents[0].hash, hash); + + result = await client.TriggerSceneExpression( + new TriggerSceneExpressionRequest + { + Path = EMOTE_PATH, + SceneNumber = SCENE_NUMBER, + Loop = false, + }); + + Assert.IsTrue(result.Success); + Assert.IsTrue(SceneEmoteHelper.TryGetDataFromEmoteId(userProfile.avatar.expressionTriggerId, out hash, out loop)); + Assert.IsFalse(loop); + Assert.AreEqual(scene.contentProvider.contents[0].hash, hash); } - private ((string bodyShae, string emoteId)emoteData, IParcelScene scene) SetUpWorkingEnvironment(int sceneNumber, string emotePath) + private ((string bodyShape, string emoteId) emoteData, IParcelScene scene) SetUpWorkingEnvironment(int sceneNumber, string emotePath) { const string BODY_SHAPE = "someBodyShape"; - var contentProvider = new ContentProvider() + var contentProvider = new ContentProvider { contents = { - new ContentServerUtils.MappingPair() { file = emotePath, hash = "0066688" } - } + new ContentServerUtils.MappingPair + { file = emotePath, hash = "0066688" }, + }, }; contentProvider.BakeHashes(); @@ -347,16 +297,18 @@ public IEnumerator GenerateEmoteId_Correctly() worldState.ContainsScene(sceneNumber).Returns(true); - var playerModel = new Player() + var playerModel = new Player { - avatar = Substitute.For() + avatar = Substitute.For(), }; ownPlayer.Set(playerModel); userProfile.avatar.bodyShape = BODY_SHAPE; - SceneEmoteHelper.TryGenerateEmoteId(scene, emotePath, false, out var emoteId); - return (emoteData: (bodyShae: BODY_SHAPE, emoteId: emoteId), scene: scene); + SceneEmoteHelper.TryGenerateEmoteId(scene, emotePath, false, out string emoteId); + emoteReference = Substitute.For(); + emotesService.RequestEmote(BODY_SHAPE, emoteId, Arg.Any()).Returns(UniTask.FromResult(emoteReference)); + return (emoteData: (bodyShape: BODY_SHAPE, emoteId: emoteId), scene: scene); } private async UniTask CreateRpcClient() @@ -369,19 +321,19 @@ private async UniTask CreateRpcClient() rpcServer.SetHandler((port, t, c) => { + emotesRendererServiceImpl = new EmotesRendererServiceImpl( + port, + worldState, + sceneController, + userProfile, + ownPlayer, + emotesService, + equippedEmotesByScene, + cancellationTokenSources + ); + EmotesRendererServiceCodeGen.RegisterService(port, - new EmotesRendererServiceImpl( - port, - worldState, - sceneController, - userProfile, - ownPlayer, - animations, - emotesInUse, - pendingEmotesByScene, - equippedEmotesByScene, - cancellationTokenSources - )); + emotesRendererServiceImpl); }); RpcClient client = new RpcClient(clientTransport); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs index 96fb62931d..71b03128e9 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs @@ -97,8 +97,8 @@ private void OnDebugModeSet(bool current, bool previous) public void Dispose() { - tokenSource.Cancel(); - tokenSource.Dispose(); + tokenSource?.Cancel(); + tokenSource?.Dispose(); Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update); Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.LateUpdate, LateUpdate); diff --git a/unity-renderer/Assets/Scripts/Tests/IntegrationTestSuite_Legacy.cs b/unity-renderer/Assets/Scripts/Tests/IntegrationTestSuite_Legacy.cs index dd441fd9cb..a6bbd8864d 100644 --- a/unity-renderer/Assets/Scripts/Tests/IntegrationTestSuite_Legacy.cs +++ b/unity-renderer/Assets/Scripts/Tests/IntegrationTestSuite_Legacy.cs @@ -4,6 +4,7 @@ using DCL.CameraTool; using DCL.Configuration; using DCL.Emotes; +using DCL.Helpers; using DCL.Helpers.NFT.Markets; using DCL.ProfanityFiltering; using DCL.Providers; @@ -112,9 +113,7 @@ protected IEnumerator TearDown_LegacySystems() Settings.i.Dispose(); foreach ( var go in legacySystems ) - { - Object.Destroy(go); - } + Utils.SafeDestroy(go); yield return null; } From d05a9a134a1415d5ac5f2277c6f92f2fa89c9e6e Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 30 Aug 2023 11:34:49 -0300 Subject: [PATCH 03/35] Fix legacy tests --- .../Assets/DCLServices/EmotesService/EmotesService.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs index 7cb70565cf..e059b9857c 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs @@ -53,6 +53,9 @@ public async UniTask InitializeAsync(CancellationToken cancellationToken) { EmbeddedEmotesSO embeddedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); + // early return for not configured emotesCatalogService substitutes in legacy test base + if (embeddedEmotes == null) return; + foreach (EmbeddedEmote embeddedEmote in embeddedEmotes.emotes) { if (embeddedEmote.maleAnimation != null) From 1ef0d6d62526c804bcba4aa527c1761df933bd6b Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 30 Aug 2023 12:55:37 -0300 Subject: [PATCH 04/35] fixed null reference during test tear down --- .../HUD/EmotesWheelHUD/EmotesWheelController.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs index de26f3c0e5..029d653e5c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs @@ -2,14 +2,12 @@ using Cysharp.Threading.Tasks; using System.Collections.Generic; using DCL.Emotes; +using DCL.Helpers; using DCLServices.WearablesCatalogService; -using System; using System.Linq; using System.Threading; -using System.Threading.Tasks; using UnityEngine; using UnityEngine.Pool; -using Object = UnityEngine.Object; namespace DCL.EmotesWheel { @@ -86,10 +84,12 @@ public EmotesWheelController( emotesCustomizationDataStore.isWheelInitialized.Set(true); DataStore.i.player.ownPlayer.OnChange += OnPlayerSet; + OnPlayerSet(DataStore.i.player.ownPlayer.Get(), null); } private void OnPlayerSet(Player current, Player previous) { + if (current == null) return; emotesController = current.avatar.GetEmotesController(); emotesController.OnEmoteEquipped += OnEmoteEquipped; emotesController.OnEmoteUnequipped += OnEmoteUnequipped; @@ -270,8 +270,13 @@ public void Dispose() auxShortcut7InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; auxShortcut8InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; auxShortcut9InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; - emotesController.OnEmoteEquipped -= OnEmoteEquipped; - emotesController.OnEmoteUnequipped -= OnEmoteUnequipped; + + if (emotesController != null) + { + emotesController.OnEmoteEquipped -= OnEmoteEquipped; + emotesController.OnEmoteUnequipped -= OnEmoteUnequipped; + } + cts?.Cancel(); cts?.Dispose(); cts = null; @@ -279,7 +284,7 @@ public void Dispose() if (view != null) { view.CleanUp(); - Object.Destroy(view.gameObject); + Utils.SafeDestroy(view.gameObject); } } From 6d1deaac1f377c6b76cc1391e2e79262f6bf5491 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Thu, 31 Aug 2023 12:04:01 -0300 Subject: [PATCH 05/35] Fixed issues when changing emotes --- .../DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs | 2 +- .../DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs index 029d653e5c..9540e7d875 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs @@ -156,7 +156,7 @@ private void UpdateEmoteSlots() thumbnailSprite = equippedEmoteData.cachedThumbnail, }); } else - equippedEmotes.Add(null); + emotesToSet.Add(null); } ListPool.Release(equippedEmotes); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs index fde648dfd3..ec94dd5f7a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelView.cs @@ -94,7 +94,7 @@ public void SetupEmoteWheelSlot(EmoteWheelSlot emoteWheelSlot, EmoteSlotData slo emoteWheelSlot.onSlotHover -= OnSlotHover; emoteWheelSlot.onSlotHover += OnSlotHover; - if (slotData != null) + if (slotData is { emoteItem: not null }) { emoteWheelSlot.button.onClick.AddListener(() => onEmoteClicked?.Invoke(slotData.emoteItem.id)); From 30e84e788df38da90715ab09e0b119a9bca2dbcc Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Thu, 31 Aug 2023 13:01:24 -0300 Subject: [PATCH 06/35] Added support for audio sources --- .../EmotesService/EmoteAnimationLoader.cs | 45 ++++++++++++++++--- .../EmotesService/EmotesService.asmdef | 5 ++- .../Interfaces/IEmoteAnimationLoader.cs | 2 +- .../Interfaces/NftEmoteReference.cs | 2 +- .../CharacterPreviewController.cs | 1 - .../EmotesWheelHUD/EmotesWheelController.cs | 24 +++++++--- .../DCL/Models/AvatarAssets/EmoteClipData.cs | 18 ++++++-- 7 files changed, 79 insertions(+), 18 deletions(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index cbdf051d6c..eeb7257649 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -2,6 +2,7 @@ using System; using System.Threading; using Cysharp.Threading.Tasks; +using System.Collections; using UnityEngine; namespace DCL.Emotes @@ -11,7 +12,9 @@ public class EmoteAnimationLoader : IEmoteAnimationLoader private readonly IWearableRetriever retriever; public AnimationClip mainClip { get; internal set; } public GameObject container { get; private set; } - public AudioClip audioClip { get; private set; } + public AudioSource audioSource { get; private set; } + + private AudioClip audioClip; public EmoteAnimationLoader(IWearableRetriever retriever) { @@ -41,10 +44,7 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s return; } - if (animation.GetClipCount() > 1) - { - this.container = rendereable.container; - } + if (animation.GetClipCount() > 1) { this.container = rendereable.container; } animation.enabled = false; var animationClip = animation.clip; @@ -58,6 +58,41 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s //Setting animation name equal to emote id to avoid unity animation clip duplication on Animation.AddClip() this.mainClip = animationClip; animationClip.name = emote.id; + + var contentProvider = emote.GetContentProvider(bodyShapeId); + + foreach (var contentMap in contentProvider.contents) + { + if (!contentMap.file.EndsWith(".mp3")) continue; //do we need to support more of em? + + try + { + await AsyncLoadAudioClip(contentMap.file, contentProvider).ToUniTask(cancellationToken: ct); + } + catch (Exception e) + { + Debug.LogError(e); + } + + if (audioClip != null) + { + audioSource = targetContainer.AddComponent(); + audioSource.clip = audioClip; + } + + break; + } + } + + private IEnumerator AsyncLoadAudioClip(string file, ContentProvider contentProvider) + { + var audioClipPromise = new AssetPromise_AudioClip(file, contentProvider); + audioClipPromise.OnSuccessEvent += asset => audioClip = asset.audioClip; + audioClipPromise.OnFailEvent += (_, e) => throw e; + + AssetPromiseKeeper_AudioClip.i.Keep(audioClipPromise); + + yield return audioClipPromise; } public void Dispose() diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef index 183dc7d251..f27af42855 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef @@ -12,7 +12,10 @@ "GUID:cc6bfabbfe87b7949aa248893f89ce37", "GUID:8af21c3a612af2645a9953d4b9b3f6d5", "GUID:49176a91bbf7f8a4aaf35f6df0643d1a", - "GUID:2d39cc535b437e749965d4a8258f0c13" + "GUID:2d39cc535b437e749965d4a8258f0c13", + "GUID:b24824f3bc2a60641a01e2083614f802", + "GUID:6e6a87f97192ec947993f360104e75b7", + "GUID:a3ceb534947fac14da25035bc5c24788" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs index 6331ee6e2d..5b11cccd3f 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs @@ -9,7 +9,7 @@ public interface IEmoteAnimationLoader : IDisposable { AnimationClip mainClip { get; } GameObject container { get; } - AudioClip audioClip { get; } + AudioSource audioSource { get; } UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default); } } diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs index 5ac38e7621..649abe6263 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs @@ -10,7 +10,7 @@ public NftEmoteReference(WearableItem emoteItem, IEmoteAnimationLoader loader, b { this.emoteItem = emoteItem; this.loader = loader; - emoteClipData = new EmoteClipData(loader.mainClip, loader.container, loader.audioClip, loop); + emoteClipData = new EmoteClipData(loader.mainClip, loader.container, loader.audioSource, loop); } public WearableItem GetEntity() => diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs index 0e6518a97e..f7f3607ef3 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs @@ -227,7 +227,6 @@ public IAvatarEmotesController GetEmotesController() => public void PlayEmote(string emoteId, long timestamp) { - Debug.Log("[Character Preview] Playing emote " + emoteId); avatar.GetEmotesController().PlayEmote(emoteId, timestamp); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs index 9540e7d875..08afd45fff 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs @@ -141,12 +141,26 @@ private void UpdateEmoteSlots() { var entity = emote.GetEntity(); - emotesToSet.Add(new EmotesWheelView.EmoteSlotData + if (entity == null) { - emoteId = equippedEmoteData.id, - emoteItem = entity, - thumbnailSprite = entity.thumbnailSprite != null ? entity.thumbnailSprite : equippedEmoteData.cachedThumbnail, - }); + Debug.LogError("Something is not quite right"); + + emotesToSet.Add(new EmotesWheelView.EmoteSlotData + { + emoteId = equippedEmoteData.id, + emoteItem = null, + thumbnailSprite = equippedEmoteData.cachedThumbnail, + }); + } + else + { + emotesToSet.Add(new EmotesWheelView.EmoteSlotData + { + emoteId = equippedEmoteData.id, + emoteItem = entity, + thumbnailSprite = entity.thumbnailSprite != null ? entity.thumbnailSprite : equippedEmoteData.cachedThumbnail, + }); + } } else emotesToSet.Add(new EmotesWheelView.EmoteSlotData diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index 771929bb70..bb099255d3 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -10,23 +10,24 @@ public class EmoteClipData public bool Loop { get; } [CanBeNull] private Animation animation; - [CanBeNull] public GameObject ExtraContent { get; private set; } - [CanBeNull] public AudioClip AudioClip { get; private set; } + [CanBeNull] public GameObject ExtraContent { get; } [CanBeNull] private Renderer[] renderers; + [CanBeNull] private AudioSource audioSource; + public EmoteClipData(AnimationClip avatarClip, bool loop = false) { this.AvatarClip = avatarClip; this.Loop = loop; } - public EmoteClipData(AnimationClip mainClip, GameObject container, AudioClip audioClip, bool loop = false) + public EmoteClipData(AnimationClip mainClip, GameObject container, AudioSource audioSource, bool loop = false) { this.AvatarClip = mainClip; this.Loop = loop; this.ExtraContent = container; - this.AudioClip = audioClip; + this.audioSource = audioSource; if (ExtraContent == null) return; @@ -63,6 +64,12 @@ public void PlayAllAnimations(int gameObjectLayer) animation.enabled = true; } + + if (audioSource != null) + { + audioSource.loop = Loop; + audioSource.Play(); + } } public void StopAllAnimations() @@ -85,6 +92,9 @@ public void StopAllAnimations() animation.enabled = false; } + + if (audioSource != null) + audioSource.Stop(); } } } From e72fbfe1d34df70a6fc5a5097956d492fbce254a Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Thu, 31 Aug 2023 13:16:55 -0300 Subject: [PATCH 07/35] Fixed the audio container and 3d spatial settings --- .../Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index eeb7257649..d633966532 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -76,8 +76,11 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s if (audioClip != null) { - audioSource = targetContainer.AddComponent(); + audioSource = rendereable.container.AddComponent(); audioSource.clip = audioClip; + audioSource.rolloffMode = AudioRolloffMode.Linear; + audioSource.minDistance = 3; + audioSource.maxDistance = 30; } break; From 87f739a1b58ddaf05fedb361ccb6eaf0ad7fff86 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Thu, 31 Aug 2023 14:54:25 -0300 Subject: [PATCH 08/35] Fix nre --- .../Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs index 08afd45fff..e376b2566f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/EmotesWheelHUD/EmotesWheelController.cs @@ -139,12 +139,10 @@ private void UpdateEmoteSlots() { if (emotesController.TryGetEquippedEmote(userProfile.avatar.bodyShape, equippedEmoteData.id, out var emote)) { - var entity = emote.GetEntity(); + var entity = emote?.GetEntity(); - if (entity == null) + if (entity == null) // emote exists but its not loaded yet { - Debug.LogError("Something is not quite right"); - emotesToSet.Add(new EmotesWheelView.EmoteSlotData { emoteId = equippedEmoteData.id, From 88a8f46aaed41cc0f98d01e7116aa57866ce54a7 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Thu, 31 Aug 2023 17:49:22 -0300 Subject: [PATCH 09/35] fixed emotes not stopping, spatial not working and hiccup during emote execution --- .../EmotesService/EmoteAnimationLoader.cs | 1 + .../Components/Avatar/AvatarAnimatorLegacy.cs | 49 ++++++++++--------- .../AdditionalInfoOptionsModel.cs | 43 ++++++++++++++++ ...yProfileAdditionalInfoListComponentView.cs | 2 + .../DCL/Models/AvatarAssets/EmoteClipData.cs | 1 - 5 files changed, 73 insertions(+), 23 deletions(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index d633966532..d3d41a6c1d 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -81,6 +81,7 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s audioSource.rolloffMode = AudioRolloffMode.Linear; audioSource.minDistance = 3; audioSource.maxDistance = 30; + audioSource.spatialBlend = 1; } break; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 0da4d77f73..6f2b213d18 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -397,52 +397,41 @@ private void StopEmote(BlackBoard bb) lastExtendedEmoteData?.StopAllAnimations(); } - private void SetExpressionValues(string expressionTriggerId, long expressionTriggerTimestamp) + private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp) { if (animation == null) return; - if (string.IsNullOrEmpty(expressionTriggerId)) + if (string.IsNullOrEmpty(emoteId)) return; - if (animation.GetClip(expressionTriggerId) == null) + if (animation.GetClip(emoteId) == null) return; - var mustTriggerAnimation = !string.IsNullOrEmpty(expressionTriggerId) + var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) && blackboard.expressionTriggerTimestamp != expressionTriggerTimestamp; - blackboard.expressionTriggerId = expressionTriggerId; + blackboard.expressionTriggerId = emoteId; blackboard.expressionTriggerTimestamp = expressionTriggerTimestamp; if (mustTriggerAnimation) { - if (!string.IsNullOrEmpty(expressionTriggerId)) + StartEmote(emoteId); + + if (!string.IsNullOrEmpty(emoteId)) { - animation.Stop(expressionTriggerId); + animation.Stop(emoteId); latestAnimation = AvatarAnimation.IDLE; } - blackboard.shouldLoop = emoteClipDataMap.TryGetValue(expressionTriggerId, out var clipData) && clipData.Loop; + blackboard.shouldLoop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.Loop; currentState = State_Expression; OnUpdateWithDeltaTime(Time.deltaTime); } } - public void Reset() - { - if (animation == null) - return; - - //It will set the animation to the first frame, but due to the nature of the script and its Update. It wont stop the animation from playing - animation.Stop(); - } - - public void SetIdleFrame() { animation.Play(currentLocomotions.idle.name); } - - public void PlayEmote(string emoteId, long timestamps) + private void StartEmote(string emoteId) { - SetExpressionValues(emoteId, timestamps); - if (!string.IsNullOrEmpty(emoteId)) { lastExtendedEmoteData?.StopAllAnimations(); @@ -459,6 +448,22 @@ public void PlayEmote(string emoteId, long timestamps) } } + public void Reset() + { + if (animation == null) + return; + + //It will set the animation to the first frame, but due to the nature of the script and its Update. It wont stop the animation from playing + animation.Stop(); + } + + public void SetIdleFrame() { animation.Play(currentLocomotions.idle.name); } + + public void PlayEmote(string emoteId, long timestamps) + { + SetExpressionValues(emoteId, timestamps); + } + public void EquipBaseClip(AnimationClip clip) { var clipId = clip.name; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/AdditionalInfoOptionsModel.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/AdditionalInfoOptionsModel.cs index a463f228f1..8903ea519a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/AdditionalInfoOptionsModel.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/AdditionalInfoOptionsModel.cs @@ -13,6 +13,7 @@ public enum InputType Date } + public class Option { public Action OnValueSubmitted; @@ -23,8 +24,50 @@ public class Option public InputType InputType { get; set; } [CanBeNull] public string[] Values { get; set; } [CanBeNull] public string DateFormat { get; set; } + + protected bool Equals(Option other) => + IsAvailable == other.IsAvailable && Name == other.Name && InputType == other.InputType && Equals(Values, other.Values) && DateFormat == other.DateFormat; + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((Option)obj); + } + + public override int GetHashCode() => + HashCode.Combine(IsAvailable, Name, (int)InputType, Values, DateFormat); } public Dictionary Options { get; set; } + + protected bool Equals(AdditionalInfoOptionsModel other) + { + if (Options.Count != other.Options.Count) + return false; + + foreach (string key in Options.Keys) + { + if (!other.Options.ContainsKey(key)) + return false; + + if (!Options[key].Equals(other.Options[key])) + return false; + } + + return true; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((AdditionalInfoOptionsModel)obj); + } + + public override int GetHashCode() => + (Options != null ? Options.GetHashCode() : 0); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/MyProfileAdditionalInfoListComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/MyProfileAdditionalInfoListComponentView.cs index d9f834fc17..5580a322ef 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/MyProfileAdditionalInfoListComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/MyProfileAdditionalInfoListComponentView.cs @@ -72,6 +72,8 @@ private void Awake() public void SetOptions(AdditionalInfoOptionsModel model) { + if (optionsModel != null && optionsModel.Equals(model)) return; + optionsModel = model; optionToggles.Clear(); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index bb099255d3..b15bd973dc 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -39,7 +39,6 @@ public EmoteClipData(AnimationClip mainClip, GameObject container, AudioSource a renderers = ExtraContent.GetComponentsInChildren(); } - public void PlayAllAnimations(int gameObjectLayer) { if (renderers != null) From ef4f7d540684b39250d71126dbfb5aa41ca60a4e Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Fri, 1 Sep 2023 15:38:39 -0300 Subject: [PATCH 10/35] Bugfixes --- .../EmotesService/EmoteAnimationLoader.cs | 1 + .../AvatarSystem/AvatarEmotesController.cs | 4 +- .../DCL/AvatarSystem/Definitions/IAnimator.cs | 2 +- .../Definitions/IAvatarEmotesController.cs | 2 +- .../Components/Avatar/AvatarAnimatorLegacy.cs | 64 +++++++++++++------ .../EmoteSlotSelectorComponentView.cs | 7 +- .../EmotesCustomizationComponentController.cs | 6 +- .../EmotesCustomizationComponentView.cs | 6 +- .../IEmoteSlotSelectorComponentView.cs | 2 +- .../IEmotesCustomizationComponentView.cs | 2 +- .../EmoteSlotSelectorComponentViewTests.cs | 4 +- ...esCustomizationComponentControllerTests.cs | 2 +- .../EmotesCustomizationComponentViewTests.cs | 4 +- .../CharacterPreviewController.cs | 2 +- .../DCL/Models/AvatarAssets/EmoteClipData.cs | 5 +- 15 files changed, 72 insertions(+), 41 deletions(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index d3d41a6c1d..a1359765b1 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -82,6 +82,7 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s audioSource.minDistance = 3; audioSource.maxDistance = 30; audioSource.spatialBlend = 1; + audioSource.playOnAwake = false; } break; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs index 8f4a11a390..96c50dae39 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -64,14 +64,14 @@ private async UniTask AsyncEmoteLoad(string bodyShapeId, string emoteId) } } - public void PlayEmote(string emoteId, long timestamps) + public void PlayEmote(string emoteId, long timestamps, bool spatialSound) { if (string.IsNullOrEmpty(emoteId)) return; (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); if (emotes.ContainsKey(emoteKey)) - animator.PlayEmote(emoteId, timestamps); + animator.PlayEmote(emoteId, timestamps, spatialSound); } public void EquipEmote(string emoteId, IEmoteReference emoteReference) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs index e7b3acd1ed..6716a2e9b9 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs @@ -6,7 +6,7 @@ namespace AvatarSystem public interface IAnimator { bool Prepare(string bodyshapeId, GameObject container); - void PlayEmote(string emoteId, long timestamps); + void PlayEmote(string emoteId, long timestamps, bool spatialSound); void EquipEmote(string emoteId, EmoteClipData emoteClipData); void UnequipEmote(string emoteId); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs index 728d1bf673..aabe97dc84 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs @@ -8,7 +8,7 @@ public interface IAvatarEmotesController : IDisposable { void LoadEmotes(string bodyShapeId, IEnumerable emotes); - void PlayEmote(string emoteId, long timestamps); + void PlayEmote(string emoteId, long timestamps, bool spatialSound = true); void EquipEmote(string emoteId, IEmoteReference emoteReference); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 6f2b213d18..37d9cf99f6 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using AvatarSystem; +using Cysharp.Threading.Tasks; using DCL; using DCL.Components; using DCL.Emotes; @@ -102,7 +103,7 @@ public class BlackBoard private string idleAnimationName; private string jumpAnimationName; private string fallAnimationName; - private AvatarAnimation latestAnimation; + private AvatarAnimation latestAnimationState; private AnimationState runAnimationState; private AnimationState walkAnimationState; private bool isUpdateRegistered = false; @@ -110,6 +111,7 @@ public class BlackBoard private Ray rayCache; private bool hasTarget; private EmoteClipData lastExtendedEmoteData; + private string lastCrossFade; private void Awake() { @@ -317,15 +319,16 @@ void State_Ground(BlackBoard bb) } } - private void CrossFadeTo(AvatarAnimation avatarAnimation, string animationName, + private void CrossFadeTo(AvatarAnimation animationState, string animationName, float runTransitionTime, PlayMode playMode = PlayMode.StopSameLayer) { - if (latestAnimation == avatarAnimation) + if (latestAnimationState == animationState) return; - animation.wrapMode = avatarAnimation.ShouldLoop() ? WrapMode.Loop : WrapMode.Once; - animation.CrossFade(animationName, runTransitionTime, playMode); - latestAnimation = avatarAnimation; + lastCrossFade = animationName; + latestAnimationState = animationState; + animation.wrapMode = latestAnimationState.ShouldLoop() ? WrapMode.Loop : WrapMode.Once; + animation.CrossFade(lastCrossFade, runTransitionTime, playMode); } void State_Air(BlackBoard bb) @@ -350,8 +353,7 @@ void State_Air(BlackBoard bb) private void State_Expression(BlackBoard bb) { - var prevAnimation = latestAnimation; - CrossFadeTo(AvatarAnimation.EMOTE, bb.expressionTriggerId, EXPRESSION_EXIT_TRANSITION_TIME, PlayMode.StopAll); + var prevAnimation = latestAnimationState; var exitTransitionStarted = false; @@ -387,17 +389,19 @@ bool ExpressionGroundTransitionCondition(AnimationState animationState) } } - private void StopEmote(BlackBoard bb) + private void StopEmote(BlackBoard bb, bool immediate = false) { - animation.Blend(bb.expressionTriggerId, 0, EXPRESSION_EXIT_TRANSITION_TIME); + if (bb.expressionTriggerId == null) return; + + animation.Blend(bb.expressionTriggerId, 0, !immediate ? EXPRESSION_EXIT_TRANSITION_TIME : 0); bb.expressionTriggerId = null; bb.shouldLoop = false; - OnUpdateWithDeltaTime(bb.deltaTime); + lastExtendedEmoteData?.Stop(); - lastExtendedEmoteData?.StopAllAnimations(); + if (!immediate) OnUpdateWithDeltaTime(bb.deltaTime); } - private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp) + private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp, bool spatialSound) { if (animation == null) return; @@ -415,36 +419,39 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp if (mustTriggerAnimation) { - StartEmote(emoteId); + StartEmote(emoteId, spatialSound); if (!string.IsNullOrEmpty(emoteId)) { animation.Stop(emoteId); - latestAnimation = AvatarAnimation.IDLE; + latestAnimationState = AvatarAnimation.IDLE; } + blackboard.shouldLoop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.Loop; + CrossFadeTo(AvatarAnimation.EMOTE, emoteId, EXPRESSION_EXIT_TRANSITION_TIME, PlayMode.StopAll); + currentState = State_Expression; OnUpdateWithDeltaTime(Time.deltaTime); } } - private void StartEmote(string emoteId) + private void StartEmote(string emoteId, bool spatialSound) { if (!string.IsNullOrEmpty(emoteId)) { - lastExtendedEmoteData?.StopAllAnimations(); + lastExtendedEmoteData?.Stop(); if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) { lastExtendedEmoteData = emoteClipData; - emoteClipData.PlayAllAnimations(gameObject.layer); + emoteClipData.Play(gameObject.layer, spatialSound); } } else { - lastExtendedEmoteData?.StopAllAnimations(); + lastExtendedEmoteData?.Stop(); } } @@ -459,9 +466,9 @@ public void Reset() public void SetIdleFrame() { animation.Play(currentLocomotions.idle.name); } - public void PlayEmote(string emoteId, long timestamps) + public void PlayEmote(string emoteId, long timestamps, bool spatialSound) { - SetExpressionValues(emoteId, timestamps); + SetExpressionValues(emoteId, timestamps, spatialSound); } public void EquipBaseClip(AnimationClip clip) @@ -547,10 +554,25 @@ private void OnEnable() return; animation.enabled = true; + SetIdleFrame(); } private void OnDisable() { + if (animation == null) + return; + + StopEmote(blackboard, true); + CrossFadeTo(AvatarAnimation.IDLE, idleAnimationName, 0); + currentState = State_Ground; + + AsyncAnimationStop().Forget(); + } + + private async UniTaskVoid AsyncAnimationStop() + { + await UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate); + if (animation == null) return; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteSlotSelectorComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteSlotSelectorComponentView.cs index 7d2436810a..4f29735c8f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteSlotSelectorComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteSlotSelectorComponentView.cs @@ -15,7 +15,7 @@ public class EmoteSlotSelectorComponentView : BaseComponentView, IEmoteSlotSelec public int selectedSlot => model.selectedSlot; - public event Action onSlotSelected; + public event Action onSlotSelected; public void Start() { @@ -49,6 +49,8 @@ public override void Dispose() public void SelectSlot(int slotNumber) { + bool isInitialized = model.selectedSlot < 0; + model.selectedSlot = slotNumber; if (emotesSlots == null) @@ -60,7 +62,8 @@ public void SelectSlot(int slotNumber) if (slot.model.slotNumber == slotNumber) { slot.SetEmoteAsSelected(true); - onSlotSelected?.Invoke(slotNumber, slot.model.emoteId); + + onSlotSelected?.Invoke(slotNumber, slot.model.emoteId, !isInitialized); } else { diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs index 2401cb6d5c..73f4073245 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs @@ -289,7 +289,11 @@ internal void OnEmoteUnequipped(string emoteId, int slotNumber) internal void OnSellEmoteClicked(string emoteId) { onEmoteSell?.Invoke(emoteId); } - internal void OnSlotSelected(string emoteId, int slotNumber) { onEmotePreviewed?.Invoke(emoteId); } + internal void OnSlotSelected(string emoteId, int slotNumber, bool playEmote) + { + if (playEmote) + onEmotePreviewed?.Invoke(emoteId); + } internal void ConfigureShortcuts() { diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentView.cs index 2893f9cc49..e0213f9870 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentView.cs @@ -22,7 +22,7 @@ public class EmotesCustomizationComponentView : BaseComponentView, IEmotesCustom public event Action onEmoteEquipped; public event Action onEmoteUnequipped; public event Action onSellEmoteClicked; - public event Action onSlotSelected; + public event Action onSlotSelected; internal Pool emoteCardsPool; @@ -214,7 +214,7 @@ internal EmoteCardComponentView InstantiateAndConfigureEmoteCard(EmoteCardCompon return emoteGO; } - internal void OnSlotSelected(int slotNumber, string emoteId) + internal void OnSlotSelected(int slotNumber, string emoteId, bool playEmote) { List currentEmoteCards = GetAllEmoteCards(); foreach (var existingEmoteCard in currentEmoteCards) @@ -223,7 +223,7 @@ internal void OnSlotSelected(int slotNumber, string emoteId) } SetEmoteInfoPanelActive(false); - onSlotSelected?.Invoke(emoteId, slotNumber); + onSlotSelected?.Invoke(emoteId, slotNumber, playEmote); } internal List GetAllEmoteCards() diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmoteSlotSelectorComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmoteSlotSelectorComponentView.cs index 63aa185cec..7f230b747a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmoteSlotSelectorComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmoteSlotSelectorComponentView.cs @@ -13,7 +13,7 @@ public interface IEmoteSlotSelectorComponentView /// /// It will be triggered when a slot is selected. It returns the selected slot number and the assigned emote id. /// - event Action onSlotSelected; + event Action onSlotSelected; /// /// Select a slot. diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmotesCustomizationComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmotesCustomizationComponentView.cs index 6e1ec059ff..cc90df1bec 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmotesCustomizationComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/IEmotesCustomizationComponentView.cs @@ -24,7 +24,7 @@ public interface IEmotesCustomizationComponentView /// /// It will be triggered when a slot is selected. /// - event Action onSlotSelected; + event Action onSlotSelected; /// /// It represents the container transform of the component. diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs index 0857367707..154ac5c7e7 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmoteSlotSelectorComponentViewTests.cs @@ -56,7 +56,7 @@ public void SelectSlotCorrectly(int slotNumber) int slotNumberReceived = -1; string emoteIdReceived = ""; - emoteSlotSelectorComponent.onSlotSelected += (slotNumber, emoteId) => + emoteSlotSelectorComponent.onSlotSelected += (slotNumber, emoteId, playEmote) => { slotNumberReceived = slotNumber; emoteIdReceived = emoteId; @@ -92,7 +92,7 @@ public void AssignEmoteIntoSlotCorrectly(int slotNumber) int slotNumberReceived = -1; string emoteIdReceived = ""; - emoteSlotSelectorComponent.onSlotSelected += (slotNumber, emoteId) => + emoteSlotSelectorComponent.onSlotSelected += (slotNumber, emoteId, playEmote) => { slotNumberReceived = slotNumber; emoteIdReceived = emoteId; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs index 28f6eef8c1..4d7bdb48d0 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentControllerTests.cs @@ -273,7 +273,7 @@ public void RaiseOnSlotSelectedCorrectly() emotesCustomizationComponentController.onEmotePreviewed += (id) => { receivedId = id; }; // Act - emotesCustomizationComponentController.OnSlotSelected(emoteId, 0); + emotesCustomizationComponentController.OnSlotSelected(emoteId, 0, false); // Assert Assert.AreEqual(emoteId, receivedId); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs index 5afda170bb..b045dd5112 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Tests/EmotesCustomization/EmotesCustomizationComponentViewTests.cs @@ -300,14 +300,14 @@ public void RaiseOnSlotSelectedCorrectly(int slotNumber) string selectedSlotEmoteID = ""; int selectedSlotNumber = -1; - emotesCustomizationComponent.onSlotSelected += (emoteId, slotNumber) => + emotesCustomizationComponent.onSlotSelected += (emoteId, slotNumber, playEmote) => { selectedSlotEmoteID = emoteId; selectedSlotNumber = slotNumber; }; // Act - emotesCustomizationComponent.OnSlotSelected(slotNumber, testEventCardModel.id); + emotesCustomizationComponent.OnSlotSelected(slotNumber, testEventCardModel.id, false); // Assert Assert.IsTrue(testEventCard.model.isAssignedInSelectedSlot); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs index f7f3607ef3..974be54c4d 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs @@ -227,7 +227,7 @@ public IAvatarEmotesController GetEmotesController() => public void PlayEmote(string emoteId, long timestamp) { - avatar.GetEmotesController().PlayEmote(emoteId, timestamp); + avatar.GetEmotesController().PlayEmote(emoteId, timestamp, false); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index b15bd973dc..d0746c9da0 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -39,7 +39,7 @@ public EmoteClipData(AnimationClip mainClip, GameObject container, AudioSource a renderers = ExtraContent.GetComponentsInChildren(); } - public void PlayAllAnimations(int gameObjectLayer) + public void Play(int gameObjectLayer, bool spatialSound) { if (renderers != null) { @@ -66,12 +66,13 @@ public void PlayAllAnimations(int gameObjectLayer) if (audioSource != null) { + audioSource.spatialBlend = spatialSound ? 1 : 0; audioSource.loop = Loop; audioSource.Play(); } } - public void StopAllAnimations() + public void Stop() { if (renderers != null) { From 51a270a6a1693e50e2283f40ab60b43fcb859887 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Tue, 5 Sep 2023 12:31:21 -0300 Subject: [PATCH 11/35] Emotes sound are now tied to an Audio Container which uses the Avatar SFX Channel --- .../AssetGroups/Essentials.asset | 4 ++ .../EmotesService/EmoteAnimationLoader.cs | 10 ++-- .../EmotesService/EmotesService.asmdef | 3 +- .../EmotesService/EmotesService.cs | 14 ++++- .../EmotesServiceDefinitions.asmdef | 3 +- .../Interfaces/IEmoteAnimationLoader.cs | 2 +- .../Components/Avatar/AvatarAnimatorLegacy.cs | 3 +- .../Avatar/EmotesAudioContainer.prefab | 56 +++++++++++++++++++ .../Avatar/EmotesAudioContainer.prefab.meta | 7 +++ .../DCL/Controllers/Audio/Audio.asmdef | 2 +- .../Scripts/SettingsPanelHUD.asmdef | 3 +- .../SettingsPanelHUDTests_PlayMode.asmdef | 3 +- .../ServiceLocatorFactory.cs | 3 +- .../Editor/ReorderableEditor.asmdef | 3 +- .../ReorderableArray/ReorderableArray.asmdef | 3 + .../ReorderableArray.asmdef.meta | 7 +++ .../DCL/Helpers/Utils/Utils.asmdef | 3 +- 17 files changed, 112 insertions(+), 17 deletions(-) create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab.meta create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef.meta diff --git a/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset b/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset index 2547c2aee4..c6d7bf4840 100644 --- a/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset +++ b/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset @@ -72,6 +72,10 @@ MonoBehaviour: m_Address: VRMExporter m_ReadOnly: 0 m_SerializedLabels: [] + - m_GUID: de6eca589c40ed44cb89c60d770db729 + m_Address: EmotesAudioContainer + m_ReadOnly: 0 + m_SerializedLabels: [] m_ReadOnly: 0 m_Settings: {fileID: 11400000, guid: 436e0d4fdc1cdfa4aaef13be2e8bcef8, type: 2} m_SchemaSet: diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index a1359765b1..b77a08214d 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -21,7 +21,7 @@ public EmoteAnimationLoader(IWearableRetriever retriever) this.retriever = retriever; } - public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default) + public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, AudioContainer audioContainer, CancellationToken ct = default) { if (targetContainer == null) throw new NullReferenceException("Container cannot be null"); @@ -78,10 +78,10 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s { audioSource = rendereable.container.AddComponent(); audioSource.clip = audioClip; - audioSource.rolloffMode = AudioRolloffMode.Linear; - audioSource.minDistance = 3; - audioSource.maxDistance = 30; - audioSource.spatialBlend = 1; + audioSource.outputAudioMixerGroup = audioContainer.audioMixerGroup; + audioSource.minDistance = audioContainer.minDistance; + audioSource.maxDistance = audioContainer.maxDistance; + audioSource.spatialBlend = audioContainer.spatialBlend; audioSource.playOnAwake = false; } diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef index f27af42855..227181a311 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef @@ -15,7 +15,8 @@ "GUID:2d39cc535b437e749965d4a8258f0c13", "GUID:b24824f3bc2a60641a01e2083614f802", "GUID:6e6a87f97192ec947993f360104e75b7", - "GUID:a3ceb534947fac14da25035bc5c24788" + "GUID:a3ceb534947fac14da25035bc5c24788", + "GUID:99cea83ca76dcd846abed7e61a8c90bd" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs index e059b9857c..75a08add2a 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs @@ -1,6 +1,7 @@ using AvatarAssets; using Cysharp.Threading.Tasks; using DCL.Configuration; +using DCL.Providers; using DCLServices.WearablesCatalogService; using System; using System.Collections.Generic; @@ -25,13 +26,17 @@ public class EmotesService : IEmotesService private GameObject animationsModelsContainer; private readonly Dictionary<(string, string), IEmoteReference> embeddedEmotes = new (); + private IAddressableResourceProvider assetProvider; + private AudioContainer audioContainer; public EmotesService( EmoteAnimationLoaderFactory emoteAnimationLoaderFactory, IEmotesCatalogService emotesCatalogService, IWearablesCatalogService wearablesCatalogService, - ICatalyst catalyst) + ICatalyst catalyst, + IAddressableResourceProvider assetProvider) { + this.assetProvider = assetProvider; this.emoteAnimationLoaderFactory = emoteAnimationLoaderFactory; this.emotesCatalogService = emotesCatalogService; this.wearablesCatalogService = wearablesCatalogService; @@ -51,6 +56,11 @@ public void Initialize() public async UniTask InitializeAsync(CancellationToken cancellationToken) { + audioContainer = await assetProvider.GetAddressable("EmotesAudioContainer", cancellationToken); + + if (audioContainer == null) + throw new Exception("EmotesAudioContainer is missing"); + EmbeddedEmotesSO embeddedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); // early return for not configured emotesCatalogService substitutes in legacy test base @@ -91,7 +101,7 @@ public async UniTask RequestEmote(string bodyShapeId, string em } IEmoteAnimationLoader animationLoader = emoteAnimationLoaderFactory.Get(); - await animationLoader.LoadEmote(animationsModelsContainer, emote, bodyShapeId, cancellationToken); + await animationLoader.LoadEmote(animationsModelsContainer, emote, bodyShapeId, audioContainer, cancellationToken); if (animationLoader.mainClip == null) Debug.LogError("Emote animation failed to load for emote " + emote.id); diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef index 4b2b4ba166..e54df0b60d 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef @@ -4,7 +4,8 @@ "references": [ "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", "GUID:3b80b0b562b1cbc489513f09fc1b8f69", - "GUID:f51ebe6a0ceec4240a699833d6309b23" + "GUID:f51ebe6a0ceec4240a699833d6309b23", + "GUID:99cea83ca76dcd846abed7e61a8c90bd" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs index 5b11cccd3f..4986a9763c 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs @@ -10,6 +10,6 @@ public interface IEmoteAnimationLoader : IDisposable AnimationClip mainClip { get; } GameObject container { get; } AudioSource audioSource { get; } - UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default); + UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, AudioContainer audioContainer, CancellationToken ct = default); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 37d9cf99f6..17c71f4093 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -391,7 +391,8 @@ bool ExpressionGroundTransitionCondition(AnimationState animationState) private void StopEmote(BlackBoard bb, bool immediate = false) { - if (bb.expressionTriggerId == null) return; + if (string.IsNullOrEmpty(bb.expressionTriggerId)) return; + if (animation.GetClip(bb.expressionTriggerId) == null) return; animation.Blend(bb.expressionTriggerId, 0, !immediate ? EXPRESSION_EXIT_TRANSITION_TIME : 0); bb.expressionTriggerId = null; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab new file mode 100644 index 0000000000..05d5243427 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &6072649541444775017 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7400991319973154898} + - component: {fileID: 8692226335097150525} + m_Layer: 0 + m_Name: EmotesAudioContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7400991319973154898 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6072649541444775017} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &8692226335097150525 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6072649541444775017} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 19e7434f0c30cd34ab81edae8ab53843, type: 3} + m_Name: + m_EditorClassIdentifier: + instantiateEvents: 1 + audioMixerGroup: {fileID: 4864224931565128906, guid: 97507d628c02bcf47859b9f108ab1823, + type: 2} + spatialBlend: 1 + overrideDefaults: 1 + dopplerLevel: 1 + minDistance: 5 + maxDistance: 200 + audioEvents: + array: [] diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab.meta new file mode 100644 index 0000000000..b27e584fe3 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: de6eca589c40ed44cb89c60d770db729 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/Audio/Audio.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/Audio/Audio.asmdef index 78b586eadb..2144bfaa9a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/Audio/Audio.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/Audio/Audio.asmdef @@ -2,7 +2,7 @@ "name": "Audio", "rootNamespace": "", "references": [ - "GUID:b1087c5731ff68448a0a9c625bb7e52d" + "GUID:56fa5598de9cc474c92493db91af18b5" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Scripts/SettingsPanelHUD.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Scripts/SettingsPanelHUD.asmdef index 349daca430..9015bd9872 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Scripts/SettingsPanelHUD.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Scripts/SettingsPanelHUD.asmdef @@ -20,7 +20,8 @@ "GUID:d7f1765642f0c22cda30addd0275b5e1", "GUID:1e6b57fe78f7b724e9567f29f6a40c2c", "GUID:a6361293c4e094e4ca3cf05e62b59bc4", - "GUID:81f3218b29e049144b175dad2ebbac1b" + "GUID:81f3218b29e049144b175dad2ebbac1b", + "GUID:56fa5598de9cc474c92493db91af18b5" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Tests/PlayMode/SettingsPanelHUDTests_PlayMode.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Tests/PlayMode/SettingsPanelHUDTests_PlayMode.asmdef index 1f6a457a29..0322aef52c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Tests/PlayMode/SettingsPanelHUDTests_PlayMode.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/SettingsPanelHUD/Tests/PlayMode/SettingsPanelHUDTests_PlayMode.asmdef @@ -16,7 +16,8 @@ "SettingsControllers", "UIHelpers", "HUDInterfaces", - "BaseVariable" + "BaseVariable", + "ReorderableArray" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs index 6e2a653992..b23db17e94 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs @@ -162,7 +162,8 @@ public static ServiceLocator CreateDefault() result.Register(() => new EmotesService(new EmoteAnimationLoaderFactory(), result.Get(), result.Get(), - result.Get().catalyst)); + result.Get().catalyst, + addressableResourceProvider)); result.Register(() => new ThrottledRegexProfanityFilter( new ProfanityWordProviderFromResourcesJson("Profanity/badwords"), 20)); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/Editor/ReorderableEditor.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/Editor/ReorderableEditor.asmdef index 60db55a48d..e830bb1387 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/Editor/ReorderableEditor.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/Editor/ReorderableEditor.asmdef @@ -1,7 +1,8 @@ { "name": "ReorderableEditor", + "rootNamespace": "", "references": [ - "GUID:b1087c5731ff68448a0a9c625bb7e52d" + "GUID:56fa5598de9cc474c92493db91af18b5" ], "includePlatforms": [ "Editor" diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef new file mode 100644 index 0000000000..260d7f4f51 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef @@ -0,0 +1,3 @@ +{ + "name": "ReorderableArray" +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef.meta new file mode 100644 index 0000000000..588d0dbd23 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/ReorderableArray.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 56fa5598de9cc474c92493db91af18b5 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/Utils.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/Utils.asmdef index 3c0701edff..c9e53b9573 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/Utils.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/Utils.asmdef @@ -13,7 +13,8 @@ "GUID:3b80b0b562b1cbc489513f09fc1b8f69", "GUID:15fc0a57446b3144c949da3e2b9737a9", "GUID:029c1c1b674aaae47a6841a0b89ad80e", - "GUID:3c7b57a14671040bd8c549056adc04f5" + "GUID:3c7b57a14671040bd8c549056adc04f5", + "GUID:56fa5598de9cc474c92493db91af18b5" ], "includePlatforms": [], "excludePlatforms": [], From 90336abe050ae42566a34204c6e8661132719e20 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Tue, 5 Sep 2023 16:55:22 -0300 Subject: [PATCH 12/35] Added audio clip disposal --- .../EmotesService/EmoteAnimationLoader.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index b77a08214d..05fd5f0c4c 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -15,6 +15,7 @@ public class EmoteAnimationLoader : IEmoteAnimationLoader public AudioSource audioSource { get; private set; } private AudioClip audioClip; + private AssetPromise_AudioClip audioClipPromise; public EmoteAnimationLoader(IWearableRetriever retriever) { @@ -65,14 +66,8 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s { if (!contentMap.file.EndsWith(".mp3")) continue; //do we need to support more of em? - try - { - await AsyncLoadAudioClip(contentMap.file, contentProvider).ToUniTask(cancellationToken: ct); - } - catch (Exception e) - { - Debug.LogError(e); - } + try { await AsyncLoadAudioClip(contentMap.file, contentProvider).ToUniTask(cancellationToken: ct); } + catch (Exception e) { Debug.LogError(e); } if (audioClip != null) { @@ -91,7 +86,7 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s private IEnumerator AsyncLoadAudioClip(string file, ContentProvider contentProvider) { - var audioClipPromise = new AssetPromise_AudioClip(file, contentProvider); + audioClipPromise = new AssetPromise_AudioClip(file, contentProvider); audioClipPromise.OnSuccessEvent += asset => audioClip = asset.audioClip; audioClipPromise.OnFailEvent += (_, e) => throw e; @@ -102,6 +97,7 @@ private IEnumerator AsyncLoadAudioClip(string file, ContentProvider contentProvi public void Dispose() { + AssetPromiseKeeper_AudioClip.i.Forget(audioClipPromise); retriever?.Dispose(); } } From aa007bb4f8d764bb4389b9b107b645142a14496f Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 6 Sep 2023 13:34:44 -0300 Subject: [PATCH 13/35] Fix emotes not looping --- .../MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 17c71f4093..ab570493bb 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -327,7 +327,7 @@ private void CrossFadeTo(AvatarAnimation animationState, string animationName, lastCrossFade = animationName; latestAnimationState = animationState; - animation.wrapMode = latestAnimationState.ShouldLoop() ? WrapMode.Loop : WrapMode.Once; + animation.wrapMode = latestAnimationState.ShouldLoop() || blackboard.shouldLoop ? WrapMode.Loop : WrapMode.Once; animation.CrossFade(lastCrossFade, runTransitionTime, playMode); } @@ -428,7 +428,6 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp latestAnimationState = AvatarAnimation.IDLE; } - blackboard.shouldLoop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.Loop; CrossFadeTo(AvatarAnimation.EMOTE, emoteId, EXPRESSION_EXIT_TRANSITION_TIME, PlayMode.StopAll); From 5fd18684a1f6ffd69488a81596eb1111d3e2b073 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 6 Sep 2023 13:47:48 -0300 Subject: [PATCH 14/35] Changed emotes audio mixed bus to see if it works in build --- .../DCL/Components/Avatar/EmotesAudioContainer.prefab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab index 05d5243427..7550e8206f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab @@ -44,8 +44,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 19e7434f0c30cd34ab81edae8ab53843, type: 3} m_Name: m_EditorClassIdentifier: - instantiateEvents: 1 - audioMixerGroup: {fileID: 4864224931565128906, guid: 97507d628c02bcf47859b9f108ab1823, + instantiateEvents: 0 + audioMixerGroup: {fileID: 4026341753330727387, guid: 97507d628c02bcf47859b9f108ab1823, type: 2} spatialBlend: 1 overrideDefaults: 1 From a2609ca0f9989286b054c324d7459641bed386bd Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 6 Sep 2023 13:53:02 -0300 Subject: [PATCH 15/35] test: always trigger loop emotes --- .../DCL/Components/Avatar/AvatarAnimatorLegacy.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index ab570493bb..67d22c7b2a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -413,12 +413,14 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp if (animation.GetClip(emoteId) == null) return; - var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) - && blackboard.expressionTriggerTimestamp != expressionTriggerTimestamp; + bool loop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.Loop; + + var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) && blackboard.expressionTriggerTimestamp != expressionTriggerTimestamp; + blackboard.expressionTriggerId = emoteId; blackboard.expressionTriggerTimestamp = expressionTriggerTimestamp; - if (mustTriggerAnimation) + if (mustTriggerAnimation || loop) { StartEmote(emoteId, spatialSound); @@ -428,7 +430,7 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp latestAnimationState = AvatarAnimation.IDLE; } - blackboard.shouldLoop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.Loop; + blackboard.shouldLoop = loop; CrossFadeTo(AvatarAnimation.EMOTE, emoteId, EXPRESSION_EXIT_TRANSITION_TIME, PlayMode.StopAll); From 35f0769338d9469e4b3c36dcbf4ceb8383ca8427 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 6 Sep 2023 14:13:29 -0300 Subject: [PATCH 16/35] Fixed backpack snapshot texture being taken when not having the avatar in Idle --- .../AvatarSystem/AvatarEmotesController.cs | 5 ++++ .../DCL/AvatarSystem/Definitions/IAnimator.cs | 2 ++ .../Definitions/IAvatarEmotesController.cs | 2 ++ .../Components/Avatar/AvatarAnimatorLegacy.cs | 23 +++++++++++-------- .../Scripts/AvatarEditorHUDView.cs | 5 +++- .../BackpackPreviewPanel.cs | 2 +- .../CharacterPreviewController.cs | 4 ++++ .../ICharacterPreviewController.cs | 2 ++ 8 files changed, 34 insertions(+), 11 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs index 96c50dae39..e7b7707d7c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -74,6 +74,11 @@ public void PlayEmote(string emoteId, long timestamps, bool spatialSound) animator.PlayEmote(emoteId, timestamps, spatialSound); } + public void StopEmote() + { + animator.StopEmote(); + } + public void EquipEmote(string emoteId, IEmoteReference emoteReference) { if (emotes.ContainsKey((bodyShapeId, emoteId))) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs index 6716a2e9b9..11ec78052f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs @@ -7,7 +7,9 @@ public interface IAnimator { bool Prepare(string bodyshapeId, GameObject container); void PlayEmote(string emoteId, long timestamps, bool spatialSound); + void StopEmote(); void EquipEmote(string emoteId, EmoteClipData emoteClipData); void UnequipEmote(string emoteId); + } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs index aabe97dc84..51fd3ea403 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs @@ -10,6 +10,8 @@ public interface IAvatarEmotesController : IDisposable void PlayEmote(string emoteId, long timestamps, bool spatialSound = true); + void StopEmote(); + void EquipEmote(string emoteId, IEmoteReference emoteReference); void UnEquipEmote(string emoteId); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 67d22c7b2a..3ccec95374 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -370,7 +370,7 @@ private void State_Expression(BlackBoard bb) } if (exitTransitionStarted) - StopEmote(bb); + StopEmoteInternal(false); else if (prevAnimation != AvatarAnimation.EMOTE) // this condition makes Blend be called only in first frame of the state { animation.wrapMode = bb.shouldLoop ? WrapMode.Loop : WrapMode.Once; @@ -389,17 +389,22 @@ bool ExpressionGroundTransitionCondition(AnimationState animationState) } } - private void StopEmote(BlackBoard bb, bool immediate = false) + public void StopEmote() { - if (string.IsNullOrEmpty(bb.expressionTriggerId)) return; - if (animation.GetClip(bb.expressionTriggerId) == null) return; + StopEmoteInternal(true); + } + + private void StopEmoteInternal(bool immediate) + { + if (string.IsNullOrEmpty(blackboard.expressionTriggerId)) return; + if (animation.GetClip(blackboard.expressionTriggerId) == null) return; - animation.Blend(bb.expressionTriggerId, 0, !immediate ? EXPRESSION_EXIT_TRANSITION_TIME : 0); - bb.expressionTriggerId = null; - bb.shouldLoop = false; + animation.Blend(blackboard.expressionTriggerId, 0, !immediate ? EXPRESSION_EXIT_TRANSITION_TIME : 0); + blackboard.expressionTriggerId = null; + blackboard.shouldLoop = false; lastExtendedEmoteData?.Stop(); - if (!immediate) OnUpdateWithDeltaTime(bb.deltaTime); + if (!immediate) OnUpdateWithDeltaTime(blackboard.deltaTime); } private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp, bool spatialSound) @@ -564,7 +569,7 @@ private void OnDisable() if (animation == null) return; - StopEmote(blackboard, true); + StopEmoteInternal(true); CrossFadeTo(AvatarAnimation.IDLE, idleAnimationName, 0); currentState = State_Ground; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDView.cs index 235014aa06..fe868f6cdc 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/AvatarEditorHUDView.cs @@ -720,7 +720,10 @@ internal void SetSectionActive(int sectionIndex, bool isActive) public void PlayPreviewEmote(string emoteId) { CharacterPreview.PlayEmote(emoteId, (long)Time.realtimeSinceStartup); } - public void ResetPreviewEmote() { PlayPreviewEmote(RESET_PREVIEW_ANIMATION); } + public void ResetPreviewEmote() + { + CharacterPreview.StopEmote(); + } public void ToggleThirdPartyCollection(string collectionId, bool isOn) { diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs index 0e9f81e9d3..4fd37ad309 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackPreviewPanel.cs @@ -133,7 +133,7 @@ public void PlayPreviewEmote(string emoteId, long timestamp) => characterPreviewController.PlayEmote(emoteId, timestamp); public void ResetPreviewEmote() => - PlayPreviewEmote(RESET_PREVIEW_ANIMATION); + characterPreviewController.StopEmote(); public void ResetPreviewRotation() => characterPreviewController.ResetRotation(); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs index 974be54c4d..39dc7fa556 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs @@ -230,6 +230,10 @@ public void PlayEmote(string emoteId, long timestamp) avatar.GetEmotesController().PlayEmote(emoteId, timestamp, false); } + public void StopEmote() + { + avatar.GetEmotesController().StopEmote(); + } public void Dispose() => Destroy(gameObject); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs index c0a7c4eafa..54a6bcddd1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/ICharacterPreviewController.cs @@ -13,6 +13,7 @@ public interface ICharacterPreviewController : IDisposable IReadOnlyList originalVisibleRenderers { get; } void PlayEmote(string emoteId, long timestamp); + void StopEmote(); UniTask TryUpdateModelAsync(AvatarModel newModel, CancellationToken cancellationToken = default); void SetFocus(PreviewCameraFocus focus, bool useTransition = true); void SetEnabled(bool enabled); @@ -26,5 +27,6 @@ public interface ICharacterPreviewController : IDisposable void SetCharacterShadowActive(bool isActive); IAvatarEmotesController GetEmotesController(); + } } From e81017ce5b4cf8f6401743a6b47d28ac30fe6265 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 6 Sep 2023 16:28:18 -0300 Subject: [PATCH 17/35] Fixed looped emotes not playing after user connects near a user that already triggered the emote --- .../Components/Avatar/AvatarAnimatorLegacy.cs | 20 +++++++++++++++++++ .../DCL/Components/Avatar/AvatarShape.cs | 2 ++ .../DCL/UserProfile/UserProfile.cs | 12 +++++++---- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 3ccec95374..10906cac2d 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -112,6 +112,8 @@ public class BlackBoard private bool hasTarget; private EmoteClipData lastExtendedEmoteData; private string lastCrossFade; + private AnimationState currentEmote; + private int lastEmoteLoopCount; private void Awake() { @@ -377,6 +379,16 @@ private void State_Expression(BlackBoard bb) animation.Blend(bb.expressionTriggerId, 1, EXPRESSION_ENTER_TRANSITION_TIME); } + // If we reach the emote loop, we send the RPC message again to refresh new users + if (bb.shouldLoop && isOwnPlayer) + { + int emoteLoop = GetCurrentEmoteLoopCount(); + if (emoteLoop != lastEmoteLoopCount) + UserProfile.GetOwnUserProfile().SetAvatarExpression(bb.expressionTriggerId, UserProfile.EmoteSource.EmoteLoop, true); + + lastEmoteLoopCount = emoteLoop; + } + return; bool ExpressionGroundTransitionCondition(AnimationState animationState) @@ -389,6 +401,9 @@ bool ExpressionGroundTransitionCondition(AnimationState animationState) } } + private int GetCurrentEmoteLoopCount() => + Mathf.RoundToInt(currentEmote.time / currentEmote.length); + public void StopEmote() { StopEmoteInternal(true); @@ -422,6 +437,9 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) && blackboard.expressionTriggerTimestamp != expressionTriggerTimestamp; + if (loop && blackboard.expressionTriggerId == emoteId) + return; + blackboard.expressionTriggerId = emoteId; blackboard.expressionTriggerTimestamp = expressionTriggerTimestamp; @@ -439,6 +457,8 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp CrossFadeTo(AvatarAnimation.EMOTE, emoteId, EXPRESSION_EXIT_TRANSITION_TIME, PlayMode.StopAll); + currentEmote = animation[emoteId]; + lastEmoteLoopCount = GetCurrentEmoteLoopCount(); currentState = State_Expression; OnUpdateWithDeltaTime(Time.deltaTime); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs index 3b035aa75f..3a4bc4b1a0 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs @@ -236,6 +236,8 @@ public override IEnumerator ApplyChanges(BaseModel newModel) sceneEmoteHandler.SetExpressionLamportTimestamp(model.expressionTriggerTimestamp); + Debug.Log($"{model.name} emote state: {model.expressionTriggerId}"); + if (sceneEmoteHandler.IsSceneEmote(model.expressionTriggerId)) { sceneEmoteHandler diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/UserProfile/UserProfile.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/UserProfile/UserProfile.cs index 1b5b1a6cca..a330de9350 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/UserProfile/UserProfile.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/UserProfile/UserProfile.cs @@ -18,6 +18,7 @@ public enum EmoteSource Shortcut, Command, Backpack, + EmoteLoop, } private const string FALLBACK_NAME = "fallback"; @@ -61,6 +62,7 @@ private AvatarModel AvatarFallback() => AvatarModel.FallbackModel(FALLBACK_NAME, this.GetInstanceID()); private int emoteLamportTimestamp = 1; + private ClientEmotesKernelService emotes => Environment.i.serviceLocator.Get().Emotes(); public void UpdateData(UserProfileModel newModel) { @@ -130,13 +132,12 @@ public void OverrideAvatar(AvatarModel newModel, Texture2D newFaceSnapshot) OnUpdate?.Invoke(this); } - public void SetAvatarExpression(string id, EmoteSource source) + public void SetAvatarExpression(string id, EmoteSource source, bool rpcOnly = false) { int timestamp = emoteLamportTimestamp++; avatar.expressionTriggerId = id; avatar.expressionTriggerTimestamp = timestamp; - ClientEmotesKernelService emotes = Environment.i.serviceLocator.Get().Emotes(); // TODO: fix message `Timestamp` should NOT be `float`, we should use `int lamportTimestamp` or `long timeStamp` emotes?.TriggerExpression(new TriggerExpressionRequest() { @@ -144,8 +145,11 @@ public void SetAvatarExpression(string id, EmoteSource source) Timestamp = timestamp }); - OnUpdate?.Invoke(this); - OnAvatarEmoteSet?.Invoke(id, timestamp, source); + if (!rpcOnly) + { + OnUpdate?.Invoke(this); + OnAvatarEmoteSet?.Invoke(id, timestamp, source); + } } public void SetInventory(IEnumerable inventoryIds) From c0c09355dcd6f96b3b597cf796387fb839d7adcc Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Thu, 7 Sep 2023 13:54:57 -0300 Subject: [PATCH 18/35] Fix emote not stopping when avatar is rebuilt, fix emote wheel not sending you yo emote editor --- .../DCL/Components/Avatar/AvatarAnimatorLegacy.cs | 12 ++++-------- .../Components/Avatar/EmotesAudioContainer.prefab | 2 +- .../BackpackEditorHUDV2ComponentView.cs | 12 ++++++++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 10906cac2d..1b4ca4e654 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -127,6 +127,8 @@ private void Awake() // AvatarSystem entry points public bool Prepare(string bodyshapeId, GameObject container) { + StopEmote(); + animation = container.gameObject.GetOrCreateComponent(); container.gameObject.GetOrCreateComponent(); @@ -522,15 +524,12 @@ public void EquipEmote(string emoteId, EmoteClipData emoteClipData) animation.AddClip(emoteClipData.AvatarClip, emoteId); - // Enhanced emotes setup - if (emoteClipData.ExtraContent != null) { - emoteClipData.ExtraContent.transform.SetParent(animation.transform, false); + emoteClipData.ExtraContent.transform.SetParent(animation.transform.parent, false); emoteClipData.ExtraContent.transform.ResetLocalTRS(); + emoteClipData.ExtraContent.transform.localPosition = animation.transform.localPosition; } - - // TODO: Setup sound clip for this emote } public void UnequipEmote(string emoteId) @@ -545,11 +544,8 @@ public void UnequipEmote(string emoteId) if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) { - // Enhanced emotes setup if (emoteClipData.ExtraContent != null) emoteClipData.ExtraContent.transform.SetParent(null, false); - - // TODO: Setup sound clip for this emote } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab index 7550e8206f..8462a51def 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab @@ -45,7 +45,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: instantiateEvents: 0 - audioMixerGroup: {fileID: 4026341753330727387, guid: 97507d628c02bcf47859b9f108ab1823, + audioMixerGroup: {fileID: 4864224931565128906, guid: 97507d628c02bcf47859b9f108ab1823, type: 2} spatialBlend: 1 overrideDefaults: 1 diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs index f7c14e6d32..a1b55d8477 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/BackpackEditorHUDV2ComponentView.cs @@ -54,6 +54,7 @@ public class BackpackEditorHUDV2ComponentView : BaseComponentView avatarSlotsView; public BackpackFiltersComponentView BackpackFiltersComponentView => backpackFiltersComponentView; public OutfitsSectionComponentView OutfitsSectionComponentView => outfitsSectionComponentView; + private DataStore_EmotesCustomization emotesCustomizationDataStore => DataStore.i.emotesCustomization; private Transform thisTransform; private bool isAvatarDirty; @@ -136,6 +137,7 @@ public override void Dispose() sectionSelector.GetSection(AVATAR_SECTION_INDEX).onSelect.RemoveAllListeners(); sectionSelector.GetSection(EMOTES_SECTION_INDEX).onSelect.RemoveAllListeners(); + emotesCustomizationDataStore.isEmotesCustomizationSelected.OnChange -= OnEmotesCustomizationSelected; backpackPreviewPanel.Dispose(); colorPickerComponentView.OnColorChanged -= OnColorPickerColorChanged; @@ -284,11 +286,21 @@ private void ConfigureSectionSelector() sectionSelector.GetSection(EMOTES_SECTION_INDEX) .onSelect.AddListener((isSelected) => { + emotesCustomizationDataStore.isEmotesCustomizationSelected.Set(isSelected); + emotesSection.SetActive(isSelected); if (isSelected) ResetPreviewPanel(); }); + + emotesCustomizationDataStore.isEmotesCustomizationSelected.OnChange += OnEmotesCustomizationSelected; + } + + private void OnEmotesCustomizationSelected(bool current, bool previous) + { + if (current) + sectionSelector.GetSection(EMOTES_SECTION_INDEX).SelectToggle(); } public void ResetPreviewPanel() From b1c44bd4ba73bdd3d63961c20d921ba085b1e4cb Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 11 Sep 2023 13:17:35 -0300 Subject: [PATCH 19/35] Slight refactor for code review --- .../AssetGroups/Essentials.asset | 4 +- .../{Interfaces.meta => Domain.meta} | 0 .../EmbedEmoteReference.cs | 0 .../EmbedEmoteReference.cs.meta | 0 .../EmotesService/Domain/EmoteBodyId.cs | 32 +++++ .../EmotesService/Domain/EmoteBodyId.cs.meta | 3 + .../EmotesServiceDefinitions.asmdef | 0 .../EmotesServiceDefinitions.asmdef.meta | 0 .../IEmoteAnimationLoader.cs | 2 +- .../IEmoteAnimationLoader.cs.meta | 0 .../{Interfaces => Domain}/IEmoteReference.cs | 0 .../IEmoteReference.cs.meta | 0 .../{Interfaces => Domain}/IEmotesService.cs | 2 +- .../IEmotesService.cs.meta | 0 .../NftEmoteReference.cs | 0 .../NftEmoteReference.cs.meta | 0 .../EmotesService/EmoteAnimationLoader.cs | 38 ++--- .../EmoteAnimationLoaderFactory.cs | 13 +- .../EmotesService/EmotesService.cs | 73 ++++------ .../AvatarSystem/AvatarEmotesController.cs | 38 ++--- .../Avatar/AvatarSceneEmoteHandler.cs | 10 +- .../DCL/Components/Avatar/AvatarShape.cs | 2 - .../Components/Avatar/EmoteAudioSource.prefab | 131 ++++++++++++++++++ ...efab.meta => EmoteAudioSource.prefab.meta} | 2 +- .../Avatar/EmotesAudioContainer.prefab | 56 -------- .../Tests/AvatarSceneEmoteHandlerShould.cs | 13 +- .../ServiceLocatorFactory.cs | 5 +- .../EmotesRendererServiceImpl.cs | 20 +-- .../Tests/TriggerSceneExpressionShould.cs | 20 +-- 29 files changed, 284 insertions(+), 180 deletions(-) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces.meta => Domain.meta} (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/EmbedEmoteReference.cs (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/EmbedEmoteReference.cs.meta (100%) create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs.meta rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/EmotesServiceDefinitions.asmdef (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/EmotesServiceDefinitions.asmdef.meta (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/IEmoteAnimationLoader.cs (79%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/IEmoteAnimationLoader.cs.meta (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/IEmoteReference.cs (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/IEmoteReference.cs.meta (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/IEmotesService.cs (54%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/IEmotesService.cs.meta (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/NftEmoteReference.cs (100%) rename unity-renderer/Assets/DCLServices/EmotesService/{Interfaces => Domain}/NftEmoteReference.cs.meta (100%) create mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab rename unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/{EmotesAudioContainer.prefab.meta => EmoteAudioSource.prefab.meta} (74%) delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab diff --git a/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset b/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset index c6d7bf4840..a3c3e88961 100644 --- a/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset +++ b/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset @@ -72,8 +72,8 @@ MonoBehaviour: m_Address: VRMExporter m_ReadOnly: 0 m_SerializedLabels: [] - - m_GUID: de6eca589c40ed44cb89c60d770db729 - m_Address: EmotesAudioContainer + - m_GUID: fd6cf4a6f210c0b44945d9f5f646cd99 + m_Address: EmoteAudioSource m_ReadOnly: 0 m_SerializedLabels: [] m_ReadOnly: 0 diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain.meta similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmbedEmoteReference.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs new file mode 100644 index 0000000000..2eb55cabb5 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs @@ -0,0 +1,32 @@ +using System; + +namespace DCL.Emotes +{ + public class EmoteBodyId + { + public string BodyShapeId { get; } + public string EmoteId { get; } + + public EmoteBodyId(string bodyShapeId, string emoteId) + { + this.BodyShapeId = bodyShapeId; + this.EmoteId = emoteId; + } + + public override string ToString() => + $"{BodyShapeId}:{EmoteId}"; + + private bool Equals(EmoteBodyId other) => + BodyShapeId == other.BodyShapeId && EmoteId == other.EmoteId; + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == this.GetType() && Equals((EmoteBodyId)obj); + } + + public override int GetHashCode() => + HashCode.Combine(BodyShapeId, EmoteId); + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs.meta new file mode 100644 index 0000000000..7a64be9958 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteBodyId.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3f0f7609a46948d3acf3e9276852418a +timeCreated: 1694443392 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef.meta similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/EmotesServiceDefinitions.asmdef.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs similarity index 79% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs index 4986a9763c..5b11cccd3f 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs @@ -10,6 +10,6 @@ public interface IEmoteAnimationLoader : IDisposable AnimationClip mainClip { get; } GameObject container { get; } AudioSource audioSource { get; } - UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, AudioContainer audioContainer, CancellationToken ct = default); + UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default); } } diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteAnimationLoader.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmoteReference.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs similarity index 54% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs index 66df709240..5f6b2b2ea3 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs @@ -5,6 +5,6 @@ namespace DCL.Emotes { public interface IEmotesService : IService { - UniTask RequestEmote(string bodyShapeId, string emoteId, CancellationToken cancellationToken); + UniTask RequestEmote(EmoteBodyId emoteBodyId, CancellationToken cancellationToken); } } diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/IEmotesService.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLServices/EmotesService/Interfaces/NftEmoteReference.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index 05fd5f0c4c..0c571a69e4 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -2,27 +2,30 @@ using System; using System.Threading; using Cysharp.Threading.Tasks; -using System.Collections; +using DCL.Providers; using UnityEngine; namespace DCL.Emotes { public class EmoteAnimationLoader : IEmoteAnimationLoader { + private const string EMOTE_AUDIO_SOURCE = "EmoteAudioSource"; private readonly IWearableRetriever retriever; - public AnimationClip mainClip { get; internal set; } + private readonly AddressableResourceProvider resourceProvider; + public AnimationClip mainClip { get; private set; } public GameObject container { get; private set; } public AudioSource audioSource { get; private set; } private AudioClip audioClip; private AssetPromise_AudioClip audioClipPromise; - public EmoteAnimationLoader(IWearableRetriever retriever) + public EmoteAnimationLoader(IWearableRetriever retriever, AddressableResourceProvider resourceProvider) { this.retriever = retriever; + this.resourceProvider = resourceProvider; } - public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, AudioContainer audioContainer, CancellationToken ct = default) + public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default) { if (targetContainer == null) throw new NullReferenceException("Container cannot be null"); @@ -56,43 +59,40 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s return; } - //Setting animation name equal to emote id to avoid unity animation clip duplication on Animation.AddClip() this.mainClip = animationClip; + + //Clip names should be unique because of the Legacy Animation string based usage animationClip.name = emote.id; var contentProvider = emote.GetContentProvider(bodyShapeId); foreach (var contentMap in contentProvider.contents) { - if (!contentMap.file.EndsWith(".mp3")) continue; //do we need to support more of em? + if (!IsValidAudioClip(contentMap.file)) continue; - try { await AsyncLoadAudioClip(contentMap.file, contentProvider).ToUniTask(cancellationToken: ct); } + try { await AsyncLoadAudioClip(contentMap.file, contentProvider); } catch (Exception e) { Debug.LogError(e); } if (audioClip != null) { - audioSource = rendereable.container.AddComponent(); + audioSource = await resourceProvider.Instantiate(EMOTE_AUDIO_SOURCE, "EmoteAudioSource", rendereable.container.transform, ct); audioSource.clip = audioClip; - audioSource.outputAudioMixerGroup = audioContainer.audioMixerGroup; - audioSource.minDistance = audioContainer.minDistance; - audioSource.maxDistance = audioContainer.maxDistance; - audioSource.spatialBlend = audioContainer.spatialBlend; - audioSource.playOnAwake = false; } + // we only support one audio clip break; } } - private IEnumerator AsyncLoadAudioClip(string file, ContentProvider contentProvider) + private bool IsValidAudioClip(string fileName) => + fileName.EndsWith(".ogg") || fileName.EndsWith(".mp3"); + + private async UniTask AsyncLoadAudioClip(string file, ContentProvider contentProvider) { audioClipPromise = new AssetPromise_AudioClip(file, contentProvider); - audioClipPromise.OnSuccessEvent += asset => audioClip = asset.audioClip; - audioClipPromise.OnFailEvent += (_, e) => throw e; - AssetPromiseKeeper_AudioClip.i.Keep(audioClipPromise); - - yield return audioClipPromise; + await audioClipPromise; + return audioClipPromise.asset.audioClip; } public void Dispose() diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs index 0c1ba74ae7..eac6e406ef 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs @@ -1,9 +1,18 @@ using AvatarSystem; +using DCL.Providers; namespace DCL.Emotes { public class EmoteAnimationLoaderFactory { - public virtual IEmoteAnimationLoader Get() { return new EmoteAnimationLoader(new WearableRetriever()); } + private readonly AddressableResourceProvider resourceProvider; + + public EmoteAnimationLoaderFactory(AddressableResourceProvider resourceProvider) + { + this.resourceProvider = resourceProvider; + } + + public virtual IEmoteAnimationLoader Get() => + new EmoteAnimationLoader(new WearableRetriever(), resourceProvider); } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs index 75a08add2a..ebd9a7e089 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs @@ -1,11 +1,8 @@ using AvatarAssets; using Cysharp.Threading.Tasks; using DCL.Configuration; -using DCL.Providers; using DCLServices.WearablesCatalogService; -using System; using System.Collections.Generic; -using System.Runtime.ExceptionServices; using System.Threading; using UnityEngine; using Object = UnityEngine.Object; @@ -25,18 +22,14 @@ public class EmotesService : IEmotesService private readonly ICatalyst catalyst; private GameObject animationsModelsContainer; - private readonly Dictionary<(string, string), IEmoteReference> embeddedEmotes = new (); - private IAddressableResourceProvider assetProvider; - private AudioContainer audioContainer; + private readonly Dictionary embeddedEmotes = new (); public EmotesService( EmoteAnimationLoaderFactory emoteAnimationLoaderFactory, IEmotesCatalogService emotesCatalogService, IWearablesCatalogService wearablesCatalogService, - ICatalyst catalyst, - IAddressableResourceProvider assetProvider) + ICatalyst catalyst) { - this.assetProvider = assetProvider; this.emoteAnimationLoaderFactory = emoteAnimationLoaderFactory; this.emotesCatalogService = emotesCatalogService; this.wearablesCatalogService = wearablesCatalogService; @@ -56,17 +49,12 @@ public void Initialize() public async UniTask InitializeAsync(CancellationToken cancellationToken) { - audioContainer = await assetProvider.GetAddressable("EmotesAudioContainer", cancellationToken); - - if (audioContainer == null) - throw new Exception("EmotesAudioContainer is missing"); - - EmbeddedEmotesSO embeddedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); + EmbeddedEmotesSO embedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); // early return for not configured emotesCatalogService substitutes in legacy test base - if (embeddedEmotes == null) return; + if (embedEmotes == null) return; - foreach (EmbeddedEmote embeddedEmote in embeddedEmotes.emotes) + foreach (EmbeddedEmote embeddedEmote in embedEmotes.emotes) { if (embeddedEmote.maleAnimation != null) SetupEmbeddedClip(embeddedEmote, embeddedEmote.maleAnimation, MALE); @@ -75,54 +63,49 @@ public async UniTask InitializeAsync(CancellationToken cancellationToken) SetupEmbeddedClip(embeddedEmote, embeddedEmote.femaleAnimation, FEMALE); } - wearablesCatalogService.AddEmbeddedWearablesToCatalog(embeddedEmotes.emotes); + wearablesCatalogService.AddEmbeddedWearablesToCatalog(embedEmotes.emotes); } private void SetupEmbeddedClip(EmbeddedEmote embeddedEmote, AnimationClip clip, string urnPrefix) { clip.name = embeddedEmote.id; var clipData = new EmoteClipData(clip, embeddedEmote.emoteDataV0?.loop ?? false); - embeddedEmotes.Add((urnPrefix, embeddedEmote.id), new EmbedEmoteReference(embeddedEmote, clipData)); + embeddedEmotes.Add(new EmoteBodyId(urnPrefix, embeddedEmote.id), new EmbedEmoteReference(embeddedEmote, clipData)); } - public async UniTask RequestEmote(string bodyShapeId, string emoteId, CancellationToken cancellationToken = default) + public async UniTask RequestEmote(EmoteBodyId emoteBodyId, CancellationToken cancellationToken = default) { - if (embeddedEmotes.ContainsKey((bodyShapeId, emoteId))) - return embeddedEmotes[(bodyShapeId, emoteId)]; + if (embeddedEmotes.TryGetValue(emoteBodyId, out var value)) + return value; - try - { - var emote = await FetchEmote(bodyShapeId, emoteId, cancellationToken); + var emote = await FetchEmote(emoteBodyId, cancellationToken); - if (emote == null) - { - Debug.LogError($"Unexpected null emote when requesting {bodyShapeId} {emoteId}"); - return null; - } + if (emote == null) + { + Debug.LogError($"Unexpected null emote when requesting {emoteBodyId}"); + return null; + } - IEmoteAnimationLoader animationLoader = emoteAnimationLoaderFactory.Get(); - await animationLoader.LoadEmote(animationsModelsContainer, emote, bodyShapeId, audioContainer, cancellationToken); + // Loader disposal is being handled by the emote reference + IEmoteAnimationLoader animationLoader = emoteAnimationLoaderFactory.Get(); + await animationLoader.LoadEmote(animationsModelsContainer, emote, emoteBodyId.BodyShapeId, cancellationToken); - if (animationLoader.mainClip == null) - Debug.LogError("Emote animation failed to load for emote " + emote.id); + if (animationLoader.mainClip == null) + Debug.LogError("Emote animation failed to load for emote " + emote.id); - bool loop = emote is EmoteItem newEmoteItem ? newEmoteItem.data.loop : emote.emoteDataV0?.loop ?? false; - IEmoteReference emoteReference = new NftEmoteReference(emote, animationLoader, loop); - return emoteReference; - } - catch (Exception e) - { - ExceptionDispatchInfo.Capture(e).Throw(); - throw; - } + bool loop = emote is EmoteItem newEmoteItem ? newEmoteItem.data.loop : emote.emoteDataV0?.loop ?? false; + IEmoteReference emoteReference = new NftEmoteReference(emote, animationLoader, loop); + return emoteReference; } - private UniTask FetchEmote(string bodyShapeId, string emoteId, CancellationToken ct) + private UniTask FetchEmote(EmoteBodyId emoteBodyId, CancellationToken ct) { + string emoteId = emoteBodyId.EmoteId; + if (!SceneEmoteHelper.IsSceneEmote(emoteId)) return emotesCatalogService.RequestEmoteAsync(emoteId, ct); - WearableItem emoteItem = SceneEmoteHelper.TryGetDataFromEmoteId(emoteId, out string emoteHash, out bool loop) ? new EmoteItem(bodyShapeId, emoteId, emoteHash, catalyst.contentUrl, loop) : null; + WearableItem emoteItem = SceneEmoteHelper.TryGetDataFromEmoteId(emoteId, out string emoteHash, out bool loop) ? new EmoteItem(emoteId, emoteBodyId.BodyShapeId, emoteHash, catalyst.contentUrl, loop) : null; return new UniTask(emoteItem); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs index e7b7707d7c..3c4d48160c 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -17,7 +17,7 @@ public class AvatarEmotesController : IAvatarEmotesController private string bodyShapeId = ""; private readonly IAnimator animator; private readonly IEmotesService emotesService; - private readonly Dictionary<(string, string), IEmoteReference> emotes = new (); + private readonly Dictionary equippedEmotes = new (); private readonly CancellationTokenSource cts = new (); public AvatarEmotesController(IAnimator animator, IEmotesService emotesService) @@ -27,7 +27,7 @@ public AvatarEmotesController(IAnimator animator, IEmotesService emotesService) } public bool TryGetEquippedEmote(string bodyShape, string emoteId, out IEmoteReference emoteReference) => - emotes.TryGetValue((bodyShape, emoteId), out emoteReference); + equippedEmotes.TryGetValue(new EmoteBodyId(bodyShape, emoteId), out emoteReference); // ReSharper disable once PossibleMultipleEnumeration (its intended) public void LoadEmotes(string bodyShapeId, IEnumerable newEmotes) @@ -40,21 +40,21 @@ public void LoadEmotes(string bodyShapeId, IEnumerable newEmotes) private void LoadEmote(string bodyShapeId, WearableItem emote) { - (string bodyShapeId, string id) emoteKey = (bodyShapeId, emote.id); - if (emotes.ContainsKey(emoteKey)) return; - emotes.Add(emoteKey, null); + var emoteKey = new EmoteBodyId(bodyShapeId, emote.id); + if (equippedEmotes.ContainsKey(emoteKey)) return; + equippedEmotes.Add(emoteKey, null); AsyncEmoteLoad(bodyShapeId, emote.id).Forget(); } private async UniTask AsyncEmoteLoad(string bodyShapeId, string emoteId) { - (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); try { - IEmoteReference emoteReference = await emotesService.RequestEmote(bodyShapeId, emoteId, cts.Token); + IEmoteReference emoteReference = await emotesService.RequestEmote(emoteKey, cts.Token); animator.EquipEmote(emoteId, emoteReference.GetData()); - emotes[emoteKey] = emoteReference; + equippedEmotes[emoteKey] = emoteReference; OnEmoteEquipped?.Invoke(emoteId, emoteReference); } catch (OperationCanceledException) { } @@ -68,9 +68,9 @@ public void PlayEmote(string emoteId, long timestamps, bool spatialSound) { if (string.IsNullOrEmpty(emoteId)) return; - (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); - if (emotes.ContainsKey(emoteKey)) + if (equippedEmotes.ContainsKey(emoteKey)) animator.PlayEmote(emoteId, timestamps, spatialSound); } @@ -81,27 +81,29 @@ public void StopEmote() public void EquipEmote(string emoteId, IEmoteReference emoteReference) { - if (emotes.ContainsKey((bodyShapeId, emoteId))) + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); + + if (equippedEmotes.ContainsKey(emoteKey)) { // we avoid dangling references in case an emote was loaded twice emoteReference.Dispose(); return; } - emotes.Add((bodyShapeId, emoteId), emoteReference); + equippedEmotes.Add(emoteKey, emoteReference); animator.EquipEmote(emoteId, emoteReference.GetData()); OnEmoteEquipped?.Invoke(emoteId, emoteReference); } public void UnEquipEmote(string emoteId) { - (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); - if (emotes.ContainsKey(emoteKey)) + if (equippedEmotes.ContainsKey(emoteKey)) { animator.UnequipEmote(emoteId); - emotes[emoteKey].Dispose(); - emotes.Remove(emoteKey); + equippedEmotes[emoteKey].Dispose(); + equippedEmotes.Remove(emoteKey); } } @@ -110,10 +112,10 @@ public void Dispose() { cts.SafeCancelAndDispose(); - foreach (var kvp in emotes) + foreach (var kvp in equippedEmotes) kvp.Value.Dispose(); - emotes.Clear(); + equippedEmotes.Clear(); } } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs index 74ce44db38..f8c604af0e 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs @@ -14,7 +14,7 @@ public class AvatarSceneEmoteHandler { private readonly IAvatarEmotesController emotesController; private readonly IEmotesService emotesService; - private readonly HashSet<(string bodyshapeId, string emoteId)> equippedEmotes; + private readonly HashSet equippedEmotes; private long lamportTimestamp; internal CancellationTokenSource cts; @@ -23,7 +23,7 @@ public AvatarSceneEmoteHandler(IAvatarEmotesController emotesController, IEmotes { this.emotesController = emotesController; this.emotesService = emotesService; - this.equippedEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); + this.equippedEmotes = new HashSet(); } public bool IsSceneEmote(string emoteId) => @@ -39,11 +39,11 @@ public async UniTask LoadAndPlayEmote(string bodyShapeId, string emoteId) long timestamp = lamportTimestamp; cts ??= new CancellationTokenSource(); - (string bodyShapeId, string emoteId) emoteKey = (bodyShapeId, emoteId); + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); try { - var loadedEmote = await emotesService.RequestEmote(bodyShapeId, emoteId, cts.Token); + var loadedEmote = await emotesService.RequestEmote(emoteKey, cts.Token); emotesController.EquipEmote(emoteId, loadedEmote); equippedEmotes.Add(emoteKey); @@ -63,7 +63,7 @@ public void CleanUp() cts = null; foreach (var emoteData in equippedEmotes) - emotesController?.UnEquipEmote(emoteData.emoteId); + emotesController?.UnEquipEmote(emoteData.EmoteId); equippedEmotes.Clear(); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs index 3a4bc4b1a0..3b035aa75f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarShape.cs @@ -236,8 +236,6 @@ public override IEnumerator ApplyChanges(BaseModel newModel) sceneEmoteHandler.SetExpressionLamportTimestamp(model.expressionTriggerTimestamp); - Debug.Log($"{model.name} emote state: {model.expressionTriggerId}"); - if (sceneEmoteHandler.IsSceneEmote(model.expressionTriggerId)) { sceneEmoteHandler diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab new file mode 100644 index 0000000000..b66653244b --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab @@ -0,0 +1,131 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &2180456685581696734 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2180456685581696704} + - component: {fileID: 2180456685581696705} + m_Layer: 0 + m_Name: EmoteAudioSource + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2180456685581696704 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2180456685581696734} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 204.62283, y: 604.0454, z: 3.317958} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &2180456685581696705 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2180456685581696734} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 4864224931565128906, guid: 97507d628c02bcf47859b9f108ab1823, + type: 2} + m_audioClip: {fileID: 0} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 20 + Pan2D: 0 + rolloffMode: 2 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0.011015746 + outSlope: 0.011015746 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.17047451 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab.meta similarity index 74% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab.meta rename to unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab.meta index b27e584fe3..bfe1fd2099 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab.meta +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: de6eca589c40ed44cb89c60d770db729 +guid: fd6cf4a6f210c0b44945d9f5f646cd99 PrefabImporter: externalObjects: {} userData: diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab deleted file mode 100644 index 8462a51def..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmotesAudioContainer.prefab +++ /dev/null @@ -1,56 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &6072649541444775017 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7400991319973154898} - - component: {fileID: 8692226335097150525} - m_Layer: 0 - m_Name: EmotesAudioContainer - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &7400991319973154898 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6072649541444775017} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &8692226335097150525 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6072649541444775017} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 19e7434f0c30cd34ab81edae8ab53843, type: 3} - m_Name: - m_EditorClassIdentifier: - instantiateEvents: 0 - audioMixerGroup: {fileID: 4864224931565128906, guid: 97507d628c02bcf47859b9f108ab1823, - type: 2} - spatialBlend: 1 - overrideDefaults: 1 - dopplerLevel: 1 - minDistance: 5 - maxDistance: 200 - audioEvents: - array: [] diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs index 141f8b0c20..e0808939b7 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/Tests/AvatarSceneEmoteHandlerShould.cs @@ -35,8 +35,8 @@ public async Task LoadAndPlayEmote_Success() await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - emotesService.Received(1).RequestEmote(emoteData.bodyshapeId, emoteData.emoteId, Arg.Any()); + var emoteData = new EmoteBodyId(BODY_SHAPE, EMOTE_ID); + emotesService.Received(1).RequestEmote(emoteData, Arg.Any()); emotesController.Received(1).EquipEmote(EMOTE_ID, emote); emotesController.Received(1).PlayEmote(EMOTE_ID, 0); } @@ -47,12 +47,12 @@ public async Task LoadAndPlayEmote_Cancelled() const string BODY_SHAPE = "nogender"; const string EMOTE_ID = "emoteId"; - emotesService.RequestEmote(BODY_SHAPE, EMOTE_ID, Arg.Any()).Throws(new OperationCanceledException()); + var emoteData = new EmoteBodyId(BODY_SHAPE, EMOTE_ID); + emotesService.RequestEmote(emoteData, Arg.Any()).Throws(new OperationCanceledException()); await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); - var emoteData = (bodyshapeId: BODY_SHAPE, emoteId: EMOTE_ID); - emotesService.Received(1).RequestEmote(emoteData.bodyshapeId, emoteData.emoteId, Arg.Any()); + emotesService.Received(1).RequestEmote(emoteData, Arg.Any()); emotesController.DidNotReceive().EquipEmote(Arg.Any(), Arg.Any()); emotesController.DidNotReceive().PlayEmote(Arg.Any(), Arg.Any()); } @@ -105,7 +105,8 @@ public async Task CleanUp() private IEmoteReference SetupEmoteService(string bodyShape, string emoteId) { var emote = Substitute.For(); - emotesService.RequestEmote(bodyShape, emoteId, Arg.Any()).Returns(_ => GetResult(emote)); + var emoteData = new EmoteBodyId(bodyShape, emoteId); + emotesService.RequestEmote(emoteData, Arg.Any()).Returns(_ => GetResult(emote)); return emote; } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs index b23db17e94..838975f80a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Environment/Factories/ServiceLocatorFactory/ServiceLocatorFactory.cs @@ -159,11 +159,10 @@ public static ServiceLocator CreateDefault() result.Register(WebInterfaceCustomNftCatalogBridge.GetOrCreate); - result.Register(() => new EmotesService(new EmoteAnimationLoaderFactory(), + result.Register(() => new EmotesService(new EmoteAnimationLoaderFactory(addressableResourceProvider), result.Get(), result.Get(), - result.Get().catalyst, - addressableResourceProvider)); + result.Get().catalyst)); result.Register(() => new ThrottledRegexProfanityFilter( new ProfanityWordProviderFromResourcesJson("Profanity/badwords"), 20)); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs index 3fe93cb140..cf3b79edac 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs @@ -25,7 +25,7 @@ public class EmotesRendererServiceImpl : IEmotesRendererService private readonly BaseVariable ownPlayer; private readonly IEmotesService emotesService; - private readonly IDictionary> emotesByScene; + private readonly IDictionary> emotesByScene; private readonly IDictionary cancellationTokenSources; private IAvatarEmotesController emotesController; @@ -41,7 +41,7 @@ public static void RegisterService(RpcServerPort port) userProfile: UserProfile.GetOwnUserProfile(), ownPlayer: DataStore.i.player.ownPlayer, emotesService: Environment.i.serviceLocator.Get(), - emotesByScene: new Dictionary>(), + emotesByScene: new Dictionary>(), cancellationTokenSources: new Dictionary() )); } @@ -53,7 +53,7 @@ public EmotesRendererServiceImpl( UserProfile userProfile, BaseVariable ownPlayer, IEmotesService emotesService, - IDictionary> emotesByScene, + IDictionary> emotesByScene, IDictionary cancellationTokenSources ) { @@ -101,9 +101,9 @@ public async UniTask TriggerSceneExpression(TriggerSceneExpress string userBodyShape = userProfile.avatar.bodyShape; // get hashset for scene emotes that are already equipped - if (!emotesByScene.TryGetValue(scene, out HashSet<(string bodyShape, string emoteId)> sceneEquippedEmotes)) + if (!emotesByScene.TryGetValue(scene, out HashSet sceneEquippedEmotes)) { - sceneEquippedEmotes = new HashSet<(string bodyShape, string emoteId)>(); + sceneEquippedEmotes = new HashSet(); emotesByScene.Add(scene, sceneEquippedEmotes); } @@ -121,11 +121,13 @@ public async UniTask TriggerSceneExpression(TriggerSceneExpress { await UniTask.SwitchToMainThread(ct); - if (!emotesByScene[scene].Contains((userBodyShape, emoteId))) + var emoteKey = new EmoteBodyId(userBodyShape, emoteId); + + if (!emotesByScene[scene].Contains(emoteKey)) { - var result = await emotesService.RequestEmote(userBodyShape, emoteId, cancellationTokenSource.Token); + var result = await emotesService.RequestEmote(emoteKey, cancellationTokenSource.Token); emotesController.EquipEmote(emoteId, result); - emotesByScene[scene].Add((userBodyShape, emoteId)); + emotesByScene[scene].Add(emoteKey); } userProfile.SetAvatarExpression(emoteId, UserProfile.EmoteSource.Command); @@ -155,7 +157,7 @@ private void OnSceneRemoved(IParcelScene scene) if (!emotesByScene.TryGetValue(scene, out var equippedEmotes)) return; foreach (var emoteData in equippedEmotes) - emotesController?.UnEquipEmote(emoteData.emoteId); + emotesController?.UnEquipEmote(emoteData.EmoteId); emotesByScene.Remove(scene); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs index 2bcd4ed389..710f0b79fa 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/Tests/TriggerSceneExpressionShould.cs @@ -29,7 +29,7 @@ public class TriggerSceneExpressionShould private UserProfile userProfile; private BaseVariable ownPlayer; - private IDictionary> equippedEmotesByScene; + private IDictionary> equippedEmotesByScene; private IDictionary cancellationTokenSources; private IClientEmotesRendererService client; private IEmotesService emotesService; @@ -45,7 +45,7 @@ public async Task SetUp() emotesService = Substitute.For(); userProfile = UserProfile.GetOwnUserProfile(); ownPlayer = new BaseVariable(); - equippedEmotesByScene = new Dictionary>(); + equippedEmotesByScene = new Dictionary>(); cancellationTokenSources = new Dictionary(); Environment.i.serviceLocator.Register(() => Substitute.For()); client = await CreateRpcClient(); @@ -163,8 +163,8 @@ public async Task Success_LoadingAndPlayingEmote_Twice() Assert.IsTrue(result.Success); - avatar.Received(1).EquipEmote(emoteData.emoteId, emoteReference); - Assert.AreEqual(userProfile.avatar.expressionTriggerId, emoteData.emoteId); + avatar.Received(1).EquipEmote(emoteData.EmoteId, emoteReference); + Assert.AreEqual(userProfile.avatar.expressionTriggerId, emoteData.EmoteId); } [Test] @@ -183,8 +183,8 @@ public async Task Success_LoadingAndPlayingEmote() }); Assert.IsTrue(result.Success); - avatar.Received(1).EquipEmote(emoteData.emoteId, emoteReference); - Assert.AreEqual(emoteData.emoteId, userProfile.avatar.expressionTriggerId); + avatar.Received(1).EquipEmote(emoteData.EmoteId, emoteReference); + Assert.AreEqual(emoteData.EmoteId, userProfile.avatar.expressionTriggerId); Assert.IsTrue(equippedEmotesByScene[scene].Contains(emoteData)); } @@ -208,7 +208,7 @@ public async Task Cancelled_When_SceneRemovedWhileLoading() Assert.IsFalse(result.Success); Assert.IsTrue(equippedEmotesByScene[scene].Count == 0); - avatar.Received(1).EquipEmote(emoteData.emoteId, emoteReference); + avatar.Received(1).EquipEmote(emoteData.EmoteId, emoteReference); } [Test] @@ -270,7 +270,7 @@ public async Task GenerateEmoteId_Correctly() Assert.AreEqual(scene.contentProvider.contents[0].hash, hash); } - private ((string bodyShape, string emoteId) emoteData, IParcelScene scene) SetUpWorkingEnvironment(int sceneNumber, string emotePath) + private (EmoteBodyId emoteData, IParcelScene scene) SetUpWorkingEnvironment(int sceneNumber, string emotePath) { const string BODY_SHAPE = "someBodyShape"; @@ -307,8 +307,8 @@ public async Task GenerateEmoteId_Correctly() SceneEmoteHelper.TryGenerateEmoteId(scene, emotePath, false, out string emoteId); emoteReference = Substitute.For(); - emotesService.RequestEmote(BODY_SHAPE, emoteId, Arg.Any()).Returns(UniTask.FromResult(emoteReference)); - return (emoteData: (bodyShape: BODY_SHAPE, emoteId: emoteId), scene: scene); + emotesService.RequestEmote(new EmoteBodyId(BODY_SHAPE, emoteId), Arg.Any()).Returns(UniTask.FromResult(emoteReference)); + return (emoteData: new EmoteBodyId(BODY_SHAPE, emoteId), scene); } private async UniTask CreateRpcClient() From d49ecdf63a580cfe84b0c18a389bfa9211dc3965 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 11 Sep 2023 13:59:11 -0300 Subject: [PATCH 20/35] Fixed tests --- .../Tests/BackpackEditorHUDV2ComponentViewShould.cs | 2 +- .../HUD/BackpackEditorHUDV2/Tests/BackpackPreviewPanelTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackEditorHUDV2ComponentViewShould.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackEditorHUDV2ComponentViewShould.cs index 92a652963f..6b9ad3b356 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackEditorHUDV2ComponentViewShould.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackEditorHUDV2ComponentViewShould.cs @@ -163,7 +163,7 @@ public void ResetPreviewPanelCorrectly() backpackEditorHUDV2ComponentView.ResetPreviewPanel(); // Assert - characterPreviewController.Received(1).PlayEmote("Idle", (long)Time.realtimeSinceStartup); + characterPreviewController.Received(1).StopEmote(); characterPreviewController.Received(1).ResetRotation(); characterPreviewController.Received(1).SetFocus(PreviewCameraFocus.DefaultEditing, false); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackPreviewPanelTests.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackPreviewPanelTests.cs index 25ac78a7e2..66460042c6 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackPreviewPanelTests.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Tests/BackpackPreviewPanelTests.cs @@ -119,7 +119,7 @@ public void ResetPreviewEmoteCorrectly() backpackPreviewPanel.ResetPreviewEmote(); // Assert - characterPreviewController.Received(1).PlayEmote("Idle", (long)Time.realtimeSinceStartup); + characterPreviewController.Received(1).StopEmote(); } [Test] From b9c717b84ee938f373378eb8487195c0103c0aac Mon Sep 17 00:00:00 2001 From: Romina Marchetti Date: Mon, 11 Sep 2023 15:45:02 -0300 Subject: [PATCH 21/35] Add sound texture. Update and rename corner rarity asset. --- .../BackpackV2/BackpackTextures/SoundIcn.png | 3 + .../BackpackTextures/SoundIcn.png.meta} | 32 ++++------ .../Assets/Textures/UI/Common/CornerFlap.png | 3 + ...nerEmotes.png.meta => CornerFlap.png.meta} | 62 ++++--------------- .../Textures/UI/Common/OutlineGradient.png | 4 +- .../Assets/Textures/UI/Common/Rarity.png | 3 - .../Textures/UI/Common/RarityCornerEmotes.png | 3 - 7 files changed, 33 insertions(+), 77 deletions(-) create mode 100644 unity-renderer/Assets/Textures/UI/BackpackV2/BackpackTextures/SoundIcn.png rename unity-renderer/Assets/Textures/UI/{Common/Rarity.png.meta => BackpackV2/BackpackTextures/SoundIcn.png.meta} (83%) create mode 100644 unity-renderer/Assets/Textures/UI/Common/CornerFlap.png rename unity-renderer/Assets/Textures/UI/Common/{RarityCornerEmotes.png.meta => CornerFlap.png.meta} (66%) delete mode 100644 unity-renderer/Assets/Textures/UI/Common/Rarity.png delete mode 100644 unity-renderer/Assets/Textures/UI/Common/RarityCornerEmotes.png diff --git a/unity-renderer/Assets/Textures/UI/BackpackV2/BackpackTextures/SoundIcn.png b/unity-renderer/Assets/Textures/UI/BackpackV2/BackpackTextures/SoundIcn.png new file mode 100644 index 0000000000..02482550bc --- /dev/null +++ b/unity-renderer/Assets/Textures/UI/BackpackV2/BackpackTextures/SoundIcn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a73a1965be512a0c3120bda0c99ce51d083fd03151c34203a8356fa2e95b22c +size 406 diff --git a/unity-renderer/Assets/Textures/UI/Common/Rarity.png.meta b/unity-renderer/Assets/Textures/UI/BackpackV2/BackpackTextures/SoundIcn.png.meta similarity index 83% rename from unity-renderer/Assets/Textures/UI/Common/Rarity.png.meta rename to unity-renderer/Assets/Textures/UI/BackpackV2/BackpackTextures/SoundIcn.png.meta index ac174bd05e..cd176ec2ad 100644 --- a/unity-renderer/Assets/Textures/UI/Common/Rarity.png.meta +++ b/unity-renderer/Assets/Textures/UI/BackpackV2/BackpackTextures/SoundIcn.png.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 87c2ea01f3aa94b648d225daa8b22214 +guid: 86700c29929bc4233a4561fb3da6140b TextureImporter: internalIDToNameTable: [] externalObjects: {} @@ -20,11 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMasterTextureLimit: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -63,11 +64,12 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - cookieLightType: 1 + swizzle: 50462976 + cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 128 + maxTextureSize: 64 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,23 +77,12 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 128 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: WebGL - maxTextureSize: 128 + maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -99,11 +90,12 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Server - maxTextureSize: 128 + maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -111,6 +103,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -127,9 +120,8 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - spritePackingTag: + mipmapLimitGroupName: pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/unity-renderer/Assets/Textures/UI/Common/CornerFlap.png b/unity-renderer/Assets/Textures/UI/Common/CornerFlap.png new file mode 100644 index 0000000000..fcacd45a60 --- /dev/null +++ b/unity-renderer/Assets/Textures/UI/Common/CornerFlap.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb39853604f86d999e0888e52fc8bdf9d8b7e2d0ead88faa43c75c4fdeb92002 +size 709 diff --git a/unity-renderer/Assets/Textures/UI/Common/RarityCornerEmotes.png.meta b/unity-renderer/Assets/Textures/UI/Common/CornerFlap.png.meta similarity index 66% rename from unity-renderer/Assets/Textures/UI/Common/RarityCornerEmotes.png.meta rename to unity-renderer/Assets/Textures/UI/Common/CornerFlap.png.meta index 27e802a265..5621767ffe 100644 --- a/unity-renderer/Assets/Textures/UI/Common/RarityCornerEmotes.png.meta +++ b/unity-renderer/Assets/Textures/UI/Common/CornerFlap.png.meta @@ -1,12 +1,12 @@ fileFormatVersion: 2 -guid: 9440a54c9ef22324ebdbd9239d2e6021 +guid: 021c13bbe34f24b98a25864263580404 TextureImporter: internalIDToNameTable: [] externalObjects: {} serializedVersion: 12 mipmaps: mipMapMode: 0 - enableMipMap: 0 + enableMipMap: 1 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -36,13 +36,13 @@ TextureImporter: filterMode: 1 aniso: 1 mipBias: 0 - wrapU: 1 - wrapV: 1 + wrapU: 0 + wrapV: 0 wrapW: 0 - nPOTScale: 0 + nPOTScale: 1 lightmap: 0 compressionQuality: 50 - spriteMode: 1 + spriteMode: 0 spriteExtrude: 1 spriteMeshType: 1 alignment: 0 @@ -51,9 +51,9 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 1 + alphaIsTransparency: 0 spriteTessellationDetail: -1 - textureType: 8 + textureType: 0 textureShape: 1 singleChannelComponent: 0 flipbookRows: 1 @@ -63,11 +63,11 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - cookieLightType: 1 + cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 128 + maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -79,43 +79,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 128 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: iPhone - maxTextureSize: 128 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Android - maxTextureSize: 128 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: WebGL - maxTextureSize: 128 + maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -127,7 +91,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Server - maxTextureSize: 128 + maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -143,7 +107,7 @@ TextureImporter: outline: [] physicsShape: [] bones: [] - spriteID: 5e97eb03825dee720800000000000000 + spriteID: internalID: 0 vertices: [] indices: diff --git a/unity-renderer/Assets/Textures/UI/Common/OutlineGradient.png b/unity-renderer/Assets/Textures/UI/Common/OutlineGradient.png index b10c0ecdda..36e097d77b 100644 --- a/unity-renderer/Assets/Textures/UI/Common/OutlineGradient.png +++ b/unity-renderer/Assets/Textures/UI/Common/OutlineGradient.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3b28c6d76074729726f4321009cc887c3a63e3a45d5f8c10b79113ca2efa58c -size 8791 +oid sha256:57492fb12d19f85887af15308faa65363988eb21f96e0d257ea3ddfa7cdea4dc +size 9945 diff --git a/unity-renderer/Assets/Textures/UI/Common/Rarity.png b/unity-renderer/Assets/Textures/UI/Common/Rarity.png deleted file mode 100644 index 52f562c10b..0000000000 --- a/unity-renderer/Assets/Textures/UI/Common/Rarity.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:10c40c69d6d11e526a3d8c4d05c20201abb701572e8a15e23be5ddcf0a40004e -size 583 diff --git a/unity-renderer/Assets/Textures/UI/Common/RarityCornerEmotes.png b/unity-renderer/Assets/Textures/UI/Common/RarityCornerEmotes.png deleted file mode 100644 index e112712480..0000000000 --- a/unity-renderer/Assets/Textures/UI/Common/RarityCornerEmotes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a3604d810d4cd9d40cb677db0dedfe2ccd345c550a8ebc8092aef990ff8e800c -size 326 From a91c6456ef1e614f06b95735232f76988e62c218 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 11 Sep 2023 15:44:10 -0300 Subject: [PATCH 22/35] Fixed avatar audio not working --- .../EmotesService/EmoteAnimationLoader.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index 0c571a69e4..00ebc41d4c 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -2,6 +2,7 @@ using System; using System.Threading; using Cysharp.Threading.Tasks; +using DCL.Helpers; using DCL.Providers; using UnityEngine; @@ -70,13 +71,18 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s { if (!IsValidAudioClip(contentMap.file)) continue; - try { await AsyncLoadAudioClip(contentMap.file, contentProvider); } - catch (Exception e) { Debug.LogError(e); } + try { audioClip = await AsyncLoadAudioClip(contentMap.file, contentProvider); } + catch (Exception e) + { + Debug.LogError(e); + } if (audioClip != null) { - audioSource = await resourceProvider.Instantiate(EMOTE_AUDIO_SOURCE, "EmoteAudioSource", rendereable.container.transform, ct); + audioSource = await resourceProvider.Instantiate(EMOTE_AUDIO_SOURCE, "EmoteAudioSource", cancellationToken: ct); audioSource.clip = audioClip; + audioSource.transform.SetParent(rendereable.container.transform, false); + audioSource.transform.ResetLocalTRS(); } // we only support one audio clip From 4b3eefefa8c56be79d8937c29816567da4c567a6 Mon Sep 17 00:00:00 2001 From: Romina Marchetti Date: Mon, 11 Sep 2023 15:46:02 -0300 Subject: [PATCH 23/35] Add sound icon to emote item --- .../EmotesCustomization/EmoteCard.prefab | 175 ++++++++++++++---- 1 file changed, 139 insertions(+), 36 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab index 4d9abee987..92276a7bd7 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab @@ -35,11 +35,10 @@ RectTransform: m_Children: - {fileID: 7813602602508462412} m_Father: {fileID: 4635205700294361718} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} m_AnchorMax: {x: 0.5, y: 1} - m_AnchoredPosition: {x: 0, y: 7.3} + m_AnchoredPosition: {x: 0, y: 7} m_SizeDelta: {x: 0, y: 46} m_Pivot: {x: 0.5, y: 0} --- !u!222 &4678249007657490095 @@ -63,7 +62,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0, g: 0, b: 0, a: 1} + m_Color: {r: 0.08627451, g: 0.08235294, b: 0.09411765, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -97,7 +96,9 @@ Canvas: m_OverrideSorting: 1 m_OverridePixelPerfect: 0 m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 m_SortingOrder: 100 m_TargetDisplay: 0 @@ -172,11 +173,10 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7256802595478311341} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 1, y: 0} - m_AnchorMax: {x: 1, y: 0} - m_AnchoredPosition: {x: -13.8, y: 13.799988} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 12, y: 14} m_SizeDelta: {x: 23, y: 23} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &8175677344269608629 @@ -310,8 +310,8 @@ RectTransform: - {fileID: 5350492626275246499} - {fileID: 7256802595478311341} - {fileID: 1392357348360559249} + - {fileID: 587592046657593429} m_Father: {fileID: 4635205700294361718} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -339,6 +339,81 @@ Animator: m_AllowConstantClipSamplingOptimization: 1 m_KeepAnimatorStateOnDisable: 0 m_WriteDefaultValuesOnDisable: 0 +--- !u!1 &3514777347215158055 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 587592046657593429} + - component: {fileID: 7702333427976139097} + - component: {fileID: 1760703340312379724} + m_Layer: 5 + m_Name: SoundIcn + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &587592046657593429 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3514777347215158055} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4731531340183057157} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -14, y: -14} + m_SizeDelta: {x: 14, y: 14} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7702333427976139097 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3514777347215158055} + m_CullTransparentMesh: 1 +--- !u!114 &1760703340312379724 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3514777347215158055} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.08627451, g: 0.08235294, b: 0.09411765, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 86700c29929bc4233a4561fb3da6140b, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &3931554030590363641 GameObject: m_ObjectHideFlags: 0 @@ -370,7 +445,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4731531340183057157} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -446,7 +520,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4429920434037374047} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -583,12 +656,11 @@ RectTransform: m_Children: - {fileID: 387580975842957322} m_Father: {fileID: 4731531340183057157} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: -0.000022888184, y: 0.000022888184} - m_SizeDelta: {x: 38, y: 38} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 42, y: 42} m_Pivot: {x: 0, y: 1} --- !u!222 &8147596497719133046 CanvasRenderer: @@ -618,7 +690,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 87c2ea01f3aa94b648d225daa8b22214, type: 3} + m_Sprite: {fileID: 21300000, guid: b3148da633cc64974a01bd0083bd1e59, type: 3} m_Type: 0 m_PreserveAspect: 0 m_FillCenter: 1 @@ -659,12 +731,11 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1392357348360559249} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 2.8, y: -3} - m_SizeDelta: {x: 15.6212, y: 15.6212} + m_AnchoredPosition: {x: 4, y: -4} + m_SizeDelta: {x: 16, y: 16} m_Pivot: {x: 0, y: 1} --- !u!222 &1067968680794964267 CanvasRenderer: @@ -735,12 +806,11 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4731531340183057157} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 9.1545, y: 9.1545} + m_SizeDelta: {x: 12, y: 11.999999} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &3412954697840994360 CanvasRenderer: @@ -779,7 +849,7 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 2.3 + m_PixelsPerUnitMultiplier: 2 --- !u!1 &5734192123004538221 GameObject: m_ObjectHideFlags: 0 @@ -817,7 +887,6 @@ RectTransform: - {fileID: 761347738224745034} - {fileID: 1185556401247729995} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -945,7 +1014,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4635205700294361718} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 1, y: 0} m_AnchorMax: {x: 1, y: 0} @@ -991,7 +1059,6 @@ RectTransform: - {fileID: 3802009592106433176} - {fileID: 8953212341848207916} m_Father: {fileID: 4731531340183057157} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1019,7 +1086,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.95294124, g: 0.9490197, b: 0.95294124, a: 1} + m_Color: {r: 0.9882353, g: 0.9882353, b: 0.9882353, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -1120,6 +1187,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 4635205700294361718} m_Modifications: - target: {fileID: 1166888513132788191, guid: d565b61885fb1ef41b1582a285e748e9, @@ -1238,6 +1306,9 @@ PrefabInstance: value: 0 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: d565b61885fb1ef41b1582a285e748e9, type: 3} --- !u!224 &1185556401247729995 stripped RectTransform: @@ -1256,6 +1327,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 54622623229548845, guid: fb037d81b9c10ad439a13e356a17bab6, @@ -1531,6 +1603,9 @@ PrefabInstance: value: 1 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fb037d81b9c10ad439a13e356a17bab6, type: 3} --- !u!224 &2274818967121730081 stripped RectTransform: @@ -1543,6 +1618,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 54622623229548845, guid: fb037d81b9c10ad439a13e356a17bab6, @@ -1832,6 +1908,9 @@ PrefabInstance: value: 1 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fb037d81b9c10ad439a13e356a17bab6, type: 3} --- !u!224 &3802009592106433176 stripped RectTransform: @@ -1844,6 +1923,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 439785820983603457, guid: 88cd164bd30b4c446917e9faee11dd6a, @@ -1870,7 +1950,7 @@ PrefabInstance: - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_AnchorMax.x - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} @@ -1880,7 +1960,7 @@ PrefabInstance: - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_AnchorMin.x - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} @@ -1890,12 +1970,12 @@ PrefabInstance: - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_SizeDelta.x - value: 16 + value: 20 objectReference: {fileID: 0} - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_SizeDelta.y - value: 16 + value: 20 objectReference: {fileID: 0} - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} @@ -1935,12 +2015,12 @@ PrefabInstance: - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_AnchoredPosition.x - value: 4.9 + value: -24 objectReference: {fileID: 0} - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_AnchoredPosition.y - value: 4.8 + value: 4 objectReference: {fileID: 0} - target: {fileID: 1359034845905531969, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} @@ -1957,6 +2037,21 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 2379607339829342679, guid: 88cd164bd30b4c446917e9faee11dd6a, + type: 3} + propertyPath: m_MinWidth + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 2379607339829342679, guid: 88cd164bd30b4c446917e9faee11dd6a, + type: 3} + propertyPath: m_MinHeight + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 2379607339829342679, guid: 88cd164bd30b4c446917e9faee11dd6a, + type: 3} + propertyPath: m_PreferredHeight + value: 14 + objectReference: {fileID: 0} - target: {fileID: 6467206373962124139, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_Name @@ -1971,24 +2066,28 @@ PrefabInstance: type: 3} propertyPath: m_Sprite value: - objectReference: {fileID: 21300000, guid: c7f41b8bc4324443a82a0e197610125d, + objectReference: {fileID: 21300000, guid: 67be8ef53d02c4d108cd3c14933e851d, type: 3} - target: {fileID: 8811823188519358461, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_Color.b - value: 0.83137256 + value: 0.65882355 objectReference: {fileID: 0} - target: {fileID: 8811823188519358461, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_Color.g - value: 0.8039216 + value: 0.60784316 objectReference: {fileID: 0} - target: {fileID: 8811823188519358461, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} propertyPath: m_Color.r - value: 0.8117647 + value: 0.627451 objectReference: {fileID: 0} - m_RemovedComponents: [] + m_RemovedComponents: + - {fileID: 2379607339829342679, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 88cd164bd30b4c446917e9faee11dd6a, type: 3} --- !u!114 &7531741591106090860 stripped MonoBehaviour: @@ -2013,6 +2112,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 4936655407855709455, guid: 4849d2ed3b5a18948bf3cd46256869a4, @@ -2160,7 +2260,7 @@ PrefabInstance: - target: {fileID: 6719010960977733696, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} propertyPath: m_Name - value: EmoteImage + value: EmoteThumbnail objectReference: {fileID: 0} - target: {fileID: 8638032630233208891, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} @@ -2168,6 +2268,9 @@ PrefabInstance: value: 0 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} --- !u!224 &2790442048819812607 stripped RectTransform: From d2a9d1dd67c7b4c180b15bb9d95a3d859ba19cad Mon Sep 17 00:00:00 2001 From: Romina Marchetti Date: Mon, 11 Sep 2023 15:46:34 -0300 Subject: [PATCH 24/35] Polish info card and emote selected card --- .../EmotesCustomization/EmoteInfoPanel.prefab | 294 ++++++++---------- .../EmotesCustomization/EmoteSlotCard.prefab | 10 +- 2 files changed, 142 insertions(+), 162 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteInfoPanel.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteInfoPanel.prefab index f2d6427c75..89c769765b 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteInfoPanel.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteInfoPanel.prefab @@ -28,6 +28,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4913807375479836774} m_RootOrder: 0 @@ -103,14 +104,15 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5318570694798987130} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 59.4, y: 0} - m_SizeDelta: {x: 63.6018, y: 21.34} + m_AnchoredPosition: {x: 64, y: 0} + m_SizeDelta: {x: 80, y: 22} m_Pivot: {x: 0.5, y: 0} --- !u!222 &4688404213833188363 CanvasRenderer: @@ -142,16 +144,15 @@ MonoBehaviour: m_Calls: [] m_text: Polygon m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 26b03903800224f718b64e9afbc91b61, type: 2} - m_sharedMaterial: {fileID: -6892909264025736228, guid: 26b03903800224f718b64e9afbc91b61, - type: 2} + m_fontAsset: {fileID: 11400000, guid: a02669827dd9144f39b4b164e753a21a, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 74b83fa9a54124695b9bdd8bea96fa17, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4281479730 - m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + rgba: 4279768342 + m_fontColor: {r: 0.08627451, g: 0.08235294, b: 0.09411765, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -169,11 +170,11 @@ MonoBehaviour: serializedVersion: 2 rgba: 4294967295 m_fontSize: 12 - m_fontSizeBase: 6.01 + m_fontSizeBase: 12 m_fontWeight: 400 - m_enableAutoSizing: 1 + m_enableAutoSizing: 0 m_fontSizeMin: 11 - m_fontSizeMax: 12 + m_fontSizeMax: 11 m_fontStyle: 16 m_HorizontalAlignment: 1 m_VerticalAlignment: 512 @@ -184,7 +185,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -193,6 +194,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -207,7 +209,7 @@ MonoBehaviour: m_margin: {x: 0, y: 0, z: 0, w: 0} m_isUsingLegacyAnimationComponent: 0 m_isVolumetricText: 0 - m_hasFontAssetChanged: 1 + m_hasFontAssetChanged: 0 m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!1 &674317848198643006 @@ -239,11 +241,12 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 8788380480592711890} - {fileID: 314182990563550652} m_Father: {fileID: 6677185329619746147} - m_RootOrder: 7 + m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} @@ -338,6 +341,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7844748285268685156} m_RootOrder: 0 @@ -413,6 +417,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 5398411851438650255} m_Father: {fileID: 314182990563550652} @@ -489,6 +494,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 526586896386913764} m_RootOrder: 0 @@ -564,6 +570,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8655709810779176039} m_RootOrder: 1 @@ -603,8 +610,8 @@ MonoBehaviour: m_Calls: [] m_text: Emote Name m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 0da28b1264c7140eda8582804e5d094b, type: 2} - m_sharedMaterial: {fileID: 2100000, guid: 263d3c969cdca4dfaaa71514f806a4c2, type: 2} + m_fontAsset: {fileID: 11400000, guid: a02669827dd9144f39b4b164e753a21a, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 74b83fa9a54124695b9bdd8bea96fa17, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] @@ -644,7 +651,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -653,6 +660,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -698,6 +706,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7847811208035094998} m_Father: {fileID: 314182990563550652} @@ -774,6 +783,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3701599438158329820} m_RootOrder: 0 @@ -849,6 +859,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 4090852742891663886} m_Father: {fileID: 314182990563550652} @@ -925,6 +936,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1026856899374076953} m_RootOrder: 1 @@ -1000,14 +1012,15 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2461423672287350586} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 59.1, y: 0} - m_SizeDelta: {x: 63.6018, y: 21.34} + m_AnchoredPosition: {x: 66, y: 0} + m_SizeDelta: {x: 80, y: 22} m_Pivot: {x: 0.5, y: 0} --- !u!222 &4851881732200232403 CanvasRenderer: @@ -1046,8 +1059,8 @@ MonoBehaviour: m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4278190080 - m_fontColor: {r: 0, g: 0, b: 0, a: 1} + rgba: 4279768342 + m_fontColor: {r: 0.08627451, g: 0.08235294, b: 0.09411765, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -1064,12 +1077,12 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 11.5 - m_fontSizeBase: 6.01 + m_fontSize: 12 + m_fontSizeBase: 12 m_fontWeight: 400 - m_enableAutoSizing: 1 + m_enableAutoSizing: 0 m_fontSizeMin: 11 - m_fontSizeMax: 12 + m_fontSizeMax: 11 m_fontStyle: 16 m_HorizontalAlignment: 1 m_VerticalAlignment: 512 @@ -1080,7 +1093,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -1089,6 +1102,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -1134,6 +1148,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7648221977878622141} m_Father: {fileID: 314182990563550652} @@ -1210,6 +1225,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8236048323503335790} m_RootOrder: 1 @@ -1290,7 +1306,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -1299,6 +1315,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -1344,6 +1361,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2461423672287350586} m_RootOrder: 0 @@ -1351,7 +1369,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} m_AnchoredPosition: {x: 8.4, y: 0} - m_SizeDelta: {x: 14, y: 16} + m_SizeDelta: {x: 12, y: 14} m_Pivot: {x: 0, y: 0.5} --- !u!222 &4903210054394542890 CanvasRenderer: @@ -1419,6 +1437,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3017036827035786529} m_RootOrder: 0 @@ -1492,6 +1511,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 314182990563550652} m_RootOrder: 1 @@ -1531,6 +1551,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4558183650348080465} m_RootOrder: 0 @@ -1611,7 +1632,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -1620,6 +1641,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -1701,6 +1723,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 827020544718114853} m_RootOrder: 0 @@ -1782,7 +1805,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -1791,6 +1814,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -1870,6 +1894,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 709537727302124812} m_RootOrder: 0 @@ -1951,6 +1976,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 4344232554486030901} - {fileID: 6540603307328415427} @@ -2163,6 +2189,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3028432359565156811} m_RootOrder: 0 @@ -2238,6 +2265,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 6990771184367375000} m_Father: {fileID: 314182990563550652} @@ -2314,6 +2342,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 5540613570130055267} - {fileID: 3434542883179956457} @@ -2322,8 +2351,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 128.4, y: -0.30000305} - m_SizeDelta: {x: 100.6633, y: 22} + m_AnchoredPosition: {x: 120, y: -0.30000305} + m_SizeDelta: {x: 96, y: 22} m_Pivot: {x: 0.5, y: 0} --- !u!222 &2056649071241881136 CanvasRenderer: @@ -2346,7 +2375,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Color: {r: 0.9254902, g: 0.92156863, b: 0.92941177, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -2362,7 +2391,7 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 2 + m_PixelsPerUnitMultiplier: 4 --- !u!1 &3902542311477435212 GameObject: m_ObjectHideFlags: 0 @@ -2393,6 +2422,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7660192891870380523} - {fileID: 6493778365609098485} @@ -2516,6 +2546,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5318570694798987130} m_RootOrder: 0 @@ -2523,7 +2554,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} m_AnchoredPosition: {x: 4.9999924, y: 0} - m_SizeDelta: {x: 20, y: 20} + m_SizeDelta: {x: 16, y: 16} m_Pivot: {x: 0, y: 0.5} --- !u!222 &6102344823841315607 CanvasRenderer: @@ -2591,6 +2622,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3338843044772166640} m_Father: {fileID: 314182990563550652} @@ -2672,9 +2704,9 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 292382630088478071} - - {fileID: 146489289089697502} - {fileID: 337482348967408730} - {fileID: 8655709810779176039} - {fileID: 3156037698745630027} @@ -2749,7 +2781,7 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1.9 + m_PixelsPerUnitMultiplier: 2 --- !u!114 &6052313431908293864 MonoBehaviour: m_ObjectHideFlags: 0 @@ -2804,9 +2836,11 @@ MonoBehaviour: ethNetwork: {fileID: 3426099895505772951} l2Network: {fileID: 4918921970127134414} backgroundImage: {fileID: 5300491281650717398} + gradientImage: {fileID: 0} rarityName: {fileID: 7138154577954775612} sellButton: {fileID: 5320130153494383211} closeButton: {fileID: 5903637973219978735} + categoryInfoContainer: {fileID: 0} --- !u!114 &4792473028036476023 MonoBehaviour: m_ObjectHideFlags: 0 @@ -2892,6 +2926,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8741428791985623325} m_RootOrder: 0 @@ -2967,6 +3002,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8655709810779176039} m_RootOrder: 0 @@ -3006,15 +3042,15 @@ MonoBehaviour: m_Calls: [] m_text: rarity name m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 0da28b1264c7140eda8582804e5d094b, type: 2} - m_sharedMaterial: {fileID: 2100000, guid: 263d3c969cdca4dfaaa71514f806a4c2, type: 2} + m_fontAsset: {fileID: 11400000, guid: 6b705423dc77d4fceb4122f6d7e571d6, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 9d9df32282a3c40299019c36b2157d37, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4292993505 - m_fontColor: {r: 0.88235295, g: 0.88235295, b: 0.88235295, a: 1} + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -3031,12 +3067,12 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 16 + m_fontSize: 14 m_fontSizeBase: 36 m_fontWeight: 400 m_enableAutoSizing: 1 m_fontSizeMin: 11 - m_fontSizeMax: 16 + m_fontSizeMax: 14 m_fontStyle: 16 m_HorizontalAlignment: 2 m_VerticalAlignment: 512 @@ -3047,7 +3083,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -3056,6 +3092,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -3099,6 +3136,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4277705823136100929} m_RootOrder: 0 @@ -3136,6 +3174,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 6873238449468388590} m_Father: {fileID: 314182990563550652} @@ -3212,6 +3251,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3687470892097437312} m_Father: {fileID: 314182990563550652} @@ -3288,6 +3328,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3169936328511317201} m_Father: {fileID: 314182990563550652} @@ -3364,6 +3405,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7390526354164871457} m_RootOrder: 0 @@ -3439,6 +3481,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 879484974887387149} m_Father: {fileID: 314182990563550652} @@ -3515,6 +3558,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 1290977766796556120} - {fileID: 6525510961967249650} @@ -3523,8 +3567,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 125.3, y: -0.30000305} - m_SizeDelta: {x: 94.403, y: 22} + m_AnchoredPosition: {x: 118, y: -0.30000305} + m_SizeDelta: {x: 90, y: 22} m_Pivot: {x: 0.5, y: 0} --- !u!222 &7564891026472758065 CanvasRenderer: @@ -3547,14 +3591,14 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Color: {r: 0.9254902, g: 0.92156863, b: 0.92941177, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Sprite: {fileID: 21300000, guid: d254a3a3b9d5642e1ad6432c441d7f43, type: 3} + m_Sprite: {fileID: 21300000, guid: f02af068e11cb4902a1a4faad10b890a, type: 3} m_Type: 1 m_PreserveAspect: 0 m_FillCenter: 1 @@ -3563,7 +3607,7 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 2 + m_PixelsPerUnitMultiplier: 4 --- !u!1 &4952263464800277205 GameObject: m_ObjectHideFlags: 0 @@ -3592,6 +3636,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3537824250057932395} m_RootOrder: 0 @@ -3671,14 +3716,15 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6677185329619746147} - m_RootOrder: 2 + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 248.4, y: -16.599976} - m_SizeDelta: {x: 12, y: 12} + m_AnchoredPosition: {x: 251, y: -16} + m_SizeDelta: {x: 10, y: 10} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &4744216878482875378 CanvasRenderer: @@ -3813,102 +3859,6 @@ MonoBehaviour: playClick: 1 playRelease: 1 extraClickEvent: {fileID: 0} ---- !u!1 &5173571069999706513 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 146489289089697502} - - component: {fileID: 5856606621939246705} - - component: {fileID: 2941815661153714099} - - component: {fileID: 205952707557543649} - m_Layer: 5 - m_Name: Gradient - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &146489289089697502 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5173571069999706513} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 6677185329619746147} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 1} - m_AnchorMax: {x: 0.5, y: 1} - m_AnchoredPosition: {x: -0.00024414062, y: 0} - m_SizeDelta: {x: 227.16553, y: 170.11395} - m_Pivot: {x: 0.5, y: 1} ---- !u!222 &5856606621939246705 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5173571069999706513} - m_CullTransparentMesh: 0 ---- !u!114 &2941815661153714099 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5173571069999706513} - m_Enabled: 0 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.9528302, g: 0.9528302, b: 0.9528302, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 1a1d2bd47f28a47c28035a04ee136edd, type: 3} - m_Type: 1 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 2 ---- !u!114 &205952707557543649 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5173571069999706513} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreLayout: 1 - m_MinWidth: -1 - m_MinHeight: -1 - m_PreferredWidth: -1 - m_PreferredHeight: -1 - m_FlexibleWidth: -1 - m_FlexibleHeight: -1 - m_LayoutPriority: 1 --- !u!1 &5287024639694563350 GameObject: m_ObjectHideFlags: 0 @@ -3937,6 +3887,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3144133163719130774} m_Father: {fileID: 314182990563550652} @@ -4013,6 +3964,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 6136417662423149967} m_Father: {fileID: 314182990563550652} @@ -4088,11 +4040,12 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 6934716065501165882} - {fileID: 7079114604660014754} m_Father: {fileID: 6677185329619746147} - m_RootOrder: 9 + m_RootOrder: 8 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} @@ -4154,10 +4107,11 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7514760204919876985} m_Father: {fileID: 6677185329619746147} - m_RootOrder: 8 + m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -4252,6 +4206,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5862283708822078899} m_RootOrder: 0 @@ -4327,6 +4282,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3553032217143319116} m_Father: {fileID: 4778874162488046027} @@ -4408,7 +4364,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -4417,6 +4373,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -4462,6 +4419,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 712720623137334865} m_Father: {fileID: 314182990563550652} @@ -4538,6 +4496,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3156037698745630027} m_RootOrder: 0 @@ -4614,10 +4573,11 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 8236048323503335790} m_Father: {fileID: 6677185329619746147} - m_RootOrder: 5 + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -4712,6 +4672,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3966476897907044659} m_Father: {fileID: 314182990563550652} @@ -4786,6 +4747,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 314182990563550652} m_RootOrder: 0 @@ -4823,6 +4785,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 9218282352425601923} m_Father: {fileID: 314182990563550652} @@ -4899,6 +4862,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 397783170722641867} m_RootOrder: 0 @@ -4974,6 +4938,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4511738032937061545} m_RootOrder: 0 @@ -5049,6 +5014,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2352783266535977029} m_RootOrder: 0 @@ -5124,6 +5090,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1026856899374076953} m_RootOrder: 0 @@ -5205,7 +5172,7 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} @@ -5214,6 +5181,7 @@ MonoBehaviour: m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -5259,6 +5227,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2656008347426834750} m_RootOrder: 0 @@ -5334,6 +5303,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5782496104983487541} m_RootOrder: 0 @@ -5410,11 +5380,12 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3509575154537980714} - {fileID: 148120788220426797} m_Father: {fileID: 6677185329619746147} - m_RootOrder: 3 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5510,10 +5481,11 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 5088803481094463133} m_Father: {fileID: 6677185329619746147} - m_RootOrder: 4 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5609,6 +5581,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6677185329619746147} m_RootOrder: 0 @@ -5639,7 +5612,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.9528302, g: 0.9528302, b: 0.9528302, a: 1} + m_Color: {r: 0.9882353, g: 0.9882353, b: 0.9882353, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -5655,7 +5628,7 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 2 + m_PixelsPerUnitMultiplier: 2.5 --- !u!114 &5696864880677747559 MonoBehaviour: m_ObjectHideFlags: 0 @@ -5702,12 +5675,13 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 4277705823136100929} - {fileID: 2461423672287350586} - {fileID: 5318570694798987130} m_Father: {fileID: 6677185329619746147} - m_RootOrder: 6 + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -5742,6 +5716,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 4839555983224544829} m_Father: {fileID: 314182990563550652} @@ -5818,6 +5793,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7310257252029763277} m_RootOrder: 0 @@ -5893,6 +5869,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 6667571703317080969} m_Father: {fileID: 314182990563550652} @@ -5970,6 +5947,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8236048323503335790} m_RootOrder: 0 @@ -6065,6 +6043,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5885358838239003861} m_RootOrder: 0 @@ -6140,6 +6119,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7380191876128156276} m_Father: {fileID: 314182990563550652} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteSlotCard.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteSlotCard.prefab index 1f716eb3ce..62b1e2c870 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteSlotCard.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteSlotCard.prefab @@ -37,7 +37,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} m_AnchoredPosition: {x: 0.79999924, y: -1.2} - m_SizeDelta: {x: 25.6587, y: 25.6587} + m_SizeDelta: {x: 26, y: 26} m_Pivot: {x: 0, y: 1} --- !u!222 &1534267669551493954 CanvasRenderer: @@ -67,7 +67,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 87c2ea01f3aa94b648d225daa8b22214, type: 3} + m_Sprite: {fileID: 21300000, guid: b3148da633cc64974a01bd0083bd1e59, type: 3} m_Type: 0 m_PreserveAspect: 0 m_FillCenter: 1 @@ -437,7 +437,7 @@ GameObject: - component: {fileID: 4850818203974739451} - component: {fileID: 1621967979247099342} m_Layer: 5 - m_Name: Star + m_Name: Icon m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -460,8 +460,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 2.8, y: -2.6} - m_SizeDelta: {x: 8.4147, y: 8.4147} + m_AnchoredPosition: {x: 2, y: -2} + m_SizeDelta: {x: 11, y: 11} m_Pivot: {x: 0, y: 1} --- !u!222 &4850818203974739451 CanvasRenderer: From 47bf873ee93def78b6f5e6f89b3e7d1016eb8da7 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 11 Sep 2023 15:55:37 -0300 Subject: [PATCH 25/35] Forgot to push this --- .../Assets/DCLServices/EmotesService/EmotesService.asmdef | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef index 227181a311..9cb4ac4b06 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef @@ -16,7 +16,8 @@ "GUID:b24824f3bc2a60641a01e2083614f802", "GUID:6e6a87f97192ec947993f360104e75b7", "GUID:a3ceb534947fac14da25035bc5c24788", - "GUID:99cea83ca76dcd846abed7e61a8c90bd" + "GUID:99cea83ca76dcd846abed7e61a8c90bd", + "GUID:b1087c5731ff68448a0a9c625bb7e52d" ], "includePlatforms": [], "excludePlatforms": [], From 34130d4abc0028d232403ba93421d3023eb0da35 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 11 Sep 2023 16:04:43 -0300 Subject: [PATCH 26/35] Wired up sound icon in emote cards --- .../EmotesCustomization/EmoteCard.prefab | 3 ++- .../EmoteCardComponentModel.cs | 3 ++- .../EmoteCardComponentView.cs | 12 ++++++++++-- .../EmotesCustomizationComponentController.cs | 3 ++- .../DCL/Models/AvatarAssets/EmoteClipData.cs | 16 ++++++++-------- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab index 92276a7bd7..ce96170640 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab @@ -356,7 +356,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &587592046657593429 RectTransform: m_ObjectHideFlags: 0 @@ -953,6 +953,7 @@ MonoBehaviour: rarityMark: {fileID: 5565824628307748902} emoteInfoAnchor: {fileID: 761347738224745034} loadingSpinnerGO: {fileID: 2317431530199778845} + soundIcon: {fileID: 3514777347215158055} defaultEmotePicture: {fileID: 21300000, guid: af3ceb136e126477f809677ea5eb67e2, type: 3} nonEmoteAssignedPicture: {fileID: 21300000, guid: 6b35c647bc47eb94486089adcb53c8b9, diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentModel.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentModel.cs index b7e8c713bd..3367c8e4e8 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentModel.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentModel.cs @@ -18,6 +18,7 @@ public class EmoteCardComponentModel : BaseComponentModel public bool isInL2; public bool isLoading = false; public bool isCollectible = false; + public bool hasSound; } [Serializable] @@ -26,4 +27,4 @@ public class EmoteRarity public string rarity; public Color markColor; } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentView.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentView.cs index fa7747c12f..1b31114a16 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentView.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmoteCardComponentView.cs @@ -23,6 +23,7 @@ public class EmoteCardComponentView : BaseComponentView, IEmoteCardComponentView [SerializeField] internal Image rarityMark; [SerializeField] internal Transform emoteInfoAnchor; [SerializeField] internal GameObject loadingSpinnerGO; + [SerializeField] internal GameObject soundIcon; [Header("Configuration")] [SerializeField] internal Sprite defaultEmotePicture; @@ -32,7 +33,7 @@ public class EmoteCardComponentView : BaseComponentView, IEmoteCardComponentView public Button.ButtonClickedEvent onMainClick => mainButton?.onClick; public Button.ButtonClickedEvent onInfoClick => infoButton?.onClick; - + public event Action onEmoteSelected; public override void Awake() @@ -44,6 +45,8 @@ public override void Awake() if (cardSelectionFrame != null) cardSelectionFrame.SetActive(false); + + SetSoundIcon(false); } public void Configure(EmoteCardComponentModel newModel) @@ -283,5 +286,10 @@ internal void OnEmoteImageLoaded(Sprite sprite) else SetEmotePicture(sprite: null); } + + public void SetSoundIcon(bool active) + { + soundIcon.gameObject.SetActive(active); + } } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs index 73f4073245..617f0eea9e 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs @@ -202,12 +202,13 @@ private void OnAnimationAdded(string emoteId, IEmoteReference emoteClipData) internal void RefreshEmoteLoadingState(string emoteId) { - if (emotesController.TryGetEquippedEmote(bodyShapeId, emoteId, out IEmoteReference _)) + if (emotesController.TryGetEquippedEmote(bodyShapeId, emoteId, out IEmoteReference emoteReference)) { emotesInLoadingState.TryGetValue(emoteId, out EmoteCardComponentView emoteCard); if (emoteCard != null) { emoteCard.SetAsLoading(false); + emoteCard.SetSoundIcon(emoteReference.GetData().AudioSource != null); emotesInLoadingState.Remove(emoteId); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index d0746c9da0..c4f14180e1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -14,7 +14,7 @@ public class EmoteClipData [CanBeNull] private Renderer[] renderers; - [CanBeNull] private AudioSource audioSource; + [CanBeNull] public AudioSource AudioSource { get; } public EmoteClipData(AnimationClip avatarClip, bool loop = false) { @@ -27,7 +27,7 @@ public EmoteClipData(AnimationClip mainClip, GameObject container, AudioSource a this.AvatarClip = mainClip; this.Loop = loop; this.ExtraContent = container; - this.audioSource = audioSource; + this.AudioSource = audioSource; if (ExtraContent == null) return; @@ -64,11 +64,11 @@ public void Play(int gameObjectLayer, bool spatialSound) animation.enabled = true; } - if (audioSource != null) + if (AudioSource != null) { - audioSource.spatialBlend = spatialSound ? 1 : 0; - audioSource.loop = Loop; - audioSource.Play(); + AudioSource.spatialBlend = spatialSound ? 1 : 0; + AudioSource.loop = Loop; + AudioSource.Play(); } } @@ -93,8 +93,8 @@ public void Stop() animation.enabled = false; } - if (audioSource != null) - audioSource.Stop(); + if (AudioSource != null) + AudioSource.Stop(); } } } From c3d7b94bbe6a6b630c42d08199e9b073511c64d0 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Tue, 12 Sep 2023 13:14:22 -0300 Subject: [PATCH 27/35] Fixed sound not working on WebgL --- .../AvatarSystem/AvatarEmotesController.cs | 23 ++++-- .../DCL/AvatarSystem/AvatarSystem.asmdef | 3 +- .../DCL/AvatarSystem/Definitions/IAnimator.cs | 2 +- .../Definitions/IAvatarEmotesController.cs | 2 +- .../DCL/Components/Audio/DCLAudioSource.cs | 8 +-- .../Components/Avatar/AvatarAnimatorLegacy.cs | 71 +++++++++---------- .../Components/Avatar/EmoteAudioSource.prefab | 5 +- .../DataStore/DataStore_VirtualAudioMixer.cs | 12 ++-- .../DCL/Models/AvatarAssets/EmoteClipData.cs | 5 +- 9 files changed, 70 insertions(+), 61 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs index 3c4d48160c..2d291bd71e 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -1,19 +1,23 @@ using Cysharp.Threading.Tasks; +using DCL; using System.Collections.Generic; using DCL.Emotes; +using DCL.Helpers; +using DCL.SettingsCommon; using DCL.Tasks; using System; using System.Threading; using UnityEngine; +using AudioSettings = DCL.SettingsCommon.AudioSettings; namespace AvatarSystem { public class AvatarEmotesController : IAvatarEmotesController { + private const float BASE_VOLUME = 0.6f; public event Action OnEmoteEquipped; public event Action OnEmoteUnequipped; - private string bodyShapeId = ""; private readonly IAnimator animator; private readonly IEmotesService emotesService; @@ -64,14 +68,25 @@ private async UniTask AsyncEmoteLoad(string bodyShapeId, string emoteId) } } - public void PlayEmote(string emoteId, long timestamps, bool spatialSound) + public void PlayEmote(string emoteId, long timestamps, bool spatial) { if (string.IsNullOrEmpty(emoteId)) return; var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); - + var volume = GetEmoteVolume(); if (equippedEmotes.ContainsKey(emoteKey)) - animator.PlayEmote(emoteId, timestamps, spatialSound); + animator.PlayEmote(emoteId, timestamps, spatial, volume); + } + + // TODO: We have to decouple this volume logic into an IAudioMixer.GetVolume(float, Channel) since we are doing the same calculations everywhere + // Using AudioMixer does not work in WebGL so we calculate the volume manually + private float GetEmoteVolume() + { + // no cache since the data can change + AudioSettings audioSettingsData = Settings.i != null ? Settings.i.audioSettings.Data : new AudioSettings(); + float baseVolume = BASE_VOLUME * Utils.ToVolumeCurve(audioSettingsData.avatarSFXVolume * audioSettingsData.masterVolume); + Debug.Log($"Total: {baseVolume} avatar:{audioSettingsData.avatarSFXVolume} master:{audioSettingsData.masterVolume} curve:{Utils.ToVolumeCurve(audioSettingsData.avatarSFXVolume * audioSettingsData.masterVolume)}"); + return baseVolume; } public void StopEmote() diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef index dc2a39cd19..b2522d2f84 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystem.asmdef @@ -34,7 +34,8 @@ "GUID:a881b57670b1d2747a6d7f9e32b63230", "GUID:4d3366a36e77f41cfb7436340334e236", "GUID:0c0c18c12967b3944b844b79c47c2320", - "GUID:2d39cc535b437e749965d4a8258f0c13" + "GUID:2d39cc535b437e749965d4a8258f0c13", + "GUID:301149363e31a4bdaa1943465a825c8e" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs index 11ec78052f..7dd6445aac 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs @@ -6,7 +6,7 @@ namespace AvatarSystem public interface IAnimator { bool Prepare(string bodyshapeId, GameObject container); - void PlayEmote(string emoteId, long timestamps, bool spatialSound); + void PlayEmote(string emoteId, long timestamps, bool spatial, float volume); void StopEmote(); void EquipEmote(string emoteId, EmoteClipData emoteClipData); void UnequipEmote(string emoteId); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs index 51fd3ea403..6491b76352 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs @@ -8,7 +8,7 @@ public interface IAvatarEmotesController : IDisposable { void LoadEmotes(string bodyShapeId, IEnumerable emotes); - void PlayEmote(string emoteId, long timestamps, bool spatialSound = true); + void PlayEmote(string emoteId, long timestamps, bool spatial = true); void StopEmote(); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs index 947e5ae7ec..c5ba8a5b94 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs @@ -162,11 +162,9 @@ private void UpdateAudioSourceVolume() // isOutOfBoundaries will always be false for global scenes. if (!isOutOfBoundaries) { - AudioSettings audioSettingsData = - Settings.i != null ? Settings.i.audioSettings.Data : new AudioSettings(); - newVolume = ((Model) model).volume * Utils.ToVolumeCurve( - DataStore.i.virtualAudioMixer.sceneSFXVolume.Get() * audioSettingsData.sceneSFXVolume * - audioSettingsData.masterVolume); + AudioSettings audioSettingsData = Settings.i != null ? Settings.i.audioSettings.Data : new AudioSettings(); + float baseVolume = ((Model) model).volume; + newVolume = baseVolume * Utils.ToVolumeCurve(DataStore.i.virtualAudioMixer.sceneSFXVolume.Get() * audioSettingsData.sceneSFXVolume * audioSettingsData.masterVolume); } if (scene != null) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 1b4ca4e654..f733cff927 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -424,7 +424,36 @@ private void StopEmoteInternal(bool immediate) if (!immediate) OnUpdateWithDeltaTime(blackboard.deltaTime); } - private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp, bool spatialSound) + private void StartEmote(string emoteId, bool spatial, float volume) + { + if (!string.IsNullOrEmpty(emoteId)) + { + lastExtendedEmoteData?.Stop(); + + if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) + { + lastExtendedEmoteData = emoteClipData; + emoteClipData.Play(gameObject.layer, spatial, volume); + } + } + else + { + lastExtendedEmoteData?.Stop(); + } + } + + public void Reset() + { + if (animation == null) + return; + + //It will set the animation to the first frame, but due to the nature of the script and its Update. It wont stop the animation from playing + animation.Stop(); + } + + public void SetIdleFrame() { animation.Play(currentLocomotions.idle.name); } + + public void PlayEmote(string emoteId, long timestamps, bool spatial, float volume) { if (animation == null) return; @@ -437,17 +466,17 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp bool loop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.Loop; - var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) && blackboard.expressionTriggerTimestamp != expressionTriggerTimestamp; + var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) && blackboard.expressionTriggerTimestamp != timestamps; if (loop && blackboard.expressionTriggerId == emoteId) return; blackboard.expressionTriggerId = emoteId; - blackboard.expressionTriggerTimestamp = expressionTriggerTimestamp; + blackboard.expressionTriggerTimestamp = timestamps; if (mustTriggerAnimation || loop) { - StartEmote(emoteId, spatialSound); + StartEmote(emoteId, spatial, volume); if (!string.IsNullOrEmpty(emoteId)) { @@ -466,40 +495,6 @@ private void SetExpressionValues(string emoteId, long expressionTriggerTimestamp } } - private void StartEmote(string emoteId, bool spatialSound) - { - if (!string.IsNullOrEmpty(emoteId)) - { - lastExtendedEmoteData?.Stop(); - - if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) - { - lastExtendedEmoteData = emoteClipData; - emoteClipData.Play(gameObject.layer, spatialSound); - } - } - else - { - lastExtendedEmoteData?.Stop(); - } - } - - public void Reset() - { - if (animation == null) - return; - - //It will set the animation to the first frame, but due to the nature of the script and its Update. It wont stop the animation from playing - animation.Stop(); - } - - public void SetIdleFrame() { animation.Play(currentLocomotions.idle.name); } - - public void PlayEmote(string emoteId, long timestamps, bool spatialSound) - { - SetExpressionValues(emoteId, timestamps, spatialSound); - } - public void EquipBaseClip(AnimationClip clip) { var clipId = clip.name; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab index b66653244b..6b950a54ad 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab @@ -24,13 +24,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2180456685581696734} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 204.62283, y: 604.0454, z: 3.317958} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!82 &2180456685581696705 AudioSource: @@ -41,8 +41,7 @@ AudioSource: m_GameObject: {fileID: 2180456685581696734} m_Enabled: 1 serializedVersion: 4 - OutputAudioMixerGroup: {fileID: 4864224931565128906, guid: 97507d628c02bcf47859b9f108ab1823, - type: 2} + OutputAudioMixerGroup: {fileID: 0} m_audioClip: {fileID: 0} m_PlayOnAwake: 0 m_Volume: 1 diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_VirtualAudioMixer.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_VirtualAudioMixer.cs index f5a8a838a8..150076fb5d 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_VirtualAudioMixer.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/DataStore/DataStore_VirtualAudioMixer.cs @@ -5,10 +5,10 @@ namespace DCL /// public class DataStore_VirtualAudioMixer { - public readonly BaseVariable musicVolume = new BaseVariable(1f); - public readonly BaseVariable sceneSFXVolume = new BaseVariable(1f); - public readonly BaseVariable voiceChatVolume = new BaseVariable(1f); - public readonly BaseVariable uiSFXVolume = new BaseVariable(1f); - public readonly BaseVariable avatarSFXVolume = new BaseVariable(1f); + public readonly BaseVariable musicVolume = new (1f); + public readonly BaseVariable sceneSFXVolume = new (1f); + public readonly BaseVariable voiceChatVolume = new (1f); + public readonly BaseVariable uiSFXVolume = new (1f); + public readonly BaseVariable avatarSFXVolume = new (1f); } -} \ No newline at end of file +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index c4f14180e1..daa40c6e3a 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -39,7 +39,7 @@ public EmoteClipData(AnimationClip mainClip, GameObject container, AudioSource a renderers = ExtraContent.GetComponentsInChildren(); } - public void Play(int gameObjectLayer, bool spatialSound) + public void Play(int gameObjectLayer, bool spatial, float volume) { if (renderers != null) { @@ -66,7 +66,8 @@ public void Play(int gameObjectLayer, bool spatialSound) if (AudioSource != null) { - AudioSource.spatialBlend = spatialSound ? 1 : 0; + AudioSource.spatialBlend = spatial ? 1 : 0; + AudioSource.volume = volume; AudioSource.loop = Loop; AudioSource.Play(); } From e6649a441015d8e506df6b7a8a1f88a71ade48d3 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 13 Sep 2023 12:00:09 -0300 Subject: [PATCH 28/35] Tweaked emotes section anchors and margins --- .../EmotesCustomizationSectionV2.prefab | 241 +++++++++++++----- .../EmotesCustomizationComponentController.cs | 5 + .../Resources/BackpackEditorHUDV2.prefab | 78 ++---- 3 files changed, 212 insertions(+), 112 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab index 48100c7c47..1b5b0d0369 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab @@ -31,7 +31,6 @@ RectTransform: - {fileID: 7289964697046869131} - {fileID: 804718257881196857} m_Father: {fileID: 7777758932990698070} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -69,7 +68,6 @@ RectTransform: - {fileID: 4889934307542534785} - {fileID: 5061346044692837862} m_Father: {fileID: 804718257881196857} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 1, y: 1} @@ -107,7 +105,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4889934307542534785} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -243,7 +240,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8492592820780035306} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -379,7 +375,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6982706028976930151} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -516,7 +511,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 661289199007478368} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -606,7 +600,6 @@ RectTransform: m_Children: - {fileID: 3360905887761755250} m_Father: {fileID: 5651959887632496349} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -685,7 +678,6 @@ RectTransform: m_Children: - {fileID: 6489510294950322203} m_Father: {fileID: 6728270776760203143} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 1, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -781,7 +773,6 @@ RectTransform: m_Children: - {fileID: 3204891808307788364} m_Father: {fileID: 6982706028976930151} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -856,7 +847,6 @@ RectTransform: m_Children: - {fileID: 6728270776760203143} m_Father: {fileID: 7615494773261984459} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -895,7 +885,6 @@ RectTransform: - {fileID: 7777758932990698070} - {fileID: 7128940001899798189} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -955,7 +944,6 @@ RectTransform: - {fileID: 5651959887632496349} - {fileID: 661289199007478368} m_Father: {fileID: 2093926198178965483} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1074,7 +1062,6 @@ RectTransform: m_Children: - {fileID: 7516117061748555988} m_Father: {fileID: 8492592820780035306} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -1152,7 +1139,6 @@ RectTransform: m_Children: - {fileID: 7934882489759809722} m_Father: {fileID: 6728270776760203143} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1241,7 +1227,6 @@ RectTransform: - {fileID: 6982706028976930151} - {fileID: 8492592820780035306} m_Father: {fileID: 4623429712703141772} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 0} @@ -1281,7 +1266,6 @@ RectTransform: m_Children: - {fileID: 9154448218146335532} m_Father: {fileID: 4623429712703141772} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} @@ -1342,42 +1326,6 @@ MonoBehaviour: emotesSlots: {fileID: 6598929307786099729} model: selectedSlot: -1 ---- !u!1 &6912453401298887337 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5714927038119754119} - m_Layer: 5 - m_Name: EmptyColumn - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &5714927038119754119 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6912453401298887337} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 7777758932990698070} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 400, y: 0} - m_Pivot: {x: 0.5, y: 0.5} --- !u!1 &7001188241549587995 GameObject: m_ObjectHideFlags: 0 @@ -1409,7 +1357,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1782861045882750573} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1545,7 +1492,6 @@ RectTransform: - {fileID: 1782861045882750573} - {fileID: 3307476571606723064} m_Father: {fileID: 804718257881196857} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 1, y: 1} @@ -1582,7 +1528,6 @@ RectTransform: m_Children: - {fileID: 2093926198178965483} m_Father: {fileID: 7777758932990698070} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1594,6 +1539,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -1772,12 +1718,22 @@ PrefabInstance: value: 6 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &6117429642351410580 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 575195052635206558} + m_PrefabAsset: {fileID: 0} --- !u!1001 &1342535260079962774 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -1956,12 +1912,22 @@ PrefabInstance: value: 4 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &4737608377028211868 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 1342535260079962774} + m_PrefabAsset: {fileID: 0} --- !u!1001 &1387269628721425343 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 6660936951930056133} m_Modifications: - target: {fileID: 1387697037911684119, guid: cfed952f63812a44d86ff7609367aceb, @@ -1982,12 +1948,12 @@ PrefabInstance: - target: {fileID: 4290547755063670293, guid: cfed952f63812a44d86ff7609367aceb, type: 3} propertyPath: m_Padding.m_Top - value: 70 + value: 20 objectReference: {fileID: 0} - target: {fileID: 4290547755063670293, guid: cfed952f63812a44d86ff7609367aceb, type: 3} propertyPath: m_Padding.m_Left - value: 50 + value: 20 objectReference: {fileID: 0} - target: {fileID: 5345362429814289567, guid: cfed952f63812a44d86ff7609367aceb, type: 3} @@ -2132,7 +2098,7 @@ PrefabInstance: - target: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, type: 3} propertyPath: m_AnchorMax.y - value: 0.5 + value: 1 objectReference: {fileID: 0} - target: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, type: 3} @@ -2142,7 +2108,7 @@ PrefabInstance: - target: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, type: 3} propertyPath: m_AnchorMin.y - value: 0.5 + value: 0 objectReference: {fileID: 0} - target: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, type: 3} @@ -2152,7 +2118,7 @@ PrefabInstance: - target: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, type: 3} propertyPath: m_SizeDelta.y - value: 1080 + value: 0 objectReference: {fileID: 0} - target: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, type: 3} @@ -2215,6 +2181,25 @@ PrefabInstance: value: 0 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, + type: 3} + insertIndex: -1 + addedObject: {fileID: 4623429712703141772} + - targetCorrespondingSourceObject: {fileID: 8696649798073764329, guid: cfed952f63812a44d86ff7609367aceb, + type: 3} + insertIndex: -1 + addedObject: {fileID: 7615494773261984459} + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 1387697037911684119, guid: cfed952f63812a44d86ff7609367aceb, + type: 3} + insertIndex: -1 + addedObject: {fileID: 7368978811562638295} + - targetCorrespondingSourceObject: {fileID: 1387697037911684119, guid: cfed952f63812a44d86ff7609367aceb, + type: 3} + insertIndex: -1 + addedObject: {fileID: 7282016342397040552} m_SourcePrefab: {fileID: 100100000, guid: cfed952f63812a44d86ff7609367aceb, type: 3} --- !u!1 &709709442490280 stripped GameObject: @@ -2271,6 +2256,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7934882489759809722} m_Modifications: - target: {fileID: 125520531231553932, guid: a0b08d9ca8421644db83c1bd3f2e2e48, @@ -2346,7 +2332,7 @@ PrefabInstance: - target: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, type: 3} propertyPath: m_SizeDelta.x - value: 845.5 + value: 0 objectReference: {fileID: 0} - target: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, type: 3} @@ -2391,7 +2377,7 @@ PrefabInstance: - target: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, type: 3} propertyPath: m_AnchoredPosition.x - value: 15 + value: 0 objectReference: {fileID: 0} - target: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, type: 3} @@ -2669,6 +2655,9 @@ PrefabInstance: value: EmotesGrid objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: a0b08d9ca8421644db83c1bd3f2e2e48, type: 3} --- !u!114 &737305017821576015 stripped MonoBehaviour: @@ -2693,6 +2682,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 6660936951930056133} m_Modifications: - target: {fileID: 148120788220426797, guid: ed97e568b39c83d418f317eca9336523, @@ -3173,6 +3163,9 @@ PrefabInstance: value: -25 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: ed97e568b39c83d418f317eca9336523, type: 3} --- !u!224 &7128940001899798189 stripped RectTransform: @@ -3197,6 +3190,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -3375,12 +3369,22 @@ PrefabInstance: value: 5 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &1694919290289551690 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 4943660594520962880} + m_PrefabAsset: {fileID: 0} --- !u!1001 &6277102367019702928 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -3559,12 +3563,22 @@ PrefabInstance: value: 9 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &288870683077235866 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 6277102367019702928} + m_PrefabAsset: {fileID: 0} --- !u!1001 &6778047546148135998 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -3743,12 +3757,22 @@ PrefabInstance: value: 3 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &940846978490755636 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 6778047546148135998} + m_PrefabAsset: {fileID: 0} --- !u!1001 &7123186655167707300 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -3927,12 +3951,22 @@ PrefabInstance: value: 8 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &3586094036558821038 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 7123186655167707300} + m_PrefabAsset: {fileID: 0} --- !u!1001 &7139655493980753079 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7289964697046869131} m_Modifications: - target: {fileID: 1407031049187557207, guid: a0b08d9ca8421644db83c1bd3f2e2e48, @@ -4301,6 +4335,49 @@ PrefabInstance: value: EmoteSlotsGrid objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 2943456768401129165} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 4177630495850436924} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 940846978490755636} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 4737608377028211868} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 1694919290289551690} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 6117429642351410580} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 4239078007248413724} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 3586094036558821038} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 288870683077235866} + - targetCorrespondingSourceObject: {fileID: 2026062374757361563, guid: a0b08d9ca8421644db83c1bd3f2e2e48, + type: 3} + insertIndex: -1 + addedObject: {fileID: 2470837369973237255} + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: a0b08d9ca8421644db83c1bd3f2e2e48, type: 3} --- !u!114 &6598929307786099729 stripped MonoBehaviour: @@ -4325,6 +4402,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -4503,12 +4581,22 @@ PrefabInstance: value: 7 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &4239078007248413724 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 7623120821864147478} + m_PrefabAsset: {fileID: 0} --- !u!1001 &7703149663124182838 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -4692,12 +4780,22 @@ PrefabInstance: value: 2 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &4177630495850436924 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 7703149663124182838} + m_PrefabAsset: {fileID: 0} --- !u!1001 &8166385654464063501 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -4866,12 +4964,22 @@ PrefabInstance: value: 0 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &2470837369973237255 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 8166385654464063501} + m_PrefabAsset: {fileID: 0} --- !u!1001 &8919303567260152007 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 9154448218146335532} m_Modifications: - target: {fileID: 15081824087338214, guid: fc8ae579143d63741bc0f33c409ca892, @@ -5055,4 +5163,13 @@ PrefabInstance: value: 1 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: fc8ae579143d63741bc0f33c409ca892, type: 3} +--- !u!224 &2943456768401129165 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 5989498347712335370, guid: fc8ae579143d63741bc0f33c409ca892, + type: 3} + m_PrefabInstance: {fileID: 8919303567260152007} + m_PrefabAsset: {fileID: 0} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs index 617f0eea9e..080170e61b 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using DCL.Emotes; +using DCL.Helpers; using DCL.Tasks; using System.Threading; using UnityEngine; @@ -151,8 +152,12 @@ internal void OnEquippedEmotesSet(IEnumerable equippedEmotes) private void ConfigureView(Transform parent, string viewPath) { view = CreateView(viewPath); + if (view.viewTransform != null) + { view.viewTransform.SetParent(parent, false); + view.viewTransform.ResetLocalTRS(); + } view.onEmoteEquipped += OnEmoteEquipped; view.onEmoteUnequipped += OnEmoteUnequipped; view.onSellEmoteClicked += OnSellEmoteClicked; diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Resources/BackpackEditorHUDV2.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Resources/BackpackEditorHUDV2.prefab index 3b1443200f..a77dc45d09 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Resources/BackpackEditorHUDV2.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Resources/BackpackEditorHUDV2.prefab @@ -31,7 +31,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -107,7 +106,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6328930397804721303} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 1, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -243,7 +241,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6328930397804721303} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 1, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -381,7 +378,6 @@ RectTransform: m_Children: - {fileID: 4165967543594959923} m_Father: {fileID: 3150290541654462627} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 1, y: 0.5} @@ -470,7 +466,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5369915736583580992} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -549,7 +544,6 @@ RectTransform: - {fileID: 8870671573072448641} - {fileID: 7362392692425171482} m_Father: {fileID: 3150290541654462627} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0.321, y: 1} @@ -625,7 +619,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -763,7 +756,6 @@ RectTransform: - {fileID: 1823971132997614253} - {fileID: 4257772792497704525} m_Father: {fileID: 8123435181804342355} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} m_AnchorMax: {x: 0.5, y: 1} @@ -839,7 +831,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -915,7 +906,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6553298992627456305} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -991,7 +981,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3973398771568002495} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 1, y: 1} @@ -1127,7 +1116,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1859360765932788867} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} @@ -1274,7 +1262,6 @@ RectTransform: - {fileID: 8509127120294317601} - {fileID: 5524500279841468122} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1298,7 +1285,9 @@ Canvas: m_OverrideSorting: 0 m_OverridePixelPerfect: 0 m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 m_SortingOrder: 10 m_TargetDisplay: 0 @@ -1435,7 +1424,6 @@ RectTransform: - {fileID: 6896365345249182675} - {fileID: 2009290568801649861} m_Father: {fileID: 3973398771568002495} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0} m_AnchorMax: {x: 0.5, y: 0} @@ -1674,7 +1662,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -1750,7 +1737,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1332459953862512925} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -1826,7 +1812,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1332459953862512925} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0} m_AnchorMax: {x: 0.5, y: 1} @@ -1964,7 +1949,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5369915736583580992} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 1, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2103,7 +2087,6 @@ RectTransform: m_Children: - {fileID: 6774232023209469465} m_Father: {fileID: 3150290541654462627} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -2245,7 +2228,6 @@ RectTransform: - {fileID: 6898135960386834224} - {fileID: 9222180925196709489} m_Father: {fileID: 3150290541654462627} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2283,7 +2265,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5369915736583580992} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 1, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2419,7 +2400,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -2555,7 +2535,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -2635,7 +2614,6 @@ RectTransform: - {fileID: 4911467823985580687} - {fileID: 1859360765932788867} m_Father: {fileID: 5524500279841468122} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -2724,7 +2702,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3796049446928469386} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -2861,7 +2838,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8509127120294317601} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -2937,7 +2913,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6328930397804721303} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -3019,7 +2994,6 @@ RectTransform: - {fileID: 9090333417083232009} - {fileID: 7945654548937859520} m_Father: {fileID: 8870671573072448641} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -3165,7 +3139,6 @@ RectTransform: - {fileID: 3477912684092409739} - {fileID: 9147133735904795619} m_Father: {fileID: 8870671573072448641} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -3308,7 +3281,6 @@ RectTransform: m_Children: - {fileID: 362296789904435488} m_Father: {fileID: 3150290543190354886} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0} m_AnchorMax: {x: 0.5, y: 0} @@ -3444,7 +3416,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3796049446928469386} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -3530,7 +3501,6 @@ RectTransform: - {fileID: 1073041373383437235} - {fileID: 5476183973245626945} m_Father: {fileID: 3973398771568002495} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0} m_AnchorMax: {x: 0.5, y: 0} @@ -3772,7 +3742,6 @@ RectTransform: - {fileID: 7761738458315618656} - {fileID: 1332459953862512925} m_Father: {fileID: 3150290541654462627} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -3824,7 +3793,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6328930397804721303} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -3900,7 +3868,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6328930397804721303} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -3976,7 +3943,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 9198681665345318605} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -4113,7 +4079,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1859360765932788867} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} @@ -4212,7 +4177,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5524500279841468122} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -4367,7 +4331,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2808822538381467795} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -4444,7 +4407,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4911467823985580687} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} @@ -4543,7 +4505,6 @@ RectTransform: m_Children: - {fileID: 1292220468979140246} m_Father: {fileID: 3150290541654462627} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -4679,7 +4640,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4911467823985580687} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} @@ -4815,7 +4775,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5369915736583580992} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -4891,7 +4850,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -5027,12 +4985,11 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8123435181804342355} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: -30.000244} - m_SizeDelta: {x: -2.1807861, y: -59.41565} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!1 &8581991486692599835 GameObject: @@ -5065,7 +5022,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5369915736583580992} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -5141,7 +5097,6 @@ RectTransform: - {fileID: 4694772234820174201} - {fileID: 3973398771568002495} m_Father: {fileID: 3150290541654462627} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -5179,7 +5134,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6978439095690722522} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 0, y: 0.5} @@ -5289,6 +5243,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 3796049446928469386} m_Modifications: - target: {fileID: 124653197761324908, guid: add5c116a0ce3a449a365130213aa3d5, @@ -6253,6 +6208,17 @@ PrefabInstance: value: 0.9607843 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 4934202114834473616, guid: add5c116a0ce3a449a365130213aa3d5, + type: 3} + insertIndex: -1 + addedObject: {fileID: 5369915736583580992} + - targetCorrespondingSourceObject: {fileID: 4934202114834473616, guid: add5c116a0ce3a449a365130213aa3d5, + type: 3} + insertIndex: -1 + addedObject: {fileID: 6328930397804721303} + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: add5c116a0ce3a449a365130213aa3d5, type: 3} --- !u!114 &793955541419473785 stripped MonoBehaviour: @@ -6289,6 +6255,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 8123435181804342355} m_Modifications: - target: {fileID: 2422816476665487895, guid: 210aa713bbb1ba742ae68e327564eb24, @@ -6477,6 +6444,13 @@ PrefabInstance: value: 0.43137255 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 7059152913108139601, guid: 210aa713bbb1ba742ae68e327564eb24, + type: 3} + insertIndex: -1 + addedObject: {fileID: 9198681665345318605} + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 210aa713bbb1ba742ae68e327564eb24, type: 3} --- !u!114 &1525771720304835258 stripped MonoBehaviour: @@ -6501,6 +6475,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 8123435181804342355} m_Modifications: - target: {fileID: 389451657606281639, guid: 7987c409c7fea4189954a35a350cfd2a, @@ -7771,6 +7746,9 @@ PrefabInstance: value: 3 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 7987c409c7fea4189954a35a350cfd2a, type: 3} --- !u!1 &211765849088223244 stripped GameObject: From 2ab3670038234a0540fc28d994d46d425ee8590f Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 13 Sep 2023 14:55:51 -0300 Subject: [PATCH 29/35] Rollback margin --- .../EmotesCustomization/EmotesCustomizationSectionV2.prefab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab index 1b5b0d0369..1ff3abe20e 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmotesCustomizationSectionV2.prefab @@ -1953,7 +1953,7 @@ PrefabInstance: - target: {fileID: 4290547755063670293, guid: cfed952f63812a44d86ff7609367aceb, type: 3} propertyPath: m_Padding.m_Left - value: 20 + value: 50 objectReference: {fileID: 0} - target: {fileID: 5345362429814289567, guid: cfed952f63812a44d86ff7609367aceb, type: 3} From cf4d95d20bba55880db5e17cd1bff52762c05bda Mon Sep 17 00:00:00 2001 From: Romina Marchetti Date: Wed, 13 Sep 2023 16:25:19 -0300 Subject: [PATCH 30/35] Update wearable item: send highlight asset backward and swap new and PEX tags Y position --- .../Prefabs/WearableGridItemView.prefab | 152 +++--------------- 1 file changed, 26 insertions(+), 126 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Prefabs/WearableGridItemView.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Prefabs/WearableGridItemView.prefab index 570b0f199c..0e3f4647b1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Prefabs/WearableGridItemView.prefab +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/Prefabs/WearableGridItemView.prefab @@ -32,7 +32,6 @@ RectTransform: m_Children: - {fileID: 2998271857483350378} m_Father: {fileID: 8152899778130412207} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -107,7 +106,6 @@ RectTransform: m_Children: - {fileID: 2247431285224316392} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -146,7 +144,6 @@ RectTransform: m_Children: - {fileID: 5499949369635885969} m_Father: {fileID: 4558418130336684269} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -222,7 +219,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1283282150179751461} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -298,7 +294,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2293051074121960227} - m_RootOrder: 10 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -375,11 +370,10 @@ RectTransform: m_Children: - {fileID: 5888312532399504360} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 8 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 51.2, y: -51} + m_AnchoredPosition: {x: 51.2, y: 51} m_SizeDelta: {x: 20, y: 20} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &1389017365883158615 @@ -451,12 +445,11 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 710840717449915001} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -7.0423, y: -4.4878} - m_SizeDelta: {x: 23.797, y: 27.6904} + m_AnchoredPosition: {x: -7.0423, y: -4.6} + m_SizeDelta: {x: 28.5742, y: 33.2492} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &1097925692717792079 CanvasRenderer: @@ -527,7 +520,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2247431285224316392} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -662,7 +654,6 @@ RectTransform: m_Children: - {fileID: 6207607156480397176} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -699,7 +690,6 @@ RectTransform: m_Children: - {fileID: 4028660702948142198} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -736,7 +726,6 @@ RectTransform: m_Children: - {fileID: 4364070469624019513} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -777,7 +766,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2293051074121960227} - m_RootOrder: 11 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -925,7 +913,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4598811192155891101} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -962,8 +949,8 @@ MonoBehaviour: m_Calls: [] m_text: NEW m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 6b705423dc77d4fceb4122f6d7e571d6, type: 2} - m_sharedMaterial: {fileID: 2100000, guid: 9d9df32282a3c40299019c36b2157d37, type: 2} + m_fontAsset: {fileID: 11400000, guid: a02669827dd9144f39b4b164e753a21a, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 74b83fa9a54124695b9bdd8bea96fa17, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] @@ -987,8 +974,8 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 10 - m_fontSizeBase: 10 + m_fontSize: 11 + m_fontSizeBase: 11 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 @@ -1061,7 +1048,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1743110760381771954} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1137,7 +1123,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4364070469624019513} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1274,7 +1259,6 @@ RectTransform: m_Children: - {fileID: 4416164722920421327} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 1, y: 0.5} @@ -1351,7 +1335,6 @@ RectTransform: m_Children: - {fileID: 3629207497277848457} m_Father: {fileID: 4701902971670868393} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -1427,7 +1410,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6659443429011966609} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1502,16 +1484,14 @@ RectTransform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 4176316531501050124} - {fileID: 5129987909616715235} - {fileID: 2744664520410721924} m_Father: {fileID: 1743110760381771954} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 19.7, y: -19.7} - m_SizeDelta: {x: 38, y: 38} + m_AnchoredPosition: {x: 22, y: -22} + m_SizeDelta: {x: 42, y: 42} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &8885351344316319645 CanvasRenderer: @@ -1582,7 +1562,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4598811192155891101} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1626,83 +1605,7 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 5 ---- !u!1 &6046721764185051111 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4176316531501050124} - - component: {fileID: 2375342413455813145} - - component: {fileID: 1592937487543956914} - m_Layer: 5 - m_Name: Flap - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &4176316531501050124 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6046721764185051111} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 710840717449915001} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.000049591064, y: 0} - m_SizeDelta: {x: 38, y: 38} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &2375342413455813145 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6046721764185051111} - m_CullTransparentMesh: 1 ---- !u!114 &1592937487543956914 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6046721764185051111} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0, g: 0, b: 0, a: 0.11764706} - m_RaycastTarget: 0 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: b3148da633cc64974a01bd0083bd1e59, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 + m_PixelsPerUnitMultiplier: 4 --- !u!1 &6404741619441899086 GameObject: m_ObjectHideFlags: 0 @@ -1737,7 +1640,6 @@ RectTransform: - {fileID: 710840717449915001} - {fileID: 6631022829580717899} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1783,7 +1685,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2293051074121960227} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1845,7 +1746,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!224 &5071096869884117952 RectTransform: m_ObjectHideFlags: 0 @@ -1859,12 +1760,11 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2293051074121960227} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 3.4903, y: 3.4903} + m_SizeDelta: {x: 6, y: 6.000001} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &8541929103086107471 CanvasRenderer: @@ -1903,7 +1803,7 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 3 + m_PixelsPerUnitMultiplier: 2.5 --- !u!1 &7399930155521199071 GameObject: m_ObjectHideFlags: 0 @@ -1935,7 +1835,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4028660702948142198} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2070,10 +1969,10 @@ RectTransform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: + - {fileID: 5071096869884117952} - {fileID: 3578954038529326123} - {fileID: 1743110760381771954} - {fileID: 4598811192155891101} - - {fileID: 5071096869884117952} - {fileID: 4558418130336684269} - {fileID: 8152899778130412207} - {fileID: 2667185010987982867} @@ -2084,7 +1983,6 @@ RectTransform: - {fileID: 786872348792479096} - {fileID: 3260968257429975976} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2165,7 +2063,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2293051074121960227} - m_RootOrder: 9 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2242,7 +2139,6 @@ RectTransform: m_Children: - {fileID: 8299956933053450942} m_Father: {fileID: 2667185010987982867} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -2320,7 +2216,6 @@ RectTransform: m_Children: - {fileID: 2147695891105667184} m_Father: {fileID: 1743110760381771954} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2409,7 +2304,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6207607156480397176} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2545,12 +2439,11 @@ RectTransform: - {fileID: 7382988516535949352} - {fileID: 1004753941569948756} m_Father: {fileID: 2293051074121960227} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 99, y: -7} - m_SizeDelta: {x: 30, y: 16} + m_AnchoredPosition: {x: 95, y: -110} + m_SizeDelta: {x: 34, y: 18} m_Pivot: {x: 0, y: 1} --- !u!1 &9110061562146683237 GameObject: @@ -2583,7 +2476,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3260968257429975976} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2693,6 +2585,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 1743110760381771954} m_Modifications: - target: {fileID: 5573392751968575400, guid: 4849d2ed3b5a18948bf3cd46256869a4, @@ -2811,6 +2704,9 @@ PrefabInstance: value: Thumbnail objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} --- !u!114 &134086463821417477 stripped MonoBehaviour: @@ -2835,6 +2731,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 710840717449915001} m_Modifications: - target: {fileID: 5168634940499044205, guid: 4849d2ed3b5a18948bf3cd46256869a4, @@ -2956,12 +2853,12 @@ PrefabInstance: - target: {fileID: 6302203761313059702, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} propertyPath: m_AnchoredPosition.x - value: -8.5 + value: -9.8 objectReference: {fileID: 0} - target: {fileID: 6302203761313059702, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} propertyPath: m_AnchoredPosition.y - value: 9.11 + value: 9.5 objectReference: {fileID: 0} - target: {fileID: 6302203761313059702, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} @@ -2984,6 +2881,9 @@ PrefabInstance: value: TypeIcon objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 4849d2ed3b5a18948bf3cd46256869a4, type: 3} --- !u!224 &2744664520410721924 stripped RectTransform: From a49e4957cac868c8fab4d4e7e7a2773b40b9a86d Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 18 Sep 2023 15:55:25 -0300 Subject: [PATCH 31/35] Fixed emotes with different animation order or nomenclature not working properly. --- .../EmotesService/EmoteAnimationLoader.cs | 29 ++++++++++++++----- .../AvatarSystem/AvatarEmotesController.cs | 1 - .../Components/Avatar/AvatarAnimatorLegacy.cs | 1 + .../DCL/Models/AvatarAssets/EmoteClipData.cs | 5 ++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index 00ebc41d4c..5bd94174a9 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -41,6 +41,9 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s Rendereable rendereable = await retriever.Retrieve(targetContainer, emote, bodyShapeId, ct); + foreach (Renderer renderer in rendereable.renderers) + renderer.enabled = false; + var animation = rendereable.container.GetComponentInChildren(); if (animation == null) @@ -49,21 +52,31 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s return; } - if (animation.GetClipCount() > 1) { this.container = rendereable.container; } + this.mainClip = animation.clip; - animation.enabled = false; - var animationClip = animation.clip; + if (animation.GetClipCount() > 1) + { + this.container = rendereable.container; - if (animationClip == null) + foreach (AnimationState state in animation) + { + if (state.clip.name.Contains("avatar", StringComparison.OrdinalIgnoreCase) || + state.clip.name == emote.id) { this.mainClip = state.clip; } + + // There's a bug with the legacy animation where animations start ahead of time the first time + // our workaround is to play every animation while we load the audio clip and then disable the animator + animation.Play(state.clip.name); + } + } + + if (mainClip == null) { Debug.LogError("AnimationClip not found in the container for emote " + emote.id); return; } - this.mainClip = animationClip; - //Clip names should be unique because of the Legacy Animation string based usage - animationClip.name = emote.id; + mainClip.name = emote.id; var contentProvider = emote.GetContentProvider(bodyShapeId); @@ -88,6 +101,8 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s // we only support one audio clip break; } + + animation.enabled = false; } private bool IsValidAudioClip(string fileName) => diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs index 2d291bd71e..6200af2c57 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -85,7 +85,6 @@ private float GetEmoteVolume() // no cache since the data can change AudioSettings audioSettingsData = Settings.i != null ? Settings.i.audioSettings.Data : new AudioSettings(); float baseVolume = BASE_VOLUME * Utils.ToVolumeCurve(audioSettingsData.avatarSFXVolume * audioSettingsData.masterVolume); - Debug.Log($"Total: {baseVolume} avatar:{audioSettingsData.avatarSFXVolume} master:{audioSettingsData.masterVolume} curve:{Utils.ToVolumeCurve(audioSettingsData.avatarSFXVolume * audioSettingsData.masterVolume)}"); return baseVolume; } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index f733cff927..36112ca41b 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -385,6 +385,7 @@ private void State_Expression(BlackBoard bb) if (bb.shouldLoop && isOwnPlayer) { int emoteLoop = GetCurrentEmoteLoopCount(); + if (emoteLoop != lastEmoteLoopCount) UserProfile.GetOwnUserProfile().SetAvatarExpression(bb.expressionTriggerId, UserProfile.EmoteSource.EmoteLoop, true); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index daa40c6e3a..a3cd30b2ac 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -54,14 +54,15 @@ public void Play(int gameObjectLayer, bool spatial, float volume) { var layer = 0; + animation.enabled = true; + foreach (AnimationState state in animation) { if (state.clip == AvatarClip) continue; state.layer = layer++; + state.wrapMode = Loop ? WrapMode.Loop : WrapMode.Once; animation.Play(state.clip.name); } - - animation.enabled = true; } if (AudioSource != null) From 89bde91e2f48042ce843dd1f03e677be9e668529 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 18 Sep 2023 16:00:55 -0300 Subject: [PATCH 32/35] Fixed loop emotes being out of sync --- .../Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index 5bd94174a9..a9c2312bca 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -102,6 +102,7 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s break; } + animation.Stop(); animation.enabled = false; } From da0f93a92f22b0a85bb40129f300a0680b31b37c Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Mon, 18 Sep 2023 16:15:15 -0300 Subject: [PATCH 33/35] Post rebase fix --- .../Assets/DCLServices/EmotesService/EmotesService.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs index ebd9a7e089..1f0e36294b 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs @@ -105,6 +105,9 @@ private UniTask FetchEmote(EmoteBodyId emoteBodyId, CancellationTo if (!SceneEmoteHelper.IsSceneEmote(emoteId)) return emotesCatalogService.RequestEmoteAsync(emoteId, ct); + if (!emoteId.StartsWith("urn")) + return emotesCatalogService.RequestEmoteFromBuilderAsync(emoteId, ct); + WearableItem emoteItem = SceneEmoteHelper.TryGetDataFromEmoteId(emoteId, out string emoteHash, out bool loop) ? new EmoteItem(emoteId, emoteBodyId.BodyShapeId, emoteHash, catalyst.contentUrl, loop) : null; return new UniTask(emoteItem); From 1ea95d5d22b17d92818577b63fdd9bc9cf94f95f Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Tue, 19 Sep 2023 09:50:33 -0300 Subject: [PATCH 34/35] Backpack emotes now will not occlude their renderers --- .../DCL/AvatarSystem/AvatarEmotesController.cs | 4 ++-- .../MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs | 2 +- .../AvatarSystem/Definitions/IAvatarEmotesController.cs | 2 +- .../DCL/Components/Avatar/AvatarAnimatorLegacy.cs | 8 ++++---- .../HUD/CharacterPreview/CharacterPreviewController.cs | 2 +- .../MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs | 3 ++- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs index 6200af2c57..3a31bb9063 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -68,14 +68,14 @@ private async UniTask AsyncEmoteLoad(string bodyShapeId, string emoteId) } } - public void PlayEmote(string emoteId, long timestamps, bool spatial) + public void PlayEmote(string emoteId, long timestamps, bool spatial, bool occlude) { if (string.IsNullOrEmpty(emoteId)) return; var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); var volume = GetEmoteVolume(); if (equippedEmotes.ContainsKey(emoteKey)) - animator.PlayEmote(emoteId, timestamps, spatial, volume); + animator.PlayEmote(emoteId, timestamps, spatial, volume, occlude); } // TODO: We have to decouple this volume logic into an IAudioMixer.GetVolume(float, Channel) since we are doing the same calculations everywhere diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs index 7dd6445aac..ba16727705 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs @@ -6,7 +6,7 @@ namespace AvatarSystem public interface IAnimator { bool Prepare(string bodyshapeId, GameObject container); - void PlayEmote(string emoteId, long timestamps, bool spatial, float volume); + void PlayEmote(string emoteId, long timestamps, bool spatial, float volume, bool occlude); void StopEmote(); void EquipEmote(string emoteId, EmoteClipData emoteClipData); void UnequipEmote(string emoteId); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs index 6491b76352..d406acf76d 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs @@ -8,7 +8,7 @@ public interface IAvatarEmotesController : IDisposable { void LoadEmotes(string bodyShapeId, IEnumerable emotes); - void PlayEmote(string emoteId, long timestamps, bool spatial = true); + void PlayEmote(string emoteId, long timestamps, bool spatial = true, bool occlude = true); void StopEmote(); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 36112ca41b..8ff6baa57f 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -425,7 +425,7 @@ private void StopEmoteInternal(bool immediate) if (!immediate) OnUpdateWithDeltaTime(blackboard.deltaTime); } - private void StartEmote(string emoteId, bool spatial, float volume) + private void StartEmote(string emoteId, bool spatial, float volume, bool occlude) { if (!string.IsNullOrEmpty(emoteId)) { @@ -434,7 +434,7 @@ private void StartEmote(string emoteId, bool spatial, float volume) if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) { lastExtendedEmoteData = emoteClipData; - emoteClipData.Play(gameObject.layer, spatial, volume); + emoteClipData.Play(gameObject.layer, spatial, volume, occlude); } } else @@ -454,7 +454,7 @@ public void Reset() public void SetIdleFrame() { animation.Play(currentLocomotions.idle.name); } - public void PlayEmote(string emoteId, long timestamps, bool spatial, float volume) + public void PlayEmote(string emoteId, long timestamps, bool spatial, float volume, bool occlude) { if (animation == null) return; @@ -477,7 +477,7 @@ public void PlayEmote(string emoteId, long timestamps, bool spatial, float volum if (mustTriggerAnimation || loop) { - StartEmote(emoteId, spatial, volume); + StartEmote(emoteId, spatial, volume, occlude); if (!string.IsNullOrEmpty(emoteId)) { diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs index 39dc7fa556..0fb374aa5e 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/CharacterPreview/CharacterPreviewController.cs @@ -227,7 +227,7 @@ public IAvatarEmotesController GetEmotesController() => public void PlayEmote(string emoteId, long timestamp) { - avatar.GetEmotesController().PlayEmote(emoteId, timestamp, false); + avatar.GetEmotesController().PlayEmote(emoteId, timestamp, false, false); } public void StopEmote() diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs index a3cd30b2ac..ec487096b9 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs @@ -39,7 +39,7 @@ public EmoteClipData(AnimationClip mainClip, GameObject container, AudioSource a renderers = ExtraContent.GetComponentsInChildren(); } - public void Play(int gameObjectLayer, bool spatial, float volume) + public void Play(int gameObjectLayer, bool spatial, float volume, bool occlude) { if (renderers != null) { @@ -47,6 +47,7 @@ public void Play(int gameObjectLayer, bool spatial, float volume) { renderer.enabled = true; renderer.gameObject.layer = gameObjectLayer; + renderer.allowOcclusionWhenDynamic = occlude; } } From 4f9a5534b1fb41e7e19a4c213f8bb12a2f3964c5 Mon Sep 17 00:00:00 2001 From: Patricio Guerra Date: Wed, 20 Sep 2023 17:01:10 -0300 Subject: [PATCH 35/35] Added sequential emotes support --- .../EmotesService/Domain/AnimationSequence.cs | 14 + .../Domain/AnimationSequence.cs.meta | 3 + .../Domain/EmbedEmoteReference.cs | 13 +- .../Domain/EmoteAnimationData.cs | 281 ++++++++++++++++++ .../Domain/EmoteAnimationData.cs.meta} | 0 .../Domain/EmotesServiceDefinitions.asmdef | 4 +- .../Domain/IEmoteAnimationLoader.cs | 4 + .../EmotesService/Domain/IEmoteReference.cs | 5 +- .../EmotesService/Domain/NftEmoteReference.cs | 17 +- .../EmotesService/EmoteAnimationLoader.cs | 83 +++++- .../EmotesService/EmotesService.cs | 3 +- .../AvatarSystem/AvatarEmotesController.cs | 2 +- .../DCL/AvatarSystem/Definitions/IAnimator.cs | 3 +- .../Components/Avatar/AvatarAnimatorLegacy.cs | 126 ++++---- .../DCLCharacterController.cs | 11 +- .../EmotesCustomizationComponentController.cs | 2 +- .../DCL/Models/AvatarAssets/EmoteClipData.cs | 103 ------- 17 files changed, 467 insertions(+), 207 deletions(-) create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs.meta create mode 100644 unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteAnimationData.cs rename unity-renderer/Assets/{Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs.meta => DCLServices/EmotesService/Domain/EmoteAnimationData.cs.meta} (100%) delete mode 100644 unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs new file mode 100644 index 0000000000..ce547f9376 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +namespace DCLServices.EmotesService.Domain +{ + public struct AnimationSequence + { + public AnimationClip AvatarStart; + public AnimationClip AvatarLoop; + public AnimationClip AvatarEnd; + public AnimationClip PropStart; + public AnimationClip PropLoop; + public AnimationClip PropEnd; + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs.meta new file mode 100644 index 0000000000..8c523d3c02 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/AnimationSequence.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dd75e8ffbceb4184bcc265406c3f25dc +timeCreated: 1695136539 \ No newline at end of file diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs index adc08e5538..45d886d6e4 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs @@ -1,23 +1,24 @@ -using System; +using DCLServices.EmotesService.Domain; +using System; namespace DCL.Emotes { public class EmbedEmoteReference : IEmoteReference { private readonly WearableItem emoteItem; - private readonly EmoteClipData clipData; + private readonly EmoteAnimationData animationData; - public EmbedEmoteReference(WearableItem emoteItem, EmoteClipData clipData) + public EmbedEmoteReference(WearableItem emoteItem, EmoteAnimationData animationData) { this.emoteItem = emoteItem; - this.clipData = clipData; + this.animationData = animationData; } public WearableItem GetEntity() => emoteItem; - public EmoteClipData GetData() => - clipData; + public EmoteAnimationData GetData() => + animationData; public void Dispose() { diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteAnimationData.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteAnimationData.cs new file mode 100644 index 0000000000..9609bcf59a --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteAnimationData.cs @@ -0,0 +1,281 @@ +using JetBrains.Annotations; +using System; +using UnityEngine; + +namespace DCLServices.EmotesService.Domain +{ + public enum EmoteState + { + PLAYING, + STOPPING, + STOPPED, + } + public class EmoteAnimationData + { + private const float EXPRESSION_EXIT_TRANSITION_TIME = 0.2f; + private const float EXPRESSION_ENTER_TRANSITION_TIME = 0.1f; + + [CanBeNull] private readonly Animation extraContentAnimation; + [CanBeNull] private readonly GameObject extraContent; + [CanBeNull] private readonly Renderer[] renderers; + [CanBeNull] private readonly AudioSource audioSource; + + private readonly AnimationClip avatarClip; + private readonly bool loop; + private AnimationSequence animationSequence; + private Animation avatarAnimation; + private bool isSequential; + private AnimationState currentAvatarAnimation; + private AnimationState avatarClipState; + private AnimationState sequenceAvatarLoopState; + private EmoteState currentState = EmoteState.STOPPED; + + // Constructor used by Embed Emotes + public EmoteAnimationData(AnimationClip avatarClip, bool loop = false) + { + this.avatarClip = avatarClip; + this.loop = loop; + } + + // Constructor used by Remote Emotes + public EmoteAnimationData(AnimationClip mainClip, GameObject container, AudioSource audioSource, bool loop = false) + { + this.avatarClip = mainClip; + this.loop = loop; + this.extraContent = container; + this.audioSource = audioSource; + + if (extraContent == null) return; + + extraContentAnimation = extraContent.GetComponentInChildren(); + + if (extraContentAnimation == null) + Debug.LogError($"Animation {avatarClip.name} extra content does not have an animation"); + + renderers = extraContent.GetComponentsInChildren(); + } + + public bool IsLoop() => + loop; + + public bool HasAudio() => + audioSource != null; + + public void UnEquip() + { + if (extraContent != null) + extraContent.transform.SetParent(null, false); + + if (isSequential) + { + + avatarAnimation.RemoveClip(animationSequence.AvatarStart); + avatarAnimation.RemoveClip(animationSequence.AvatarLoop); + avatarAnimation.RemoveClip(animationSequence.AvatarEnd); + } + else + { + avatarAnimation.RemoveClip(avatarClip); + Debug.Log("UnEquip " + avatarClip); + } + } + + public int GetLoopCount() => + Mathf.RoundToInt(currentAvatarAnimation.time / currentAvatarAnimation.length); + + public void Equip(Animation animation) + { + avatarAnimation = animation; + if (isSequential) + { + avatarAnimation.AddClip(animationSequence.AvatarStart, animationSequence.AvatarStart.name); + avatarAnimation.AddClip(animationSequence.AvatarLoop, animationSequence.AvatarLoop.name); + avatarAnimation.AddClip(animationSequence.AvatarEnd, animationSequence.AvatarEnd.name); + sequenceAvatarLoopState = avatarAnimation[animationSequence.AvatarLoop.name]; + } + else + { + avatarAnimation.AddClip(avatarClip, avatarClip.name); + avatarClipState = animation[avatarClip.name]; + Debug.Log(avatarClip.name, avatarAnimation); + } + + // We set the extra content as a child of the avatar gameobject and use its local position to mimick its positioning and correction + if (extraContent != null) + { + Transform animationTransform = animation.transform; + extraContent.transform.SetParent(animationTransform.parent, false); + extraContent.transform.localRotation = animationTransform.localRotation; + extraContent.transform.localScale = animationTransform.localScale; + extraContent.transform.localPosition = animationTransform.localPosition; + } + } + + public void Play(int layer, bool spatial, float volume, bool occlude) + { + currentState = EmoteState.PLAYING; + + EnableRenderers(layer, occlude); + + if (isSequential) + PlaySequential(spatial, volume); + else + PlayNormal(spatial, volume); + } + + private void EnableRenderers(int gameObjectLayer, bool occlude) + { + if (renderers == null) return; + + foreach (Renderer renderer in renderers) + { + renderer.enabled = true; + renderer.gameObject.layer = gameObjectLayer; + renderer.allowOcclusionWhenDynamic = occlude; + } + } + + private void PlayNormal(bool spatial, float volume) + { + string avatarClipName = avatarClip.name; + + if (avatarAnimation.IsPlaying(avatarClipName)) + avatarAnimation.Rewind(avatarClipName); + + avatarAnimation.CrossFade(avatarClipName, EXPRESSION_ENTER_TRANSITION_TIME, PlayMode.StopAll); + currentAvatarAnimation = avatarClipState; + + if (extraContentAnimation != null) + { + var layer = 0; + + extraContentAnimation.enabled = true; + + foreach (AnimationState state in extraContentAnimation) + { + if (state.clip == avatarClip) continue; + state.layer = layer++; + state.wrapMode = loop ? WrapMode.Loop : WrapMode.Once; + extraContentAnimation.Play(state.clip.name); + } + } + + if (audioSource != null) + { + audioSource.spatialBlend = spatial ? 1 : 0; + audioSource.volume = volume; + audioSource.loop = loop; + audioSource.Play(); + } + } + + private void PlaySequential(bool spatial, float volume) + { + avatarAnimation.wrapMode = WrapMode.Default; + avatarAnimation[animationSequence.AvatarStart.name].wrapMode = WrapMode.Once; + avatarAnimation[animationSequence.AvatarLoop.name].wrapMode = WrapMode.Loop; + avatarAnimation.Stop(); + avatarAnimation.CrossFadeQueued(animationSequence.AvatarStart.name, EXPRESSION_ENTER_TRANSITION_TIME, QueueMode.PlayNow); + avatarAnimation.CrossFadeQueued(animationSequence.AvatarLoop.name, 0, QueueMode.CompleteOthers); + currentAvatarAnimation = sequenceAvatarLoopState; + + if (extraContentAnimation != null) + { + extraContentAnimation.enabled = true; + extraContentAnimation.wrapMode = WrapMode.Default; + extraContentAnimation[animationSequence.PropStart.name].wrapMode = WrapMode.Once; + extraContentAnimation[animationSequence.PropLoop.name].wrapMode = WrapMode.Loop; + extraContentAnimation.Stop(); + extraContentAnimation.CrossFadeQueued(animationSequence.PropStart.name, EXPRESSION_ENTER_TRANSITION_TIME, QueueMode.PlayNow); + extraContentAnimation.CrossFadeQueued(animationSequence.PropLoop.name, 0 ,QueueMode.CompleteOthers); + } + + if (audioSource == null) return; + + audioSource.spatialBlend = spatial ? 1 : 0; + audioSource.volume = volume; + audioSource.loop = loop; + audioSource.Play(); + } + + public void Stop(bool immediate) + { + if (isSequential) + { + SequentialStop(immediate); + currentState = !immediate ? EmoteState.STOPPING : EmoteState.STOPPED; + } + else + { + NormalStop(immediate); + currentState = EmoteState.STOPPED; + } + + if (audioSource != null) + audioSource.Stop(); + } + + private void SequentialStop(bool immediate) + { + avatarAnimation[animationSequence.AvatarEnd.name].wrapMode = WrapMode.Once; + avatarAnimation.Stop(); + + if (!immediate) + avatarAnimation.CrossFade(animationSequence.AvatarEnd.name, EXPRESSION_EXIT_TRANSITION_TIME); + + currentAvatarAnimation = avatarAnimation[animationSequence.AvatarEnd.name]; + + if (extraContentAnimation == null) return; + + extraContentAnimation[animationSequence.PropEnd.name].wrapMode = WrapMode.Once; + extraContentAnimation.Stop(); + + if (!immediate) + extraContentAnimation.CrossFade(animationSequence.PropEnd.name, EXPRESSION_EXIT_TRANSITION_TIME); + } + + private void NormalStop(bool immediate) + { + avatarAnimation.Blend(avatarClip.name, 0, !immediate ? EXPRESSION_EXIT_TRANSITION_TIME : 0); + + if (renderers != null) + foreach (Renderer renderer in renderers) + renderer.enabled = false; + + if (extraContentAnimation == null) return; + + foreach (AnimationState state in extraContentAnimation) + { + if (state.clip == avatarClip) continue; + extraContentAnimation.Stop(state.clip.name); + } + + extraContentAnimation.enabled = false; + } + + public void SetupSequentialAnimation(AnimationSequence sequence) + { + isSequential = true; + animationSequence = sequence; + + if (extraContentAnimation == null) return; + + extraContentAnimation.AddClip(animationSequence.PropStart, animationSequence.PropStart.name); + extraContentAnimation.AddClip(animationSequence.PropLoop, animationSequence.PropLoop.name); + extraContentAnimation.AddClip(animationSequence.PropEnd, animationSequence.PropEnd.name); + } + + public bool CanTransitionOut() => + !isSequential || IsFinished(); + + public bool IsFinished() + { + if (loop && !isSequential) return false; + float timeTillEnd = currentAvatarAnimation == null ? 0 : currentAvatarAnimation.length - currentAvatarAnimation.time; + return timeTillEnd < EXPRESSION_EXIT_TRANSITION_TIME; + } + + public EmoteState GetState() => + currentState; + } +} diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteAnimationData.cs.meta similarity index 100% rename from unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/EmoteAnimationData.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef index e54df0b60d..815138debb 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef @@ -2,10 +2,10 @@ "name": "EmotesServiceDefinitions", "rootNamespace": "", "references": [ - "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e", "GUID:3b80b0b562b1cbc489513f09fc1b8f69", "GUID:f51ebe6a0ceec4240a699833d6309b23", - "GUID:99cea83ca76dcd846abed7e61a8c90bd" + "GUID:99cea83ca76dcd846abed7e61a8c90bd", + "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs index 5b11cccd3f..9f99d49891 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using Cysharp.Threading.Tasks; +using DCLServices.EmotesService.Domain; using UnityEngine; namespace DCL.Emotes @@ -10,6 +11,9 @@ public interface IEmoteAnimationLoader : IDisposable AnimationClip mainClip { get; } GameObject container { get; } AudioSource audioSource { get; } + bool IsSequential { get; } + AnimationSequence GetSequence(); + UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default); } } diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs index dd1c46f28c..41b27b7e96 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs @@ -1,10 +1,11 @@ -using System; +using DCLServices.EmotesService.Domain; +using System; namespace DCL.Emotes { public interface IEmoteReference : IDisposable { WearableItem GetEntity(); - EmoteClipData GetData(); + EmoteAnimationData GetData(); } } diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs index 649abe6263..7451c15d1a 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs @@ -1,23 +1,30 @@ -namespace DCL.Emotes +using DCLServices.EmotesService.Domain; + +namespace DCL.Emotes { public class NftEmoteReference : IEmoteReference { private readonly WearableItem emoteItem; private readonly IEmoteAnimationLoader loader; - private readonly EmoteClipData emoteClipData; + private readonly EmoteAnimationData emoteAnimationData; public NftEmoteReference(WearableItem emoteItem, IEmoteAnimationLoader loader, bool loop) { this.emoteItem = emoteItem; this.loader = loader; - emoteClipData = new EmoteClipData(loader.mainClip, loader.container, loader.audioSource, loop); + emoteAnimationData = new EmoteAnimationData(loader.mainClip, loader.container, loader.audioSource, loop); + + if (loader.IsSequential) + { + emoteAnimationData.SetupSequentialAnimation(loader.GetSequence()); + } } public WearableItem GetEntity() => emoteItem; - public EmoteClipData GetData() => - emoteClipData; + public EmoteAnimationData GetData() => + emoteAnimationData; public void Dispose() { diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs index a9c2312bca..45ebc02229 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -4,21 +4,33 @@ using Cysharp.Threading.Tasks; using DCL.Helpers; using DCL.Providers; +using DCLServices.EmotesService.Domain; +using System.Collections.Generic; using UnityEngine; namespace DCL.Emotes { public class EmoteAnimationLoader : IEmoteAnimationLoader { + private const string AVATAR_START = "avatar_start"; + private const string AVATAR_LOOP = "avatar_loop"; + private const string AVATAR_END = "avatar_end"; + private const string PROP_START = "prop_start"; + private const string PROP_LOOP = "prop_loop"; + private const string PROP_END = "prop_end"; private const string EMOTE_AUDIO_SOURCE = "EmoteAudioSource"; + private readonly IWearableRetriever retriever; private readonly AddressableResourceProvider resourceProvider; + private AudioClip audioClip; + private AssetPromise_AudioClip audioClipPromise; + public AnimationClip mainClip { get; private set; } public GameObject container { get; private set; } public AudioSource audioSource { get; private set; } + public bool IsSequential { get; private set; } - private AudioClip audioClip; - private AssetPromise_AudioClip audioClipPromise; + private AnimationSequence animationSequence; public EmoteAnimationLoader(IWearableRetriever retriever, AddressableResourceProvider resourceProvider) { @@ -26,6 +38,9 @@ public EmoteAnimationLoader(IWearableRetriever retriever, AddressableResourcePro this.resourceProvider = resourceProvider; } + public AnimationSequence GetSequence() => + animationSequence; + public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default) { if (targetContainer == null) @@ -54,12 +69,20 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s this.mainClip = animation.clip; + var requiredAnimationSequence = new HashSet + { + AVATAR_END, AVATAR_LOOP, AVATAR_START, + PROP_END, PROP_LOOP, PROP_START, + }; + if (animation.GetClipCount() > 1) { this.container = rendereable.container; foreach (AnimationState state in animation) { + FillAnimationSequence(requiredAnimationSequence, state.clip); + if (state.clip.name.Contains("avatar", StringComparison.OrdinalIgnoreCase) || state.clip.name == emote.id) { this.mainClip = state.clip; } @@ -69,6 +92,9 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s } } + if (requiredAnimationSequence.Count == 0) + IsSequential = true; + if (mainClip == null) { Debug.LogError("AnimationClip not found in the container for emote " + emote.id); @@ -76,7 +102,16 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s } //Clip names should be unique because of the Legacy Animation string based usage - mainClip.name = emote.id; + if (IsSequential) + { + animationSequence.AvatarStart.name = RenameIfValid(animationSequence.AvatarStart.name, $"{emote.id}:{animationSequence.AvatarStart.name}"); + animationSequence.AvatarLoop.name = RenameIfValid(animationSequence.AvatarLoop.name, $"{emote.id}:{animationSequence.AvatarLoop.name}"); + animationSequence.AvatarEnd.name = RenameIfValid(animationSequence.AvatarEnd.name, $"{emote.id}:{animationSequence.AvatarEnd.name}"); + } + else + { + mainClip.name = RenameIfValid(mainClip.name, emote.id); + } var contentProvider = emote.GetContentProvider(bodyShapeId); @@ -85,10 +120,7 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s if (!IsValidAudioClip(contentMap.file)) continue; try { audioClip = await AsyncLoadAudioClip(contentMap.file, contentProvider); } - catch (Exception e) - { - Debug.LogError(e); - } + catch (Exception e) { Debug.LogError(e); } if (audioClip != null) { @@ -106,6 +138,43 @@ public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, s animation.enabled = false; } + // Kinerius note: There was a weird case when testing where 2 emotes with different urn ids where using the same GLTF, + // when the second one loads the clip gets renamed and that causes the first user to not be able to use the emote. + // To avoid this, we rename only when the clip is not already renamed + private string RenameIfValid(string from, string to) => + from.StartsWith("urn") ? from : to; + + private void FillAnimationSequence(HashSet requiredAnimationSequence, AnimationClip clip) + { + string name = clip.name.ToLower(); + + if (!requiredAnimationSequence.Contains(name)) return; + + switch (name) + { + case AVATAR_START: + animationSequence.AvatarStart = clip; + break; + case AVATAR_LOOP: + animationSequence.AvatarLoop = clip; + break; + case AVATAR_END: + animationSequence.AvatarEnd = clip; + break; + case PROP_START: + animationSequence.PropStart = clip; + break; + case PROP_LOOP: + animationSequence.PropLoop = clip; + break; + case PROP_END: + animationSequence.PropEnd = clip; + break; + } + + requiredAnimationSequence.Remove(name); + } + private bool IsValidAudioClip(string fileName) => fileName.EndsWith(".ogg") || fileName.EndsWith(".mp3"); diff --git a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs index 1f0e36294b..6e06f68946 100644 --- a/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.cs @@ -1,6 +1,7 @@ using AvatarAssets; using Cysharp.Threading.Tasks; using DCL.Configuration; +using DCLServices.EmotesService.Domain; using DCLServices.WearablesCatalogService; using System.Collections.Generic; using System.Threading; @@ -69,7 +70,7 @@ public async UniTask InitializeAsync(CancellationToken cancellationToken) private void SetupEmbeddedClip(EmbeddedEmote embeddedEmote, AnimationClip clip, string urnPrefix) { clip.name = embeddedEmote.id; - var clipData = new EmoteClipData(clip, embeddedEmote.emoteDataV0?.loop ?? false); + var clipData = new EmoteAnimationData(clip, embeddedEmote.emoteDataV0?.loop ?? false); embeddedEmotes.Add(new EmoteBodyId(urnPrefix, embeddedEmote.id), new EmbedEmoteReference(embeddedEmote, clipData)); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs index 3a31bb9063..350eb1e7b2 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -52,6 +52,7 @@ private void LoadEmote(string bodyShapeId, WearableItem emote) private async UniTask AsyncEmoteLoad(string bodyShapeId, string emoteId) { + Debug.Log("Loading " + emoteId); var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); try @@ -121,7 +122,6 @@ public void UnEquipEmote(string emoteId) } } - public void Dispose() { cts.SafeCancelAndDispose(); diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs index ba16727705..0eaeb1c4cd 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAnimator.cs @@ -1,4 +1,5 @@ using DCL.Emotes; +using DCLServices.EmotesService.Domain; using UnityEngine; namespace AvatarSystem @@ -8,7 +9,7 @@ public interface IAnimator bool Prepare(string bodyshapeId, GameObject container); void PlayEmote(string emoteId, long timestamps, bool spatial, float volume, bool occlude); void StopEmote(); - void EquipEmote(string emoteId, EmoteClipData emoteClipData); + void EquipEmote(string emoteId, EmoteAnimationData emoteAnimationData); void UnequipEmote(string emoteId); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs index 8ff6baa57f..4a883a7bf1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -4,8 +4,8 @@ using Cysharp.Threading.Tasks; using DCL; using DCL.Components; -using DCL.Emotes; using DCL.Helpers; +using DCLServices.EmotesService.Domain; using UnityEngine; using Environment = DCL.Environment; @@ -41,8 +41,6 @@ public class AvatarAnimatorLegacy : MonoBehaviour, IPoolLifecycleHandler, IAnima const float WALK_RUN_SWITCH_TIME = 1.5f; const float JUMP_TRANSITION_TIME = 0.01f; const float FALL_TRANSITION_TIME = 0.5f; - const float EXPRESSION_EXIT_TRANSITION_TIME = 0.2f; - const float EXPRESSION_ENTER_TRANSITION_TIME = 0.1f; const float OTHER_PLAYER_MOVE_THRESHOLD = 0.02f; const float AIR_EXIT_TRANSITION_TIME = 0.2f; @@ -96,7 +94,7 @@ public class BlackBoard private float lastOnAirTime = 0; - private Dictionary emoteClipDataMap = new (); + private Dictionary emoteClipDataMap = new (); private string runAnimationName; private string walkAnimationName; @@ -110,11 +108,12 @@ public class BlackBoard private Ray rayCache; private bool hasTarget; - private EmoteClipData lastExtendedEmoteData; + private EmoteAnimationData lastExtendedEmoteData; private string lastCrossFade; - private AnimationState currentEmote; private int lastEmoteLoopCount; + private readonly DataStore_Player dataStorePlayer = DataStore.i.player; + private void Awake() { hasTarget = target != null; @@ -367,22 +366,38 @@ private void State_Expression(BlackBoard bb) exitTransitionStarted = true; } - if (ExpressionGroundTransitionCondition(animationState: animation[bb.expressionTriggerId])) + if (IsEmoteFinished()) { - currentState = State_Ground; - exitTransitionStarted = true; + bool canTransitionOut = lastExtendedEmoteData?.CanTransitionOut() ?? true; + bool isPlaying = lastExtendedEmoteData?.GetState() == EmoteState.PLAYING; + + if (isPlaying && !canTransitionOut) + { + exitTransitionStarted = true; + dataStorePlayer.canPlayerMove.Set(false); + } + + if (canTransitionOut) + { + dataStorePlayer.canPlayerMove.Set(true); + currentState = State_Ground; + } } if (exitTransitionStarted) + { StopEmoteInternal(false); - else if (prevAnimation != AvatarAnimation.EMOTE) // this condition makes Blend be called only in first frame of the state + } + + // TODO: check why we have this condition here + /*else if (prevAnimation != AvatarAnimation.EMOTE) // this condition makes Blend be called only in first frame of the state { animation.wrapMode = bb.shouldLoop ? WrapMode.Loop : WrapMode.Once; animation.Blend(bb.expressionTriggerId, 1, EXPRESSION_ENTER_TRANSITION_TIME); - } + }*/ // If we reach the emote loop, we send the RPC message again to refresh new users - if (bb.shouldLoop && isOwnPlayer) + if (bb.shouldLoop && isOwnPlayer && !IsEmoteFinished()) { int emoteLoop = GetCurrentEmoteLoopCount(); @@ -394,18 +409,20 @@ private void State_Expression(BlackBoard bb) return; - bool ExpressionGroundTransitionCondition(AnimationState animationState) + bool IsEmoteFinished() { - float timeTillEnd = animationState == null ? 0 : animationState.length - animationState.time; - bool isAnimationOver = timeTillEnd < EXPRESSION_EXIT_TRANSITION_TIME && !bb.shouldLoop; + //bool emoteIsFinished = lastExtendedEmoteData?.IsFinished() ?? true; + //bool isAnimationOver = emoteIsFinished && !bb.shouldLoop; bool isMoving = isOwnPlayer ? DCLCharacterController.i.isMovingByUserInput : Math.Abs(bb.movementSpeed) > OTHER_PLAYER_MOVE_THRESHOLD; - - return isAnimationOver || isMoving; + bool emoteIsFinished = lastExtendedEmoteData?.IsFinished() ?? true; + bool isAnimationFinishing = lastExtendedEmoteData?.GetState() == EmoteState.STOPPING; + return isMoving || isAnimationFinishing || emoteIsFinished; } } private int GetCurrentEmoteLoopCount() => - Mathf.RoundToInt(currentEmote.time / currentEmote.length); + lastExtendedEmoteData.GetLoopCount(); + public void StopEmote() { @@ -414,33 +431,24 @@ public void StopEmote() private void StopEmoteInternal(bool immediate) { - if (string.IsNullOrEmpty(blackboard.expressionTriggerId)) return; - if (animation.GetClip(blackboard.expressionTriggerId) == null) return; - - animation.Blend(blackboard.expressionTriggerId, 0, !immediate ? EXPRESSION_EXIT_TRANSITION_TIME : 0); blackboard.expressionTriggerId = null; - blackboard.shouldLoop = false; - lastExtendedEmoteData?.Stop(); + lastExtendedEmoteData?.Stop(immediate); if (!immediate) OnUpdateWithDeltaTime(blackboard.deltaTime); } private void StartEmote(string emoteId, bool spatial, float volume, bool occlude) { - if (!string.IsNullOrEmpty(emoteId)) - { - lastExtendedEmoteData?.Stop(); + lastExtendedEmoteData?.Stop(false); - if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) - { - lastExtendedEmoteData = emoteClipData; - emoteClipData.Play(gameObject.layer, spatial, volume, occlude); - } - } - else - { - lastExtendedEmoteData?.Stop(); - } + if (string.IsNullOrEmpty(emoteId)) return; + if (!emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) return; + + blackboard.expressionTriggerId = emoteId; + blackboard.shouldLoop = emoteClipData.IsLoop(); + + lastExtendedEmoteData = emoteClipData; + emoteClipData.Play(gameObject.layer, spatial, volume, occlude); } public void Reset() @@ -462,34 +470,20 @@ public void PlayEmote(string emoteId, long timestamps, bool spatial, float volum if (string.IsNullOrEmpty(emoteId)) return; - if (animation.GetClip(emoteId) == null) - return; - - bool loop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.Loop; + bool loop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.IsLoop(); var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) && blackboard.expressionTriggerTimestamp != timestamps; if (loop && blackboard.expressionTriggerId == emoteId) return; - blackboard.expressionTriggerId = emoteId; - blackboard.expressionTriggerTimestamp = timestamps; if (mustTriggerAnimation || loop) { + StopEmoteInternal(true); StartEmote(emoteId, spatial, volume, occlude); + blackboard.expressionTriggerTimestamp = timestamps; - if (!string.IsNullOrEmpty(emoteId)) - { - animation.Stop(emoteId); - latestAnimationState = AvatarAnimation.IDLE; - } - - blackboard.shouldLoop = loop; - - CrossFadeTo(AvatarAnimation.EMOTE, emoteId, EXPRESSION_EXIT_TRANSITION_TIME, PlayMode.StopAll); - - currentEmote = animation[emoteId]; lastEmoteLoopCount = GetCurrentEmoteLoopCount(); currentState = State_Expression; OnUpdateWithDeltaTime(Time.deltaTime); @@ -508,24 +502,13 @@ public void EquipBaseClip(AnimationClip clip) animation.AddClip(clip, clipId); } - public void EquipEmote(string emoteId, EmoteClipData emoteClipData) + public void EquipEmote(string emoteId, EmoteAnimationData emoteAnimationData) { if (animation == null) return; - if (animation.GetClip(emoteId) != null) - animation.RemoveClip(emoteId); - - emoteClipDataMap[emoteId] = emoteClipData; - - animation.AddClip(emoteClipData.AvatarClip, emoteId); - - if (emoteClipData.ExtraContent != null) - { - emoteClipData.ExtraContent.transform.SetParent(animation.transform.parent, false); - emoteClipData.ExtraContent.transform.ResetLocalTRS(); - emoteClipData.ExtraContent.transform.localPosition = animation.transform.localPosition; - } + emoteClipDataMap[emoteId] = emoteAnimationData; + emoteAnimationData.Equip(animation); } public void UnequipEmote(string emoteId) @@ -536,13 +519,8 @@ public void UnequipEmote(string emoteId) if (animation.GetClip(emoteId) == null) return; - animation.RemoveClip(emoteId); - if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) - { - if (emoteClipData.ExtraContent != null) - emoteClipData.ExtraContent.transform.SetParent(null, false); - } + emoteClipData.UnEquip(); } private void InitializeAvatarAudioAndParticleHandlers(Animation createdAnimation) diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/CharacterController/DCLCharacterController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/CharacterController/DCLCharacterController.cs index a4d465dbf9..5d65646a66 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/CharacterController/DCLCharacterController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/CharacterController/DCLCharacterController.cs @@ -267,15 +267,14 @@ bool Moved(Vector3 previousPosition, bool useThreshold = false) internal void LateUpdate() { - if(!dataStorePlayer.canPlayerMove.Get()) - return; - if (transform.position.y < minimumYPosition) { SetPosition(characterPosition.worldPosition); return; } + bool canMove = dataStorePlayer.canPlayerMove.Get(); + if (freeMovementController.IsActive()) { velocity = freeMovementController.CalculateMovement(); @@ -306,6 +305,9 @@ internal void LateUpdate() // Horizontal movement var speed = movementSpeed * (isWalking ? runningSpeedMultiplier : 1f); + if (!canMove) + speed = 0; + transform.forward = characterForward.Get().Value; var xzPlaneForward = Vector3.Scale(cameraForward.Get(), new Vector3(1, 0, 1)); @@ -336,7 +338,7 @@ internal void LateUpdate() bool jumpButtonPressedWithGraceTime = jumpButtonPressed && (Time.time - lastJumpButtonPressedTime < 0.15f); - if (jumpButtonPressedWithGraceTime) // almost-grounded jump button press allowed time + if (jumpButtonPressedWithGraceTime && canMove) // almost-grounded jump button press allowed time { bool justLeftGround = (Time.time - lastUngroundedTime) < 0.1f; @@ -372,6 +374,7 @@ internal void LateUpdate() { SaveLateUpdateGroundTransforms(); } + OnUpdateFinish?.Invoke(Time.deltaTime); } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs index 080170e61b..b76ec00851 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/EmotesCustomization/EmotesCustomizationComponentController.cs @@ -213,7 +213,7 @@ internal void RefreshEmoteLoadingState(string emoteId) if (emoteCard != null) { emoteCard.SetAsLoading(false); - emoteCard.SetSoundIcon(emoteReference.GetData().AudioSource != null); + emoteCard.SetSoundIcon(emoteReference.GetData().HasAudio()); emotesInLoadingState.Remove(emoteId); } } diff --git a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs deleted file mode 100644 index ec487096b9..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ /dev/null @@ -1,103 +0,0 @@ -using JetBrains.Annotations; -using System; -using UnityEngine; - -namespace DCL.Emotes -{ - public class EmoteClipData - { - public AnimationClip AvatarClip { get; } - public bool Loop { get; } - - [CanBeNull] private Animation animation; - [CanBeNull] public GameObject ExtraContent { get; } - - [CanBeNull] private Renderer[] renderers; - - [CanBeNull] public AudioSource AudioSource { get; } - - public EmoteClipData(AnimationClip avatarClip, bool loop = false) - { - this.AvatarClip = avatarClip; - this.Loop = loop; - } - - public EmoteClipData(AnimationClip mainClip, GameObject container, AudioSource audioSource, bool loop = false) - { - this.AvatarClip = mainClip; - this.Loop = loop; - this.ExtraContent = container; - this.AudioSource = audioSource; - - if (ExtraContent == null) return; - - animation = ExtraContent.GetComponentInChildren(); - - if (animation == null) - Debug.LogError($"Animation {AvatarClip.name} extra content does not have an animation"); - - renderers = ExtraContent.GetComponentsInChildren(); - } - - public void Play(int gameObjectLayer, bool spatial, float volume, bool occlude) - { - if (renderers != null) - { - foreach (Renderer renderer in renderers) - { - renderer.enabled = true; - renderer.gameObject.layer = gameObjectLayer; - renderer.allowOcclusionWhenDynamic = occlude; - } - } - - if (animation != null) - { - var layer = 0; - - animation.enabled = true; - - foreach (AnimationState state in animation) - { - if (state.clip == AvatarClip) continue; - state.layer = layer++; - state.wrapMode = Loop ? WrapMode.Loop : WrapMode.Once; - animation.Play(state.clip.name); - } - } - - if (AudioSource != null) - { - AudioSource.spatialBlend = spatial ? 1 : 0; - AudioSource.volume = volume; - AudioSource.loop = Loop; - AudioSource.Play(); - } - } - - public void Stop() - { - if (renderers != null) - { - foreach (Renderer renderer in renderers) - { - renderer.enabled = false; - } - } - - if (animation != null) - { - foreach (AnimationState state in animation) - { - if (state.clip == AvatarClip) continue; - animation.Stop(state.clip.name); - } - - animation.enabled = false; - } - - if (AudioSource != null) - AudioSource.Stop(); - } - } -}