Skip to content

fix: mouse coords to scene - #9754

Merged
lorenzo-ranciaffi merged 5 commits into
devfrom
bugsweep/toggle-hints-tooltip-position
Aug 19, 2026
Merged

fix: mouse coords to scene#9754
lorenzo-ranciaffi merged 5 commits into
devfrom
bugsweep/toggle-hints-tooltip-position

Conversation

@lorenzo-ranciaffi

@lorenzo-ranciaffi lorenzo-ranciaffi commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Pull Request Description

Fixes #9496

What does this PR change?

Reads the inputsystem pointer data when the pointer action is disabled (e.g. chat is focused) so it reads the actual coords instead of default(Vector2).

Test Steps

  1. Follow repro steps of the linked issue

Quality Checklist

  • Changes have been tested locally
  • Documentation has been updated (if required)
  • Performance impact has been considered
  • For SDK features: Test scene is included

Code Review Reference

Please review our Branch & PR Standards before submitting. It explains the automated review flow, QA/DEV approval requirements, and what each label does — especially useful for first-time contributors.

eordano and others added 3 commits August 3, 2026 19:07
Opening the chat puts it into the focused state, which disables the entire `Camera` input action map (intended to stop camera-look/zoom while typing). `PrimaryPointerInfoSystem` reads the raw pointer position through that same map's `Point` action; a disabled `InputAction` returns `default(Vector2)`, so the client writes `PBPrimaryPointerInfo.ScreenCoordinates = (0,0)` to the scene on every tick while chat is focused. The fishing-pond scene normalizes that value against the canvas size and renders the tooltip at `left:14, bottom:10` — exactly the bottom-left corner, where the chat input sits.

Fixes #9496

Includes a regression test that fails without this fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lorenzo-ranciaffi lorenzo-ranciaffi self-assigned this Aug 14, 2026
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🚦 CI Status

Build

Windows and Mac build successful in Unity Cloud! You can find a link to the downloadable artifact below.

Name Link
Commit 9c137f7
Logs https://github.com/decentraland/unity-explorer/actions/runs/32239838316
Download Windows https://github.com/decentraland/unity-explorer/suites/87395004983/artifacts/9361386161
Download Windows S3 https://explorer-artifacts.decentraland.org/@dcl/unity-explorer/branch/bugsweep/toggle-hints-tooltip-position/pr-25301-9c137f7/Decentraland_windows64.zip
Download Mac https://github.com/decentraland/unity-explorer/suites/87395004983/artifacts/9361420339
Download Mac S3 https://explorer-artifacts.decentraland.org/@dcl/unity-explorer/branch/bugsweep/toggle-hints-tooltip-position/pr-25301-9c137f7/Decentraland_macos.zip
Built on 2026-08-19T10:30:22Z

Lint

Warnings not reduced: 13116 => 13126 — remove at least 11 warnings to merge.

Warnings/errors in files changed by this PR (12)
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:36  CSharpWarnings::CS8618  Non-nullable field 'camera' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:35  CSharpWarnings::CS8618  Non-nullable field 'cameraGameObject' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:37  CSharpWarnings::CS8618  Non-nullable field 'ecsToCRDTWriter' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:39  CSharpWarnings::CS8618  Non-nullable field 'exposedCameraData' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:33  CSharpWarnings::CS8618  Non-nullable field 'globalWorld' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:34  CSharpWarnings::CS8618  Non-nullable field 'mouse' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:41  CSharpWarnings::CS8618  Non-nullable field 'putCalls' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:38  CSharpWarnings::CS8618  Non-nullable field 'sceneStateProvider' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:32  CSharpWarnings::CS8618  Non-nullable field 'sceneWorld' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Tests/PrimaryPointerInfoSystemCameraMapDisabledShould.cs:40  CSharpWarnings::CS8618  Non-nullable field 'system' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Systems/PrimaryPointerInfoSystem.cs:33  CSharpWarnings::CS8618  Non-nullable fields 'inputPoint', 'cachedCamera' must contain non-null values when exiting constructor. Consider adding the 'required' modifiers or declaring the fields as nullable.
Assets/DCL/SDKComponents/PrimaryPointerInfo/Systems/PrimaryPointerInfoSystem.cs:8  RedundantUsingDirective  Using directive is not required by the code and can be safely removed

Tests

All Unity tests passed ✅

TESTS SUITE Result Passed Failed Skipped
EditMode ✅ Passed 25188 0 13
PlayMode ✅ Passed 238 0 37

@lorenzo-ranciaffi lorenzo-ranciaffi changed the title Bugsweep/toggle hints tooltip position fix: mouse coords to scene Aug 14, 2026
@lorenzo-ranciaffi lorenzo-ranciaffi added the force-build Used to trigger a build on draft PR label Aug 14, 2026
@decentraland-bot

