Skip to content

change: mouse camera navigation#6

Merged
Wingo206 merged 5 commits into
mainfrom
navigation-changes
Aug 30, 2025
Merged

change: mouse camera navigation#6
Wingo206 merged 5 commits into
mainfrom
navigation-changes

Conversation

@Wingo206

@Wingo206 Wingo206 commented Aug 29, 2025

Copy link
Copy Markdown

Description

Issue number and link

Testing plan

Author checklist

  • I have submitted a Contributor License Agreement
  • I have added my name to CONTRIBUTORS.md
  • I have updated CHANGES.md with a short summary of my change
  • I have added or updated unit tests to ensure consistent code coverage
  • I have updated the inline documentation, and included code examples where relevant
  • I have performed a self-review of my code

Summary by CodeRabbit

  • New Features

    • Added Space key as a camera-control modifier and global Space-key handling.
    • Expanded scroll-wheel modifier support for input detection.
  • Changes

    • Camera gestures updated: Zoom via Wheel, Pinch, or Alt+Right-Drag; Rotate via Middle-Drag, Left-Drag+Space, or Right-Drag+Shift; Tilt via Right-Drag, Pinch, or Left-Drag+Alt; Look via Left-Drag+Alt.
  • Bug Fixes

    • Suppressed tile-load error logs when no listeners are attached.
  • Chores

    • Bumped engine version to 15.0.37.

@coderabbitai

coderabbitai Bot commented Aug 29, 2025

Copy link
Copy Markdown

Walkthrough

Adds a SPACE keyboard modifier and Space-key tracking; updates camera input mappings and wheel modifier checks to include ALT and SPACE; suppresses tileset console logs when no listeners exist; bumps engine package version to 15.0.37.

Changes

Cohort / File(s) Summary
Keyboard modifier enum
packages/engine/Source/Core/KeyboardEventModifier.js
Added SPACE: 3 with JSDoc; object still frozen/exported unchanged.
Screen-space input handler
packages/engine/Source/Core/ScreenSpaceEventHandler.js
Added _spaceKeyDown instance field (initialized false); added handleKeyDown/handleKeyUp to track Space (keyCode 32) and prevent default scrolling; register/unregister keyboard listeners; getModifier(event, screenSpaceEventHandler) now can return KeyboardEventModifier.SPACE; updated call sites to pass screenSpaceEventHandler.
Camera input aggregation
packages/engine/Source/Scene/CameraEventAggregator.js
anyButtonDown.wheelMoved now recognizes WHEEL with ALT and WHEEL with SPACE modifiers in addition to previous checks.
Screen-space camera controller
packages/engine/Source/Scene/ScreenSpaceCameraController.js
Updated public input mappings: zoomEventTypes now includes WHEEL, PINCH, and { eventType: RIGHT_DRAG, modifier: ALT }; rotateEventTypes now accepts MIDDLE_DRAG, { LEFT_DRAG + SPACE }, and { RIGHT_DRAG + SHIFT }; tiltEventTypes narrowed to RIGHT_DRAG, PINCH, and { LEFT_DRAG + ALT }; lookEventTypes default modifier changed from SHIFT to ALT. Public properties redefined accordingly.
Tileset failure logging
packages/engine/Source/Scene/Cesium3DTileset.js
On tile load failure, suppresses prior console logging (URL, message, stack) when there are no tileFailed listeners; still raises event when listeners exist.
Version bump
packages/engine/package.json
Package version incremented from 15.0.35 to 15.0.37.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as User
  participant Input as Input Device
  participant SSEH as ScreenSpaceEventHandler
  participant Agg as CameraEventAggregator
  participant Ctrl as ScreenSpaceCameraController
  participant Cam as Camera

  User->>Input: Drag / Wheel / Pinch / Key (Space/Shift/Alt)
  Input->>SSEH: Raw event (mouse/touch/wheel/keydown/keyup)
  SSEH->>SSEH: Track _spaceKeyDown on keydown/keyup
  SSEH->>Agg: Normalized event (type + modifier including SPACE)
  Agg->>Agg: anyButtonDown / wheelMoved checks (now includes ALT, SPACE)
  Agg-->>Ctrl: CameraEvent (type + modifier)
  Ctrl->>Ctrl: Match event to mappings (zoom/rotate/tilt/look)
  Ctrl->>Cam: Apply camera action
  Cam-->>User: Updated view
