From 879d54fac943ea01a3eefbc7c56c89e57904fe3c Mon Sep 17 00:00:00 2001 From: Nicolas Lorusso <56365551+lorux0@users.noreply.github.com> Date: Mon, 14 Sep 2026 16:26:09 -0300 Subject: [PATCH 01/14] fix: os font fallback anr (#10090) --- .../Assets/DCL/UIToolkit/DCLDebugPanelSettings.asset | 2 +- Explorer/Assets/DCL/UIToolkit/DCLDefaultTheme.tss | 9 +++++++++ Explorer/Assets/DCL/UIToolkit/DCLPanelSettings.asset | 2 +- .../Assets/DCL/UIToolkit/DCLScenePanelSettings.asset | 2 +- Explorer/Assets/DCL/UIToolkit/DCLSceneTheme.tss | 8 ++++++++ Explorer/Assets/DCL/UIToolkit/DCLTextSettings.asset | 2 +- Explorer/Assets/Launcher/LauncherPanel.asset | 2 +- 7 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Explorer/Assets/DCL/UIToolkit/DCLDebugPanelSettings.asset b/Explorer/Assets/DCL/UIToolkit/DCLDebugPanelSettings.asset index 557ab86a6ef..b8c19393872 100644 --- a/Explorer/Assets/DCL/UIToolkit/DCLDebugPanelSettings.asset +++ b/Explorer/Assets/DCL/UIToolkit/DCLDebugPanelSettings.asset @@ -49,4 +49,4 @@ MonoBehaviour: m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0} m_ICUDataAsset: {fileID: 0} forceGammaRendering: 0 - textSettings: {fileID: 0} + textSettings: {fileID: 11400000, guid: 48201d4de9f704e928ef6cf18459a8c8, type: 2} diff --git a/Explorer/Assets/DCL/UIToolkit/DCLDefaultTheme.tss b/Explorer/Assets/DCL/UIToolkit/DCLDefaultTheme.tss index 0db4ba52f8e..f36539f5e0b 100644 --- a/Explorer/Assets/DCL/UIToolkit/DCLDefaultTheme.tss +++ b/Explorer/Assets/DCL/UIToolkit/DCLDefaultTheme.tss @@ -4,5 +4,14 @@ @import url("Styles/Sprites-Interaction.uss"); @import url("Styles/CommonStyles.uss"); +:root { + /* Advanced builds its native fallback chain from every OS font family the first time any + label lays out, whatever the text says, opening and parsing each file on the main thread — + the largest single cause of pre-in-world ANRs. Standard only consults OS fonts when a + glyph is missing from the font asset and the fallbacks below it, so that cost is no longer + paid at startup. Standard is also the only generator that renders sprite-asset emoji. */ + -unity-text-generator: standard; +} + diff --git a/Explorer/Assets/DCL/UIToolkit/DCLPanelSettings.asset b/Explorer/Assets/DCL/UIToolkit/DCLPanelSettings.asset index 50916588718..dde645e2975 100644 --- a/Explorer/Assets/DCL/UIToolkit/DCLPanelSettings.asset +++ b/Explorer/Assets/DCL/UIToolkit/DCLPanelSettings.asset @@ -49,4 +49,4 @@ MonoBehaviour: m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0} m_ICUDataAsset: {fileID: 0} forceGammaRendering: 0 - textSettings: {fileID: 0} + textSettings: {fileID: 11400000, guid: 48201d4de9f704e928ef6cf18459a8c8, type: 2} diff --git a/Explorer/Assets/DCL/UIToolkit/DCLScenePanelSettings.asset b/Explorer/Assets/DCL/UIToolkit/DCLScenePanelSettings.asset index 473cb537879..befa7f5f566 100644 --- a/Explorer/Assets/DCL/UIToolkit/DCLScenePanelSettings.asset +++ b/Explorer/Assets/DCL/UIToolkit/DCLScenePanelSettings.asset @@ -49,4 +49,4 @@ MonoBehaviour: m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0} m_ICUDataAsset: {fileID: 0} forceGammaRendering: 0 - textSettings: {fileID: 0} + textSettings: {fileID: 11400000, guid: 48201d4de9f704e928ef6cf18459a8c8, type: 2} diff --git a/Explorer/Assets/DCL/UIToolkit/DCLSceneTheme.tss b/Explorer/Assets/DCL/UIToolkit/DCLSceneTheme.tss index 7ce45b38bdb..57baa37060d 100644 --- a/Explorer/Assets/DCL/UIToolkit/DCLSceneTheme.tss +++ b/Explorer/Assets/DCL/UIToolkit/DCLSceneTheme.tss @@ -8,4 +8,12 @@ @import url("project://database/Assets/DCL/SDKComponents/SceneUI/ScenesUIStyleSheet.uss"); +:root { + /* Matches DCLDefaultTheme: Advanced enumerates every OS font on first layout regardless of + content. The fallback list is cached per TextSettings, which every panel now shares, so + leaving scene UI on Advanced would keep that cost and only move it to the first scene + that draws a label. */ + -unity-text-generator: standard; +} + diff --git a/Explorer/Assets/DCL/UIToolkit/DCLTextSettings.asset b/Explorer/Assets/DCL/UIToolkit/DCLTextSettings.asset index bc98ddaa29e..ff1851d300d 100644 --- a/Explorer/Assets/DCL/UIToolkit/DCLTextSettings.asset +++ b/Explorer/Assets/DCL/UIToolkit/DCLTextSettings.asset @@ -13,6 +13,7 @@ MonoBehaviour: m_Name: DCLTextSettings m_EditorClassIdentifier: UnityEngine.dll::UnityEngine.UIElements.PanelTextSettings m_Version: + m_ShowObsoleteProperties: 0 m_DefaultFontAsset: {fileID: 0} m_DefaultFontAssetPath: Fonts & Materials/ m_FallbackFontAssets: [] @@ -27,7 +28,6 @@ MonoBehaviour: m_FallbackSpriteAssets: [] m_MissingSpriteCharacterUnicode: 0 m_DefaultStyleSheet: {fileID: 0} - m_StyleSheetsResourcePath: Text Style Sheets/ m_DefaultColorGradientPresetsPath: Text Color Gradients/ m_UnicodeLineBreakingRules: m_UnicodeLineBreakingRules: {fileID: 0} diff --git a/Explorer/Assets/Launcher/LauncherPanel.asset b/Explorer/Assets/Launcher/LauncherPanel.asset index 8504ecd0e77..1b1132935af 100644 --- a/Explorer/Assets/Launcher/LauncherPanel.asset +++ b/Explorer/Assets/Launcher/LauncherPanel.asset @@ -43,4 +43,4 @@ MonoBehaviour: m_RuntimeWorldShader: {fileID: 9102, guid: 0000000000000000f000000000000000, type: 0} m_ICUDataAsset: {fileID: 0} forceGammaRendering: 0 - textSettings: {fileID: 0} + textSettings: {fileID: 11400000, guid: 48201d4de9f704e928ef6cf18459a8c8, type: 2} From 06de13e1d490fe47b90ad4908d68820d6b8c4ffa Mon Sep 17 00:00:00 2001 From: Pravus Date: Tue, 15 Sep 2026 02:15:43 +0200 Subject: [PATCH 02/14] fix: far-away scenes broken tick after teleport (#10089) --- .../Infrastructure/SceneRunner/SceneFacade.cs | 9 ++- .../SceneRunner/Tests/SceneFacadeShould.cs | 62 ++++++++++++++++++- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/Explorer/Assets/DCL/Infrastructure/SceneRunner/SceneFacade.cs b/Explorer/Assets/DCL/Infrastructure/SceneRunner/SceneFacade.cs index 9163f64eb33..22f7a81ff14 100644 --- a/Explorer/Assets/DCL/Infrastructure/SceneRunner/SceneFacade.cs +++ b/Explorer/Assets/DCL/Infrastructure/SceneRunner/SceneFacade.cs @@ -23,6 +23,9 @@ public class SceneFacade : ISceneFacade private const int UPDATE_HANG_INTERRUPT_THRESHOLD_MS = 10000; private const int START_HANG_INTERRUPT_THRESHOLD_MS = 30000; + // Sentinel interval for a frozen scene (0 FPS): the update loop idles until a positive interval is set + private const int FROZEN_INTERVAL_MS = -1; + // Cap dt passed to JS so a slow tick (e.g. host-parking on first iteration) can't feed an // absurd value into scene code that does dt-based stepping/integration, which would otherwise // spin synchronously inside V8 for hundreds of iterations and trip the hang watchdog. @@ -123,7 +126,9 @@ private void DisposeInternal() => public void SetTargetFPS(int fps) { - intervalMS = (int)(1000f / fps); + // Casting 1000f / 0 (+Infinity) to int is platform-dependent: int.MinValue on x86/x64 but int.MaxValue + // on IL2CPP ARM64, which would turn the freeze into a multi-day Task.Delay. Set the sentinel explicitly. + intervalMS = fps <= 0 ? FROZEN_INTERVAL_MS : (int)(1000f / fps); RuntimeMetrics.TargetFps = fps; } @@ -325,7 +330,7 @@ bool TryComplete() if (TryComplete()) return false; - // Support scene freeze (0 FPS, int.MinValue) + // Support scene freeze (0 FPS, FROZEN_INTERVAL_MS) while (intervalMS < 0) { if (TryComplete()) diff --git a/Explorer/Assets/DCL/Infrastructure/SceneRunner/Tests/SceneFacadeShould.cs b/Explorer/Assets/DCL/Infrastructure/SceneRunner/Tests/SceneFacadeShould.cs index cee850f469f..340c892485a 100644 --- a/Explorer/Assets/DCL/Infrastructure/SceneRunner/Tests/SceneFacadeShould.cs +++ b/Explorer/Assets/DCL/Infrastructure/SceneRunner/Tests/SceneFacadeShould.cs @@ -255,6 +255,62 @@ async UniTask CreateAndLaunch(int fps, int lifeTime, string id) } } + [Test] + public async Task FreezeUpdateLoopOnZeroTargetFps() + { + // Arrange + const int DURATION = 500; + + var sceneFacade = new SceneFacade(Substitute.For(), new TestDeps(ecsWorldFactory, new SceneStateProvider())); + sceneFacades.Add(sceneFacade); + ISceneRuntime runtime = sceneFacade.deps.Runtime; + + await UniTask.SwitchToThreadPool(); + + // Provide basic Thread Pool synchronization context + SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); + + var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.CancelAfter(DURATION); + + // Act + await sceneFacade.StartUpdateLoopAsync(0, cancellationTokenSource.Token); + + // Assert: the first tick runs, then the loop idles instead of sleeping for an overflowed interval + await runtime.Received(1).StartScene(); + await runtime.Received(1).UpdateScene(Arg.Any()); + } + + [Test] + public async Task ResumeUpdateLoopWhenTargetFpsIsRestored() + { + // Arrange + const int FROZEN_DURATION = 200; + const int DURATION = 800; + + var sceneFacade = new SceneFacade(Substitute.For(), new TestDeps(ecsWorldFactory, new SceneStateProvider())); + sceneFacades.Add(sceneFacade); + ISceneRuntime runtime = sceneFacade.deps.Runtime; + + await UniTask.SwitchToThreadPool(); + + // Provide basic Thread Pool synchronization context + SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); + + var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.CancelAfter(DURATION); + + // Act + UniTask updateLoop = sceneFacade.StartUpdateLoopAsync(0, cancellationTokenSource.Token); + await Task.Delay(FROZEN_DURATION); + sceneFacade.SetTargetFPS(60); + await updateLoop; + + // Assert: ticks resumed after the frozen period (the frozen period contributes exactly one tick) + int updateCalls = runtime.ReceivedCalls().Count(call => call.GetMethodInfo().Name == nameof(ISceneRuntime.UpdateScene)); + Assert.Greater(updateCalls, 1); + } + [Test] public async Task DisposeEverythingOnce() { @@ -365,7 +421,9 @@ public async Task DisposeInProperOrder() public class TestDeps : SceneInstanceDependencies.WithRuntimeAndJsAPIBase { - public TestDeps(IECSWorldFactory worldFactory) : base( + public TestDeps(IECSWorldFactory worldFactory) : this(worldFactory, CreateSceneStateProvider()) { } + + public TestDeps(IECSWorldFactory worldFactory, ISceneStateProvider sceneStateProvider) : base( Substitute.For(), Substitute.For(), Substitute.For(), @@ -379,7 +437,7 @@ public TestDeps(IECSWorldFactory worldFactory) : base( Substitute.For(), Substitute.For(), Substitute.For(), - CreateSceneStateProvider(), + sceneStateProvider, Substitute.For(), worldFactory.CreateWorld(new ECSWorldFactoryArgs()), Substitute.For(), From ee1307863711ae83b8efc7d157b044e48843f80f Mon Sep 17 00:00:00 2001 From: Mikhail Agapov <118179774+mikhail-dcl@users.noreply.github.com> Date: Tue, 15 Sep 2026 15:12:23 +0300 Subject: [PATCH 03/14] fix: keep Jarvis security review label current (#10106) * fix: keep Jarvis security review label current * chore: simplify security review classifier --- .github/prompts/review-instructions.md | 3 - .../workflows/dependency-security-review.yml | 95 ++++++++--------- docs/security-review.md | 60 +++++++---- .../ci/dependency-security-review.test.cjs | 100 +++++++++++++++--- 4 files changed, 172 insertions(+), 86 deletions(-) diff --git a/.github/prompts/review-instructions.md b/.github/prompts/review-instructions.md index 42aa77cd15d..b21fcb710d2 100644 --- a/.github/prompts/review-instructions.md +++ b/.github/prompts/review-instructions.md @@ -149,9 +149,6 @@ Emit these as warnings in the review body. They do NOT cause a FAIL on their own - **Main Scene Modified** — If `Explorer/Assets/Scenes/Main.unity` or its `.meta` appears in the changed files: > ⚠️ **Main scene modified** (`Explorer/Assets/Scenes/Main.unity`). This file is rarely changed intentionally — verify this wasn't pushed by mistake. ---- Security review integration --- -Follow deployed Jarvis `skills/security-review/SKILL.md` and its Unity reference for security checks, evidence-based remedies, advisory scope and snapshot/run-marker publication. Put its single `DEPENDENCY_REVIEW` line before the verdict block below; preserve the four code-review lines and attribution. - --- STEP 9 — Verdict --- Emit exactly these four lines at the end of the review body you post to GitHub, immediately before the attribution line (order matters — downstream automation parses them): REVIEW_RESULT: PASS ✅ (or FAIL ❌) diff --git a/.github/workflows/dependency-security-review.yml b/.github/workflows/dependency-security-review.yml index b7821dc0746..42d8fa3beda 100644 --- a/.github/workflows/dependency-security-review.yml +++ b/.github/workflows/dependency-security-review.yml @@ -18,54 +18,63 @@ jobs: runs-on: ubuntu-latest permissions: pull-requests: read - statuses: write issues: write steps: - - name: Detect changes and initialize status + - name: Classify changes and maintain label id: detect uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 with: script: | const { owner, repo } = context.repo; const pull_number = context.payload.pull_request.number; - const sha = context.payload.pull_request.head.sha; - const status = (state, description) => github.rest.repos.createCommitStatus({ - owner, repo, sha, state, context: 'Dependency Security Review', description + const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number }); + if (pr.state !== 'open' || pr.head.sha !== context.payload.pull_request.head.sha || + pr.base.sha !== context.payload.pull_request.base.sha) { + core.notice('Superseded event; leaving classification to the current run.'); + return; + } + const files = await github.paginate(github.rest.pulls.listFiles, { + owner, repo, pull_number, per_page: 100 }); - try { - const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number }); - if (pr.state !== 'open' || pr.head.sha !== sha || - pr.base.sha !== context.payload.pull_request.base.sha) { - core.notice('Superseded event; leaving the current commit status to its own run.'); - return; + // GitHub caps this endpoint at 3,000 files. Never treat truncation as no changes. + if (files.length !== pr.changed_files) throw new Error('Incomplete changed-file inventory'); + const classifiedHead = pr.head.sha; + const classifiedBase = pr.base.sha; + const classifiedFileCount = pr.changed_files; + const relevant = (path) => + /(^|\/)(Packages\/(manifest|packages-lock)\.json|package\.json|package-lock\.json|yarn\.lock|pnpm-lock\.yaml|Cargo\.(toml|lock)|packages\.config|requirements[^/]*\.txt|pyproject\.toml|poetry\.lock)$/.test(path) || + /^(Explorer|avatar-preview-renderer)\/Packages\/[^/]+\//.test(path) || + /(^|\/)(Assets\/Plugins|Editor|scripts|\.github|\.claude|\.agents|\.codex|unity-shared-dependencies)\//.test(path) || + /\.(dll|so(\.[0-9.]+)?|dylib|bundle|aar|jar|a|lib|exe|wasm|jslib|asmdef|asmref)(\.meta)?$/i.test(path) || + /\.bundle\//i.test(path) || + /(^|\/)(AGENTS\.md|CLAUDE\.md|SKILL\.md|CODEOWNERS|\.gitmodules|\.npmrc|Dockerfile[^/]*|Build[^/]*\.cs)$/.test(path); + const hasChanges = files.some(f => relevant(f.filename) || (f.previous_filename && relevant(f.previous_filename))); + const { data: current } = await github.rest.pulls.get({ owner, repo, pull_number }); + if (current.state !== 'open' || current.head.sha !== classifiedHead || + current.base.sha !== classifiedBase || current.changed_files !== classifiedFileCount) { + core.notice('PR changed during classification; leaving label maintenance to the current run.'); + return; + } + const hasLabel = current.labels.some(label => label.name === 'new-dependency'); + if (!hasChanges) { + if (hasLabel) { + try { + await github.rest.issues.removeLabel({ + owner, repo, issue_number: pull_number, name: 'new-dependency' + }); + } catch (error) { + if (error.status !== 404) throw error; + } } - await status('pending', 'Detecting security-relevant changes for Jarvis'); - const files = await github.paginate(github.rest.pulls.listFiles, { - owner, repo, pull_number, per_page: 100 + core.setOutput('request', 'false'); + return; + } + if (!hasLabel) { + await github.rest.issues.addLabels({ + owner, repo, issue_number: pull_number, labels: ['new-dependency'] }); - // GitHub caps this endpoint at 3,000 files. Never treat truncation as no changes. - if (files.length !== pr.changed_files) throw new Error('Incomplete changed-file inventory'); - const relevant = (path) => - /(^|\/)(Packages\/(manifest|packages-lock)\.json|package\.json|package-lock\.json|yarn\.lock|pnpm-lock\.yaml|Cargo\.(toml|lock)|packages\.config|requirements[^/]*\.txt|pyproject\.toml|poetry\.lock)$/.test(path) || - /(^|\/)(Assets\/Plugins|Editor|scripts|\.github|\.claude|\.agents|\.codex|unity-shared-dependencies)\//.test(path) || - /\.(dll|so(\.[0-9.]+)?|dylib|bundle|aar|jar|a|lib|exe|wasm|jslib|asmdef|asmref)(\.meta)?$/i.test(path) || - /\.bundle\//i.test(path) || - /(^|\/)(AGENTS\.md|CLAUDE\.md|SKILL\.md|CODEOWNERS|\.gitmodules|\.npmrc|Dockerfile[^/]*|Build[^/]*\.cs)$/.test(path); - const hasChanges = files.some(f => relevant(f.filename) || (f.previous_filename && relevant(f.previous_filename))); - if (!hasChanges) { - await status('success', 'No dependency, automation or Unity plugin changes'); - return; - } - await github.rest.issues.addLabels({ owner, repo, issue_number: pull_number, labels: ['new-dependency'] }) - .catch(e => core.warning(`Could not add informational label: ${e.message}`)); - await status('pending', pr.draft - ? 'Security review required when this draft is ready' - : 'Awaiting Jarvis security review; request decentraland-bot'); - core.setOutput('request', (!pr.draft).toString()); - } catch (error) { - await status('failure', 'Security change detection failed; inspect workflow logs'); - throw error; } + core.setOutput('request', (!current.draft).toString()); - name: Request Jarvis through the existing reviewer webhook if: steps.detect.outputs.request == 'true' @@ -79,7 +88,8 @@ jobs: const pull_number = context.payload.pull_request.number; const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number }); if (pr.state !== 'open' || pr.draft || pr.head.sha !== context.payload.pull_request.head.sha || - pr.base.sha !== context.payload.pull_request.base.sha) return; + pr.base.sha !== context.payload.pull_request.base.sha || + !pr.labels.some(label => label.name === 'new-dependency')) return; // External authors cannot auto-start a credential-bearing agent. // A collaborator requests decentraland-bot manually after inspecting the PR. let allowed = false; @@ -99,14 +109,3 @@ jobs: // follow-up code reviews are on demand. Existing pending requests share // that review; a stale run remains non-green and needs a re-request. await github.rest.pulls.requestReviewers({ owner, repo, pull_number, reviewers: ['decentraland-bot'] }); - - - name: Report request failure - if: failure() && steps.detect.outputs.request == 'true' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - await github.rest.repos.createCommitStatus({ - ...context.repo, sha: context.payload.pull_request.head.sha, state: 'failure', - context: 'Dependency Security Review', - description: 'Jarvis request failed; request decentraland-bot manually' - }); diff --git a/docs/security-review.md b/docs/security-review.md index 64ea43aba7c..0a8221589c1 100644 --- a/docs/security-review.md +++ b/docs/security-review.md @@ -1,32 +1,52 @@ -# Jarvis security review pilot +# Jarvis security-review pilot -Keep `Dependency Security Review` advisory: it is optional and does not itself change code verdicts, approvals, QA waivers or merge requirements. Concrete findings follow ordinary review criteria. Enforcement requires a later explicit decision. +`Dependency Security Review` is an advisory status for security-relevant Unity Explorer changes. It does not change approvals, QA waivers, branch protection, or merge requirements. Ordinary reviews continue to check code and general security without the detailed Unity pass. -For review policy, use [Jarvis's shared security-review skill](https://github.com/decentraland/agent-server/blob/main/skills/security-review/SKILL.md). For placement rationale and remaining risks, read [the migration assessment](https://github.com/decentraland/agent-server/blob/main/docs/security-review-migration.md). +The detailed policy lives in [Agent Server's Unity security-review skill](https://github.com/decentraland/agent-server/blob/main/skills/security-review/SKILL.md). Its placement and host safeguards are documented in the [migration assessment](https://github.com/decentraland/agent-server/blob/main/docs/security-review-migration.md). ## Review flow -The [workflow](../.github/workflows/dependency-security-review.yml) inventories changes using trusted default-branch code, without checkout or model execution. It labels relevant PRs `new-dependency` and requests `decentraland-bot` for ready PRs by repository writers. External authors need a maintainer request; drafts wait until ready. Security-relevant pushes request review even when ordinary follow-ups are on demand. +The [trusted workflow](../.github/workflows/dependency-security-review.yml) reads PR metadata and the complete changed-file inventory. It never checks out or executes PR code. -Jarvis incorporates security into its full review. Its host validates bot identity, inspected commit, run marker and verdict before writing the status. PASS becomes success, NEEDS_ATTENTION stays pending, and BLOCK or invalid/failed review becomes failure. A complete irrelevant inventory gets no-changes success. Slack/CLI and review-both reviews without the host marker cannot complete this status. +1. The workflow classifies the current base/head change. +2. It adds `new-dependency` when detailed review applies, or removes a stale label when it does not. +3. For a ready PR by a repository writer, it requests `decentraland-bot` after the label update finishes. Drafts wait until ready. External authors require a maintainer to request the bot. +4. Agent Server reads repository and label state from the signed review-request webhook. Only Unity Explorer with `new-dependency` starts the detailed path. +5. Jarvis performs one normal review and extends it with the applicable Unity dependency/plugin or automation checks. It posts one COMMENT review. +6. Agent Server verifies the bot, head commit, run marker, and verdict, then updates `Dependency Security Review` on that commit. -## Coordinated rollout +An irrelevant PR has no detailed status. A label or classification failure does not request Jarvis. Agent Server alone writes the security status; the workflow does not infer a result from comments. -1. **Drain:** pause requests, disable the legacy workflow and drain/cancel its runs plus Jarvis's review queue. Continue only when old runs cannot race to publish the same status. -2. **Deploy Jarvis:** deploy runtime and skills together. Verify bot read/review/status-write access and requester write-access enforcement. `ORG_ACCESS_TOKEN` must request reviewers through an actor Jarvis authorizes for this repository. -3. **Switch Unity:** merge the consumer changes into default branch `dev`, then re-enable the workflow and resume requests. `pull_request_target` uses trusted default-branch code; the proposed PR YAML cannot bootstrap itself. The existing review-request webhook subscription suffices. -4. **Exercise the pilot:** re-request the bot on open relevant PRs. Check renderer-only and shared-package changes, importer/asmdef and CI/prompt changes, plus unrelated documentation. Confirm one review with matching `commit_id`, run marker and verdict, and the corresponding advisory status. Missing/stale verdicts must not pass. +## What triggers the detailed pass -Local workflow check: `node --test scripts/ci/dependency-security-review.test.cjs`. +- UPM manifests, locks, embedded/local packages, and shared package contents in `Explorer/`, `avatar-preview-renderer/`, or `unity-shared-dependencies/` +- managed/native plugin payloads, importer metadata, assemblies, and editor/build/install hooks +- workflows, local actions, build scripts, review prompts, skills, and other privileged automation +- renamed, removed, or patchless files whose old or new path matches this scope -## Recovery +Mixed changes run both specialized branches. The detailed pass reuses the normal review's diff, inventory, context, and security findings instead of collecting them again. -| Result | Action | -| --- | --- | -| Draft or external-author pending | Mark ready as appropriate; a maintainer requests the bot | -| NEEDS_ATTENTION | Supply missing evidence or resolve the concern, then re-request | -| Stale/missing verdict | Wait for the run to finish, then use the Reviewers-panel re-request arrow | -| Request/API/agent failure | Check Actions/Jarvis logs and permissions, resolve the failure, then re-request | -| Truncated inventory | Request a Jarvis review using an immutable git diff and explicit coverage reporting | +## Results -For rollback, disable routing and drain runs before reverting both consumer and runtime changes. Re-enable the legacy path only when it is the sole review-result writer. Restoring the old prompt alone does not restore execution; rollback also restores its documented gaps, so keep the status advisory. +| Result | Status | Next action | +| --- | --- | --- | +| PASS | Success for repository writers; pending for external authors | Review the COMMENT findings; obtain human confirmation for external authors | +| NEEDS_ATTENTION | Pending | Supply evidence or resolve the concern, then re-request | +| BLOCK | Failure | Resolve the high-risk finding, then re-request | +| Missing, invalid, stale, or failed review | Failure on the captured commit | Check workflow/Jarvis logs, then re-request on the current head | + +Concrete findings use the normal code-review severity rules. The status is a pilot signal, not an approval. + +## Rollout and recovery + +Deploy this workflow change with or before Agent Server's label routing. Reclassify open PRs so stale `new-dependency` labels are removed, and drain legacy model runs before relying on Jarvis as the sole status writer. + +After deployment, exercise a renderer-only change, shared-package change, binary/importer or assembly change, automation/prompt change, and unrelated documentation change. Confirm the label matches the current head and that relevant PRs produce one COMMENT review with the matching `commit_id`, run marker, verdict, and advisory status. + +Re-request Jarvis after a push, retarget, stale snapshot, invalid verdict, or failed run. If the workflow cannot classify the inventory or maintain the label, fix that failure before requesting manually; otherwise the webhook will intentionally run only the ordinary review. + +Run the local workflow checks with: + +```text +node --test scripts/ci/dependency-security-review.test.cjs +``` diff --git a/scripts/ci/dependency-security-review.test.cjs b/scripts/ci/dependency-security-review.test.cjs index 2bf7223be9e..b76ba3ed585 100644 --- a/scripts/ci/dependency-security-review.test.cjs +++ b/scripts/ci/dependency-security-review.test.cjs @@ -4,26 +4,34 @@ const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor; -const workflow = fs.readFileSync(path.join(__dirname, '../../.github/workflows/dependency-security-review.yml'), 'utf8'); +const workflow = fs.readFileSync(path.join(__dirname, '../../.github/workflows/dependency-security-review.yml'), 'utf8').replace(/\r\n/g, '\n'); +const reviewPrompt = fs.readFileSync(path.join(__dirname, '../../.github/prompts/review-instructions.md'), 'utf8'); function script(name) { const step = workflow.split('\n - name: ').find(x => x.startsWith(name + '\n')); const body = step.split(' script: |\n')[1].split('\n').filter(x => x.startsWith(' ')).map(x => x.slice(12)).join('\n'); return new AsyncFunction('github', 'context', 'core', body); } -const detect = script('Detect changes and initialize status'); +const detect = script('Classify changes and maintain label'); const request = script('Request Jarvis through the existing reviewer webhook'); function fixture(files = []) { - const pr = { number: 42, state: 'open', draft: false, head: { sha: 'a'.repeat(40) }, base: { sha: 'b'.repeat(40) }, changed_files: files.length, user: { login: 'author' } }; - const statuses = [], requests = [], outputs = {}; + const pr = { number: 42, state: 'open', draft: false, head: { sha: 'a'.repeat(40) }, base: { sha: 'b'.repeat(40) }, changed_files: files.length, user: { login: 'author' }, labels: [] }; + const requests = [], outputs = {}, operations = []; const github = { paginate: async () => files, rest: { - pulls: { get: async () => ({ data: pr }), listFiles: () => {}, requestReviewers: async args => requests.push(args) }, - repos: { createCommitStatus: async args => statuses.push(args), getCollaboratorPermissionLevel: async () => ({ data: { permission: 'write' } }) }, - issues: { addLabels: async () => {} } + pulls: { + get: async () => ({ data: structuredClone(pr) }), + listFiles: () => {}, + requestReviewers: async args => { operations.push('request'); requests.push(args); } + }, + repos: { getCollaboratorPermissionLevel: async () => ({ data: { permission: 'write' } }) }, + issues: { + addLabels: async () => { operations.push('add'); pr.labels.push({ name: 'new-dependency' }); }, + removeLabel: async () => { operations.push('remove'); pr.labels = pr.labels.filter(label => label.name !== 'new-dependency'); } + } } }; - return { pr, statuses, requests, outputs, github, + return { pr, requests, outputs, operations, github, context: { repo: { owner: 'decentraland', repo: 'unity-explorer' }, payload: { pull_request: structuredClone(pr) } }, core: { notice() {}, warning() {}, setOutput: (key, value) => { outputs[key] = value } } }; @@ -31,6 +39,8 @@ function fixture(files = []) { for (const filename of [ 'Explorer/Packages/manifest.json', 'Explorer/Packages/packages-lock.json', 'avatar-preview-renderer/Packages/manifest.json', 'avatar-preview-renderer/Packages/packages-lock.json', + 'Explorer/Packages/com.decentraland.embedded/Runtime/Test.cs', + 'avatar-preview-renderer/Packages/com.decentraland.embedded/Editor/Test.cs', 'unity-shared-dependencies/package.json', 'unity-shared-dependencies/Runtime/test.cs', 'avatar-preview-renderer/Assets/Plugins/Test.cs', 'Explorer/Assets/Somewhere/test.dll.meta', 'Explorer/Assets/Somewhere/libtest.so.1', 'Explorer/Assets/Somewhere/a.bundle/Contents/Info.plist', @@ -43,7 +53,7 @@ for (const filename of [ const f = fixture([{ filename }]); await detect(f.github, f.context, f.core); assert.equal(f.outputs.request, 'true'); - assert.equal(f.statuses.at(-1).state, 'pending'); + assert.deepEqual(f.operations, ['add']); }); } test('covers renamed and removed files', async () => { @@ -53,11 +63,26 @@ test('covers renamed and removed files', async () => { assert.equal(f.outputs.request, 'true'); } }); -test('reports success only for a complete irrelevant inventory', async () => { +test('leaves an irrelevant inventory unlabeled', async () => { const f = fixture([{ filename: 'docs/example.md' }]); await detect(f.github, f.context, f.core); - assert.equal(f.statuses.at(-1).state, 'success'); - assert.equal(f.outputs.request, undefined); + assert.equal(f.outputs.request, 'false'); + assert.deepEqual(f.operations, []); +}); +test('removes a stale label when the current inventory is irrelevant', async () => { + const f = fixture([{ filename: 'docs/example.md' }]); + f.pr.labels.push({ name: 'new-dependency' }); + await detect(f.github, f.context, f.core); + assert.equal(f.outputs.request, 'false'); + assert.deepEqual(f.operations, ['remove']); + assert.deepEqual(f.pr.labels, []); +}); +test('treats a missing stale label as already removed', async () => { + const f = fixture([{ filename: 'docs/example.md' }]); + f.pr.labels.push({ name: 'new-dependency' }); + f.github.rest.issues.removeLabel = async () => { const error = new Error('missing'); error.status = 404; throw error; }; + await detect(f.github, f.context, f.core); + assert.equal(f.outputs.request, 'false'); }); test('fails closed when file inventory is truncated or unavailable', async () => { for (const unavailable of [false, true]) { @@ -65,7 +90,8 @@ test('fails closed when file inventory is truncated or unavailable', async () => if (unavailable) f.github.paginate = async () => { throw new Error('API down'); }; else f.pr.changed_files = 3001; await assert.rejects(detect(f.github, f.context, f.core)); - assert.equal(f.statuses.at(-1).state, 'failure'); + assert.equal(f.outputs.request, undefined); + assert.deepEqual(f.operations, []); } }); test('leaves drafts pending without requesting the agent', async () => { @@ -73,24 +99,62 @@ test('leaves drafts pending without requesting the agent', async () => { f.pr.draft = true; await detect(f.github, f.context, f.core); assert.equal(f.outputs.request, 'false'); - assert.equal(f.statuses.at(-1).state, 'pending'); + assert.deepEqual(f.operations, ['add']); }); test('ignores stale events', async () => { const f = fixture([{ filename: 'Explorer/Packages/manifest.json' }]); f.pr.head.sha = 'c'.repeat(40); await detect(f.github, f.context, f.core); await request(f.github, f.context, f.core); - assert.deepEqual(f.statuses, []); + assert.deepEqual(f.operations, []); + assert.deepEqual(f.requests, []); +}); +test('does not mutate a label when the head changes during classification', async () => { + const files = [{ filename: 'Explorer/Packages/manifest.json' }]; + const f = fixture(files); + f.github.paginate = async () => { f.pr.head.sha = 'c'.repeat(40); return files; }; + await detect(f.github, f.context, f.core); + assert.equal(f.outputs.request, undefined); + assert.deepEqual(f.operations, []); +}); +test('updates the label before requesting Jarvis', async () => { + const f = fixture([{ filename: 'Explorer/Packages/manifest.json' }]); + await detect(f.github, f.context, f.core); + await request(f.github, f.context, f.core); + assert.deepEqual(f.operations, ['add', 'request']); +}); +test('does not repeat an existing relevant label', async () => { + const f = fixture([{ filename: 'Explorer/Packages/manifest.json' }]); + f.pr.labels.push({ name: 'new-dependency' }); + await detect(f.github, f.context, f.core); + assert.equal(f.outputs.request, 'true'); + assert.deepEqual(f.operations, []); +}); +test('does not request Jarvis when the classifier label is removed after detection', async () => { + const f = fixture([{ filename: 'Explorer/Packages/manifest.json' }]); + await detect(f.github, f.context, f.core); + f.pr.labels = []; + await request(f.github, f.context, f.core); + assert.deepEqual(f.operations, ['add']); + assert.deepEqual(f.requests, []); +}); +test('does not request Jarvis when label maintenance fails', async () => { + const f = fixture([{ filename: 'Explorer/Packages/manifest.json' }]); + f.github.rest.issues.addLabels = async () => { throw new Error('labels unavailable'); }; + await assert.rejects(detect(f.github, f.context, f.core)); + assert.equal(f.outputs.request, undefined); assert.deepEqual(f.requests, []); }); test('requests a collaborator PR through the bot reviewer', async () => { const f = fixture(); + f.pr.labels.push({ name: 'new-dependency' }); await request(f.github, f.context, f.core); assert.deepEqual(f.requests, [{ owner: 'decentraland', repo: 'unity-explorer', pull_number: 42, reviewers: ['decentraland-bot'] }]); }); test('requires a maintainer request for external authors or failed authorization', async () => { for (const unavailable of [false, true]) { const f = fixture(); + f.pr.labels.push({ name: 'new-dependency' }); f.github.rest.repos.getCollaboratorPermissionLevel = async () => { if (unavailable) throw new Error('API down'); return { data: { permission: 'read' } }; @@ -99,3 +163,9 @@ test('requires a maintainer request for external authors or failed authorization assert.deepEqual(f.requests, []); } }); +test('leaves security status publication to Agent Server', () => { + assert.doesNotMatch(workflow, /createCommitStatus|statuses:\s*write/); +}); +test('leaves detailed skill activation to the Agent Server snapshot', () => { + assert.doesNotMatch(reviewPrompt, /security-review\/SKILL\.md|DEPENDENCY_REVIEW/); +}); From 86512e402b58c7d877f66243b5ffb042fc84fa2f Mon Sep 17 00:00:00 2001 From: lorenzo-ranciaffi <41125365+lorenzo-ranciaffi@users.noreply.github.com> Date: Tue, 15 Sep 2026 16:37:04 +0200 Subject: [PATCH 04/14] fix: crash when a deleted entity still lists destroyed children (#10067) --- .../Systems/ParentingTransformSystem.cs | 81 +++++++---- .../Tests/ParentingTransformSystemShould.cs | 135 +++++++++++++++++- 2 files changed, 183 insertions(+), 33 deletions(-) diff --git a/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Systems/ParentingTransformSystem.cs b/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Systems/ParentingTransformSystem.cs index 33fce9f7fb9..a8cf67178e1 100644 --- a/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Systems/ParentingTransformSystem.cs +++ b/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Systems/ParentingTransformSystem.cs @@ -11,6 +11,7 @@ using ECS.LifeCycle.Components; using ECS.Unity.Transforms.Components; using System.Collections.Generic; +using System.Diagnostics; using UnityEngine; namespace ECS.Unity.Transforms.Systems @@ -37,29 +38,32 @@ protected override void Update(float t) } [Query] - [All(typeof(SDKTransform), typeof(DeleteEntityIntention))] + [All(typeof(DeleteEntityIntention))] private void DereferenceParentingOfDeletedEntity(in Entity entity, ref TransformComponent transformComponentToBeDeleted) { - Entity parent = transformComponentToBeDeleted.Parent; - - if (!World.IsAlive(parent)) return; - - var parentTransform = World!.TryGetRef(parent, out bool exists); - - if (exists && parentTransform.Children.Remove(entity) == false) - ReportHub.LogError( - GetReportData(), - $"Entity {entity} is not a child of its parent {parent}" - ); + RemoveFromParent(in transformComponentToBeDeleted, entity); } [Query] - [All(typeof(SDKTransform), typeof(DeleteEntityIntention))] - private void OrphanChildrenOfDeletedEntity(ref TransformComponent transformComponentToBeDeleted) + [All(typeof(DeleteEntityIntention))] + private void OrphanChildrenOfDeletedEntity(in Entity entity, in CRDTEntity crdtEntity, ref TransformComponent transformComponentToBeDeleted) { foreach (Entity childEntity in transformComponentToBeDeleted.Children) { - ref TransformComponent transformComponent = ref World!.Get(childEntity); + // Arch ignores the entity version, so a stale id can resolve to a dead slot or to an unrelated recycled entity + if (!World.IsAlive(childEntity)) + { + ReportStaleChild(entity, crdtEntity, childEntity, false, false, Entity.Null); + continue; + } + + ref TransformComponent transformComponent = ref World.TryGetRef(childEntity, out bool hasTransform); + + if (!hasTransform || transformComponent.Parent != entity) + { + ReportStaleChild(entity, crdtEntity, childEntity, true, hasTransform, hasTransform ? transformComponent.Parent : Entity.Null); + continue; + } SetNewChild( ref transformComponent, @@ -81,17 +85,13 @@ private void DoParenting(in Entity entity, CRDTEntity crdtEntity, ref SDKTransfo { if (!sdkTransform.IsDirty) return; - Entity parentReference = sceneRoot; + // A parent the scene never materialized in this world falls back to the scene root + if (!entitiesMap.TryGetValue(sdkTransform.ParentId, out Entity parentReference)) + parentReference = sceneRoot; - if (entitiesMap.TryGetValue(sdkTransform.ParentId, out Entity newParentEntity)) - { - parentReference = newParentEntity; - - //We have to remove the child from the old parent - if (transformComponent.Parent != parentReference) - RemoveFromParent(transformComponent, entity); - } + if (transformComponent.Parent == parentReference) return; + RemoveFromParent(in transformComponent, entity); SetNewChild(ref transformComponent, entity, crdtEntity, parentReference, sdkTransform.ParentId); } @@ -103,7 +103,8 @@ private void SetNewChild(ref TransformComponent childComponent, Entity childEnti if (!World.IsAlive(parentEntity)) { - ReportHub.LogError(GetReportData(), $"Trying to parent entity {childEntityReference} ({childCRDTEntity}) to a dead entity parent"); + ReportHub.LogError(GetReportData(), $"Trying to parent entity {childEntityReference} ({childCRDTEntity}) to a dead entity parent, falling back to the scene root"); + AssignToSceneRoot(ref childComponent, childEntityReference); return; } @@ -111,17 +112,39 @@ private void SetNewChild(ref TransformComponent childComponent, Entity childEnti if (!success) { - ReportHub.LogError(GetReportData(), $"Trying to parent entity {childEntityReference} ({childCRDTEntity}) to parent {parentEntity} ({parentId}) that doesn't have a TransformComponent"); + ReportHub.LogError(GetReportData(), $"Trying to parent entity {childEntityReference} ({childCRDTEntity}) to parent {parentEntity} ({parentId}) that doesn't have a TransformComponent, falling back to the scene root"); + AssignToSceneRoot(ref childComponent, childEntityReference); return; } childComponent.AssignParent(childEntityReference, parentEntity, in parentComponent); } - private void RemoveFromParent(TransformComponent childComponent, Entity childEntityReference) + // Keeps Parent and the parent's Children consistent when the requested parent cannot be used + private void AssignToSceneRoot(ref TransformComponent childComponent, Entity childEntityReference) + { + if (childComponent.Parent == sceneRoot) + return; + + childComponent.AssignParent(childEntityReference, sceneRoot, in World.Get(sceneRoot)); + } + + private void RemoveFromParent(in TransformComponent childComponent, Entity childEntityReference) + { + if (!World.IsAlive(childComponent.Parent)) return; + + ref TransformComponent parentComponent = ref World.TryGetRef(childComponent.Parent, out bool exists); + + if (exists && !parentComponent.Children.Remove(childEntityReference)) + ReportHub.LogError(GetReportData(), $"Entity {childEntityReference} is not a child of its parent {childComponent.Parent}"); + } + + [Conditional("UNITY_EDITOR")] + [Conditional("DEVELOPMENT_BUILD")] + private void ReportStaleChild(Entity deletedEntity, CRDTEntity deletedCrdtEntity, Entity childEntity, bool childIsAlive, bool childHasTransform, Entity childParent) { - if (World.IsAlive(childComponent.Parent)) - World.Get(childComponent.Parent).Children.Remove(childEntityReference); + ReportHub.LogWarning(GetReportData(), + $"Deleted entity {deletedEntity} ({deletedCrdtEntity}) lists {childEntity} as a child but it is not one anymore: alive={childIsAlive}, hasTransform={childHasTransform}, parent={childParent}"); } } } diff --git a/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Tests/ParentingTransformSystemShould.cs b/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Tests/ParentingTransformSystemShould.cs index 31cf1b5c079..6ae3a27ca52 100644 --- a/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Tests/ParentingTransformSystemShould.cs +++ b/Explorer/Assets/DCL/Infrastructure/ECS/Unity/Transforms/Tests/ParentingTransformSystemShould.cs @@ -1,14 +1,15 @@ using Arch.Core; using CRDT; using CrdtEcsBridge.Components.Transform; -using DCL.Diagnostics; using ECS.LifeCycle.Components; using ECS.TestSuite; using ECS.Unity.Transforms.Components; using ECS.Unity.Transforms.Systems; using NUnit.Framework; using System.Collections.Generic; +using System.Text.RegularExpressions; using UnityEngine; +using UnityEngine.TestTools; namespace ECS.Unity.Transforms.Tests { @@ -52,8 +53,8 @@ public void SetUp() system = new ParentingTransformSystem(world, crdtToEntityDict, rootEntity); } - private SDKTransform parentSDKTransform; - private SDKTransform childSDKTransform; + private SDKTransform parentSDKTransform = null!; + private SDKTransform childSDKTransform = null!; private TransformComponent parentTransformComponent; private TransformComponent childTransformComponent; @@ -67,7 +68,7 @@ public void SetUp() private Entity parentEntity; private Entity childEntity; - private Dictionary crdtToEntityDict; + private Dictionary crdtToEntityDict = null!; [Test] public void ParentTransform() @@ -123,5 +124,131 @@ public void ParentChildToSceneRootIfParentIsDeleted() Assert.AreEqual(0, parentTransformComponent.Children.Count); Assert.IsTrue(childTransformComponent.Transform.IsChildOf(sceneRoot.Transform)); } + + [Test] + public void NotThrowWhenDeletedParentListsDestroyedChild() + { + // Arrange + system.Update(0f); + + // Destroyed without being dereferenced, so the parent still lists it + world.Destroy(childEntity); + world.Add(parentEntity, new DeleteEntityIntention()); + crdtToEntityDict.Remove(parentCRDTEntity); + + // Act & Assert + Assert.DoesNotThrow(() => system.Update(0f)); + Assert.AreEqual(0, parentTransformComponent.Children.Count); + } + + [Test] + public void NotTouchStrangerReusingDestroyedChildId() + { + // Arrange + system.Update(0f); + world.Destroy(childEntity); + + // Arch recycles the id with a bumped version, so the stale entry now resolves to an unrelated entity + Entity stranger = world.Create(new CRDTEntity(600)); + Assume.That(stranger.Id, Is.EqualTo(childEntity.Id)); + Assume.That(stranger.Version, Is.Not.EqualTo(childEntity.Version)); + + world.Add(parentEntity, new DeleteEntityIntention()); + crdtToEntityDict.Remove(parentCRDTEntity); + + // Act & Assert + Assert.DoesNotThrow(() => system.Update(0f)); + Assert.IsFalse(world.Has(stranger)); + Assert.AreEqual(0, parentTransformComponent.Children.Count); + } + + [Test] + public void NotReparentStrangerWithTransformReusingDestroyedChildId() + { + // Arrange + system.Update(0f); + world.Destroy(childEntity); + + var strangerTransform = new TransformComponent(new GameObject("STRANGER").transform); + Entity stranger = world.Create(new CRDTEntity(600), strangerTransform); + Assume.That(stranger.Id, Is.EqualTo(childEntity.Id)); + + world.Add(parentEntity, new DeleteEntityIntention()); + crdtToEntityDict.Remove(parentCRDTEntity); + + // Act + Assert.DoesNotThrow(() => system.Update(0f)); + + // Assert + Assert.AreEqual(Entity.Null, world.Get(stranger).Parent); + Assert.IsNull(strangerTransform.Transform.parent); + Assert.IsFalse(sceneRoot.Children.Contains(stranger)); + } + + [Test] + public void RemoveFromOldParentWhenReparentedToUnknownParent() + { + // Arrange + system.Update(0f); + + world.Set(childEntity, new SDKTransform + { + IsDirty = true, + ParentId = new CRDTEntity(999), + }); + + // Act + system.Update(0f); + + // Assert + Assert.AreEqual(0, parentTransformComponent.Children.Count); + Assert.IsTrue(sceneRoot.Children.Contains(childEntity)); + Assert.AreEqual(rootEntity, world.Get(childEntity).Parent); + Assert.AreEqual(sceneRoot.Transform, childTransformComponent.Transform.parent); + } + + [Test] + public void FallBackToSceneRootWhenParentHasNoTransform() + { + // Arrange + system.Update(0f); + + var noTransformCrdtEntity = new CRDTEntity(700); + crdtToEntityDict[noTransformCrdtEntity] = world.Create(noTransformCrdtEntity); + + world.Set(childEntity, new SDKTransform + { + IsDirty = true, + ParentId = noTransformCrdtEntity, + }); + + LogAssert.Expect(LogType.Error, new Regex("doesn't have a TransformComponent, falling back to the scene root")); + + // Act + system.Update(0f); + + // Assert + Assert.AreEqual(0, parentTransformComponent.Children.Count); + Assert.IsTrue(sceneRoot.Children.Contains(childEntity)); + Assert.AreEqual(rootEntity, world.Get(childEntity).Parent); + } + + [Test] + public void DereferenceDeletedChildWithoutSdkTransform() + { + // Arrange + system.Update(0f); + + var noSdkTransform = new TransformComponent(new GameObject("NO_SDK_TRANSFORM").transform); + Entity noSdkEntity = world.Create(new CRDTEntity(514)); + noSdkTransform.AssignParent(noSdkEntity, parentEntity, in world.Get(parentEntity)); + world.Add(noSdkEntity, noSdkTransform, new DeleteEntityIntention()); + + // Act + system.Update(0f); + + // Assert + Assert.IsFalse(parentTransformComponent.Children.Contains(noSdkEntity)); + } } } From d83bd21a4b2dc65a61ff69ad5a35e770281291f8 Mon Sep 17 00:00:00 2001 From: Nicolas Lorusso <56365551+lorux0@users.noreply.github.com> Date: Tue, 15 Sep 2026 11:46:53 -0300 Subject: [PATCH 05/14] feat: guest login (#9888) --- .../AssetGroups/Essentials.asset | 5 + .../Prefabs/Authentication.MainScreen.prefab | 496 +- .../Prefabs/GuestOrSignup.Screen.prefab | 2732 +++++ .../Prefabs/GuestOrSignup.Screen.prefab.meta | 7 + .../Prefabs/Lobby.NewAccount.Screen.prefab | 181 +- .../SelectAvatar.NewAccount.Screen.prefab | 5313 +++++++++ ...SelectAvatar.NewAccount.Screen.prefab.meta | 7 + .../Assets/Textures/FemaleSlot1.png | 3 + .../Assets/Textures/FemaleSlot1.png.meta | 117 + .../Assets/Textures/FemaleSlot2.png | 3 + .../Assets/Textures/FemaleSlot2.png.meta | 117 + .../Assets/Textures/FemaleSlot3.png | 3 + .../Assets/Textures/FemaleSlot3.png.meta | 117 + .../Assets/Textures/FemaleSlot4.png | 3 + .../Assets/Textures/FemaleSlot4.png.meta | 117 + .../Assets/Textures/MaleSlot1.png | 3 + .../Assets/Textures/MaleSlot1.png.meta | 117 + .../Assets/Textures/MaleSlot2.png | 3 + .../Assets/Textures/MaleSlot2.png.meta | 117 + .../Assets/Textures/MaleSlot3.png | 3 + .../Assets/Textures/MaleSlot3.png.meta | 117 + .../Assets/Textures/MaleSlot4.png | 3 + .../Assets/Textures/MaleSlot4.png.meta | 117 + .../AuthenticationScreenController.cs | 56 +- .../AvatarPresetProvider.cs | 197 + .../AvatarPresetProvider.cs.meta | 2 + .../AvatarRandomizer.cs | 140 - .../AvatarRandomizer.cs.meta | 11 - .../States/GuestOrSignUpAuthState.cs | 152 + .../States/GuestOrSignUpAuthState.cs.meta | 3 + .../LobbyForExistingAccountAuthState.cs | 8 +- .../States/LobbyForNewAccountAuthState.cs | 127 +- .../States/LoginSelectionAuthState.cs | 8 +- .../States/ProfileFetchingAuthState.cs | 52 +- .../SelectAvatarForNewAccountAuthState.cs | 173 + ...SelectAvatarForNewAccountAuthState.cs.meta | 3 + .../AuthenticationScreenControllerShould.cs | 1 - .../Tests/AvatarRandomizerShould.cs | 208 - .../Tests/AvatarRandomizerShould.cs.meta | 11 - .../Views/AuthenticationScreenView.cs | 5 + .../Views/GuestOrSignUpAuthView.cs | 33 + .../Views/GuestOrSignUpAuthView.cs.meta | 3 + .../Views/LobbyForNewAccountAuthView.cs | 68 +- .../SelectAvatarForNewAccountAuthView.cs | 106 + .../SelectAvatarForNewAccountAuthView.cs.meta | 3 + .../Commands/GiftTransferRequestCommand.cs | 2 +- Explorer/Assets/DCL/Chat/ChatOpener.cs | 16 +- .../ChatFriends/ChatMemberFeedPresenter.cs | 22 +- .../DCL/Chat/_Refactor/ChatPanelPresenter.cs | 17 +- .../ChatTitleBar/ChatTitlebarPresenter.cs | 10 +- .../CommunitiesBrowserController.cs | 25 +- .../CommunityCardController.cs | 13 + .../CommunityCreationEditionController.cs | 17 +- .../Donations/UI/DonationsPanelController.cs | 2 +- .../DCL/FeatureFlags/FeatureFlagsStrings.cs | 1 + .../DCL/FeatureFlags/FeaturesRegistry.cs | 2 + .../ScreenshotMetadataBuilder.cs | 2 +- .../Global/AppArgs/AppArgsFlags.cs | 4 + .../Global/Dynamic/BootstrapContainer.cs | 16 +- .../Global/Dynamic/ChatContainer.cs | 2 +- .../Global/Dynamic/CommsContainer.cs | 4 +- .../Global/Dynamic/DynamicWorldContainer.cs | 4 +- .../Global/Dynamic/UIShellContainer.cs | 6 +- .../MVCFacade/MVCManagerMenusAccessFacade.cs | 2 +- .../Modules/SignedFetch/SignedFetchWrap.cs | 4 +- .../MarketplaceCreditsMenuController.cs | 11 + .../Rooms/Fixed/FixedConnectiveRoom.cs | 2 +- .../Demo/GateKeeperRoomPlayground.cs | 2 +- .../Demo/LocalSceneDevelopmentPlayground.cs | 2 +- ...SceneDevelopmentSceneRoomMetaDataSource.cs | 8 +- .../Connections/GateKeeper/Meta/MetaData.cs | 6 +- .../Meta/SceneRoomMetaDataSource.cs | 12 +- .../GateKeeper/Rooms/IGateKeeperSceneRoom.cs | 2 +- .../CommsHandshakeMetadata.cs | 10 +- .../UserBasicInfoPassportModuleController.cs | 13 +- .../Assets/DCL/Passport/PassportController.cs | 3 +- .../Analytics/AnalyticsEvents.cs | 22 + .../MVCManagerAnalyticsDecorator.cs | 2 + .../Analytics/DynamicCommonTraitsPlugin.cs | 15 +- .../AuthenticationScreenAnalytics.cs | 41 +- .../UpgradeGuestAccountAnalytics.cs | 54 + .../UpgradeGuestAccountAnalytics.cs.meta | 2 + .../Assets/DCL/Places/PlacesController.cs | 7 +- .../DCL/Places/PlacesResultsController.cs | 17 +- .../DCL/PluginSystem/Global/ChatPlugin.cs | 3 +- .../PluginSystem/Global/CommunitiesPlugin.cs | 3 +- .../Global/CreditPurchasePlugin.cs | 10 +- .../PluginSystem/Global/ExplorePanelPlugin.cs | 22 +- .../Global/GenericPopupsPlugin.cs | 30 +- .../DCL/PluginSystem/Global/PassportPlugin.cs | 2 +- .../PluginSystem/Global/Plugin Settings.asset | 6 + .../DCL/PluginSystem/Global/SidebarPlugin.cs | 3 +- .../Global/Web3AuthenticationPlugin.cs | 5 - Explorer/Assets/DCL/Prefs/DCLPrefKeys.cs | 1 + .../DCL/Profiles/Cache/IProfileCache.cs | 6 + .../DCL/Profiles/SharedAPI/ProfileBuilder.cs | 6 + .../PrivateWorlds/WorldPermissionsService.cs | 4 +- ...GenericUserProfileContextMenuController.cs | 63 +- .../Names/ProfileNameEditorController.cs | 16 +- .../ProfileNameEditorControllerShould.cs | 6 +- .../DCL/UI/Sidebar/SidebarController.cs | 23 +- .../UI/TextInputFields/EmailInputFieldView.cs | 3 + .../DCL/UI/UpgradeGuestAccountPopup.meta | 3 + .../Atlas.spriteatlasv2 | 16 + .../Atlas.spriteatlasv2.meta | 30 + .../UI/UpgradeGuestAccountPopup/DclIcn.png | 3 + .../UpgradeGuestAccountPopup/DclIcn.png.meta | 143 + .../UI/UpgradeGuestAccountPopup/EmailIcn.png | 3 + .../EmailIcn.png.meta | 117 + .../UI/UpgradeGuestAccountPopup/ErrorIcn.png | 3 + .../ErrorIcn.png.meta | 117 + .../GuestUpgradeTrigger.cs | 11 + .../GuestUpgradeTrigger.cs.meta | 2 + .../UpgradeGuestAccountPopup/SuccessIcn.png | 3 + .../SuccessIcn.png.meta | 117 + .../UpgradeGuestAccountPopup.prefab | 9782 +++++++++++++++++ .../UpgradeGuestAccountPopup.prefab.meta | 7 + .../UpgradeGuestAccountPopupController.cs | 250 + ...UpgradeGuestAccountPopupController.cs.meta | 3 + .../UpgradeGuestAccountPopupView.cs | 43 + .../UpgradeGuestAccountPopupView.cs.meta | 3 + .../Waving Avatars.png | 3 + .../Waving Avatars.png.meta | 117 + ...mmunityVoiceChatSubTitleButtonPresenter.cs | 17 +- .../VoiceChat/Core/VoiceChatOrchestrator.cs | 9 +- .../Services/RPCCommunityVoiceChatService.cs | 58 +- .../Services/RPCPrivateVoiceChatService.cs | 30 +- .../DCL/VoiceChat/UI/CallButtonPresenter.cs | 27 +- .../DCL/VoiceChat/VoiceChatContainer.cs | 3 +- .../DCL/Web3/Authenticators/AuthProvider.cs | 2 +- .../Exceptions/EmailAlreadyLinkedException.cs | 10 + .../EmailAlreadyLinkedException.cs.meta | 2 + .../GuestAccountUpgradedException.cs | 19 + .../GuestAccountUpgradedException.cs.meta | 2 + .../IAccountLinkAuthenticator.cs | 15 + .../IAccountLinkAuthenticator.cs.meta | 2 + .../Authenticators/ICompositeWeb3Provider.cs | 6 +- .../Web3/Authenticators/IWeb3Authenticator.cs | 5 + .../Implementations/CompositeWeb3Provider.cs | 76 +- .../Dapp/DappDeepLinkAuthenticator.cs | 6 +- .../Dapp/DappWeb3EthereumApi.cs | 2 +- .../PrivateKeyAuthenticator.cs | 2 +- .../RandomGeneratedWeb3Authenticator.cs | 2 +- .../ThirdWeb/GuestSessionIdProvider.cs | 39 + .../ThirdWeb/GuestSessionIdProvider.cs.meta | 2 + .../ThirdWeb/ThirdWebAuthenticator.cs | 16 +- .../ThirdWeb/ThirdWebLoginService.cs | 264 +- .../Implementations/TokenFileAuthenticator.cs | 2 +- .../Web3/Identities/DecentralandIdentity.cs | 8 +- .../DCL/Web3/Identities/IWeb3Identity.cs | 15 +- .../DCL/Web3/Identities/IWeb3IdentityCache.cs | 4 + .../DCL/Web3/Identities/LogWeb3Identity.cs | 13 +- ...ntityWithNethereumAccountJsonSerializer.cs | 7 +- ...erPrefsIdentityProvider.IdentityJsonDto.cs | 4 + .../Tests/GuestSessionIdProviderShould.cs | 146 + .../GuestSessionIdProviderShould.cs.meta | 2 + .../Tests/IdentityMethodPersistenceShould.cs | 105 + .../IdentityMethodPersistenceShould.cs.meta | 2 + Explorer/Assets/Editor/RectSpacingOverlay.cs | 108 + .../Assets/Editor/RectSpacingOverlay.cs.meta | 3 + .../Authentication Shared Data.asset | 8 + .../Authentication_en.asset | 8 + .../UISoftMaskProjectSettings.asset | 5 + 163 files changed, 22585 insertions(+), 932 deletions(-) create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/GuestOrSignup.Screen.prefab create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/GuestOrSignup.Screen.prefab.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/SelectAvatar.NewAccount.Screen.prefab create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/SelectAvatar.NewAccount.Screen.prefab.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot1.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot1.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot2.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot2.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot3.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot3.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot4.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/FemaleSlot4.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot1.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot1.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot2.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot2.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot3.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot3.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot4.png create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Textures/MaleSlot4.png.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/AvatarPresetProvider.cs create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/AvatarPresetProvider.cs.meta delete mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/AvatarRandomizer.cs delete mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/AvatarRandomizer.cs.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/States/GuestOrSignUpAuthState.cs create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/States/GuestOrSignUpAuthState.cs.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/States/SelectAvatarForNewAccountAuthState.cs create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/States/SelectAvatarForNewAccountAuthState.cs.meta delete mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Tests/AvatarRandomizerShould.cs delete mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Tests/AvatarRandomizerShould.cs.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Views/GuestOrSignUpAuthView.cs create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Views/GuestOrSignUpAuthView.cs.meta create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Views/SelectAvatarForNewAccountAuthView.cs create mode 100644 Explorer/Assets/DCL/AuthenticationScreenFlow/Views/SelectAvatarForNewAccountAuthView.cs.meta create mode 100644 Explorer/Assets/DCL/PerformanceAndDiagnostics/Analytics/EventBased/UpgradeGuestAccountAnalytics.cs create mode 100644 Explorer/Assets/DCL/PerformanceAndDiagnostics/Analytics/EventBased/UpgradeGuestAccountAnalytics.cs.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/Atlas.spriteatlasv2 create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/Atlas.spriteatlasv2.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/DclIcn.png create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/DclIcn.png.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/EmailIcn.png create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/EmailIcn.png.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/ErrorIcn.png create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/ErrorIcn.png.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/GuestUpgradeTrigger.cs create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/GuestUpgradeTrigger.cs.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/SuccessIcn.png create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/SuccessIcn.png.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/UpgradeGuestAccountPopup.prefab create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/UpgradeGuestAccountPopup.prefab.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/UpgradeGuestAccountPopupController.cs create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/UpgradeGuestAccountPopupController.cs.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/UpgradeGuestAccountPopupView.cs create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/UpgradeGuestAccountPopupView.cs.meta create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/Waving Avatars.png create mode 100644 Explorer/Assets/DCL/UI/UpgradeGuestAccountPopup/Waving Avatars.png.meta create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/Exceptions/EmailAlreadyLinkedException.cs create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/Exceptions/EmailAlreadyLinkedException.cs.meta create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/Exceptions/GuestAccountUpgradedException.cs create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/Exceptions/GuestAccountUpgradedException.cs.meta create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/IAccountLinkAuthenticator.cs create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/IAccountLinkAuthenticator.cs.meta create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/Implementations/ThirdWeb/GuestSessionIdProvider.cs create mode 100644 Explorer/Assets/DCL/Web3/Authenticators/Implementations/ThirdWeb/GuestSessionIdProvider.cs.meta create mode 100644 Explorer/Assets/DCL/Web3/Tests/GuestSessionIdProviderShould.cs create mode 100644 Explorer/Assets/DCL/Web3/Tests/GuestSessionIdProviderShould.cs.meta create mode 100644 Explorer/Assets/DCL/Web3/Tests/IdentityMethodPersistenceShould.cs create mode 100644 Explorer/Assets/DCL/Web3/Tests/IdentityMethodPersistenceShould.cs.meta create mode 100644 Explorer/Assets/Editor/RectSpacingOverlay.cs create mode 100644 Explorer/Assets/Editor/RectSpacingOverlay.cs.meta diff --git a/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset b/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset index 93b736b9181..d1788e0000d 100644 --- a/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset +++ b/Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset @@ -385,6 +385,11 @@ MonoBehaviour: m_ReadOnly: 0 m_SerializedLabels: [] FlaggedDuringContentUpdateRestriction: 0 + - m_GUID: f5f9dfc19df574348991427c083d6e04 + m_Address: Assets/DCL/UI/UpgradeGuestAccountPopup/UpgradeGuestAccountPopup.prefab + m_ReadOnly: 0 + m_SerializedLabels: [] + FlaggedDuringContentUpdateRestriction: 0 - m_GUID: f87c3e77ea2e0ec45b0ddef98bfeb066 m_Address: Assets/DCL/Backpack/Gifting/Notifications/Prefab/GiftReceivedPopup.prefab m_ReadOnly: 0 diff --git a/Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/Authentication.MainScreen.prefab b/Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/Authentication.MainScreen.prefab index 85a1bf34148..44f9f6f56c0 100644 --- a/Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/Authentication.MainScreen.prefab +++ b/Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/Authentication.MainScreen.prefab @@ -888,11 +888,13 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 4635346258636800684} + - {fileID: 4695435503195640928} - {fileID: 4467899340765049217} - {fileID: 2058660919588094189} - {fileID: 2955286010541638715} - {fileID: 2891404835539542500} - {fileID: 8986644367044729187} + - {fileID: 408413462287800446} - {fileID: 3563954350240853237} - {fileID: 524203497558662806} - {fileID: 3656817250261915516} @@ -989,12 +991,14 @@ MonoBehaviour: k__BackingField: {fileID: 8454101078806804241} k__BackingField: {fileID: 4613417570274952093} k__BackingField: {fileID: 8185437588405162452} + k__BackingField: {fileID: 8051144860011413377} k__BackingField: {fileID: 3626083524348347871} k__BackingField: {fileID: 5988428590248281739} k__BackingField: {fileID: 1435686278016238798} k__BackingField: {fileID: 3085665909425487698} k__BackingField: {fileID: 1710777244495217613} k__BackingField: {fileID: 3658734714106879794} + k__BackingField: {fileID: 2057123601052006659} k__BackingField: {fileID: 1710274344204595558} k__BackingField: {fileID: 6752555971229295883} k__BackingField: {fileID: 2664898282194929885} @@ -1906,9 +1910,13 @@ PrefabInstance: propertyPath: m_AnchorMin.y value: 1 objectReference: {fileID: 0} + - target: {fileID: 1151621360254823839, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} + propertyPath: m_AnchoredPosition.x + value: 229 + objectReference: {fileID: 0} - target: {fileID: 1151621360254823839, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} propertyPath: m_AnchoredPosition.y - value: -138.5 + value: -264.03827 objectReference: {fileID: 0} - target: {fileID: 2034299800128287215, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} propertyPath: m_AnchorMax.y @@ -1918,6 +1926,14 @@ PrefabInstance: propertyPath: m_AnchorMin.y value: 1 objectReference: {fileID: 0} + - target: {fileID: 2034299800128287215, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} + propertyPath: m_AnchoredPosition.x + value: 229 + objectReference: {fileID: 0} + - target: {fileID: 2034299800128287215, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} + propertyPath: m_AnchoredPosition.y + value: -58 + objectReference: {fileID: 0} - target: {fileID: 2545835288679838424, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} propertyPath: m_Pivot.x value: 0.5 @@ -2046,6 +2062,22 @@ PrefabInstance: propertyPath: m_AnchoredPosition.y value: -23 objectReference: {fileID: 0} + - target: {fileID: 5781027346591425177, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5781027346591425177, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5781027346591425177, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} + propertyPath: m_AnchoredPosition.x + value: 229 + objectReference: {fileID: 0} + - target: {fileID: 5781027346591425177, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} + propertyPath: m_AnchoredPosition.y + value: -131 + objectReference: {fileID: 0} - target: {fileID: 6072945466760093846, guid: dfbc5788cdafba7439818132b6790dc8, type: 3} propertyPath: m_Name value: LoginSelection.Screen @@ -2240,6 +2272,275 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 5ad4b59864104b139e86d429f0a7c59c, type: 3} m_Name: m_EditorClassIdentifier: AuthenticationScreenFlow::DCL.AuthenticationScreenFlow.ProfileFetchingAuthView +--- !u!1001 &4554368311171162068 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 9199866600602126572} + m_Modifications: + - target: {fileID: 645846241471415486, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 645846241471415486, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 645846241471415486, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.x + value: 202 + objectReference: {fileID: 0} + - target: {fileID: 645846241471415486, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 105 + objectReference: {fileID: 0} + - target: {fileID: 645846241471415486, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: -27 + objectReference: {fileID: 0} + - target: {fileID: 1711216277067559753, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_Name + value: SelectAvatar.NewAccount.Screen + objectReference: {fileID: 0} + - target: {fileID: 1711216277067559753, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4385039574291624833, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4385039574291624833, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4385039574291624833, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.x + value: 160 + objectReference: {fileID: 0} + - target: {fileID: 4385039574291624833, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.y + value: 360 + objectReference: {fileID: 0} + - target: {fileID: 4385039574291624833, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 264 + objectReference: {fileID: 0} + - target: {fileID: 4385039574291624833, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: -180 + objectReference: {fileID: 0} + - target: {fileID: 4614679254787390645, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4614679254787390645, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4614679254787390645, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.x + value: 160 + objectReference: {fileID: 0} + - target: {fileID: 4614679254787390645, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.y + value: 360 + objectReference: {fileID: 0} + - target: {fileID: 4614679254787390645, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 632 + objectReference: {fileID: 0} + - target: {fileID: 4614679254787390645, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: -180 + objectReference: {fileID: 0} + - target: {fileID: 4775672698248381961, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4775672698248381961, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4775672698248381961, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.x + value: 202 + objectReference: {fileID: 0} + - target: {fileID: 4775672698248381961, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 105 + objectReference: {fileID: 0} + - target: {fileID: 4775672698248381961, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: -75 + objectReference: {fileID: 0} + - target: {fileID: 5042982009611844503, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5042982009611844503, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5042982009611844503, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.x + value: 160 + objectReference: {fileID: 0} + - target: {fileID: 5042982009611844503, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.y + value: 360 + objectReference: {fileID: 0} + - target: {fileID: 5042982009611844503, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5042982009611844503, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: -180 + objectReference: {fileID: 0} + - target: {fileID: 5697978170972303698, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5697978170972303698, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5697978170972303698, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 84 + objectReference: {fileID: 0} + - target: {fileID: 5697978170972303698, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: -23 + objectReference: {fileID: 0} + - target: {fileID: 7405575351129385033, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7405575351129385033, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7405575351129385033, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.x + value: 160 + objectReference: {fileID: 0} + - target: {fileID: 7405575351129385033, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_SizeDelta.y + value: 360 + objectReference: {fileID: 0} + - target: {fileID: 7405575351129385033, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.x + value: 448 + objectReference: {fileID: 0} + - target: {fileID: 7405575351129385033, guid: 2ab459deeaa4547249879a063267e623, type: 3} + propertyPath: m_AnchoredPosition.y + value: -180 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 2ab459deeaa4547249879a063267e623, type: 3} +--- !u!224 &408413462287800446 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4223994061457049514, guid: 2ab459deeaa4547249879a063267e623, type: 3} + m_PrefabInstance: {fileID: 4554368311171162068} + m_PrefabAsset: {fileID: 0} +--- !u!114 &2057123601052006659 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 2573810336467642071, guid: 2ab459deeaa4547249879a063267e623, type: 3} + m_PrefabInstance: {fileID: 4554368311171162068} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 403148bac55c4039833b69841cc7beb6, type: 3} + m_Name: + m_EditorClassIdentifier: DCL.UI.Flows::DCL.AuthenticationScreenFlow.SelectAvatarForNewAccountAuthView --- !u!1001 &4619773657564849768 PrefabInstance: m_ObjectHideFlags: 0 @@ -2804,65 +3105,57 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 9199866600602126572} m_Modifications: - - target: {fileID: 1611369640940411507, guid: 0940179db0295a645a270543c7d4bedd, type: 3} - propertyPath: m_Enabled - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 3269863560478414764, guid: 0940179db0295a645a270543c7d4bedd, type: 3} - propertyPath: m_Name - value: Lobby.NewAccount.Screen - objectReference: {fileID: 0} - - target: {fileID: 3269863560478414764, guid: 0940179db0295a645a270543c7d4bedd, type: 3} - propertyPath: m_IsActive - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4087306367503763202, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 321129895855166481, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchorMax.y value: 1 objectReference: {fileID: 0} - - target: {fileID: 4087306367503763202, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 321129895855166481, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchorMin.y value: 1 objectReference: {fileID: 0} - - target: {fileID: 4087306367503763202, guid: 0940179db0295a645a270543c7d4bedd, type: 3} - propertyPath: m_AnchoredPosition.x - value: 289.5 - objectReference: {fileID: 0} - - target: {fileID: 4087306367503763202, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 321129895855166481, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchoredPosition.y - value: -23 + value: -45 objectReference: {fileID: 0} - - target: {fileID: 5960527187105256418, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 528684117119687273, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchorMax.y value: 1 objectReference: {fileID: 0} - - target: {fileID: 5960527187105256418, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 528684117119687273, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchorMin.y value: 1 objectReference: {fileID: 0} - - target: {fileID: 5960527187105256418, guid: 0940179db0295a645a270543c7d4bedd, type: 3} - propertyPath: m_AnchoredPosition.x - value: 162.5 - objectReference: {fileID: 0} - - target: {fileID: 5960527187105256418, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 528684117119687273, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchoredPosition.y - value: -23 + value: -10 objectReference: {fileID: 0} - - target: {fileID: 6581960442703234763, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 557474527508596803, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchorMax.y value: 1 objectReference: {fileID: 0} - - target: {fileID: 6581960442703234763, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 557474527508596803, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchorMin.y value: 1 objectReference: {fileID: 0} - - target: {fileID: 6581960442703234763, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 557474527508596803, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchoredPosition.x - value: 54 + value: 150 objectReference: {fileID: 0} - - target: {fileID: 6581960442703234763, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + - target: {fileID: 557474527508596803, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_AnchoredPosition.y - value: -23 + value: -120 + objectReference: {fileID: 0} + - target: {fileID: 1696928409689088436, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3269863560478414764, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + propertyPath: m_Name + value: Lobby.NewAccount.Screen + objectReference: {fileID: 0} + - target: {fileID: 3269863560478414764, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + propertyPath: m_IsActive + value: 0 objectReference: {fileID: 0} - target: {fileID: 7462045094642091666, guid: 0940179db0295a645a270543c7d4bedd, type: 3} propertyPath: m_Pivot.x @@ -2944,6 +3237,22 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 7488820279610071442, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7488820279610071442, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + propertyPath: m_AnchorMin.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7488820279610071442, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + propertyPath: m_AnchoredPosition.x + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 7488820279610071442, guid: 0940179db0295a645a270543c7d4bedd, type: 3} + propertyPath: m_AnchoredPosition.y + value: -73.5 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] @@ -2965,3 +3274,120 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b71d4207f4194f9096bce9cd29f99852, type: 3} m_Name: m_EditorClassIdentifier: AuthenticationScreenFlow::DCL.AuthenticationScreenFlow.NewUserLobbyScreenSubView +--- !u!1001 &7096852788198614712 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 9199866600602126572} + m_Modifications: + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6072945466760093846, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_Name + value: LoginSelection.Welcome.Screen + objectReference: {fileID: 0} + - target: {fileID: 6072945466760093846, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} +--- !u!224 &4695435503195640928 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 2545835288679838424, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + m_PrefabInstance: {fileID: 7096852788198614712} + m_PrefabAsset: {fileID: 0} +--- !u!114 &8051144860011413377 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 992621047954053433, guid: b50d33cba68b54ca4a0a1c7e99131392, type: 3} + m_PrefabInstance: {fileID: 7096852788198614712} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d43bf80b0eb433ba43979d4c2b6b569, type: 3} + m_Name: + m_EditorClassIdentifier: DCL.UI.Flows::DCL.AuthenticationScreenFlow.LoginSelectionWelcomeAuthView diff --git a/Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/GuestOrSignup.Screen.prefab b/Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/GuestOrSignup.Screen.prefab new file mode 100644 index 00000000000..a4266fe9a58 --- /dev/null +++ b/Explorer/Assets/DCL/AuthenticationScreenFlow/Assets/Prefabs/GuestOrSignup.Screen.prefab @@ -0,0 +1,2732 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &452479037827583423 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5225639936379264864} + - component: {fileID: 6430209642826638580} + - component: {fileID: 1622345099213584362} + - component: {fileID: 1275763054739731451} + - component: {fileID: 2634313066247946586} + - component: {fileID: 9131737607967825215} + m_Layer: 0 + m_Name: RetryButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5225639936379264864 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452479037827583423} + 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: 5378172510292386217} + m_Father: {fileID: 7415789763313651175} + 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: 103.000046, y: -106} + m_SizeDelta: {x: 190, y: 46} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6430209642826638580 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452479037827583423} + m_CullTransparentMesh: 1 +--- !u!114 &1622345099213584362 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452479037827583423} + 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 &1275763054739731451 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452479037827583423} + 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: 1622345099213584362} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &2634313066247946586 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452479037827583423} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6a66e979ca644f3d91fd0980c5cd5f5f, type: 3} + m_Name: + m_EditorClassIdentifier: +