diff --git a/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset b/unity-renderer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset index 2547c2aee4..a3c3e88961 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: fd6cf4a6f210c0b44945d9f5f646cd99 + m_Address: EmoteAudioSource + m_ReadOnly: 0 + m_SerializedLabels: [] m_ReadOnly: 0 m_Settings: {fileID: 11400000, guid: 436e0d4fdc1cdfa4aaef13be2e8bcef8, type: 2} m_SchemaSet: 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/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs deleted file mode 100644 index f2e3a2f644..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoader.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Threading; -using AvatarSystem; -using Cysharp.Threading.Tasks; -using UnityEngine; - -namespace DCL.Emotes -{ - public class EmoteAnimationLoader : IEmoteAnimationLoader - { - private readonly IWearableRetriever retriever; - public AnimationClip loadedAnimationClip { get; internal set; } - - public EmoteAnimationLoader(IWearableRetriever retriever) - { - this.retriever = retriever; - } - - public async UniTask LoadEmote(GameObject container, WearableItem emote, string bodyShapeId, CancellationToken ct = default) - { - if (container == null) - throw new NullReferenceException("Container cannot be null"); - - if (emote == null) - throw new NullReferenceException("Emote cannot be null"); - - if (string.IsNullOrEmpty(bodyShapeId)) - throw new NullReferenceException("bodyShapeId cannot be null or empty"); - - ct.ThrowIfCancellationRequested(); - - Rendereable rendereable = await retriever.Retrieve(container, emote, bodyShapeId, ct); - - var animation = rendereable.container.GetComponentInChildren(); - - if (animation == null) - { - Debug.LogError("Animation component not found in the container for emote " + emote.id); - return; - } - - animation.enabled = false; - var animationClip = animation.clip; - - if (animationClip == null) - { - Debug.LogError("AnimationClip not found in the container for emote " + emote.id); - return; - } - - //Setting animation name equal to emote id to avoid unity animation clip duplication on Animation.AddClip() - this.loadedAnimationClip = animationClip; - animationClip.name = emote.id; - } - - public void Dispose() - { - retriever?.Dispose(); - } - } -} diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoaderFactory.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoaderFactory.cs deleted file mode 100644 index 0c1ba74ae7..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationLoaderFactory.cs +++ /dev/null @@ -1,9 +0,0 @@ -using AvatarSystem; - -namespace DCL.Emotes -{ - public class EmoteAnimationLoaderFactory - { - public virtual IEmoteAnimationLoader Get() { return new EmoteAnimationLoader(new WearableRetriever()); } - } -} \ 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 fc45292341..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsTracker.cs +++ /dev/null @@ -1,216 +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 - { - 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>(); - - private CancellationTokenSource cts = new CancellationTokenSource(); - - 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() - { - //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()); - } - - 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()); - } - } - - wearablesCatalogService.EmbedWearables(embeddedEmotes.emotes); - InitializeEmotes(this.dataStore.emotesOnUse.GetAllRefCounts()); - this.dataStore.emotesOnUse.OnRefCountUpdated += OnRefCountUpdated; - } - - 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); - - 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/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs deleted file mode 100644 index 6ca1f0e008..0000000000 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Threading; -using Cysharp.Threading.Tasks; -using UnityEngine; - -namespace DCL.Emotes -{ - public interface IEmoteAnimationLoader : IDisposable - { - AnimationClip loadedAnimationClip { get; } - UniTask LoadEmote(GameObject container, WearableItem emote, string bodyShapeId, CancellationToken ct = default); - } -} \ 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 6c217c2b2c..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)]?.clip, emote.femaleAnimation); - Assert.AreEqual(dataStore.animations[(WearableLiterals.BodyShapes.MALE, emote.id)]?.clip, 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]?.clip); - } - - [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]?.clip); - }); - } -} 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/DCLServices/EmotesService/Domain.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain.meta new file mode 100644 index 0000000000..5de69e56bc --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain.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/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 new file mode 100644 index 0000000000..45d886d6e4 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs @@ -0,0 +1,28 @@ +using DCLServices.EmotesService.Domain; +using System; + +namespace DCL.Emotes +{ + public class EmbedEmoteReference : IEmoteReference + { + private readonly WearableItem emoteItem; + private readonly EmoteAnimationData animationData; + + public EmbedEmoteReference(WearableItem emoteItem, EmoteAnimationData animationData) + { + this.emoteItem = emoteItem; + this.animationData = animationData; + } + + public WearableItem GetEntity() => + emoteItem; + + public EmoteAnimationData GetData() => + animationData; + + public void Dispose() + { + + } + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmbedEmoteReference.cs.meta new file mode 100644 index 0000000000..4a27cc2b4d --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/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/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/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/Domain/EmotesServiceDefinitions.asmdef b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef new file mode 100644 index 0000000000..815138debb --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef @@ -0,0 +1,19 @@ +{ + "name": "EmotesServiceDefinitions", + "rootNamespace": "", + "references": [ + "GUID:3b80b0b562b1cbc489513f09fc1b8f69", + "GUID:f51ebe6a0ceec4240a699833d6309b23", + "GUID:99cea83ca76dcd846abed7e61a8c90bd", + "GUID:7ac9f9c835ec1084ab35e3f9b176cf1e" + ], + "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/EmoteAnimationsPlugin.asmdef.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef.meta similarity index 76% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef.meta index ab3bfe7dfc..a10d65aa3d 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef.meta +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/EmotesServiceDefinitions.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 81fbd0260d07a69449fb0fc6ed29d254 +guid: 0c0c18c12967b3944b844b79c47c2320 AssemblyDefinitionImporter: externalObjects: {} userData: diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs new file mode 100644 index 0000000000..9f99d49891 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs @@ -0,0 +1,19 @@ +using System; +using System.Threading; +using Cysharp.Threading.Tasks; +using DCLServices.EmotesService.Domain; +using UnityEngine; + +namespace DCL.Emotes +{ + 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/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs.meta similarity index 100% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/IEmoteAnimationLoader.cs.meta rename to unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteAnimationLoader.cs.meta diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs new file mode 100644 index 0000000000..41b27b7e96 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs @@ -0,0 +1,11 @@ +using DCLServices.EmotesService.Domain; +using System; + +namespace DCL.Emotes +{ + public interface IEmoteReference : IDisposable + { + WearableItem GetEntity(); + EmoteAnimationData GetData(); + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmoteReference.cs.meta new file mode 100644 index 0000000000..ee3167b5a3 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/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/Domain/IEmotesService.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs new file mode 100644 index 0000000000..5f6b2b2ea3 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs @@ -0,0 +1,10 @@ +using Cysharp.Threading.Tasks; +using System.Threading; + +namespace DCL.Emotes +{ + public interface IEmotesService : IService + { + UniTask RequestEmote(EmoteBodyId emoteBodyId, CancellationToken cancellationToken); + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/IEmotesService.cs.meta new file mode 100644 index 0000000000..29da9ed18f --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/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/Domain/NftEmoteReference.cs b/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs new file mode 100644 index 0000000000..7451c15d1a --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs @@ -0,0 +1,34 @@ +using DCLServices.EmotesService.Domain; + +namespace DCL.Emotes +{ + public class NftEmoteReference : IEmoteReference + { + private readonly WearableItem emoteItem; + private readonly IEmoteAnimationLoader loader; + private readonly EmoteAnimationData emoteAnimationData; + + public NftEmoteReference(WearableItem emoteItem, IEmoteAnimationLoader loader, bool loop) + { + this.emoteItem = emoteItem; + this.loader = loader; + emoteAnimationData = new EmoteAnimationData(loader.mainClip, loader.container, loader.audioSource, loop); + + if (loader.IsSequential) + { + emoteAnimationData.SetupSequentialAnimation(loader.GetSequence()); + } + } + + public WearableItem GetEntity() => + emoteItem; + + public EmoteAnimationData GetData() => + emoteAnimationData; + + public void Dispose() + { + loader.Dispose(); + } + } +} diff --git a/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs.meta b/unity-renderer/Assets/DCLServices/EmotesService/Domain/NftEmoteReference.cs.meta new file mode 100644 index 0000000000..5f13b88d18 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/Domain/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/EmotesService/EmoteAnimationLoader.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs new file mode 100644 index 0000000000..45ebc02229 --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoader.cs @@ -0,0 +1,195 @@ +using AvatarSystem; +using System; +using System.Threading; +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 AnimationSequence animationSequence; + + public EmoteAnimationLoader(IWearableRetriever retriever, AddressableResourceProvider resourceProvider) + { + this.retriever = retriever; + this.resourceProvider = resourceProvider; + } + + public AnimationSequence GetSequence() => + animationSequence; + + public async UniTask LoadEmote(GameObject targetContainer, WearableItem emote, string bodyShapeId, CancellationToken ct = default) + { + if (targetContainer == null) + throw new NullReferenceException("Container cannot be null"); + + if (emote == null) + throw new NullReferenceException("Emote cannot be null"); + + if (string.IsNullOrEmpty(bodyShapeId)) + throw new NullReferenceException("bodyShapeId cannot be null or empty"); + + ct.ThrowIfCancellationRequested(); + + 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) + { + Debug.LogError("Animation component not found in the container for emote " + emote.id); + return; + } + + 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; } + + // 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 (requiredAnimationSequence.Count == 0) + IsSequential = true; + + if (mainClip == null) + { + Debug.LogError("AnimationClip not found in the container for emote " + emote.id); + return; + } + + //Clip names should be unique because of the Legacy Animation string based usage + 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); + + foreach (var contentMap in contentProvider.contents) + { + if (!IsValidAudioClip(contentMap.file)) continue; + + try { audioClip = await AsyncLoadAudioClip(contentMap.file, contentProvider); } + catch (Exception e) { Debug.LogError(e); } + + if (audioClip != null) + { + 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 + break; + } + + animation.Stop(); + 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"); + + private async UniTask AsyncLoadAudioClip(string file, ContentProvider contentProvider) + { + audioClipPromise = new AssetPromise_AudioClip(file, contentProvider); + AssetPromiseKeeper_AudioClip.i.Keep(audioClipPromise); + await audioClipPromise; + return audioClipPromise.asset.audioClip; + } + + public void Dispose() + { + AssetPromiseKeeper_AudioClip.i.Forget(audioClipPromise); + retriever?.Dispose(); + } + } +} 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/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs new file mode 100644 index 0000000000..eac6e406ef --- /dev/null +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmoteAnimationLoaderFactory.cs @@ -0,0 +1,18 @@ +using AvatarSystem; +using DCL.Providers; + +namespace DCL.Emotes +{ + public class EmoteAnimationLoaderFactory + { + private readonly AddressableResourceProvider resourceProvider; + + public EmoteAnimationLoaderFactory(AddressableResourceProvider resourceProvider) + { + this.resourceProvider = resourceProvider; + } + + public virtual IEmoteAnimationLoader Get() => + new EmoteAnimationLoader(new WearableRetriever(), resourceProvider); + } +} 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 65% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef rename to unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef index 1902a4472b..9cb4ac4b06 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/EmoteAnimationsPlugin.asmdef +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef @@ -1,25 +1,23 @@ { - "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", + "GUID:b24824f3bc2a60641a01e2083614f802", + "GUID:6e6a87f97192ec947993f360104e75b7", + "GUID:a3ceb534947fac14da25035bc5c24788", + "GUID:99cea83ca76dcd846abed7e61a8c90bd", + "GUID:b1087c5731ff68448a0a9c625bb7e52d" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef.meta b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef.meta similarity index 76% rename from unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef.meta rename to unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef.meta index b64fa3ecf4..f1432b7f51 100644 --- a/unity-renderer/Assets/DCLPlugins/EmoteAnimations/Tests/EmoteAnimationsPluginTests.asmdef.meta +++ b/unity-renderer/Assets/DCLServices/EmotesService/EmotesService.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c6c6ea0310ce27d4bb0af5d6dc0205d1 +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..6e06f68946 --- /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.EmotesService.Domain; +using DCLServices.WearablesCatalogService; +using System.Collections.Generic; +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 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 embedEmotes = await emotesCatalogService.GetEmbeddedEmotes(); + + // early return for not configured emotesCatalogService substitutes in legacy test base + if (embedEmotes == null) return; + + foreach (EmbeddedEmote embeddedEmote in embedEmotes.emotes) + { + if (embeddedEmote.maleAnimation != null) + SetupEmbeddedClip(embeddedEmote, embeddedEmote.maleAnimation, MALE); + + if (embeddedEmote.femaleAnimation != null) + SetupEmbeddedClip(embeddedEmote, embeddedEmote.femaleAnimation, FEMALE); + } + + wearablesCatalogService.AddEmbeddedWearablesToCatalog(embedEmotes.emotes); + } + + private void SetupEmbeddedClip(EmbeddedEmote embeddedEmote, AnimationClip clip, string urnPrefix) + { + clip.name = embeddedEmote.id; + var clipData = new EmoteAnimationData(clip, embeddedEmote.emoteDataV0?.loop ?? false); + embeddedEmotes.Add(new EmoteBodyId(urnPrefix, embeddedEmote.id), new EmbedEmoteReference(embeddedEmote, clipData)); + } + + public async UniTask RequestEmote(EmoteBodyId emoteBodyId, CancellationToken cancellationToken = default) + { + if (embeddedEmotes.TryGetValue(emoteBodyId, out var value)) + return value; + + var emote = await FetchEmote(emoteBodyId, cancellationToken); + + if (emote == null) + { + Debug.LogError($"Unexpected null emote when requesting {emoteBodyId}"); + return null; + } + + // 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); + + 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(EmoteBodyId emoteBodyId, CancellationToken ct) + { + string emoteId = emoteBodyId.EmoteId; + + 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); + } + + 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/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..350eb1e7b2 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarEmotesController.cs @@ -0,0 +1,135 @@ +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; + private readonly Dictionary equippedEmotes = 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) => + equippedEmotes.TryGetValue(new EmoteBodyId(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) + { + 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) + { + Debug.Log("Loading " + emoteId); + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); + + try + { + IEmoteReference emoteReference = await emotesService.RequestEmote(emoteKey, cts.Token); + animator.EquipEmote(emoteId, emoteReference.GetData()); + equippedEmotes[emoteKey] = emoteReference; + OnEmoteEquipped?.Invoke(emoteId, emoteReference); + } + catch (OperationCanceledException) { } + catch (Exception e) + { + Debug.LogException(e); + } + } + + 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, occlude); + } + + // 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); + return baseVolume; + } + + public void StopEmote() + { + animator.StopEmote(); + } + + public void EquipEmote(string emoteId, IEmoteReference emoteReference) + { + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); + + if (equippedEmotes.ContainsKey(emoteKey)) + { + // we avoid dangling references in case an emote was loaded twice + emoteReference.Dispose(); + return; + } + + equippedEmotes.Add(emoteKey, emoteReference); + animator.EquipEmote(emoteId, emoteReference.GetData()); + OnEmoteEquipped?.Invoke(emoteId, emoteReference); + } + + public void UnEquipEmote(string emoteId) + { + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); + + if (equippedEmotes.ContainsKey(emoteKey)) + { + animator.UnequipEmote(emoteId); + equippedEmotes[emoteKey].Dispose(); + equippedEmotes.Remove(emoteKey); + } + } + + public void Dispose() + { + cts.SafeCancelAndDispose(); + + foreach (var kvp in equippedEmotes) + kvp.Value.Dispose(); + + equippedEmotes.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..b2522d2f84 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,10 @@ "GUID:26861d1714ac819459758e0b653efd06", "GUID:97d8897529779cb49bebd400c7f402a6", "GUID:a881b57670b1d2747a6d7f9e32b63230", - "GUID:4d3366a36e77f41cfb7436340334e236" + "GUID:4d3366a36e77f41cfb7436340334e236", + "GUID:0c0c18c12967b3944b844b79c47c2320", + "GUID:2d39cc535b437e749965d4a8258f0c13", + "GUID:301149363e31a4bdaa1943465a825c8e" ], "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..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,5 +1,5 @@ -using DCL; using DCL.Emotes; +using DCLServices.EmotesService.Domain; using UnityEngine; namespace AvatarSystem @@ -7,8 +7,10 @@ namespace AvatarSystem public interface IAnimator { bool Prepare(string bodyshapeId, GameObject container); - void PlayEmote(string emoteId, long timestamps); - void EquipEmote(string emoteId, EmoteClipData emoteClipData); + void PlayEmote(string emoteId, long timestamps, bool spatial, float volume, bool occlude); + void StopEmote(); + void EquipEmote(string emoteId, EmoteAnimationData emoteAnimationData); 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..d406acf76d --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Definitions/IAvatarEmotesController.cs @@ -0,0 +1,24 @@ +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, bool spatial = true, bool occlude = true); + + void StopEmote(); + + 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/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 94415d9384..4a883a7bf1 100644 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarAnimatorLegacy.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; using AvatarSystem; +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; @@ -40,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; @@ -95,20 +94,25 @@ public class BlackBoard private float lastOnAirTime = 0; - private Dictionary emoteClipDataMap = new (); + private Dictionary emoteClipDataMap = new (); private string runAnimationName; private string walkAnimationName; 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; private Ray rayCache; private bool hasTarget; + private EmoteAnimationData lastExtendedEmoteData; + private string lastCrossFade; + private int lastEmoteLoopCount; + + private readonly DataStore_Player dataStorePlayer = DataStore.i.player; private void Awake() { @@ -122,6 +126,8 @@ private void Awake() // AvatarSystem entry points public bool Prepare(string bodyshapeId, GameObject container) { + StopEmote(); + animation = container.gameObject.GetOrCreateComponent(); container.gameObject.GetOrCreateComponent(); @@ -316,15 +322,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() || blackboard.shouldLoop ? WrapMode.Loop : WrapMode.Once; + animation.CrossFade(lastCrossFade, runTransitionTime, playMode); } void State_Air(BlackBoard bb) @@ -349,8 +356,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; @@ -360,68 +366,89 @@ 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) { - animation.Blend(bb.expressionTriggerId, 0, EXPRESSION_EXIT_TRANSITION_TIME); - - bb.expressionTriggerId = null; - bb.shouldLoop = false; - OnUpdateWithDeltaTime(bb.deltaTime); + 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 && !IsEmoteFinished()) + { + int emoteLoop = GetCurrentEmoteLoopCount(); + + if (emoteLoop != lastEmoteLoopCount) + UserProfile.GetOwnUserProfile().SetAvatarExpression(bb.expressionTriggerId, UserProfile.EmoteSource.EmoteLoop, true); + + lastEmoteLoopCount = emoteLoop; } 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 void SetExpressionValues(string expressionTriggerId, long expressionTriggerTimestamp) + private int GetCurrentEmoteLoopCount() => + lastExtendedEmoteData.GetLoopCount(); + + + public void StopEmote() { - if (animation == null) - return; + StopEmoteInternal(true); + } - if (string.IsNullOrEmpty(expressionTriggerId)) - return; + private void StopEmoteInternal(bool immediate) + { + blackboard.expressionTriggerId = null; + lastExtendedEmoteData?.Stop(immediate); - if (animation.GetClip(expressionTriggerId) == null) - return; + if (!immediate) OnUpdateWithDeltaTime(blackboard.deltaTime); + } - var mustTriggerAnimation = !string.IsNullOrEmpty(expressionTriggerId) - && blackboard.expressionTriggerTimestamp != expressionTriggerTimestamp; - blackboard.expressionTriggerId = expressionTriggerId; - blackboard.expressionTriggerTimestamp = expressionTriggerTimestamp; + private void StartEmote(string emoteId, bool spatial, float volume, bool occlude) + { + lastExtendedEmoteData?.Stop(false); - if (mustTriggerAnimation) - { - if (!string.IsNullOrEmpty(expressionTriggerId)) - { - animation.Stop(expressionTriggerId); - latestAnimation = AvatarAnimation.IDLE; - } + if (string.IsNullOrEmpty(emoteId)) return; + if (!emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) return; - blackboard.shouldLoop = emoteClipDataMap.TryGetValue(expressionTriggerId, out var clipData) - && clipData.loop; + blackboard.expressionTriggerId = emoteId; + blackboard.shouldLoop = emoteClipData.IsLoop(); - currentState = State_Expression; - OnUpdateWithDeltaTime(Time.deltaTime); - } + lastExtendedEmoteData = emoteClipData; + emoteClipData.Play(gameObject.layer, spatial, volume, occlude); } public void Reset() @@ -435,9 +462,32 @@ 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 spatial, float volume, bool occlude) { - SetExpressionValues(emoteId, timestamps); + if (animation == null) + return; + + if (string.IsNullOrEmpty(emoteId)) + return; + + bool loop = emoteClipDataMap.TryGetValue(emoteId, out var clipData) && clipData.IsLoop(); + + var mustTriggerAnimation = !string.IsNullOrEmpty(emoteId) && blackboard.expressionTriggerTimestamp != timestamps; + + if (loop && blackboard.expressionTriggerId == emoteId) + return; + + + if (mustTriggerAnimation || loop) + { + StopEmoteInternal(true); + StartEmote(emoteId, spatial, volume, occlude); + blackboard.expressionTriggerTimestamp = timestamps; + + lastEmoteLoopCount = GetCurrentEmoteLoopCount(); + currentState = State_Expression; + OnUpdateWithDeltaTime(Time.deltaTime); + } } public void EquipBaseClip(AnimationClip clip) @@ -452,23 +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 (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); + emoteClipDataMap[emoteId] = emoteAnimationData; + emoteAnimationData.Equip(animation); } public void UnequipEmote(string emoteId) @@ -479,7 +519,8 @@ public void UnequipEmote(string emoteId) if (animation.GetClip(emoteId) == null) return; - animation.RemoveClip(emoteId); + if (emoteClipDataMap.TryGetValue(emoteId, out var emoteClipData)) + emoteClipData.UnEquip(); } private void InitializeAvatarAudioAndParticleHandlers(Animation createdAnimation) @@ -510,10 +551,25 @@ private void OnEnable() return; animation.enabled = true; + SetIdleFrame(); } private void OnDisable() { + if (animation == null) + return; + + StopEmoteInternal(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/Components/Avatar/AvatarSceneEmoteHandler.cs b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarSceneEmoteHandler.cs index 06bce53289..f8c604af0e 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 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(); } - 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(); + + var emoteKey = new EmoteBodyId(bodyShapeId, emoteId); try { - await SceneEmoteHelper.RequestLoadSceneEmote( - bodyShapeId, - emoteId, - alreadyLoadedEmotes, - emotesInUse, - pendingEmotesByScene, - equippedEmotesByScene, - cancellationTokenSource.Token - ); + var loadedEmote = await emotesService.RequestEmote(emoteKey, 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/EmoteAudioSource.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab new file mode 100644 index 0000000000..6b950a54ad --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab @@ -0,0 +1,130 @@ +%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} + 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_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: 0} + 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/EmoteAudioSource.prefab.meta b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab.meta new file mode 100644 index 0000000000..bfe1fd2099 --- /dev/null +++ b/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/EmoteAudioSource.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fd6cf4a6f210c0b44945d9f5f646cd99 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: 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..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 @@ -3,139 +3,118 @@ 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 = 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); } - [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()); - }); + var emoteData = new EmoteBodyId(BODY_SHAPE, EMOTE_ID); + emotesService.RequestEmote(emoteData, Arg.Any()).Throws(new OperationCanceledException()); + + await handler.LoadAndPlayEmote(BODY_SHAPE, EMOTE_ID); + + emotesService.Received(1).RequestEmote(emoteData, 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(); + var emoteData = new EmoteBodyId(bodyShape, emoteId); + emotesService.RequestEmote(emoteData, 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/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/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/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/Resources/EmotesCustomization/EmoteCard.prefab b/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Resources/EmotesCustomization/EmoteCard.prefab index 4d9abee987..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 @@ -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: 0 +--- !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} @@ -884,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, @@ -945,7 +1015,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 +1060,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 +1087,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 +1188,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 4635205700294361718} m_Modifications: - target: {fileID: 1166888513132788191, guid: d565b61885fb1ef41b1582a285e748e9, @@ -1238,6 +1307,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 +1328,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 54622623229548845, guid: fb037d81b9c10ad439a13e356a17bab6, @@ -1531,6 +1604,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 +1619,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 54622623229548845, guid: fb037d81b9c10ad439a13e356a17bab6, @@ -1832,6 +1909,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 +1924,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 439785820983603457, guid: 88cd164bd30b4c446917e9faee11dd6a, @@ -1870,7 +1951,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 +1961,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 +1971,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 +2016,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 +2038,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 +2067,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 +2113,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 7256802595478311341} m_Modifications: - target: {fileID: 4936655407855709455, guid: 4849d2ed3b5a18948bf3cd46256869a4, @@ -2160,7 +2261,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 +2269,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: 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: 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..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 @@ -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,7 +1948,7 @@ 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} @@ -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/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/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/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/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 2ffe3e61e2..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 @@ -1,23 +1,32 @@ +using AvatarSystem; +using Cysharp.Threading.Tasks; using System; using System.Collections.Generic; using System.Linq; using DCL.Emotes; +using DCL.Helpers; +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 +43,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 +76,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 +85,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 +96,8 @@ public void SetEmotes(WearableItem[] ownedEmotes) this.ownedEmotes[emote.id] = emote; } foreach (WearableItem emote in this.ownedEmotes.Values) - { AddEmote(emote); - } + UpdateEmoteSlots(); } @@ -120,6 +121,7 @@ public void RestoreEmoteSlots() public void Dispose() { + cts.SafeCancelAndDispose(); view.onEmoteEquipped -= OnEmoteEquipped; view.onEmoteUnequipped -= OnEmoteUnequipped; view.onSellEmoteClicked -= OnSellEmoteClicked; @@ -127,7 +129,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; @@ -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; @@ -172,8 +177,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 +195,25 @@ 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.clip != 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 emoteReference)) { - emotesInLoadingState.TryGetValue(emoteId, out EmoteCardComponentView emote); - if (emote != null) + emotesInLoadingState.TryGetValue(emoteId, out EmoteCardComponentView emoteCard); + if (emoteCard != null) { - emote.SetAsLoading(false); + emoteCard.SetAsLoading(false); + emoteCard.SetSoundIcon(emoteReference.GetData().HasAudio()); emotesInLoadingState.Remove(emoteId); } } @@ -300,7 +295,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/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/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/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..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 @@ -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] @@ -53,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; @@ -89,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; @@ -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..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 @@ -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,12 +268,12 @@ public void RaiseOnSellEmoteClickedCorrectly() public void RaiseOnSlotSelectedCorrectly() { // Arrange - string emoteId = "TestId"; - string receivedId = ""; + var emoteId = "TestId"; + var receivedId = ""; 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 087bf0bed8..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 @@ -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] @@ -297,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); @@ -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..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 @@ -1,3 +1,4 @@ +using AvatarSystem; using Cysharp.Threading.Tasks; using DCL.Tasks; using MainScripts.DCL.Controllers.HUD.CharacterPreview; @@ -46,12 +47,14 @@ 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; public AvatarSlotsView AvatarSlotsView => avatarSlotsView; public BackpackFiltersComponentView BackpackFiltersComponentView => backpackFiltersComponentView; public OutfitsSectionComponentView OutfitsSectionComponentView => outfitsSectionComponentView; + private DataStore_EmotesCustomization emotesCustomizationDataStore => DataStore.i.emotesCustomization; private Transform thisTransform; private bool isAvatarDirty; @@ -134,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; @@ -282,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() 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..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 @@ -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; @@ -131,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/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: 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: 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] 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..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 @@ -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,18 @@ 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) + { + avatar.GetEmotesController().PlayEmote(emoteId, timestamp, false, 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 f3128df606..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 @@ -1,4 +1,6 @@ +using AvatarSystem; using Cysharp.Threading.Tasks; +using DCL.Emotes; using System; using System.Collections.Generic; using System.Threading; @@ -11,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); @@ -22,5 +25,8 @@ 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..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 @@ -1,6 +1,8 @@ +using AvatarSystem; using Cysharp.Threading.Tasks; using System.Collections.Generic; using DCL.Emotes; +using DCL.Helpers; using DCLServices.WearablesCatalogService; using System.Linq; using System.Threading; @@ -19,7 +21,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 +45,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 +76,35 @@ 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; + 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; + 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,38 @@ 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)) { - emotesToSet.Add(new EmotesWheelView.EmoteSlotData + var entity = emote?.GetEntity(); + + if (entity == null) // emote exists but its not loaded yet { - emoteItem = emoteItem, - thumbnailSprite = emoteItem.thumbnailSprite != null ? emoteItem.thumbnailSprite : equippedEmoteData.cachedThumbnail - }); + 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(null); - } - } - else - { + emotesToSet.Add(new EmotesWheelView.EmoteSlotData + { + emoteId = equippedEmoteData.id, + emoteItem = null, + thumbnailSprite = equippedEmoteData.cachedThumbnail, + }); + } else emotesToSet.Add(null); - } } ListPool.Release(equippedEmotes); @@ -151,18 +190,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 +237,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 +262,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; @@ -242,14 +283,20 @@ public void Dispose() auxShortcut8InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; auxShortcut9InputAction.OnTriggered -= OnNumericShortcutInputActionTriggered; - loadOwnedWearablesCTS?.Cancel(); - loadOwnedWearablesCTS?.Dispose(); - loadOwnedWearablesCTS = null; + if (emotesController != null) + { + emotesController.OnEmoteEquipped -= OnEmoteEquipped; + emotesController.OnEmoteUnequipped -= OnEmoteUnequipped; + } + + cts?.Cancel(); + cts?.Dispose(); + cts = null; if (view != null) { view.CleanUp(); - UnityEngine.Object.Destroy(view.gameObject); + Utils.SafeDestroy(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..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 @@ -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 is { emoteItem: not 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/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/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/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/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/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/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..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 @@ -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(addressableResourceProvider), + 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/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": [], 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 deleted file mode 100644 index cdf6d623e1..0000000000 --- a/unity-renderer/Assets/Scripts/MainScripts/DCL/Models/AvatarAssets/EmoteClipData.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UnityEngine; - -namespace DCL.Emotes -{ - public class EmoteClipData - { - public readonly AnimationClip clip; - public readonly bool loop; - - public EmoteClipData(AnimationClip clip, bool loop = false) - { - this.clip = clip; - this.loop = loop; - } - - public EmoteClipData(AnimationClip clip, EmoteDataV0 emoteDataV0) - { - this.clip = clip; - loop = emoteDataV0?.loop ?? false; - } - } -} \ No newline at end of file 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/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) 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..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 @@ -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 sceneEquippedEmotes)) { - sceneEquippedEmotes = new HashSet<(string bodyshapeId, string emoteId)>(); - equippedEmotesByScene.Add(scene, sceneEquippedEmotes); + sceneEquippedEmotes = new HashSet(); + emotesByScene.Add(scene, sceneEquippedEmotes); } // get / create cancellation source for scene @@ -134,20 +121,17 @@ 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); + var emoteKey = new EmoteBodyId(userBodyShape, emoteId); - // make emote play - avatarData.EquipEmote(emoteId, alreadyLoadedEmotes[(userBodyShape, emoteId)]); + if (!emotesByScene[scene].Contains(emoteKey)) + { + var result = await emotesService.RequestEmote(emoteKey, cancellationTokenSource.Token); + emotesController.EquipEmote(emoteId, result); + emotesByScene[scene].Add(emoteKey); + } userProfile.SetAvatarExpression(emoteId, UserProfile.EmoteSource.Command); + return SUCCESS_RESPONSE; } catch (OperationCanceledException _) @@ -170,26 +154,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..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 @@ -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 (EmoteBodyId 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(new EmoteBodyId(BODY_SHAPE, emoteId), Arg.Any()).Returns(UniTask.FromResult(emoteReference)); + return (emoteData: new EmoteBodyId(BODY_SHAPE, emoteId), 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; } 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