Loading
sequenceDiagram
  autonumber
  participant Loader as Tile Loader
  participant Tileset as Cesium3DTileset
  participant Lsn as tileFailed Listeners
  participant Log as Console

  Loader->>Tileset: Tile load fails (error)
  alt Has tileFailed listeners
    Tileset-->>Lsn: Raise tileFailed(error)
    Tileset->>Log: (may log as before)
  else No listeners
    Note over Tileset: Suppress prior console logging (no output)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I twitch my whiskers, tap the Space,
I trace new drags across the place.
Wheels whisper ALT and airy SPACE,
Cameras pivot, tilt, embrace.
Silent tiles fall — hush the trace. 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5433b4a and 16d839c.

📒 Files selected for processing (2)
  • packages/engine/Source/Scene/ScreenSpaceCameraController.js (4 hunks)
  • packages/engine/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/engine/package.json
  • packages/engine/Source/Scene/ScreenSpaceCameraController.js
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch navigation-changes

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions

Copy link
Copy Markdown

🔴 There was an error checking the CLA! If this is your first contribution, please send in a Contributor License Agreement.

    TypeError: key must be a string, a buffer or an object

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/engine/Source/Scene/Cesium3DTileset.js (1)

662-666: Update JSDoc to match new no-log behavior (if you keep it silent).

The docs promise console logging; current code suppresses it. Align the comment as in the diff above to avoid misleading users.

packages/engine/Source/Scene/CameraEventAggregator.js (1)

385-397: Add or remove SPACE modifier handling

  • ScreenSpaceEventHandler has no keydown/keyup or event logic for SPACE (KeyboardEventModifier.SPACE), so CameraEventAggregator’s SPACE bindings (lines 385–397) never fire. Either implement SPACE detection in ScreenSpaceEventHandler or omit SPACE from the modifier loop.
🧹 Nitpick comments (2)
packages/engine/Source/Scene/ScreenSpaceCameraController.js (2)

187-193: Rotate mapping uses SPACE; confirm handler support and update docs.

Rotation now uses MIDDLE_DRAG and SPACE+LEFT_DRAG. Update the JSDoc default and ensure SPACE is supported by the event system; MIDDLE button may be unavailable on many devices.

Doc fix:

- * @default {@link CameraEventType.LEFT_DRAG}
+ * @default [{@link CameraEventType.MIDDLE_DRAG}, { eventType: {@link CameraEventType.LEFT_DRAG}, modifier: {@link KeyboardEventModifier.SPACE} }]

Consider keeping LEFT_DRAG (no modifier) in the list for devices without a middle button (behind a flag if necessary).


169-176: Add CHANGES.md and unit/integration tests for gesture remapping.

Given the new defaults, add:

  • CHANGES.md entry outlining the new gesture map.
  • Tests that the controller reacts to WHEEL/ALT/SPACE and modified drags as intended in 2D/CV/3D.

Would you like me to draft CHANGES.md and a few Jasmine specs targeting these mappings?

Also applies to: 187-193, 210-210, 221-224

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 85774dc and c8579ca.

📒 Files selected for processing (5)
  • packages/engine/Source/Core/KeyboardEventModifier.js (1 hunks)
  • packages/engine/Source/Scene/CameraEventAggregator.js (1 hunks)
  • packages/engine/Source/Scene/Cesium3DTileset.js (1 hunks)
  • packages/engine/Source/Scene/ScreenSpaceCameraController.js (4 hunks)
  • packages/engine/package.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/engine/Source/Scene/CameraEventAggregator.js (1)