This comment has been minimized.

@lorenzo-ranciaffi lorenzo-ranciaffi removed the force-build Used to trigger a build on draft PR label Aug 19, 2026
@lorenzo-ranciaffi
lorenzo-ranciaffi marked this pull request as ready for review August 19, 2026 09:52
@lorenzo-ranciaffi
lorenzo-ranciaffi requested review from a team as code owners August 19, 2026 09:52
@decentraland-bot
decentraland-bot self-requested a review August 19, 2026 09:52

@decentraland-bot decentraland-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

STEP 1 — Context & Scope

PR: #9754fix: mouse coords to scene
Branch: bugsweep/toggle-hints-tooltip-positiondev
Files changed: 3 (+133 −1)

  • PrimaryPointerInfoSystem.cs — 6-line production fix in UpdatePointerInfo()
  • PrimaryPointerInfoSystemCameraMapDisabledShould.cs — new 116-line regression test
  • .cs.meta — Unity asset metadata

Subsystem docs loaded: CLAUDE.md, docs/README.md, review-instructions.md. Neighbouring files read: full PrimaryPointerInfoSystem.cs, existing PrimaryPointerInfoSystemShould.cs test fixture.


STEP 2 — Root-cause check: PASS ✅

Problem: ApplyInputMapsSystem disables the entire Camera action map when UI holds input focus (e.g. chat). PrimaryPointerInfoSystem reads pointer position from DCLInput.Instance.Camera.Point — an action in that map. A disabled InputAction.ReadValue<Vector2>() returns default(Vector2) = (0, 0). The fishing-pond scene normalises these coordinates and pins the "Toggle Hints" tooltip to the bottom-left corner.

Fix: Falls back to the raw pointer device (Pointer.current?.position.ReadValue()) when the input action is disabled. This is a correct root-cause fix:

  • PrimaryPointerInfoSystem is an observation system (scene-facing CRDT data), not a control system (camera/movement). The zero-on-disable pattern used by UpdateCameraInputSystem / UpdateInputMovementSystem / UpdateInputJumpSystem is intentionally wrong here.
  • The broader alternative (moving Point to an always-on action map) would be architecturally purer but disproportionate for this bug severity.

STEP 3 — Design & integration: PASS ✅

No new long-lived unit introduced — the change modifies one private method in an existing system.

