diff --git a/Explorer/Assets/AddressableAssetsData/AddressableAssetSettings.asset b/Explorer/Assets/AddressableAssetsData/AddressableAssetSettings.asset index 3596e22a28c..97921dafb16 100644 --- a/Explorer/Assets/AddressableAssetsData/AddressableAssetSettings.asset +++ b/Explorer/Assets/AddressableAssetsData/AddressableAssetSettings.asset @@ -15,7 +15,7 @@ MonoBehaviour: m_DefaultGroup: 47f803e1e9c5079449bd106df98a0b7d m_currentHash: serializedVersion: 2 - Hash: 00000000000000000000000000000000 + Hash: f55c7e45ff2b8ab7c1b6df8ae83134d6 m_OptimizeCatalogSize: 0 m_BuildRemoteCatalog: 0 m_CatalogRequestsTimeout: 0 diff --git a/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset b/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset index 3386d369234..92b135e3c70 100644 --- a/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset +++ b/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset @@ -170,6 +170,11 @@ MonoBehaviour: m_ReadOnly: 0 m_SerializedLabels: [] FlaggedDuringContentUpdateRestriction: 0 + - m_GUID: 696c60f7fb34b41808f12ead4e67ea6c + m_Address: Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/AuthorizationPopup/Assets/PortableExperienceAuthorizationPopup.prefab + m_ReadOnly: 0 + m_SerializedLabels: [] + FlaggedDuringContentUpdateRestriction: 0 - m_GUID: 6a252383173104e17acac54eb364afc4 m_Address: Assets/DCL/AvatarRendering/AvatarShape/Assets/PointAtMarker.prefab m_ReadOnly: 0 diff --git a/Explorer/Assets/DCL/Backpack/SmartWearableAuthorizationPopupView.cs b/Explorer/Assets/DCL/Backpack/SmartWearableAuthorizationPopupView.cs index 5103b9da2d2..eb6db847185 100644 --- a/Explorer/Assets/DCL/Backpack/SmartWearableAuthorizationPopupView.cs +++ b/Explorer/Assets/DCL/Backpack/SmartWearableAuthorizationPopupView.cs @@ -48,6 +48,9 @@ public class SmartWearableAuthorizationPopupView : ViewBase, IView [field: SerializeField] public GameObject FetchAPIPermissionContent { get; private set; } + [field: SerializeField] + public GameObject SpawnPortableExperiencePermissionContent { get; private set; } + public async UniTask WaitChoiceAsync() { await UniTask.WhenAny(AuthorizeButton.OnClickAsync(), DenyButton.OnClickAsync()); @@ -68,6 +71,7 @@ public void SetPermissions(List permissions) OpenExternalUrlPermissionContent.SetActive(permissions.Contains(ScenePermissionNames.OPEN_EXTERNAL_LINK)); WebSocketPermissionContent.SetActive(permissions.Contains(ScenePermissionNames.USE_WEBSOCKET)); FetchAPIPermissionContent.SetActive(permissions.Contains(ScenePermissionNames.USE_FETCH)); + SpawnPortableExperiencePermissionContent.SetActive(permissions.Contains(ScenePermissionNames.SPAWN_PORTABLE_EXPERIENCE)); } } } diff --git a/Explorer/Assets/DCL/Chat/Commands/KillPortableExperienceChatCommand.cs b/Explorer/Assets/DCL/Chat/Commands/KillPortableExperienceChatCommand.cs index 2621ceff524..fa239a63199 100644 --- a/Explorer/Assets/DCL/Chat/Commands/KillPortableExperienceChatCommand.cs +++ b/Explorer/Assets/DCL/Chat/Commands/KillPortableExperienceChatCommand.cs @@ -1,7 +1,6 @@ using Cysharp.Threading.Tasks; using DCL.FeatureFlags; using PortableExperiences.Controller; -using Runtime.Wearables; using System; using System.Threading; @@ -22,12 +21,10 @@ public class KillPortableExperienceChatCommand : IChatCommand public bool DebugOnly => true; private readonly IPortableExperiencesController portableExperiencesController; - private readonly SmartWearableCache smartWearableCache; - public KillPortableExperienceChatCommand(IPortableExperiencesController portableExperiencesController, SmartWearableCache smartWearableCache) + public KillPortableExperienceChatCommand(IPortableExperiencesController portableExperiencesController) { this.portableExperiencesController = portableExperiencesController; - this.smartWearableCache = smartWearableCache; } public bool ValidateParameters(string[] parameters) => @@ -44,18 +41,15 @@ public async UniTask ExecuteCommandAsync(string[] parameters, Cancellati string portableExperienceId = parameters[0]; - // Try killing a px with the given ID as it is - var response = portableExperiencesController.UnloadPortableExperienceById(portableExperienceId); + var response = portableExperiencesController.KillPortableExperienceById(portableExperienceId); - // In case of failure, try appending the ENS suffix and retrying + // Users usually type the bare name without the ENS suffix. if (!response.status && !portableExperienceId.EndsWith(ENS_SUFFIX, StringComparison.OrdinalIgnoreCase)) { portableExperienceId += ENS_SUFFIX; - response = portableExperiencesController.UnloadPortableExperienceById(portableExperienceId); + response = portableExperiencesController.KillPortableExperienceById(portableExperienceId); } - if (response.status) smartWearableCache.KilledPortableExperiences.Add(portableExperienceId); - return response.status ? $"🟢 The Portable Experience {portableExperienceId} has been Killed" : $"🔴 Error. Could not Kill the Portable Experience {portableExperienceId}"; } } diff --git a/Explorer/Assets/DCL/Chat/Commands/LoadPortableExperienceChatCommand.cs b/Explorer/Assets/DCL/Chat/Commands/LoadPortableExperienceChatCommand.cs index 4e752e70274..f3347cd8704 100644 --- a/Explorer/Assets/DCL/Chat/Commands/LoadPortableExperienceChatCommand.cs +++ b/Explorer/Assets/DCL/Chat/Commands/LoadPortableExperienceChatCommand.cs @@ -2,7 +2,6 @@ using Cysharp.Threading.Tasks; using DCL.Diagnostics; using DCL.FeatureFlags; -using DCL.Utilities.Extensions; using PortableExperiences.Controller; using System; using System.Threading; @@ -52,14 +51,19 @@ public async UniTask ExecuteCommandAsync(string[] parameters, Cancellati await UniTask.SwitchToMainThread(ct); - var result = await portableExperiencesController.CreatePortableExperienceByEnsAsync(new ENS(pxName), ct, true, true).SuppressAnyExceptionWithFallback(new IPortableExperiencesController.SpawnResponse(), ReportCategory.PORTABLE_EXPERIENCE); + try + { + await portableExperiencesController.CreatePortableExperienceByEnsAsync(new ENS(pxName), ct, isGlobalPortableExperience: true, force: true, requireUserAuthorization: true); - bool isSuccess = !string.IsNullOrEmpty(result.ens); - - if (ct.IsCancellationRequested) - return "🔴 Error. The operation was canceled!"; - - return isSuccess ? $"🟢 The Portable Experience {pxName} has started loading" : $"🔴 Error. Could not load {pxName} as a Portable Experience"; + return $"🟢 The Portable Experience {pxName} has started loading"; + } + catch (OperationCanceledException) { return "🔴 Error. The operation was canceled!"; } + catch (PortableExperienceAuthorizationDeniedException) { return $"🔴 {pxName} was not loaded because you denied its authorization request"; } + catch (Exception e) + { + ReportHub.LogException(e, ReportCategory.PORTABLE_EXPERIENCE); + return $"🔴 Error. Could not load {pxName} as a Portable Experience"; + } } } } diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/Bootstraper.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/Bootstraper.cs index 2fc417b8ed2..5712c1e18cf 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/Bootstraper.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/Bootstraper.cs @@ -265,6 +265,7 @@ Entity playerEntity dynamicWorldContainer.RealmController.GlobalWorld = globalWorld; staticContainer.PortableExperiencesController.GlobalWorld = globalWorld; + staticContainer.PortableExperiencesController.AuthorizationHandler = new PortableExperienceAuthorizationPopupHandler(dynamicWorldContainer.MvcManager); InitializeDebugPanel(staticContainer.DebugContainerBuilder, debugUiRoot); diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/ChatContainer.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/ChatContainer.cs index fc5c75d6b5c..10080aba4ad 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/ChatContainer.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/ChatContainer.cs @@ -123,7 +123,7 @@ public static ChatContainer Create( new ShowEntityChatCommand(worldInfoHub), reloadSceneChatCommand, new LoadPortableExperienceChatCommand(staticContainer.PortableExperiencesController), - new KillPortableExperienceChatCommand(staticContainer.PortableExperiencesController, staticContainer.SmartWearableCache), + new KillPortableExperienceChatCommand(staticContainer.PortableExperiencesController), new VersionChatCommand(dclVersion), new SupportChatCommand(uiShellContainer.SupportRequestService), new RoomsChatCommand(commsContainer.RoomHub), diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs index 3ddc0390e04..10761414da1 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs @@ -571,6 +571,8 @@ await MapRendererContainer chatContainer.ChatEventBus, placesAndEventsContainer.EventsApiService, staticContainer.SmartWearableCache, + staticContainer.LocalPortableExperienceCache, + staticContainer.GlobalPortableExperienceCache, uiShellContainer.SupportRequestService, voiceChatContainer.JoinedCommunitiesVoiceLiveTracker), uiShellContainer.CreateErrorPopupPlugin(assetsProvisioner), @@ -783,6 +785,7 @@ await MapRendererContainer uiShellContainer.MvcManager, wearableContainer.ThumbnailProvider, identityCache), + new PortableExperienceAuthorizationPopupPlugin(assetsProvisioner, uiShellContainer.MvcManager), new AvatarLocomotionOverridesGlobalPlugin(), new JumpIndicatorPlugin(assetsProvisioner), new SpringBonesPlugin(springBoneSimulationSettings), diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/ECSPortableExperiencesController.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/ECSPortableExperiencesController.cs index bacc7912932..22304a2d8ad 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/ECSPortableExperiencesController.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/ECSPortableExperiencesController.cs @@ -19,21 +19,27 @@ using SceneRunner.Scene; using System.Linq; using DCL.Multiplayer.Connections.DecentralandUrls; -using ECS.SceneLifeCycle.Realm; using DCL.Utility; +using Runtime.Wearables; +using SceneRuntime.ScenePermissions; namespace PortableExperiences.Controller { public class ECSPortableExperiencesController : IPortableExperiencesController { - private readonly IWeb3IdentityCache web3IdentityCache; + private const int MAX_PORTABLE_EXPERIENCES_PER_SCENE = 10; + private readonly IWebRequestController webRequestController; private readonly IScenesCache scenesCache; + private readonly LocalPortableExperienceCache localPortableExperienceCache; + private readonly GlobalPortableExperienceCache globalPortableExperienceCache; + private readonly SmartWearableCache smartWearableCache; private readonly List spawnResponsesList = new (); private readonly HashSet loadingPortableExperiences = new (); + private readonly Dictionary localPortableExperiencesPerScene = new (); private readonly ILaunchMode launchMode; private readonly IDecentralandUrlsSource urlsSources; - private GlobalWorld globalWorld; + private GlobalWorld? globalWorld; public Dictionary PortableExperienceEntities { get; } = new (); @@ -44,27 +50,40 @@ public GlobalWorld GlobalWorld set => globalWorld = value; } - private World world => globalWorld.EcsWorld; + public IPortableExperienceAuthorizationHandler? AuthorizationHandler { get; set; } + + private World world => GlobalWorld.EcsWorld; - public event Action PortableExperienceLoaded; - public event Action PortableExperienceUnloaded; + public event Action? PortableExperienceLoaded; + public event Action? PortableExperienceUnloaded; public ECSPortableExperiencesController( IWeb3IdentityCache web3IdentityCache, IWebRequestController webRequestController, IScenesCache scenesCache, + LocalPortableExperienceCache localPortableExperienceCache, + GlobalPortableExperienceCache globalPortableExperienceCache, + SmartWearableCache smartWearableCache, ILaunchMode launchMode, IDecentralandUrlsSource urlsSources) { - this.web3IdentityCache = web3IdentityCache; this.webRequestController = webRequestController; this.scenesCache = scenesCache; + this.localPortableExperienceCache = localPortableExperienceCache; + this.globalPortableExperienceCache = globalPortableExperienceCache; + this.smartWearableCache = smartWearableCache; this.launchMode = launchMode; this.urlsSources = urlsSources; + + // The controller lives for the whole application lifetime, so the subscriptions are never torn down. + web3IdentityCache.OnIdentityCleared += localPortableExperienceCache.Clear; + web3IdentityCache.OnIdentityCleared += globalPortableExperienceCache.Clear; } - public async UniTask CreatePortableExperienceByEnsAsync(ENS ens, CancellationToken ct, bool isGlobalPortableExperience = false, bool force = false) + public async UniTask CreatePortableExperienceByEnsAsync(ENS ens, CancellationToken ct, bool isGlobalPortableExperience = false, bool force = false, bool requireUserAuthorization = false) { + ISceneFacade? parentScene = scenesCache.Scenes.FirstOrDefault(s => s.SceneStateProvider.IsCurrent); + if (!force) switch (isGlobalPortableExperience) { @@ -75,6 +94,9 @@ public ECSPortableExperiencesController( //If it IS a Global PX but Global PXs are disabled case true when !FeatureFlagsConfiguration.Instance.IsEnabled(FeatureFlagsStrings.GLOBAL_PORTABLE_EXPERIENCE): throw new Exception("Global Portable Experiences are disabled"); + + case false when parentScene != null && !parentScene.SceneData.SceneEntityDefinition.metadata.requiredPermissions.Contains(ScenePermissionNames.SPAWN_PORTABLE_EXPERIENCE): + throw new Exception($"The parent scene {parentScene.Info.Name} is trying to spawn a portable experience but lacks the '{ScenePermissionNames.SPAWN_PORTABLE_EXPERIENCE}' permission."); } var portableExperienceId = ens.ToString(); @@ -112,11 +134,28 @@ public ECSPortableExperiencesController( //The loaded realm does not have any fixed scene, so it cannot be loaded as a Portable Experience throw new Exception($"Scene not Available in provided Portable Experience with ens: {ens}"); + var ipfsRealm = new IpfsRealm(portableExperiencePath, result); + string parentSceneName = parentScene?.Info.Name ?? "main"; + + bool isSceneSpawned = !force && !isGlobalPortableExperience; + + if (isSceneSpawned || requireUserAuthorization) + { + if (isSceneSpawned) + EnsureSceneSpawnCapacity(parentSceneName); + + string portableExperienceName = string.IsNullOrEmpty(result.configurations.realmName) ? portableExperienceId : result.configurations.realmName; + await EnsureAuthorizedByUserAsync(portableExperienceId, portableExperienceName, ipfsRealm, ct); + + // Re-checked: concurrent spawns may have consumed the remaining capacity while awaiting. + if (isSceneSpawned) + EnsureSceneSpawnCapacity(parentSceneName); + } + var realmData = new RealmData(); realmData.Reconfigure( - new IpfsRealm(portableExperiencePath, - result), + ipfsRealm, result.configurations.realmName.EnsureNotNull("Realm name not found"), result.configurations.networkId, result.comms?.adapter ?? string.Empty, @@ -126,8 +165,6 @@ public ECSPortableExperiencesController( WorldManifest.Empty ); - ISceneFacade parentScene = scenesCache.Scenes.FirstOrDefault(s => s.SceneStateProvider.IsCurrent); - string parentSceneName = parentScene != null ? parentScene.Info.Name : "main"; Entity portableExperienceEntity = world.Create(); world.Add(portableExperienceEntity, new PortableExperienceRealmComponent(realmData, parentSceneName, isGlobalPortableExperience), new PortableExperienceComponent(ens)); world.Add(portableExperienceEntity, new PortableExperienceMetadata @@ -141,6 +178,21 @@ public ECSPortableExperiencesController( PortableExperienceEntities.Add(portableExperienceId, portableExperienceEntity); + if (isGlobalPortableExperience) + { + // A re-spawned Portable Experience must not stay marked as killed. + globalPortableExperienceCache.KilledPortableExperiences.Remove(portableExperienceId); + globalPortableExperienceCache.RunningPortableExperiences.Add(portableExperienceId); + } + else + { + localPortableExperienceCache.KilledPortableExperiences.Remove(portableExperienceId); + localPortableExperienceCache.RunningPortableExperiences.Add(portableExperienceId); + + localPortableExperiencesPerScene.TryGetValue(parentSceneName, out int count); + localPortableExperiencesPerScene[parentSceneName] = count + 1; + } + PortableExperienceLoaded?.Invoke(portableExperienceId); return new IPortableExperiencesController.SpawnResponse @@ -152,6 +204,50 @@ public ECSPortableExperiencesController( } } + private async UniTask EnsureAuthorizedByUserAsync(string portableExperienceId, string portableExperienceName, IIpfsRealm ipfsRealm, CancellationToken ct) + { + if (localPortableExperienceCache.AuthorizedPortableExperiences.Contains(portableExperienceId)) return; + + if (localPortableExperienceCache.DeniedPortableExperiences.Contains(portableExperienceId)) + throw new PortableExperienceAuthorizationDeniedException($"The user has denied authorization for the portable experience '{portableExperienceId}' in this session."); + + IReadOnlyList permissions = await localPortableExperienceCache.GetPermissionsRequiringAuthorizationAsync(portableExperienceId, ipfsRealm, ct); + + if (permissions.Count == 0) + { + localPortableExperienceCache.AuthorizedPortableExperiences.Add(portableExperienceId); + return; + } + + IPortableExperienceAuthorizationHandler? authorizationHandler = AuthorizationHandler; + + // Fail closed: a portable experience that requires permissions must never spawn without explicit consent. + if (authorizationHandler == null) + { + ReportHub.LogError(ReportCategory.PORTABLE_EXPERIENCE, $"Cannot request authorization for portable experience '{portableExperienceId}': UI is not initialized yet."); + throw new Exception($"Portable experience '{portableExperienceId}' requires user authorization but the UI is not available yet."); + } + + bool authorized = await authorizationHandler.RequestAuthorizationAsync(portableExperienceName, permissions, ct); + + // A cancelled request must not be recorded as a user decision. + ct.ThrowIfCancellationRequested(); + + if (!authorized) + { + localPortableExperienceCache.DeniedPortableExperiences.Add(portableExperienceId); + throw new PortableExperienceAuthorizationDeniedException($"The user denied the portable experience '{portableExperienceName}'."); + } + + localPortableExperienceCache.AuthorizedPortableExperiences.Add(portableExperienceId); + } + + private void EnsureSceneSpawnCapacity(string parentSceneName) + { + if (localPortableExperiencesPerScene.TryGetValue(parentSceneName, out int count) && count >= MAX_PORTABLE_EXPERIENCES_PER_SCENE) + throw new Exception($"The scene '{parentSceneName}' has reached the maximum number of portable experiences it can spawn ({MAX_PORTABLE_EXPERIENCES_PER_SCENE})."); + } + public bool CanKillPortableExperience(string id) { if (!PortableExperienceEntities.TryGetValue(id, out Entity portableExperienceEntity)) return false; @@ -167,7 +263,7 @@ public bool CanKillPortableExperience(string id) case PortableExperienceType.Local: if (!FeatureFlagsConfiguration.Instance.IsEnabled(FeatureFlagsStrings.PORTABLE_EXPERIENCE)) return false; - ISceneFacade currentSceneFacade = scenesCache.CurrentScene.Value; + ISceneFacade? currentSceneFacade = scenesCache.CurrentScene.Value; return currentSceneFacade != null && metadata.ParentSceneId == currentSceneFacade.Info.Name; case PortableExperienceType.SmartWearable: @@ -213,6 +309,26 @@ public IPortableExperiencesController.ExitResponse UnloadPortableExperienceById( { if (PortableExperienceEntities.TryGetValue(id, out Entity portableExperienceEntity)) { + PortableExperienceMetadata metadata = world.Get(portableExperienceEntity); + + switch (metadata.Type) + { + // No SmartWearable case: its running state lives in SmartWearableCache, updated through the PortableExperienceUnloaded event raised below. + case PortableExperienceType.Local: + localPortableExperienceCache.RunningPortableExperiences.Remove(id); + break; + case PortableExperienceType.Global: + globalPortableExperienceCache.RunningPortableExperiences.Remove(id); + break; + } + + if (metadata.Type == PortableExperienceType.Local && + localPortableExperiencesPerScene.TryGetValue(metadata.ParentSceneId, out int count)) + { + if (count <= 1) localPortableExperiencesPerScene.Remove(metadata.ParentSceneId); + else localPortableExperiencesPerScene[metadata.ParentSceneId] = count - 1; + } + world.Add(portableExperienceEntity); PortableExperienceEntities.Remove(id); @@ -224,5 +340,31 @@ public IPortableExperiencesController.ExitResponse UnloadPortableExperienceById( return new IPortableExperiencesController.ExitResponse { status = false }; } + + public IPortableExperiencesController.ExitResponse KillPortableExperienceById(string id) + { + if (!PortableExperienceEntities.TryGetValue(id, out Entity portableExperienceEntity)) + return new IPortableExperiencesController.ExitResponse { status = false }; + + PortableExperienceType type = world.Get(portableExperienceEntity).Type; + + IPortableExperiencesController.ExitResponse response = UnloadPortableExperienceById(id); + + if (response.status) + switch (type) + { + case PortableExperienceType.SmartWearable: + smartWearableCache.KilledPortableExperiences.Add(id); + break; + case PortableExperienceType.Local: + localPortableExperienceCache.KilledPortableExperiences.Add(id); + break; + case PortableExperienceType.Global: + globalPortableExperienceCache.KilledPortableExperiences.Add(id); + break; + } + + return response; + } } } diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/GlobalPortableExperienceCache.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/GlobalPortableExperienceCache.cs new file mode 100644 index 00000000000..a05a4228fb2 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/GlobalPortableExperienceCache.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using Utility.PortableExperiences; + +namespace PortableExperiences.Controller +{ + /// + /// Per-session state for global Portable Experiences, the counterpart of SmartWearableCache and LocalPortableExperienceCache. + /// + public class GlobalPortableExperienceCache : IPortableExperiencesStatus + { + public HashSet RunningPortableExperiences { get; } = new (StringComparer.OrdinalIgnoreCase); + + public HashSet KilledPortableExperiences { get; } = new (StringComparer.OrdinalIgnoreCase); + + IReadOnlyCollection IPortableExperiencesStatus.RunningPortableExperiences => RunningPortableExperiences; + + IReadOnlyCollection IPortableExperiencesStatus.KilledPortableExperiences => KilledPortableExperiences; + + public void Clear() + { + RunningPortableExperiences.Clear(); + KilledPortableExperiences.Clear(); + } + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/GlobalPortableExperienceCache.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/GlobalPortableExperienceCache.cs.meta new file mode 100644 index 00000000000..1c29d048113 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/GlobalPortableExperienceCache.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f91b58e71543d4fe4b587763bceb8394 \ No newline at end of file diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperienceAuthorizationHandler.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperienceAuthorizationHandler.cs new file mode 100644 index 00000000000..33aa0a04543 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperienceAuthorizationHandler.cs @@ -0,0 +1,15 @@ +using Cysharp.Threading.Tasks; +using System.Collections.Generic; +using System.Threading; + +namespace PortableExperiences.Controller +{ + /// + /// Decides whether a scene-spawned Portable Experience may run with the permissions it requests. + /// Implemented outside this assembly so the scene life-cycle does not depend on UI. + /// + public interface IPortableExperienceAuthorizationHandler + { + UniTask RequestAuthorizationAsync(string portableExperienceName, IReadOnlyList permissions, CancellationToken ct); + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperienceAuthorizationHandler.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperienceAuthorizationHandler.cs.meta new file mode 100644 index 00000000000..b8b4a2fa87b --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperienceAuthorizationHandler.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2507f65353b10418f97d60d7dd899b70 \ No newline at end of file diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperiencesController.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperiencesController.cs index 3c362168c5d..921a607b2a9 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperiencesController.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/IPortableExperiencesController.cs @@ -11,20 +11,31 @@ namespace PortableExperiences.Controller { public interface IPortableExperiencesController { - event Action PortableExperienceLoaded; + event Action? PortableExperienceLoaded; - event Action PortableExperienceUnloaded; + event Action? PortableExperienceUnloaded; Dictionary PortableExperienceEntities { get; } GlobalWorld GlobalWorld { get; set; } + /// + /// Assigned from the composition root once the UI shell exists. + /// + IPortableExperienceAuthorizationHandler? AuthorizationHandler { get; set; } + bool CanKillPortableExperience(string id); - UniTask CreatePortableExperienceByEnsAsync(ENS ens, CancellationToken ct, bool isGlobalPortableExperience = false, bool force = false); + /// Gates the spawn behind user consent even when it is global or forced; scene-spawned local Portable Experiences are always gated. + UniTask CreatePortableExperienceByEnsAsync(ENS ens, CancellationToken ct, bool isGlobalPortableExperience = false, bool force = false, bool requireUserAuthorization = false); ExitResponse UnloadPortableExperienceById(string id); + /// + /// Unloads the Portable Experience and records it as killed in the status tracker matching its type. + /// + ExitResponse KillPortableExperienceById(string id); + List GetAllPortableExperiences(); void UnloadAllPortableExperiences(); diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/LocalPortableExperienceCache.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/LocalPortableExperienceCache.cs new file mode 100644 index 00000000000..17a66ba1b8f --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/LocalPortableExperienceCache.cs @@ -0,0 +1,92 @@ +using CommunicationData.URLHelpers; +using Cysharp.Threading.Tasks; +using DCL.Diagnostics; +using DCL.Ipfs; +using DCL.WebRequests; +using SceneRuntime.ScenePermissions; +using System; +using System.Collections.Generic; +using System.Threading; +using Utility.PortableExperiences; + +namespace PortableExperiences.Controller +{ + /// + /// Per-session authorization state for local (scene-spawned) Portable Experiences, the counterpart of + /// SmartWearableCache for Smart Wearables. + /// + public class LocalPortableExperienceCache : ILocalPortableExperiencesStatus + { + private readonly IWebRequestController webRequestController; + + private readonly Dictionary> permissionsCache = new (StringComparer.OrdinalIgnoreCase); + + public LocalPortableExperienceCache(IWebRequestController webRequestController) + { + this.webRequestController = webRequestController; + } + + public HashSet AuthorizedPortableExperiences { get; } = new (StringComparer.OrdinalIgnoreCase); + + public HashSet DeniedPortableExperiences { get; } = new (StringComparer.OrdinalIgnoreCase); + + public HashSet RunningPortableExperiences { get; } = new (StringComparer.OrdinalIgnoreCase); + + public HashSet KilledPortableExperiences { get; } = new (StringComparer.OrdinalIgnoreCase); + + IReadOnlyCollection ILocalPortableExperiencesStatus.AuthorizedPortableExperiences => AuthorizedPortableExperiences; + + IReadOnlyCollection IPortableExperiencesStatus.RunningPortableExperiences => RunningPortableExperiences; + + IReadOnlyCollection IPortableExperiencesStatus.KilledPortableExperiences => KilledPortableExperiences; + + /// + /// Fetches the Portable Experience's scene definitions to compute the permissions that need explicit + /// user authorization; cached for the whole session, so the definitions are fetched only once. + /// + public async UniTask> GetPermissionsRequiringAuthorizationAsync(string portableExperienceId, IIpfsRealm ipfsRealm, CancellationToken ct) + { + if (permissionsCache.TryGetValue(portableExperienceId, out List? cachedPermissions)) + return cachedPermissions; + + var permissions = new List(); + + foreach (string urn in ipfsRealm.SceneUrns) + { + IpfsPath ipfsPath = IpfsHelper.ParseUrn(urn); + + SceneEntityDefinition sceneDefinition = await webRequestController + .GetAsync(new CommonArguments(ipfsPath.GetUrl(ipfsRealm.ContentBaseUrl)), ct, ReportCategory.PORTABLE_EXPERIENCE) + .CreateFromJson(WRJsonParser.Newtonsoft); + + List? requiredPermissions = sceneDefinition.metadata.requiredPermissions; + + if (requiredPermissions == null) continue; + + foreach (string permission in requiredPermissions) + if (PermissionRequiresUserAuthorization(permission) && !permissions.Contains(permission)) + permissions.Add(permission); + } + + permissionsCache[portableExperienceId] = permissions; + return permissions; + } + + public void Clear() + { + permissionsCache.Clear(); + AuthorizedPortableExperiences.Clear(); + DeniedPortableExperiences.Clear(); + RunningPortableExperiences.Clear(); + KilledPortableExperiences.Clear(); + } + + // Mirrors the permission set gated by SmartWearableCache.CacheWearableInternalAsync. + internal static bool PermissionRequiresUserAuthorization(string permission) => + permission is ScenePermissionNames.USE_WEB3_API + or ScenePermissionNames.OPEN_EXTERNAL_LINK + or ScenePermissionNames.USE_WEBSOCKET + or ScenePermissionNames.SPAWN_PORTABLE_EXPERIENCE + or ScenePermissionNames.USE_FETCH; + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/LocalPortableExperienceCache.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/LocalPortableExperienceCache.cs.meta new file mode 100644 index 00000000000..168bcd88965 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/LocalPortableExperienceCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 63f49ad596444477915e5856c27a802d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/PortableExperienceAuthorizationDeniedException.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/PortableExperienceAuthorizationDeniedException.cs new file mode 100644 index 00000000000..d6643cc2275 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/PortableExperienceAuthorizationDeniedException.cs @@ -0,0 +1,12 @@ +using System; + +namespace PortableExperiences.Controller +{ + /// + /// The user refused the permissions a Portable Experience requires, so the spawn was aborted. + /// + public class PortableExperienceAuthorizationDeniedException : Exception + { + public PortableExperienceAuthorizationDeniedException(string message) : base(message) { } + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/PortableExperienceAuthorizationDeniedException.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/PortableExperienceAuthorizationDeniedException.cs.meta new file mode 100644 index 00000000000..58bda835e3e --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/PortableExperienceAuthorizationDeniedException.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c12da01b5c4324fc4af557b3c9cbf04d \ No newline at end of file diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests.meta new file mode 100644 index 00000000000..95d99c2c6be --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a075142384f24d5fa4af9fb67c14d2f8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode.meta new file mode 100644 index 00000000000..a82bc1d7de8 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1ae66c55745f4a89a4a992ecf347c662 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/ECSPortableExperiencesControllerShould.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/ECSPortableExperiencesControllerShould.cs new file mode 100644 index 00000000000..3958ae026cc --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/ECSPortableExperiencesControllerShould.cs @@ -0,0 +1,162 @@ +using Arch.Core; +using DCL.Multiplayer.Connections.DecentralandUrls; +using DCL.Utility; +using DCL.Web3.Identities; +using DCL.WebRequests; +using ECS; +using ECS.LifeCycle; +using ECS.Prioritization.Components; +using ECS.SceneLifeCycle; +using Global.Dynamic; +using NSubstitute; +using NUnit.Framework; +using PortableExperiences.Controller; +using Runtime.Wearables; +using System; +using System.Threading; + +namespace PortableExperiences.Tests +{ + public class ECSPortableExperiencesControllerShould + { + private const string LOCAL_PX_ID = "localpx.dcl.eth"; + private const string GLOBAL_PX_ID = "globalpx.dcl.eth"; + private const string SMART_WEARABLE_PX_ID = "smartwearablepx.dcl.eth"; + + private World world = null!; + private CancellationTokenSource globalWorldCts = null!; + private LocalPortableExperienceCache localCache = null!; + private GlobalPortableExperienceCache globalCache = null!; + private SmartWearableCache smartWearableCache = null!; + private ECSPortableExperiencesController controller = null!; + + [SetUp] + public void Setup() + { + world = World.Create(); + globalWorldCts = new CancellationTokenSource(); + + localCache = new LocalPortableExperienceCache(Substitute.For()); + globalCache = new GlobalPortableExperienceCache(); + smartWearableCache = new SmartWearableCache(Substitute.For()); + + controller = new ECSPortableExperiencesController( + Substitute.For(), + Substitute.For(), + Substitute.For(), + localCache, + globalCache, + smartWearableCache, + Substitute.For(), + Substitute.For()); + + controller.GlobalWorld = new GlobalWorld(world, null!, Array.Empty(), + new CameraSamplingData(), new RealmSamplingData(), globalWorldCts); + } + + [TearDown] + public void TearDown() + { + world.Dispose(); + globalWorldCts.Cancel(); + globalWorldCts.Dispose(); + } + + private void SeedPortableExperience(string id, PortableExperienceType type) + { + Entity entity = world.Create(new PortableExperienceMetadata + { + Type = type, + Ens = id, + Id = id, + Name = id, + ParentSceneId = "parent-scene", + }); + + controller.AddPortableExperience(id, entity); + } + + [Test] + public void RecordKilledLocalPortableExperienceInLocalCacheOnly() + { + // Arrange + SeedPortableExperience(LOCAL_PX_ID, PortableExperienceType.Local); + localCache.RunningPortableExperiences.Add(LOCAL_PX_ID); + + // Act + IPortableExperiencesController.ExitResponse response = controller.KillPortableExperienceById(LOCAL_PX_ID); + + // Assert + Assert.IsTrue(response.status); + Assert.IsTrue(localCache.KilledPortableExperiences.Contains(LOCAL_PX_ID)); + Assert.IsFalse(localCache.RunningPortableExperiences.Contains(LOCAL_PX_ID)); + Assert.IsEmpty(smartWearableCache.KilledPortableExperiences); + Assert.IsEmpty(globalCache.KilledPortableExperiences); + } + + [Test] + public void RecordKilledGlobalPortableExperienceInGlobalCacheOnly() + { + // Arrange + SeedPortableExperience(GLOBAL_PX_ID, PortableExperienceType.Global); + globalCache.RunningPortableExperiences.Add(GLOBAL_PX_ID); + + // Act + IPortableExperiencesController.ExitResponse response = controller.KillPortableExperienceById(GLOBAL_PX_ID); + + // Assert + Assert.IsTrue(response.status); + Assert.IsTrue(globalCache.KilledPortableExperiences.Contains(GLOBAL_PX_ID)); + Assert.IsFalse(globalCache.RunningPortableExperiences.Contains(GLOBAL_PX_ID)); + Assert.IsEmpty(smartWearableCache.KilledPortableExperiences); + Assert.IsEmpty(localCache.KilledPortableExperiences); + } + + [Test] + public void RecordKilledSmartWearableInSmartWearableCacheOnly() + { + // Arrange + SeedPortableExperience(SMART_WEARABLE_PX_ID, PortableExperienceType.SmartWearable); + + // Act + IPortableExperiencesController.ExitResponse response = controller.KillPortableExperienceById(SMART_WEARABLE_PX_ID); + + // Assert + Assert.IsTrue(response.status); + Assert.IsTrue(smartWearableCache.KilledPortableExperiences.Contains(SMART_WEARABLE_PX_ID)); + Assert.IsEmpty(localCache.KilledPortableExperiences); + Assert.IsEmpty(globalCache.KilledPortableExperiences); + } + + [Test] + public void NotRecordUnloadedPortableExperienceAsKilled() + { + // Arrange + SeedPortableExperience(LOCAL_PX_ID, PortableExperienceType.Local); + localCache.RunningPortableExperiences.Add(LOCAL_PX_ID); + + // Act + IPortableExperiencesController.ExitResponse response = controller.UnloadPortableExperienceById(LOCAL_PX_ID); + + // Assert + Assert.IsTrue(response.status); + Assert.IsFalse(localCache.RunningPortableExperiences.Contains(LOCAL_PX_ID)); + Assert.IsEmpty(localCache.KilledPortableExperiences); + Assert.IsEmpty(smartWearableCache.KilledPortableExperiences); + Assert.IsEmpty(globalCache.KilledPortableExperiences); + } + + [Test] + public void FailToKillUnknownPortableExperienceWithoutMutatingAnyCache() + { + // Act + IPortableExperiencesController.ExitResponse response = controller.KillPortableExperienceById("unknown.dcl.eth"); + + // Assert + Assert.IsFalse(response.status); + Assert.IsEmpty(localCache.KilledPortableExperiences); + Assert.IsEmpty(smartWearableCache.KilledPortableExperiences); + Assert.IsEmpty(globalCache.KilledPortableExperiences); + } + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/ECSPortableExperiencesControllerShould.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/ECSPortableExperiencesControllerShould.cs.meta new file mode 100644 index 00000000000..4afec042834 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/ECSPortableExperiencesControllerShould.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 90d5d948974c8469ca7e0a966617f1cc \ No newline at end of file diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/GlobalPortableExperienceCacheShould.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/GlobalPortableExperienceCacheShould.cs new file mode 100644 index 00000000000..c47b3fa7742 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/GlobalPortableExperienceCacheShould.cs @@ -0,0 +1,43 @@ +using NUnit.Framework; +using PortableExperiences.Controller; + +namespace PortableExperiences.Tests +{ + public class GlobalPortableExperienceCacheShould + { + private GlobalPortableExperienceCache cache = null!; + + [SetUp] + public void Setup() + { + cache = new GlobalPortableExperienceCache(); + } + + [Test] + public void EmptyAllSetsWhenCleared() + { + // Arrange + cache.RunningPortableExperiences.Add("running.dcl.eth"); + cache.KilledPortableExperiences.Add("killed.dcl.eth"); + + // Act + cache.Clear(); + + // Assert + Assert.IsEmpty(cache.RunningPortableExperiences); + Assert.IsEmpty(cache.KilledPortableExperiences); + } + + [Test] + public void MatchPortableExperienceIdsIgnoringCase() + { + // Arrange + cache.RunningPortableExperiences.Add("RunningPx.dcl.eth"); + cache.KilledPortableExperiences.Add("KilledPx.dcl.eth"); + + // Assert + Assert.IsTrue(cache.RunningPortableExperiences.Contains("runningpx.dcl.eth")); + Assert.IsTrue(cache.KilledPortableExperiences.Contains("killedpx.dcl.eth")); + } + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/GlobalPortableExperienceCacheShould.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/GlobalPortableExperienceCacheShould.cs.meta new file mode 100644 index 00000000000..7de7f1c49a9 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/GlobalPortableExperienceCacheShould.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9db9c19dd759d41c98917184cdaee024 \ No newline at end of file diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/LocalPortableExperienceCacheShould.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/LocalPortableExperienceCacheShould.cs new file mode 100644 index 00000000000..51f45e77b34 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/LocalPortableExperienceCacheShould.cs @@ -0,0 +1,69 @@ +using DCL.WebRequests; +using NSubstitute; +using NUnit.Framework; +using PortableExperiences.Controller; +using SceneRuntime.ScenePermissions; + +namespace PortableExperiences.Tests +{ + public class LocalPortableExperienceCacheShould + { + private LocalPortableExperienceCache cache = null!; + + [SetUp] + public void Setup() + { + cache = new LocalPortableExperienceCache(Substitute.For()); + } + + [TestCase(ScenePermissionNames.USE_WEB3_API)] + [TestCase(ScenePermissionNames.OPEN_EXTERNAL_LINK)] + [TestCase(ScenePermissionNames.USE_WEBSOCKET)] + [TestCase(ScenePermissionNames.SPAWN_PORTABLE_EXPERIENCE)] + [TestCase(ScenePermissionNames.USE_FETCH)] + public void RequireAuthorizationForGatedPermissions(string permission) + { + Assert.IsTrue(LocalPortableExperienceCache.PermissionRequiresUserAuthorization(permission)); + } + + [TestCase(ScenePermissionNames.ALLOW_MEDIA_HOSTNAMES)] + [TestCase("some-unknown-permission")] + public void NotRequireAuthorizationForUngatedPermissions(string permission) + { + Assert.IsFalse(LocalPortableExperienceCache.PermissionRequiresUserAuthorization(permission)); + } + + [Test] + public void EmptyAllSetsWhenCleared() + { + // Arrange + cache.AuthorizedPortableExperiences.Add("authorized.dcl.eth"); + cache.DeniedPortableExperiences.Add("denied.dcl.eth"); + cache.RunningPortableExperiences.Add("running.dcl.eth"); + cache.KilledPortableExperiences.Add("killed.dcl.eth"); + + // Act + cache.Clear(); + + // Assert + Assert.IsEmpty(cache.AuthorizedPortableExperiences); + Assert.IsEmpty(cache.DeniedPortableExperiences); + Assert.IsEmpty(cache.RunningPortableExperiences); + Assert.IsEmpty(cache.KilledPortableExperiences); + } + + [Test] + public void MatchPortableExperienceIdsIgnoringCase() + { + // Arrange + cache.AuthorizedPortableExperiences.Add("SomePx.dcl.eth"); + cache.RunningPortableExperiences.Add("RunningPx.dcl.eth"); + cache.KilledPortableExperiences.Add("KilledPx.dcl.eth"); + + // Assert + Assert.IsTrue(cache.AuthorizedPortableExperiences.Contains("somepx.dcl.eth")); + Assert.IsTrue(cache.RunningPortableExperiences.Contains("runningpx.dcl.eth")); + Assert.IsTrue(cache.KilledPortableExperiences.Contains("killedpx.dcl.eth")); + } + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/LocalPortableExperienceCacheShould.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/LocalPortableExperienceCacheShould.cs.meta new file mode 100644 index 00000000000..20eb9119e20 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/LocalPortableExperienceCacheShould.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fbe1ea387472443f99874bd5514def5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperienceAuthorizationPopupControllerShould.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperienceAuthorizationPopupControllerShould.cs new file mode 100644 index 00000000000..37919d0e79c --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperienceAuthorizationPopupControllerShould.cs @@ -0,0 +1,73 @@ +using Cysharp.Threading.Tasks; +using DCL.UI.PortableExperiences; +using MVC; +using NSubstitute; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace PortableExperiences.Tests +{ + public class PortableExperienceAuthorizationPopupControllerShould + { + private static readonly List PERMISSIONS = new () { "USE_WEB3_API" }; + + private IMVCManager mvcManager; + + [SetUp] + public void Setup() + { + mvcManager = Substitute.For(); + } + + [Test] + public async Task ReturnTrueWhenAuthorized() + { + // Arrange + SetupUserChoice(true); + + // Act + bool authorized = await PortableExperienceAuthorizationPopupController.RequestAuthorizationAsync(mvcManager, "px", PERMISSIONS, CancellationToken.None); + + // Assert + Assert.IsTrue(authorized); + } + + [Test] + public async Task ReturnFalseWhenDenied() + { + // Arrange + SetupUserChoice(false); + + // Act + bool authorized = await PortableExperienceAuthorizationPopupController.RequestAuthorizationAsync(mvcManager, "px", PERMISSIONS, CancellationToken.None); + + // Assert + Assert.IsFalse(authorized); + } + + [Test] + public async Task ReturnFalseWhenCancelledBeforeShowing() + { + // Arrange + var cts = new CancellationTokenSource(); + cts.Cancel(); + + // Act + bool authorized = await PortableExperienceAuthorizationPopupController.RequestAuthorizationAsync(mvcManager, "px", PERMISSIONS, cts.Token); + + // Assert + Assert.IsFalse(authorized); + } + + private void SetupUserChoice(bool authorize) + { + mvcManager.ShowAsync( + Arg.Do>( + command => command.InputData.CompletionSource.TrySetResult(authorize)), + Arg.Any()) + .Returns(UniTask.CompletedTask); + } + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperienceAuthorizationPopupControllerShould.cs.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperienceAuthorizationPopupControllerShould.cs.meta new file mode 100644 index 00000000000..64b807b3a38 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperienceAuthorizationPopupControllerShould.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3bf99076e0c47ae8a0d6eeb43c0a49d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperiences.EditMode.Tests.asmref b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperiences.EditMode.Tests.asmref new file mode 100644 index 00000000000..5aa9fc5db6f --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperiences.EditMode.Tests.asmref @@ -0,0 +1,3 @@ +{ + "reference": "GUID:da80994a355e49d5b84f91c0a84a721f" +} diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperiences.EditMode.Tests.asmref.meta b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperiences.EditMode.Tests.asmref.meta new file mode 100644 index 00000000000..8630a337e64 --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/Tests/EditMode/PortableExperiences.EditMode.Tests.asmref.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8e2577bde36142d29c0d80bbb00b96ef +AssemblyDefinitionReferenceImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Global/StaticContainer.cs b/Explorer/Assets/DCL/Infrastructure/Global/StaticContainer.cs index 4ab4dcf5253..716a5696639 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/StaticContainer.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/StaticContainer.cs @@ -124,6 +124,8 @@ public class StaticContainer : IDCLPlugin public HttpFeatureFlagsProvider FeatureFlagsProvider { get; private set; } public IPortableExperiencesController PortableExperiencesController { get; private set; } public SmartWearableCache SmartWearableCache { get; private set; } + public LocalPortableExperienceCache LocalPortableExperienceCache { get; private set; } + public GlobalPortableExperienceCache GlobalPortableExperienceCache { get; private set; } public ImageControllerProvider ImageControllerProvider { get; private set; } public IDebugContainerBuilder DebugContainerBuilder { get; private set; } public ISceneRestrictionBusController SceneRestrictionBusController { get; private set; } @@ -238,8 +240,10 @@ public UniTask InitializeAsync(StaticSettings settings, CancellationToken ct) container.EntityCollidersGlobalCache = new EntityCollidersGlobalCache(); container.ExposedGlobalDataContainer = exposedGlobalDataContainer; container.WebRequestsContainer = webRequestsContainer; - container.PortableExperiencesController = new ECSPortableExperiencesController(web3IdentityProvider, container.WebRequestsContainer.WebRequestController, container.ScenesCache, launchMode, decentralandUrlsSource); container.SmartWearableCache = new SmartWearableCache(webRequestsContainer.WebRequestController); + container.LocalPortableExperienceCache = new LocalPortableExperienceCache(container.WebRequestsContainer.WebRequestController); + container.GlobalPortableExperienceCache = new GlobalPortableExperienceCache(); + container.PortableExperiencesController = new ECSPortableExperiencesController(web3IdentityProvider, container.WebRequestsContainer.WebRequestController, container.ScenesCache, container.LocalPortableExperienceCache, container.GlobalPortableExperienceCache, container.SmartWearableCache, launchMode, decentralandUrlsSource); container.ImageControllerProvider = new ImageControllerProvider(globalWorld); container.FeatureFlagsProvider = new HttpFeatureFlagsProvider(container.WebRequestsContainer.WebRequestController); diff --git a/Explorer/Assets/DCL/Infrastructure/ScenePermissions/ScenePermissionNames.cs b/Explorer/Assets/DCL/Infrastructure/ScenePermissions/ScenePermissionNames.cs index bcda61896b2..52eb6295217 100644 --- a/Explorer/Assets/DCL/Infrastructure/ScenePermissions/ScenePermissionNames.cs +++ b/Explorer/Assets/DCL/Infrastructure/ScenePermissions/ScenePermissionNames.cs @@ -7,5 +7,6 @@ public static class ScenePermissionNames public const string USE_WEBSOCKET = "USE_WEBSOCKET"; public const string USE_FETCH = "USE_FETCH"; public const string USE_WEB3_API = "USE_WEB3_API"; + public const string SPAWN_PORTABLE_EXPERIENCE = "SPAWN_PORTABLE_EXPERIENCE"; } } diff --git a/Explorer/Assets/DCL/Infrastructure/SceneRuntime/Apis/Modules/PortableExperiencesApi/PortableExperiencesApiWrapper.cs b/Explorer/Assets/DCL/Infrastructure/SceneRuntime/Apis/Modules/PortableExperiencesApi/PortableExperiencesApiWrapper.cs index c78336470fe..13b0e50f33b 100644 --- a/Explorer/Assets/DCL/Infrastructure/SceneRuntime/Apis/Modules/PortableExperiencesApi/PortableExperiencesApiWrapper.cs +++ b/Explorer/Assets/DCL/Infrastructure/SceneRuntime/Apis/Modules/PortableExperiencesApi/PortableExperiencesApiWrapper.cs @@ -53,7 +53,7 @@ public object Exit() => if (!portableExperiencesController.CanKillPortableExperience(portableExperienceId)) return new IPortableExperiencesController.ExitResponse { status = false }; - return portableExperiencesController.UnloadPortableExperienceById(portableExperienceId); + return portableExperiencesController.KillPortableExperienceById(portableExperienceId); } private async UniTask ExitAsync() diff --git a/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences.meta b/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences.meta new file mode 100644 index 00000000000..92183810c2d --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e1f28341668e34d6c976e4fd11bfdf29 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences/IPortableExperiencesStatus.cs b/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences/IPortableExperiencesStatus.cs new file mode 100644 index 00000000000..12140bac6df --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences/IPortableExperiencesStatus.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace Utility.PortableExperiences +{ + /// + /// Read-only view over a Portable Experience status tracker; decouples consumers from the assembly the trackers live in. + /// + public interface IPortableExperiencesStatus + { + IReadOnlyCollection RunningPortableExperiences { get; } + + IReadOnlyCollection KilledPortableExperiences { get; } + } + + public interface ILocalPortableExperiencesStatus : IPortableExperiencesStatus + { + IReadOnlyCollection AuthorizedPortableExperiences { get; } + } +} diff --git a/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences/IPortableExperiencesStatus.cs.meta b/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences/IPortableExperiencesStatus.cs.meta new file mode 100644 index 00000000000..e655c41babc --- /dev/null +++ b/Explorer/Assets/DCL/Infrastructure/Utility/PortableExperiences/IPortableExperiencesStatus.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 705565d7fe4aa4e9581bf12ff64b33d3 \ No newline at end of file diff --git a/Explorer/Assets/DCL/PluginSystem/Global/Plugin Settings.asset b/Explorer/Assets/DCL/PluginSystem/Global/Plugin Settings.asset index 681627ffd45..69624116a36 100644 --- a/Explorer/Assets/DCL/PluginSystem/Global/Plugin Settings.asset +++ b/Explorer/Assets/DCL/PluginSystem/Global/Plugin Settings.asset @@ -70,6 +70,7 @@ MonoBehaviour: - rid: 4938242198007709791 - rid: 2872862648882692098 - rid: 3414978285727645698 + - rid: 1410421217730756608 - rid: 5034765029205082208 - rid: 2008243996523495520 - rid: 250124815058075745 @@ -465,6 +466,15 @@ MonoBehaviour: - PlayerInputAction: {fileID: 5794463069454124747, guid: 6cec26357c7fb8f44b03ce452209387d, type: 3} Key: IconClass: sprite-interaction__icon-mouse-right + - rid: 1410421217730756608 + type: {class: PortableExperienceAuthorizationPopupPlugin/Settings, ns: DCL.PluginSystem.Global, asm: DCL.Plugins} + data: + AuthorizationPopup: + m_AssetGUID: 696c60f7fb34b41808f12ead4e67ea6c + m_SubObjectName: + m_SubObjectType: + m_SubObjectGUID: + m_EditorAssetChanged: 0 - rid: 1501337502808539138 type: {class: ExplorePanelPlugin/ExplorePanelSettings, ns: DCL.PluginSystem.Global, asm: DCL.Plugins} data: diff --git a/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupHandler.cs b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupHandler.cs new file mode 100644 index 00000000000..7afb2f63b5c --- /dev/null +++ b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupHandler.cs @@ -0,0 +1,25 @@ +using Cysharp.Threading.Tasks; +using DCL.UI.PortableExperiences; +using MVC; +using PortableExperiences.Controller; +using System.Collections.Generic; +using System.Threading; + +namespace DCL.PluginSystem.Global +{ + /// + /// Lets the scene life-cycle reach the MVC popup without referencing MVC itself. + /// + public class PortableExperienceAuthorizationPopupHandler : IPortableExperienceAuthorizationHandler + { + private readonly IMVCManager mvcManager; + + public PortableExperienceAuthorizationPopupHandler(IMVCManager mvcManager) + { + this.mvcManager = mvcManager; + } + + public UniTask RequestAuthorizationAsync(string portableExperienceName, IReadOnlyList permissions, CancellationToken ct) => + PortableExperienceAuthorizationPopupController.RequestAuthorizationAsync(mvcManager, portableExperienceName, permissions, ct); + } +} diff --git a/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupHandler.cs.meta b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupHandler.cs.meta new file mode 100644 index 00000000000..e7437d21ade --- /dev/null +++ b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupHandler.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5509b6a2eec3446cfa2fbc66acac07c5 \ No newline at end of file diff --git a/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupPlugin.cs b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupPlugin.cs new file mode 100644 index 00000000000..1f81b83c653 --- /dev/null +++ b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupPlugin.cs @@ -0,0 +1,46 @@ +using Arch.SystemGroups; +using Cysharp.Threading.Tasks; +using DCL.AssetsProvision; +using DCL.UI.PortableExperiences; +using MVC; +using System; +using System.Threading; +using UnityEngine; +using UnityEngine.AddressableAssets; + +namespace DCL.PluginSystem.Global +{ + /// + /// Registers the Portable Experience authorization popup with the MVC manager. + /// + public class PortableExperienceAuthorizationPopupPlugin : IDCLGlobalPlugin + { + private readonly IAssetsProvisioner assetsProvisioner; + private readonly IMVCManager mvcManager; + + public PortableExperienceAuthorizationPopupPlugin(IAssetsProvisioner assetsProvisioner, IMVCManager mvcManager) + { + this.assetsProvisioner = assetsProvisioner; + this.mvcManager = mvcManager; + } + + public void Dispose() { } + + public async UniTask InitializeAsync(Settings settings, CancellationToken ct) + { + GameObject prefab = await assetsProvisioner.ProvideMainAssetValueAsync(settings.AuthorizationPopup, ct); + var view = prefab.GetComponent(); + var viewFactory = PortableExperienceAuthorizationPopupController.CreateLazily(view, null); + + mvcManager.RegisterController(new PortableExperienceAuthorizationPopupController(viewFactory)); + } + + public void InjectToWorld(ref ArchSystemsWorldBuilder builder, in GlobalPluginArguments arguments) { } + + [Serializable] + public class Settings : IDCLPluginSettings + { + public AssetReferenceGameObject AuthorizationPopup; + } + } +} diff --git a/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupPlugin.cs.meta b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupPlugin.cs.meta new file mode 100644 index 00000000000..0f06c871ad5 --- /dev/null +++ b/Explorer/Assets/DCL/PluginSystem/Global/PortableExperienceAuthorizationPopupPlugin.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17ed8a8ec89a49b195e74aa42aaf7ad7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/PluginSystem/Global/SidebarPlugin.cs b/Explorer/Assets/DCL/PluginSystem/Global/SidebarPlugin.cs index f08f4e418d6..064296565e6 100644 --- a/Explorer/Assets/DCL/PluginSystem/Global/SidebarPlugin.cs +++ b/Explorer/Assets/DCL/PluginSystem/Global/SidebarPlugin.cs @@ -38,6 +38,7 @@ using UnityEngine.AddressableAssets; using UnityEngine.InputSystem; using Utility; +using Utility.PortableExperiences; namespace DCL.PluginSystem.Global { @@ -66,6 +67,8 @@ public class SidebarPlugin : IDCLGlobalPlugin private readonly IPassportBridge passportBridge; private readonly ChatEventBus chatEventBus; private readonly SmartWearableCache smartWearableCache; + private readonly ILocalPortableExperiencesStatus localPortableExperiencesStatus; + private readonly IPortableExperiencesStatus globalPortableExperiencesStatus; private readonly HttpEventsApiService eventsApiService; private readonly SupportRequestService supportRequestService; private readonly JoinedCommunitiesVoiceLiveTracker communitiesLiveTracker; @@ -108,6 +111,8 @@ public SidebarPlugin( ChatEventBus chatEventBus, HttpEventsApiService eventsApiService, SmartWearableCache smartWearableCache, + ILocalPortableExperiencesStatus localPortableExperiencesStatus, + IPortableExperiencesStatus globalPortableExperiencesStatus, SupportRequestService supportRequestService, JoinedCommunitiesVoiceLiveTracker communitiesLiveTracker) { @@ -133,6 +138,8 @@ public SidebarPlugin( this.decentralandUrls = decentralandUrls; this.passportBridge = passportBridge; this.smartWearableCache = smartWearableCache; + this.localPortableExperiencesStatus = localPortableExperiencesStatus; + this.globalPortableExperiencesStatus = globalPortableExperiencesStatus; this.chatEventBus = chatEventBus; this.eventsApiService = eventsApiService; this.supportRequestService = supportRequestService; @@ -174,7 +181,7 @@ public async UniTask InitializeAsync(SidebarSettings settings, CancellationToken profileButtonPresenter = new SidebarProfileButtonPresenter( mainUIView.SidebarView.ProfileWidget, web3IdentityCache, profileRepository, profileChangesBus); profileMenuController = new ProfileMenuController(() => mainUIView.SidebarView.ProfileMenuView, web3IdentityCache, globalWorld, playerEntity, webBrowser, web3Authenticator, userInAppInitializationFlow, profileCache, passportBridge, profileRepositoryWrapper); skyboxMenuController = new SkyboxMenuController(() => mainUIView.SidebarView.SkyboxMenuView, settings.SettingsAsset, sceneRestrictionBusController); - smartWearablesSideBarTooltipController = new SmartWearablesSideBarTooltipController(() => mainUIView.SidebarView.SmartWearablesTooltipView, smartWearableCache); + smartWearablesSideBarTooltipController = new SmartWearablesSideBarTooltipController(() => mainUIView.SidebarView.SmartWearablesTooltipView, smartWearableCache, localPortableExperiencesStatus, globalPortableExperiencesStatus); sidebarSettingsWidgetController = new SidebarSettingsWidgetController(() => mainUIView.SidebarView.SidebarConfigPanelView); nearbyVoicePanelController = new NearbyVoicePanelController(() => mainUIView.SidebarView.NearbyVoiceWidget!); helpMenuController = new HelpMenuController(() => mainUIView.SidebarView.HelpMenu, mvcManager, webBrowser, supportRequestService); diff --git a/Explorer/Assets/DCL/SmartWearables/Assets/SmartWearablePopup.prefab b/Explorer/Assets/DCL/SmartWearables/Assets/SmartWearablePopup.prefab index 909fd91e839..976d1e52f30 100644 --- a/Explorer/Assets/DCL/SmartWearables/Assets/SmartWearablePopup.prefab +++ b/Explorer/Assets/DCL/SmartWearables/Assets/SmartWearablePopup.prefab @@ -103,6 +103,7 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -434,6 +435,7 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -570,6 +572,7 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -603,6 +606,81 @@ MonoBehaviour: m_hasFontAssetChanged: 0 m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &2689051494555752038 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1745282580525145452} + - component: {fileID: 4246665991338690725} + - component: {fileID: 9110838282004568634} + m_Layer: 5 + m_Name: Dot + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1745282580525145452 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2689051494555752038} + 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: 8467216405086630195} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 6, y: 6} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &4246665991338690725 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2689051494555752038} + m_CullTransparentMesh: 1 +--- !u!114 &9110838282004568634 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2689051494555752038} + 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: 1, g: 1, b: 1, 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: 0f85301a9211845c8b8d39b4a4b05762, 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 &2770862484639632158 GameObject: m_ObjectHideFlags: 0 @@ -781,6 +859,144 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &3405857591728898178 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4109387798285324094} + - component: {fileID: 1630146948897990082} + - component: {fileID: 6779800072601281085} + m_Layer: 5 + m_Name: Text_FetcAPI + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4109387798285324094 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3405857591728898178} + 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: 8467216405086630195} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 6, y: 0} + m_SizeDelta: {x: -12, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1630146948897990082 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3405857591728898178} + m_CullTransparentMesh: 0 +--- !u!114 &6779800072601281085 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3405857591728898178} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, 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_text: Spawn other PEXs + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_sharedMaterial: {fileID: 1701868249614554837, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294769916 + m_fontColor: {r: 0.9882353, g: 0.9882353, b: 0.9882353, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 16 + m_fontSizeBase: 16 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 10 + m_fontSizeMax: 18 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -1559,6 +1775,7 @@ MonoBehaviour: m_VerticalAlignment: 256 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -2303,6 +2520,7 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -2439,6 +2657,7 @@ MonoBehaviour: m_VerticalAlignment: 256 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -2580,6 +2799,7 @@ RectTransform: - {fileID: 8571240714126811470} - {fileID: 2008267705617026435} - {fileID: 6815728451430577628} + - {fileID: 8467216405086630195} m_Father: {fileID: 6423328223121998152} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -3010,6 +3230,7 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -3146,6 +3367,7 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -3340,6 +3562,7 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 @@ -3373,6 +3596,64 @@ MonoBehaviour: m_hasFontAssetChanged: 0 m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &8763682686413775421 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8467216405086630195} + - component: {fileID: 165000827460257758} + m_Layer: 5 + m_Name: SpawnPEXContent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &8467216405086630195 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8763682686413775421} + 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: 1745282580525145452} + - {fileID: 4109387798285324094} + m_Father: {fileID: 2857259286252783766} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 200, y: -102.5} + m_SizeDelta: {x: 400, y: 25} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &165000827460257758 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8763682686413775421} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 25 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 --- !u!1 &8771896726793379385 GameObject: m_ObjectHideFlags: 0 @@ -3584,6 +3865,7 @@ Canvas: m_OverridePixelPerfect: 0 m_SortingBucketNormalizedSize: 0 m_VertexColorAlwaysGammaSpace: 0 + m_UseReflectionProbes: 0 m_AdditionalShaderChannelsFlag: 25 m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 @@ -3694,6 +3976,7 @@ MonoBehaviour: k__BackingField: {fileID: 8257716210183616304} k__BackingField: {fileID: 5396709543064308403} k__BackingField: {fileID: 4763347660862381246} + k__BackingField: {fileID: 8763682686413775421} --- !u!1001 &7430654409529280744 PrefabInstance: m_ObjectHideFlags: 0 @@ -3825,39 +4108,14 @@ PrefabInstance: m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] - m_AddedComponents: + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} ---- !u!1 &570498602168057259 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 6986259105694070083, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} - m_PrefabInstance: {fileID: 7430654409529280744} - m_PrefabAsset: {fileID: 0} ---- !u!1 &2475761848735125540 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 4991484376697837772, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} - m_PrefabInstance: {fileID: 7430654409529280744} - m_PrefabAsset: {fileID: 0} ---- !u!1 &3927331575391662683 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 5881230051982965427, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} - m_PrefabInstance: {fileID: 7430654409529280744} - m_PrefabAsset: {fileID: 0} ---- !u!1 &4791098279448237086 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 2694166673821375734, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} - m_PrefabInstance: {fileID: 7430654409529280744} - m_PrefabAsset: {fileID: 0} ---- !u!1 &4811526338000120843 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 2727779938357748963, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} - m_PrefabInstance: {fileID: 7430654409529280744} - m_PrefabAsset: {fileID: 0} --- !u!114 &5440208772361561913 stripped MonoBehaviour: m_CorrespondingSourceObject: {fileID: 3197975606675238865, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} m_PrefabInstance: {fileID: 7430654409529280744} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2475761848735125540} + m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} @@ -3873,7 +4131,7 @@ MonoBehaviour: m_CorrespondingSourceObject: {fileID: 3806077527122901697, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} m_PrefabInstance: {fileID: 7430654409529280744} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 570498602168057259} + m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} @@ -3884,7 +4142,7 @@ MonoBehaviour: m_CorrespondingSourceObject: {fileID: 3650771503568278903, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} m_PrefabInstance: {fileID: 7430654409529280744} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4811526338000120843} + m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} @@ -3895,14 +4153,9 @@ MonoBehaviour: m_CorrespondingSourceObject: {fileID: 231064522792734509, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} m_PrefabInstance: {fileID: 7430654409529280744} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4791098279448237086} + m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} m_Name: m_EditorClassIdentifier: ---- !u!1 &7694418294408716437 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 997244388986939517, guid: 37e9014a41ddacf4fbee8c370baf7737, type: 3} - m_PrefabInstance: {fileID: 7430654409529280744} - m_PrefabAsset: {fileID: 0} diff --git a/Explorer/Assets/DCL/SmartWearables/SmartWearableCache.cs b/Explorer/Assets/DCL/SmartWearables/SmartWearableCache.cs index 69908b018a1..9c01774ef7b 100644 --- a/Explorer/Assets/DCL/SmartWearables/SmartWearableCache.cs +++ b/Explorer/Assets/DCL/SmartWearables/SmartWearableCache.cs @@ -150,6 +150,7 @@ private async UniTask CacheWearableInternalAsync(IWearable wearable, item.RequiresAuthorization = item.RequiresWeb3API || permissions.Contains(ScenePermissionNames.OPEN_EXTERNAL_LINK) || permissions.Contains(ScenePermissionNames.USE_WEBSOCKET) || + permissions.Contains(ScenePermissionNames.SPAWN_PORTABLE_EXPERIENCE) || permissions.Contains(ScenePermissionNames.USE_FETCH); } diff --git a/Explorer/Assets/DCL/UI/PortableExperiences.meta b/Explorer/Assets/DCL/UI/PortableExperiences.meta new file mode 100644 index 00000000000..c80ee20bc28 --- /dev/null +++ b/Explorer/Assets/DCL/UI/PortableExperiences.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 19dbffb4103b4cd7b5935314269c0c71 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup.meta b/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup.meta new file mode 100644 index 00000000000..9eaa9a3ffce --- /dev/null +++ b/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f8dda734cbfa94435ace7e36b86f7c64 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup/Assets.meta b/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup/Assets.meta new file mode 100644 index 00000000000..30547a62aae --- /dev/null +++ b/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup/Assets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d339d56c8efd341ef994bf2d22921fe5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup/Assets/PortableExperienceAuthorizationPopup.prefab b/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup/Assets/PortableExperienceAuthorizationPopup.prefab new file mode 100644 index 00000000000..13702d8de56 --- /dev/null +++ b/Explorer/Assets/DCL/UI/PortableExperiences/AuthorizationPopup/Assets/PortableExperienceAuthorizationPopup.prefab @@ -0,0 +1,3591 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &569480607035033599 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1020681461664436571} + - component: {fileID: 1265595995438924520} + - component: {fileID: 7367278318638538253} + m_Layer: 5 + m_Name: Text_OpenURL + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1020681461664436571 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 569480607035033599} + 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: 8571240714126811470} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 6, y: 0} + m_SizeDelta: {x: -12, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1265595995438924520 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 569480607035033599} + m_CullTransparentMesh: 0 +--- !u!114 &7367278318638538253 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 569480607035033599} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, 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_text: Request to open an external link + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_sharedMaterial: {fileID: 1701868249614554837, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294769916 + m_fontColor: {r: 0.9882353, g: 0.9882353, b: 0.9882353, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 16 + m_fontSizeBase: 16 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 10 + m_fontSizeMax: 18 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &977118047590855751 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2104469442375949798} + - component: {fileID: 2873092557237926469} + - component: {fileID: 6480538541451795713} + m_Layer: 5 + m_Name: Web3WarningIcon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2104469442375949798 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 977118047590855751} + 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: 3472439070150357460} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 12, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &2873092557237926469 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 977118047590855751} + m_CullTransparentMesh: 1 +--- !u!114 &6480538541451795713 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 977118047590855751} + 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: 1, g: 1, b: 1, 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: 0f85301a9211845c8b8d39b4a4b05762, 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 &1012361467963591975 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4063232543674776687} + - component: {fileID: 2226524494709942453} + - component: {fileID: 1306130004730048958} + - component: {fileID: 2090035421872733937} + m_Layer: 5 + m_Name: Web3InfoIcon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4063232543674776687 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1012361467963591975} + 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: 3472439070150357460} + 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: 191.4, y: 0} + m_SizeDelta: {x: 25, y: 25} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2226524494709942453 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1012361467963591975} + m_CullTransparentMesh: 1 +--- !u!114 &1306130004730048958 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1012361467963591975} + 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: 1, g: 1, b: 1, 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: d63bc69a4cb0e4fd5b31fc3bd1f8e1fc, 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!114 &2090035421872733937 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1012361467963591975} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1306130004730048958} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &1517367032306287568 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7716752368412796278} + - component: {fileID: 4116834978988209326} + m_Layer: 5 + m_Name: SpawnPEXContent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &7716752368412796278 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517367032306287568} + 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: 8376556310911029368} + - {fileID: 2284311831969904922} + m_Father: {fileID: 2857259286252783766} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 200, y: -102.5} + m_SizeDelta: {x: 400, y: 25} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &4116834978988209326 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1517367032306287568} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 25 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &1941329943709143013 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4604578286748329139} + - component: {fileID: 6889358583835194576} + - component: {fileID: 7302635622122976652} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4604578286748329139 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1941329943709143013} + 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: 4525239263289895109} + 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: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6889358583835194576 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1941329943709143013} + m_CullTransparentMesh: 1 +--- !u!114 &7302635622122976652 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1941329943709143013} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, 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_text: NO + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 96ae0a2159a39234f858ea23bdcc74ad, type: 2} + m_sharedMaterial: {fileID: 735423033564544980, guid: 96ae0a2159a39234f858ea23bdcc74ad, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 14 + m_fontSizeBase: 14 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &2986659149956576097 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8376556310911029368} + - component: {fileID: 4923496622441757191} + - component: {fileID: 3009236417891388036} + m_Layer: 5 + m_Name: Dot + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8376556310911029368 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2986659149956576097} + 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: 7716752368412796278} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 6, y: 6} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &4923496622441757191 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2986659149956576097} + m_CullTransparentMesh: 1 +--- !u!114 &3009236417891388036 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2986659149956576097} + 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: 1, g: 1, b: 1, 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: 0f85301a9211845c8b8d39b4a4b05762, 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 &3039893959675615124 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2360012375694817246} + - component: {fileID: 2472522585224214361} + - component: {fileID: 6061366837315337756} + m_Layer: 5 + m_Name: Text_Web3API + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2360012375694817246 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3039893959675615124} + 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: 3472439070150357460} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 32.2, y: 0} + m_SizeDelta: {x: -12, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2472522585224214361 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3039893959675615124} + m_CullTransparentMesh: 0 +--- !u!114 &6061366837315337756 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3039893959675615124} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, 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_text: Request to interact with your account wallet + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_sharedMaterial: {fileID: 1701868249614554837, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294769916 + m_fontColor: {r: 0.9882353, g: 0.9882353, b: 0.9882353, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 16 + m_fontSizeBase: 16 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 10 + m_fontSizeMax: 18 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &3505416699678409761 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5519811652311879870} + - component: {fileID: 5065191524455666942} + - component: {fileID: 4647989238072481883} + m_Layer: 5 + m_Name: Dot + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5519811652311879870 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3505416699678409761} + 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: 8571240714126811470} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 6, y: 6} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &5065191524455666942 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3505416699678409761} + m_CullTransparentMesh: 1 +--- !u!114 &4647989238072481883 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3505416699678409761} + 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: 1, g: 1, b: 1, 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: 0f85301a9211845c8b8d39b4a4b05762, 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 &3553545222316724595 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6423328223121998152} + - component: {fileID: 2476352842357418747} + - component: {fileID: 7634257071159536930} + - component: {fileID: 765484108175074687} + - component: {fileID: 8059445811444406618} + - component: {fileID: 1775148925518670208} + m_Layer: 5 + m_Name: Container + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6423328223121998152 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3553545222316724595} + 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: 5000151974203908340} + - {fileID: 945104628635160112} + - {fileID: 1337524285867509162} + - {fileID: 2469228033729172624} + - {fileID: 2857259286252783766} + - {fileID: 5440410785030402750} + - {fileID: 7112222135713342020} + m_Father: {fileID: 3721001069623505348} + 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, y: 0} + m_SizeDelta: {x: 600, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2476352842357418747 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3553545222316724595} + m_CullTransparentMesh: 0 +--- !u!114 &7634257071159536930 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3553545222316724595} + 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.29803923, g: 0.078431375, b: 0.4862745, 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: 99428d9ed6da74af2966fb29d960e48f, 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 &765484108175074687 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3553545222316724595} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 385b7d1277b6c4007a84c065696e0f8c, type: 3} + m_Name: + m_EditorClassIdentifier: Coffee.SoftMaskForUGUI::Coffee.UISoftMask.SoftMask + m_ShowMaskGraphic: 1 + m_MaskingMode: 0 + m_AlphaHitTest: 0 + m_SoftnessRange: + m_Min: 0 + m_Max: 1 + m_DownSamplingRate: 1 + m_AntiAliasingThreshold: 0 + m_Alpha: -1 + m_Softness: -1 + m_PartOfParent: 0 +--- !u!114 &8059445811444406618 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3553545222316724595} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 70 + m_Bottom: 70 + m_ChildAlignment: 4 + m_Spacing: 20 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 0 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &1775148925518670208 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3553545222316724595} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!1 &3968188858371109081 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4154899758913394138} + - component: {fileID: 1620753456142016768} + - component: {fileID: 1537905915354232701} + m_Layer: 5 + m_Name: Dot + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4154899758913394138 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3968188858371109081} + 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: 3472439070150357460} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 6, y: 6} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &1620753456142016768 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3968188858371109081} + m_CullTransparentMesh: 1 +--- !u!114 &1537905915354232701 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3968188858371109081} + 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: 1, g: 1, b: 1, 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: 0f85301a9211845c8b8d39b4a4b05762, 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 &4307366659622441785 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5440410785030402750} + - component: {fileID: 481671985074297207} + m_Layer: 5 + m_Name: Space + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5440410785030402750 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4307366659622441785} + 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: 6423328223121998152} + 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: 100, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &481671985074297207 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4307366659622441785} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 5 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &4763347660862381246 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6815728451430577628} + - component: {fileID: 4513929498317771055} + m_Layer: 5 + m_Name: FetchAPIContent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &6815728451430577628 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4763347660862381246} + 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: 6359504104393393624} + - {fileID: 6443775800277903096} + m_Father: {fileID: 2857259286252783766} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 200, y: -102.5} + m_SizeDelta: {x: 400, y: 25} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &4513929498317771055 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4763347660862381246} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 25 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &4900722158030081778 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5213924262690448492} + m_Layer: 5 + m_Name: TrustToggle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &5213924262690448492 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4900722158030081778} + 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: 1441569917943927434} + - {fileID: 564943647966516947} + m_Father: {fileID: 7112222135713342020} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 400, y: 30} + m_Pivot: {x: 0.5, y: 0} +--- !u!1 &4951260246951091639 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7112222135713342020} + - component: {fileID: 2239180808049724181} + m_Layer: 5 + m_Name: BottomControlsContent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7112222135713342020 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4951260246951091639} + 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: 7910414739088270336} + - {fileID: 4525239263289895109} + - {fileID: 5213924262690448492} + m_Father: {fileID: 6423328223121998152} + 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: 1} +--- !u!114 &2239180808049724181 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4951260246951091639} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 46 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &5033577812611912176 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2469228033729172624} + - component: {fileID: 8716213118799733145} + - component: {fileID: 3261568379768116101} + m_Layer: 5 + m_Name: PermissionsText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2469228033729172624 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5033577812611912176} + 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: 6423328223121998152} + 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!222 &8716213118799733145 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5033577812611912176} + m_CullTransparentMesh: 0 +--- !u!114 &3261568379768116101 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5033577812611912176} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, 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_text: 'The PEX can:' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_sharedMaterial: {fileID: 1701868249614554837, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294769916 + m_fontColor: {r: 0.9882353, g: 0.9882353, b: 0.9882353, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 16 + m_fontSizeBase: 16 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 10 + m_fontSizeMax: 18 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &5286320648266985769 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5872025313732959718} + - component: {fileID: 8507509072795567359} + - component: {fileID: 8240417633539105581} + m_Layer: 5 + m_Name: Top + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5872025313732959718 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5286320648266985769} + 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: 5000151974203908340} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 284, y: 186} + m_SizeDelta: {x: 424.3142, y: 317.5106} + m_Pivot: {x: 1, y: 1} +--- !u!222 &8507509072795567359 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5286320648266985769} + m_CullTransparentMesh: 1 +--- !u!114 &8240417633539105581 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5286320648266985769} + 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: 1, g: 0.29411766, b: 0.92941177, a: 0.101960786} + 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: 00cc69ba88b8143baa8ef5d80c99ab63, 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 &5396709543064308403 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2008267705617026435} + - component: {fileID: 7807808593825154720} + m_Layer: 5 + m_Name: WebSocketContent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &2008267705617026435 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5396709543064308403} + 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: 8553805778832299079} + - {fileID: 7207300955268450930} + m_Father: {fileID: 2857259286252783766} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 200, y: -72.5} + m_SizeDelta: {x: 400, y: 25} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &7807808593825154720 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5396709543064308403} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 25 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &5472271628793402656 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1337524285867509162} + - component: {fileID: 4022214377488809967} + m_Layer: 5 + m_Name: Space + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1337524285867509162 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5472271628793402656} + 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: 6423328223121998152} + 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: 100, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &4022214377488809967 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5472271628793402656} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 5 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &5656676415579789541 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1441569917943927434} + - component: {fileID: 1678854547479391980} + m_Layer: 5 + m_Name: Toggle_Trust + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1441569917943927434 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5656676415579789541} + 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: 3205226359111656073} + m_Father: {fileID: 5213924262690448492} + 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: -118.1, y: 0} + m_SizeDelta: {x: 16, y: 16} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1678854547479391980 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5656676415579789541} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.8784314, g: 0.8784314, b: 0.8784314, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3247097842265188489} + toggleTransition: 1 + graphic: {fileID: 1564004221914234232} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_IsOn: 1 +--- !u!1 &5705169434686760831 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2284311831969904922} + - component: {fileID: 1001513193388542061} + - component: {fileID: 8247964790926790266} + m_Layer: 5 + m_Name: Text_FetcAPI + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2284311831969904922 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5705169434686760831} + 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: 7716752368412796278} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 6, y: 0} + m_SizeDelta: {x: -12, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1001513193388542061 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5705169434686760831} + m_CullTransparentMesh: 0 +--- !u!114 &8247964790926790266 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5705169434686760831} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, 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_text: Spawn other PEXs + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_sharedMaterial: {fileID: 1701868249614554837, guid: 35aa85d68d15435418848a03a2db81ec, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294769916 + m_fontColor: {r: 0.9882353, g: 0.9882353, b: 0.9882353, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 16 + m_fontSizeBase: 16 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 10 + m_fontSizeMax: 18 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &5975997632099239229 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3472439070150357460} + - component: {fileID: 8792155380637249775} + m_Layer: 5 + m_Name: Web3APIContent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3472439070150357460 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5975997632099239229} + 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: 4154899758913394138} + - {fileID: 2104469442375949798} + - {fileID: 2360012375694817246} + - {fileID: 4063232543674776687} + m_Father: {fileID: 2857259286252783766} + 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!114 &8792155380637249775 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5975997632099239229} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: 25 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &6390886925985447464 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 75169803762689040} + - component: {fileID: 1485552505549553447} + - component: {fileID: 6187602187507074344} + m_Layer: 5 + m_Name: Bottom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &75169803762689040 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6390886925985447464} + 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: 5000151974203908340} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 0, y: -170} + m_SizeDelta: {x: 657.6395, y: 256.0724} + m_Pivot: {x: 0.5, y: 0} +--- !u!222 &1485552505549553447 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6390886925985447464} + m_CullTransparentMesh: 1 +--- !u!114 &6187602187507074344 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6390886925985447464} + 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: 1, g: 0.29411766, b: 0.92941177, a: 0.14901961} + 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: 00cc69ba88b8143baa8ef5d80c99ab63, 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 &6410941608352318067 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7910414739088270336} + - component: {fileID: 6689158895453480032} + - component: {fileID: 8589856764071627061} + - component: {fileID: 4323582271544481263} + - component: {fileID: 4498242140924735680} + - component: {fileID: 6781683249349970935} + m_Layer: 5 + m_Name: Button_Continue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7910414739088270336 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6410941608352318067} + 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: 4974519960533566575} + m_Father: {fileID: 7112222135713342020} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 190, y: 46} + m_Pivot: {x: 1, y: 1} +--- !u!222 &6689158895453480032 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6410941608352318067} + m_CullTransparentMesh: 0 +--- !u!114 &8589856764071627061 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6410941608352318067} + 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: 1, g: 0.1764706, b: 0.33333334, 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: 12dd1efc4e826764f9b02be515a9a033, 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 &4323582271544481263 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6410941608352318067} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.8862745, g: 0.8862745, b: 0.8862745, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 8589856764071627061} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &4498242140924735680 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6410941608352318067} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6a66e979ca644f3d91fd0980c5cd5f5f, type: 3} + m_Name: + m_EditorClassIdentifier: +