packages/engine/Source/Core/KeyboardEventModifier.js (1)
  • KeyboardEventModifier (7-39)
packages/engine/Source/Scene/ScreenSpaceCameraController.js (1)
packages/engine/Source/Core/KeyboardEventModifier.js (1)
  • KeyboardEventModifier (7-39)

Comment thread packages/engine/package.json Outdated
{
"name": "@mach9/engine",
"version": "15.0.35",
"version": "15.0.36",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Bump version as a behavior change (input remapping), not a patch.

Mouse/keyboard gesture defaults changed; this is user-facing and potentially breaking. Use at least a minor bump (e.g., 15.1.0) or major if adhering to semver strictly.

-  "version": "15.0.36",
+  "version": "15.1.0",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"version": "15.0.36",
"version": "15.1.0",
🤖 Prompt for AI Agents
packages/engine/package.json lines 3-3: The version is set to "15.0.36" but the
change is a user-facing behavior change (input remapping), so update the semver
bump to at least a minor release; change the version string to "15.1.0" (or
higher if you prefer a different minor/major policy) and update any related
changelog/release notes and CI/release tooling to reflect the new version.

Comment on lines +32 to +38
/**
* Represents the space key being held down.
*
* @type {number}
* @constant
*/
SPACE: 3,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Adding SPACE is fine, but wire it end-to-end.

Ensure ScreenSpaceEventHandler detects the Space key and maps it to this constant; otherwise, SPACE-based gestures won’t work.

Would you like a follow-up patch to add SPACE handling to ScreenSpaceEventHandler (keydown/up, preventDefault on canvas to avoid page scroll)?


🏁 Script executed:

#!/bin/bash
set -e

# Locate ScreenSpaceEventHandler source file
file=$(fd ScreenSpaceEventHandler.js -t f)
echo "ScreenSpaceEventHandler file: $file"

# Inspect keydown and keyup handlers around event registration
grep -n -C3 "addEventListener.*keydown" "$file"
grep -n -C3 "addEventListener.*keyup" "$file"

# Search for mapping of SPACE constant
grep -n "KeyboardEventModifier\\.SPACE" "$file"

# Check any preventDefault logic in key handlers
grep -n "preventDefault" -C2 "$file"

Length of output: 384


🏁 Script executed:

#!/bin/bash
set -e

# Locate ScreenSpaceEventHandler source file
file=$(fd ScreenSpaceEventHandler.js -t f)
echo "File: $file"

# Check for key event handler methods
echo "\n-- this._onKeyDown references --"
grep -n "this\\._onKeyDown" -C2 "$file" || true

echo "\n-- this._onKeyUp references --"
grep -n "this\\._onKeyUp" -C2 "$file" || true

# Check for listener registrations
echo "\n-- keydown/keyup listeners --"
grep -n "addEventListener.*keydown" -C2 "$file" || true
grep -n "addEventListener.*keyup" -C2 "$file" || true

# Check for SPACE constant usage
echo "\n-- KeyboardEventModifier.SPACE usages --"
grep -n "KeyboardEventModifier\\.SPACE" -C2 "$file" || true

# Check for preventDefault calls in key handlers
echo "\n-- preventDefault calls --"
grep -n "preventDefault" -C2 "$file" || true

Length of output: 1341


🏁 Script executed:

#!/bin/bash
# Display handlers and mapping around SPACE constant in ScreenSpaceEventHandler
sed -n '160,240p' packages/engine/Source/Core/ScreenSpaceEventHandler.js

Length of output: 3319


Wire SPACE key handling in ScreenSpaceEventHandler
ScreenSpaceEventHandler currently has no keydown/keyup listeners for the Space key, so KeyboardEventModifier.SPACE is never activated. Add listeners (e.g. on the canvas) to set/reset this modifier on keydown/keyup for keyCode 32 (or event.key === ' '), and call preventDefault() on Space to avoid page scrolling, ensuring the modifier: KeyboardEventModifier.SPACE mapping in rotateEventTypes works as intended.

🤖 Prompt for AI Agents
In packages/engine/Source/Core/KeyboardEventModifier.js around lines 32 to 38,
the SPACE modifier is defined but ScreenSpaceEventHandler never wires
keydown/keyup for the Space key so the modifier is never set; add keydown and
keyup listeners (attached to the canvas element) that detect Space (event.key
=== ' ' or event.keyCode === 32), set KeyboardEventModifier.SPACE on keydown and
clear it on keyup, call event.preventDefault() on keydown to prevent page
scrolling, and ensure these listeners integrate with the existing modifier
handling so the rotateEventTypes mapping using modifier:
KeyboardEventModifier.SPACE functions correctly.

Comment on lines +427 to +432
!this._update[
getKey(CameraEventType.WHEEL, KeyboardEventModifier.ALT)
] ||
!this._update[
getKey(CameraEventType.WHEEL, KeyboardEventModifier.SPACE)
];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Don’t hardcode wheel modifiers; derive from KeyboardEventModifier to stay future-proof.

This avoids touching this block every time a modifier is added.

-      const wheelMoved =
-        !this._update[getKey(CameraEventType.WHEEL)] ||
-        !this._update[
-          getKey(CameraEventType.WHEEL, KeyboardEventModifier.SHIFT)
-        ] ||
-        !this._update[
-          getKey(CameraEventType.WHEEL, KeyboardEventModifier.CTRL)
-        ] ||
-        !this._update[
-          getKey(CameraEventType.WHEEL, KeyboardEventModifier.ALT)
-        ] ||
-        !this._update[
-          getKey(CameraEventType.WHEEL, KeyboardEventModifier.SPACE)
-        ];
+      const wheelKeys = [undefined, ...Object.values(KeyboardEventModifier)];
+      const wheelMoved = wheelKeys.some(
+        (m) => !this._update[getKey(CameraEventType.WHEEL, m)]
+      );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
!this._update[
getKey(CameraEventType.WHEEL, KeyboardEventModifier.ALT)
] ||
!this._update[
getKey(CameraEventType.WHEEL, KeyboardEventModifier.SPACE)
];
const wheelKeys = [undefined, ...Object.values(KeyboardEventModifier)];
const wheelMoved = wheelKeys.some(
(m) => !this._update[getKey(CameraEventType.WHEEL, m)]
);

Comment on lines +2670 to 2673
//console.log(`A 3D tile failed to load: ${url}`);
//console.log(`Error: ${message}`);
//console.log(error.stack);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Silent failure path now contradicts the documented behavior.

You commented out console logging when there are no tileFailed listeners, but the JSDoc above still states errors will be logged. Fix docs or restore minimal logging.

Option A (update docs to reflect silence):

@@
  /**
   * The event fired to indicate that a tile's content failed to load.
   * <p>
-  * If there are no event listeners, error messages will be logged to the console.
+  * If there are no event listeners, no message is logged to the console.
   * </p>

Option B (keep low-noise logging):

   } else {
-    //console.log(`A 3D tile failed to load: ${url}`);
-    //console.log(`Error: ${message}`);
-    //console.log(error.stack);
+    oneTimeWarning(
+      "tileset-tileFailed-no-listeners",
+      "A 3D tile failed to load, but no tileFailed listeners are registered."
+    );
   }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/engine/Source/Scene/Cesium3DTileset.js around lines 2670-2673, the
code comments out console logging for tile load failures which contradicts the
existing JSDoc that promises errors will be logged; either update the JSDoc to
state that failures are silent when there are no tileFailed listeners (Option A)
or restore minimal low-noise logging (Option B) — if you choose Option A, edit
the JSDoc text to explicitly say no logging occurs when there are no listeners;
if you choose Option B, reintroduce a single minimal console.error/console.warn
call that logs the tile URL and error message (and stack if available) only when
there are no tileFailed listeners, keeping it concise and low-noise.

Comment on lines 169 to 176
this.zoomEventTypes = [
CameraEventType.RIGHT_DRAG,
CameraEventType.WHEEL,
CameraEventType.PINCH,
{
eventType: CameraEventType.RIGHT_DRAG,
modifier: KeyboardEventModifier.SHIFT,
},
];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Zoom mapping change: doc and compatibility.

Defaults changed to require SHIFT+RIGHT_DRAG for zoom (instead of plain RIGHT_DRAG). Update the JSDoc default and consider a feature flag to preserve legacy mappings for existing users.

Doc fix:

- * @default [{@link CameraEventType.RIGHT_DRAG}, {@link CameraEventType.WHEEL}, {@link CameraEventType.PINCH}]
+ * @default [{@link CameraEventType.WHEEL}, {@link CameraEventType.PINCH}, { eventType: {@link CameraEventType.RIGHT_DRAG}, modifier: {@link KeyboardEventModifier.SHIFT} }]

Optional: expose an inputScheme: "legacy" | "space-alt" (default "space-alt") to switch mappings.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.zoomEventTypes = [
CameraEventType.RIGHT_DRAG,
CameraEventType.WHEEL,
CameraEventType.PINCH,
{
eventType: CameraEventType.RIGHT_DRAG,
modifier: KeyboardEventModifier.SHIFT,
},
];
/**
* The input event types to use for zooming the camera.
*
* @default [{@link CameraEventType.WHEEL}, {@link CameraEventType.PINCH}, { eventType: {@link CameraEventType.RIGHT_DRAG}, modifier: {@link KeyboardEventModifier.SHIFT} }]
*/
this.zoomEventTypes = [
CameraEventType.WHEEL,
CameraEventType.PINCH,
{
eventType: CameraEventType.RIGHT_DRAG,
modifier: KeyboardEventModifier.SHIFT,
},
];
🤖 Prompt for AI Agents
In packages/engine/Source/Scene/ScreenSpaceCameraController.js around lines 169
to 176, the default zoom mapping was changed to require SHIFT+RIGHT_DRAG but the
JSDoc still documents the old plain RIGHT_DRAG behavior and there is no way to
opt into the legacy mapping; update the JSDoc default to reflect the new
SHIFT+RIGHT_DRAG mapping, and add an optional inputScheme option (e.g.
inputScheme: "legacy" | "space-alt" defaulting to "space-alt") to toggle between
the new mapping and the legacy RIGHT_DRAG behavior — implement logic that sets
this.zoomEventTypes based on the inputScheme (legacy -> RIGHT_DRAG, space-alt ->
SHIFT+RIGHT_DRAG) and surface the option in the constructor/API so existing
users can preserve the old mapping.

modifier: KeyboardEventModifier.CTRL,
},
];
this.tiltEventTypes = [CameraEventType.RIGHT_DRAG, CameraEventType.PINCH];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Tilt mapping narrowed; update docs and check overlap with new zoom mapping.