Lifecycle check:

  • Pointer.current is a static point-in-time read, not a subscription — no leak, no disposal needed.
  • The cached inputPoint reference remains valid when disabled (Disable() stops processing but doesn't destroy the action).
  • previousPosition was already tracked by the system; the fallback to it is natural.

Teardown trace: No new subscriptions, events, callbacks, connections, or resources added. Nothing to unsubscribe.


STEP 4 — Member audit: N/A

No new public properties, accessors, or exported members.


STEP 5 — Line-level review

A. Blocking issues: None

  • Allocation-free ✅ — inputPoint.enabled (property read), Pointer.current (static property), .position.ReadValue() (struct read), ?? (value-type coalescing). No heap allocations, no LINQ, no closures, no boxing.
  • Null safety ✅ — Pointer.current?. handles absent device; ?? previousPosition provides final fallback. After Initialize() calls UpdatePointerInfo(), previousPosition always reflects a real position.
  • Transition correctness ✅ — previousPosition = rawPosition executes regardless of source, so lock/unlock and enable/disable transitions remain spike-free.
  • No resource leaks ✅ — No subscriptions, events, or connections added.
  • No detached async ✅.
  • Security ✅ — No auth changes, no secrets, no injection vectors. Pointer.current reads the same physical device as Camera.Point — not a new input channel. (Scenes now receive real coordinates during UI focus, which is the intended fix, not a vulnerability.)

B. Design smells

[P2] Comment enumerates specific UI panels that will go stale (PrimaryPointerInfoSystem.cs lines 68–70):
The comment lists "chat, passport, explore panel" — these specific panels can change as the UI evolves, silently making the comment inaccurate. Additionally, the raw-device fallback bypasses any action-level InputProcessors on Camera.Point; today there are none, but noting the assumption aids future maintainers. See inline suggestion.

[P2] Test fixture duplication (PrimaryPointerInfoSystemCameraMapDisabledShould.cs):
The new fixture duplicates ~90 lines of setup/teardown from the existing PrimaryPointerInfoSystemShould: identical fields (sceneWorld, globalWorld, mouse, camera, ecsToCRDTWriter, sceneStateProvider, exposedCameraData, system, putCalls), near-identical SetUp(), identical Cleanup(). The single test method needs only two unique lines in its Arrange section:

Set(mouse.position, simulatedPosition);
DCLInput.Instance.Camera.Disable();

Suggestion: Add NotReportZeroScreenCoordinatesWhenCameraMapDisabledByChatFocus() to the existing PrimaryPointerInfoSystemShould fixture, eliminating the new file entirely. If more disabled-map tests are planned, extract a shared base class later.


STEP 6 — Complexity: COMPLEX

Touches input handling (InputAction.enabled check, raw Pointer.current device read) and scene-facing CRDT data flow (PBPrimaryPointerInfo.ScreenCoordinates).


STEP 7 — QA: YES

Modifies runtime input behaviour visible to users and scenes. Manual verification needed: follow repro steps from #9496.


STEP 8 — Non-blocking warnings

None. Main.unity is not modified.


STEP 9 — Verdict

REVIEW_RESULT: PASS ✅
COMPLEXITY: COMPLEX
COMPLEXITY_REASON: Modifies input handling (InputAction/Pointer device read) and scene-facing CRDT data flow
QA_REQUIRED: YES


Reviewed by Jarvis 🤖 · Requested by decentraland-bot via GitHub

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Jarvis reviewed this PR and found no blocking issues, but assessed it as complex — human DEV review is still required before merging.

@decentraland-bot

Copy link
Copy Markdown
Contributor

PR #9754, run #32243052524

Builds: Windows change, Windows baseline, macOS change, macOS baseline

How to read this table
  • Each build is measured 3 times. The values are the median, and (min–max) is the lowest and highest of those runs — a wide range means the metric is noisy and small differences are not trustworthy.
  • Δ is Change minus Baseline (a negative Δ means Change is faster).
  • 🟢 faster / 🔴 slower — a real difference: larger than both 3% and the run-to-run range.
  • ⚪ within noise — the difference is smaller than how much the build varies between its own runs, so it cannot be told apart from random variation. Treat it as no change.
  • Exceptions per run — the average number of exceptions in a run's log; more than the baseline is flagged 🔴 even when frame times look fine. The Exception breakdown under each table groups them by the explorer's report category and exception type (as totals across the runs).
  • A run that logged unusually many exceptions (at least 10 and 5× the median of its build's runs — e.g. a service was down during it) is excluded from all numbers and called out under the table.

Intel Core i5

Metric Baseline Change Δ Result
Samples 2313 (×3) 2366 (×3)
CPU average 38.6 ms (33.4–38.8) 37.7 ms (37.1–37.8) -0.9 ms ⚪ within noise
CPU 1% worst 322.6 ms (57.0–343.5) 294.1 ms (289.1–306.0) -28.5 ms ⚪ within noise
CPU 0.1% worst 344.1 ms (341.1–360.3) 307.3 ms (304.0–325.2) -36.9 ms 🟢 11% faster
GPU average 9.5 ms (9.2–9.6) 9.4 ms (9.4–9.5) -0.1 ms ⚪ within noise
GPU 1% worst 35.6 ms (23.5–37.7) 31.9 ms (30.4–32.9) -3.7 ms ⚪ within noise
GPU 0.1% worst 44.4 ms (39.8–45.0) 38.9 ms (37.5–39.3) -5.5 ms 🟢 12% faster
Exceptions per run 66 65 -1 🟢 fewer errors
Exception breakdown
Exception Baseline (3 runs) Change (3 runs)
[UI] DllNotFoundException 192 192
[ENGINE] ObjectDisposedException 3 3
[ENGINE] NullReferenceException 3 0

Apple M1

Metric Baseline Change Δ Result
Samples 4105 (×3) 3973 (×3)
CPU average 21.8 ms (21.8–22.9) 22.6 ms (22.1–22.8) 0.8 ms ⚪ within noise
CPU 1% worst 215.9 ms (215.7–217.7) 230.1 ms (227.7–234.7) 14.2 ms 🔴 7% slower
CPU 0.1% worst 226.3 ms (222.9–228.8) 239.5 ms (239.2–245.6) 13.3 ms 🔴 6% slower
GPU average 2.5 ms (2.0–3.2) 6.2 ms (5.4–6.4) 3.7 ms 🔴 148% slower
GPU 1% worst 34.3 ms (34.2–36.2) 35.4 ms (35.0–36.0) 1.1 ms ⚪ within noise
GPU 0.1% worst 36.3 ms (34.8–37.5) 36.9 ms (36.0–37.2) 0.7 ms ⚪ within noise
Exceptions per run 0 0 0 ⚪ none new

@anicalbano anicalbano left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️ Tested and working as expected in both Windows and macOS systems
✔️ No regressions were found

19.08.2026_08.05.55_REC.mp4

@lorenzo-ranciaffi
lorenzo-ranciaffi merged commit 3699c28 into dev Aug 19, 2026
55 of 69 checks passed
@lorenzo-ranciaffi
lorenzo-ranciaffi deleted the bugsweep/toggle-hints-tooltip-position branch August 19, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix "Toggle hints" tooltip rendering at wrong position when chat is open

5 participants