Tilt is now RIGHT_DRAG (no modifier) and PINCH. Update the JSDoc block accordingly. Verify no conflict with SHIFT+RIGHT_DRAG zoom in practice (it should be fine via modifier-specific handlers).

Doc fix:

- * @default [{@link CameraEventType.MIDDLE_DRAG}, {@link CameraEventType.PINCH}, { ...CTRL combos... }]
+ * @default [{@link CameraEventType.RIGHT_DRAG}, {@link CameraEventType.PINCH}]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.tiltEventTypes = [CameraEventType.RIGHT_DRAG, CameraEventType.PINCH];
/**
* The event types that will be interpreted as tilt
*
* @type {CameraEventType[]}
* @default [{@link CameraEventType.RIGHT_DRAG}, {@link CameraEventType.PINCH}]
*/
this.tiltEventTypes = [CameraEventType.RIGHT_DRAG, CameraEventType.PINCH];

Comment on lines 221 to 224
this.lookEventTypes = {
eventType: CameraEventType.LEFT_DRAG,
modifier: KeyboardEventModifier.SHIFT,
modifier: KeyboardEventModifier.ALT,
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Look mapping changed to ALT; update the documented default.

Docs still mention SHIFT; change to ALT to avoid confusing integrators.

- * @default { eventType : {@link CameraEventType.LEFT_DRAG}, modifier : {@link KeyboardEventModifier.SHIFT} }
+ * @default { eventType : {@link CameraEventType.LEFT_DRAG}, modifier : {@link KeyboardEventModifier.ALT} }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.lookEventTypes = {
eventType: CameraEventType.LEFT_DRAG,
modifier: KeyboardEventModifier.SHIFT,
modifier: KeyboardEventModifier.ALT,
};
* @default { eventType : {@link CameraEventType.LEFT_DRAG}, modifier : {@link KeyboardEventModifier.ALT} }
🤖 Prompt for AI Agents
In packages/engine/Source/Scene/ScreenSpaceCameraController.js around lines 221
to 224, the code sets the look modifier to ALT but documentation/comments still
say SHIFT; update the documented default to ALT. Locate any inline comments,
JSDoc, README, or API docs that state the default look modifier as SHIFT and
change those references to ALT (and update any examples showing SHIFT key
usage), and run a quick grep across the repo for "look mapping", "look
modifier", "SHIFT", or "default look" to ensure all user-facing docs and
examples are consistent with the new ALT mapping.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
packages/engine/Source/Core/ScreenSpaceEventHandler.js (3)

34-46: SPACE modifier precedence: confirm intended behavior (single modifier only).

As implemented, SPACE is only returned when SHIFT/CTRL/ALT are not pressed. If combos like SHIFT+SPACE are desired, current single-modifier model won’t express them. Please confirm this precedence matches the updated mappings in ScreenSpaceCameraController and CameraEventAggregator.


62-67: Mirror robust Space detection in keyup.

Small consistency improvement; no behavior change otherwise.

-function handleKeyUp(screenSpaceEventHandler, event) {
-  if (event.keyCode === 32) {
+function handleKeyUp(screenSpaceEventHandler, event) {
+  if (event.code === "Space" || event.keyCode === 32 || event.key === " ") {
     // Space key code
     screenSpaceEventHandler._spaceKeyDown = false;
   }
 }

1022-1023: State init: LGTM; optional JSDoc for clarity.

Consider a brief private JSDoc (e.g., “Tracks whether Space is currently pressed”) to aid readers.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c8579ca and 5433b4a.

📒 Files selected for processing (1)
  • packages/engine/Source/Core/ScreenSpaceEventHandler.js (11 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/engine/Source/Core/ScreenSpaceEventHandler.js (1)
packages/engine/Source/Core/KeyboardEventModifier.js (1)
  • KeyboardEventModifier (7-39)
🔇 Additional comments (1)
packages/engine/Source/Core/ScreenSpaceEventHandler.js (1)

262-267: Passing handler into getModifier: LGTM.

Call sites consistently forward screenSpaceEventHandler so SPACE state is respected across mouse, touch, dblclick, and wheel paths.

Also applies to: 291-300, 386-399, 432-437, 476-481, 569-607, 779-817

Comment on lines +54 to +61
function handleKeyDown(screenSpaceEventHandler, event) {
if (event.keyCode === 32) {
// Space key code
screenSpaceEventHandler._spaceKeyDown = true;
event.preventDefault(); // Prevent page scrolling
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Don’t preventDefault on Space globally—blocks typing and page scroll outside the canvas.

Keydown on document will swallow spaces in inputs/contenteditable and stop page scrolling site-wide. Restrict preventDefault to events originating within the handler element and non-editable targets; also broaden Space detection for robustness.

-function handleKeyDown(screenSpaceEventHandler, event) {
-  if (event.keyCode === 32) {
-    // Space key code
-    screenSpaceEventHandler._spaceKeyDown = true;
-    event.preventDefault(); // Prevent page scrolling
-  }
-}
+function handleKeyDown(screenSpaceEventHandler, event) {
+  // Robust Space detection across browsers
+  if (event.code === "Space" || event.keyCode === 32 || event.key === " ") {
+    screenSpaceEventHandler._spaceKeyDown = true;
+
+    // Only block default if inside our element and not an editable control
+    const el = screenSpaceEventHandler._element;
+    const t = event.target;
+    const inside =
+      t === el || (el && typeof el.contains === "function" && el.contains(t));
+    const isEditable =
+      t &&
+      (t.isContentEditable ||
+        /^(input|textarea|select)$/i.test(t.tagName));
+    if (inside && !isEditable) {
+      event.preventDefault(); // Prevent page scroll when interacting with the canvas
+    }
+  }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function handleKeyDown(screenSpaceEventHandler, event) {
if (event.keyCode === 32) {
// Space key code
screenSpaceEventHandler._spaceKeyDown = true;
event.preventDefault(); // Prevent page scrolling
}
}
function handleKeyDown(screenSpaceEventHandler, event) {
// Robust Space detection across browsers
if (event.code === "Space" || event.keyCode === 32 || event.key === " ") {
screenSpaceEventHandler._spaceKeyDown = true;
// Only block default if inside our element and not an editable control
const el = screenSpaceEventHandler._element;
const t = event.target;
const inside =
t === el || (el && typeof el.contains === "function" && el.contains(t));
const isEditable =
t &&
(t.isContentEditable ||
/^(input|textarea|select)$/i.test(t.tagName));
if (inside && !isEditable) {
event.preventDefault(); // Prevent page scroll when interacting with the canvas
}
}
}
🤖 Prompt for AI Agents
In packages/engine/Source/Core/ScreenSpaceEventHandler.js around lines 54-61,
the current keydown handler unconditionally preventsDefault for Space, which
blocks typing and scrolling site-wide; update it to (1) detect Space robustly
using event.key === ' ' || event.code === 'Space' || event.keyCode === 32, (2)
ensure the event originated from the handler's element (or its descendant)
before acting, and (3) skip calling preventDefault if the event.target is an
editable element (input, textarea, or has contentEditable not "false"); only
when the event is a Space key, comes from inside the handler element, and the
target is non-editable set _spaceKeyDown = true and call preventDefault.

Comment on lines +190 to +202
// Add keyboard event listeners for space key tracking
registerListener(
screenSpaceEventHandler,
"keydown",
alternateElement,
handleKeyDown,
);
registerListener(
screenSpaceEventHandler,
"keyup",
alternateElement,
handleKeyUp,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clear “stuck” SPACE state on window blur/page hide.

If keyup is missed (tab switch, window blur, visibility change), _spaceKeyDown can get stuck true. Add blur/visibilitychange listeners to reset ephemeral keyboard state.

   registerListener(
     screenSpaceEventHandler,
     "keyup",
     alternateElement,
     handleKeyUp,
   );
+
+  // Reset transient keyboard state if focus is lost or page is hidden
+  registerListener(
+    screenSpaceEventHandler,
+    "blur",
+    window,
+    handleBlurOrVisibilityChange,
+  );
+  registerListener(
+    screenSpaceEventHandler,
+    "visibilitychange",
+    document,
+    handleBlurOrVisibilityChange,
+  );

Add this helper near other handlers:

function handleBlurOrVisibilityChange(screenSpaceEventHandler, event) {
  if (event.type === "blur" || document.visibilityState === "hidden") {
    screenSpaceEventHandler._spaceKeyDown = false;
  }
}
🤖 Prompt for AI Agents
In packages/engine/Source/Core/ScreenSpaceEventHandler.js around lines 190 to
202, add handling to clear a stuck _spaceKeyDown when the page loses focus or
visibility changes: register blur and visibilitychange listeners on the same
element or window and implement a small handler that sets
screenSpaceEventHandler._spaceKeyDown = false when event.type === "blur" or
document.visibilityState === "hidden"; attach this handler alongside the
existing keydown/keyup registrations and remove it on destroy if applicable.

@Wingo206 Wingo206 merged commit 3620386 into main Aug 30, 2025
1 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant