Skip to content

Add controller LED color API and Blockly block#596

Open
tracygardner wants to merge 8 commits intomainfrom
codex/add-block-to-control-game-controller-leds
Open

Add controller LED color API and Blockly block#596
tracygardner wants to merge 8 commits intomainfrom
codex/add-block-to-control-game-controller-leds

Conversation

@tracygardner
Copy link
Copy Markdown
Contributor

@tracygardner tracygardner commented Apr 30, 2026

Motivation

  • Provide a simple way to control a connected game controller's LED color from code and from the visual Blockly editor for XR projects.

Description

  • Added setControllerLedColor(controllerIndex, color) to api/xr.js which accepts a controller index and a hex color string, converts it to RGB, and attempts to set the color using common controller properties (lightIndicator.setColor or leds[0].setColor).
  • Introduced a new Blockly block set_controller_led_color in blocks/xr.js and a corresponding JavaScript generator in generators/generators-scene.js that emits setControllerLedColor(...) calls.
  • Added the new block to the XR toolbox in toolbox.js with default shadow inputs for index and color.
  • Added English and Spanish locale strings and tooltips in locale/en.js and locale/es.js for the block and tooltip text.

Testing

  • No new automated tests were added for this change, and the project's existing automated test suite and linter were run against the modified code with no failures observed.

Codex Task

Summary by CodeRabbit

  • New Features

    • Added a visual block to set XR controller LED colors by controller index and color; includes toolbox entry and defaults so it’s ready to use. Tooltip clarifies behavior when LED control isn’t supported.
  • Localization

    • Added English and Spanish text and tooltips for the new controller LED block.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Warning

Rate limit exceeded

@tracygardner has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 39 minutes and 34 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd8c56d9-c923-4058-b10d-1a84aeb6984c

📥 Commits

Reviewing files that changed from the base of the PR and between 5d0dbd5 and cf2b3de.

📒 Files selected for processing (1)
  • api/xr.js
📝 Walkthrough

Walkthrough

Adds XR controller LED color control: new async API methods to set controller LED color (including a WebHID helper), Blockly block and generator, toolbox entry, and English/Spanish localization; also exposes the API to the iframe sandbox.

Changes

Cohort / File(s) Summary
API Implementation
api/xr.js
Adds setControllerLedColor(controllerIndex, color) and setPlayStationControllerLedViaHid(gamepad, rgb) to flockXR. Normalizes controllerIndex, builds XR + navigator gamepad pools, parses strict #RRGGBB color to {r,g,b}, attempts LED updates via lightIndicator.setColor or leds[0].setColor, falls back to WebHID helper, and handles/catches failures.
Block Definition
blocks/xr.js
Adds a new Blockly.Blocks["set_controller_led_color"] block with typed inputs: CONTROLLER_INDEX (Number) and COLOR (Colour), tooltip, help URL, and Scene styling.
Code Generator
generators/generators-scene.js
Introduces JS generator for set_controller_led_color that emits await setControllerLedColor(controllerIndex, color) using safe defaults ("0" and "#ffffff") when inputs are absent.
Localization
locale/en.js, locale/es.js
Adds English and Spanish strings for the new block label and tooltip describing index-based LED selection and no-op behavior on unsupported hardware.
Toolbox Configuration
toolbox.js
Registers set_controller_led_color in the XR toolbox with shadow defaults for CONTROLLER_INDEX and COLOR.
Sandbox Whitelist
flock.js
Exposes setControllerLedColor to the iframe sandbox API whitelist and includes it in guarded side-effect APIs so runs abort safely on token mismatch.

Sequence Diagram(s)

sequenceDiagram
  participant Block as Blockly Block
  participant Runner as Runtime (iframe/host)
  participant flockXR as flockXR API
  participant XRInput as XR input sources
  participant GP as navigator.getGamepads()
  participant HW as Controller Hardware / WebHID

  Block->>Runner: execute generated code
  Runner->>flockXR: await setControllerLedColor(index, "#RRGGBB")
  flockXR->>XRInput: query XR input sources
  flockXR->>GP: query navigator.getGamepads()
  flockXR->>flockXR: select gamepad by normalized index
  flockXR->>HW: try lightIndicator.setColor / leds[0].setColor
  alt supported
    HW-->>flockXR: success
  else unsupported
    flockXR->>HW: setPlayStationControllerLedViaHid(gamepad, rgb)
    HW-->>flockXR: success/failure
  end
  flockXR-->>Runner: return (void)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I nibble hex and hop with glee,
I send bright LEDs to controllers three;
From Blockly block to HID's hum,
Colors dance, the XR rabbits come! 🎨✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding a controller LED color API and corresponding Blockly block, which aligns with the primary objective of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/add-block-to-control-game-controller-leds

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 39 minutes and 34 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 30, 2026

Deploying flockxr with  Cloudflare Pages  Cloudflare Pages

Latest commit: cf2b3de
Status: ✅  Deploy successful!
Preview URL: https://ae0d8f12.flockxr.pages.dev
Branch Preview URL: https://codex-add-block-to-control-g.flockxr.pages.dev

View logs

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/xr.js`:
- Around line 54-57: The code in setControllerLedColor uses
navigator?.getGamepads which throws if navigator is undeclared; change the guard
to check existence with typeof navigator !== "undefined" (e.g., typeof navigator
!== "undefined" && typeof navigator.getGamepads === "function") before calling
getGamepads so the fallback to [] runs safely; update the gamepads assignment
and the retrieval of gamepad (gamepads?.[Math.trunc(Number(controllerIndex))])
accordingly to ensure no ReferenceError in non-browser environments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e33c9714-ac55-48cf-8ab3-1e21928ba465

📥 Commits

Reviewing files that changed from the base of the PR and between 43d5784 and 075dfae.

📒 Files selected for processing (6)
  • api/xr.js
  • blocks/xr.js
  • generators/generators-scene.js
  • locale/en.js
  • locale/es.js
  • toolbox.js

Comment thread api/xr.js Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
api/xr.js (1)

61-61: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use typeof navigator !== "undefined" guards instead of navigator?.… at root.

Line [61] and Line [144] can still throw in environments where navigator is undeclared, so the fallback path is not guaranteed.

🔧 Proposed fix
-    const browserGamepads = Array.from(navigator?.getGamepads?.() ?? []).filter(
-      Boolean,
-    );
+    const browserGamepads = Array.from(
+      typeof navigator !== "undefined" &&
+        typeof navigator.getGamepads === "function"
+        ? navigator.getGamepads()
+        : [],
+    ).filter(Boolean);
-      if (!navigator?.hid) return false;
+      if (typeof navigator === "undefined" || !navigator.hid) return false;
#!/bin/bash
# Verify remaining risky optional-chaining root usages in JS files.
rg -nP --type=js '\bnavigator\?\.' -C2

Also applies to: 144-144

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/xr.js` at line 61, Replace root-level optional chaining on navigator with
an explicit typeof check: update the browserGamepads initialization (the
Array.from(navigator?.getGamepads?.() ?? []) expression) to first confirm typeof
navigator !== "undefined" and typeof navigator.getGamepads === "function" before
calling getGamepads, falling back to an empty array otherwise; apply the same
pattern to the other occurrence referenced around line 144 so no call or
property access uses navigator?.… at module/root scope.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/xr.js`:
- Around line 95-109: The hex-only validator hexToRgb in api/xr.js rejects named
colors (causing setControllerLedColor to no-op when generators send 'red');
update hexToRgb (or add a new normalizeColor helper used before calling
hexToRgb) to accept common CSS color names (at least 'red', 'green', 'blue',
'black', 'white') by mapping them to their hex equivalents, or use a small
parsing fallback that converts named colors to hex before parseInt runs, then
ensure the call site that logs "[setControllerLedColor] invalid color format"
uses the normalized value so generators/generators-scene.js can continue to pass
names without causing silent failures.

---

Duplicate comments:
In `@api/xr.js`:
- Line 61: Replace root-level optional chaining on navigator with an explicit
typeof check: update the browserGamepads initialization (the
Array.from(navigator?.getGamepads?.() ?? []) expression) to first confirm typeof
navigator !== "undefined" and typeof navigator.getGamepads === "function" before
calling getGamepads, falling back to an empty array otherwise; apply the same
pattern to the other occurrence referenced around line 144 so no call or
property access uses navigator?.… at module/root scope.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 32c68768-87f1-471e-9f96-f33eb2fb33bd

📥 Commits

Reviewing files that changed from the base of the PR and between 075dfae and 5d0dbd5.

📒 Files selected for processing (3)
  • api/xr.js
  • flock.js
  • generators/generators-scene.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • generators/generators-scene.js

Comment thread api/xr.js
Comment on lines +95 to +109
const match = trimmed.match(/^#?([0-9a-fA-F]{6})$/);
if (!match) return null;
const value = match[1];
return {
r: parseInt(value.slice(0, 2), 16),
g: parseInt(value.slice(2, 4), 16),
b: parseInt(value.slice(4, 6), 16),
};
};

const rgb = hexToRgb(color);
if (!rgb) {
console.log("[setControllerLedColor] invalid color format", { color });
return;
}
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 | 🟡 Minor | ⚡ Quick win

Generator/API default color mismatch can cause silent no-op.

This API only accepts hex at Line [95], but generators/generators-scene.js currently falls back to 'red' when COLOR is missing. That path will always hit invalid-format return at Line [106]-Line [109].

🔧 Suggested cross-file adjustment
-    const color =
-      javascriptGenerator.valueToCode(
-        block,
-        "COLOR",
-        javascriptGenerator.ORDER_NONE,
-      ) || "'red'";
+    const color =
+      javascriptGenerator.valueToCode(
+        block,
+        "COLOR",
+        javascriptGenerator.ORDER_NONE,
+      ) || "'#ff0000'";
🧰 Tools
🪛 GitHub Actions: Prettier

[warning] Prettier reported formatting/style issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/xr.js` around lines 95 - 109, The hex-only validator hexToRgb in
api/xr.js rejects named colors (causing setControllerLedColor to no-op when
generators send 'red'); update hexToRgb (or add a new normalizeColor helper used
before calling hexToRgb) to accept common CSS color names (at least 'red',
'green', 'blue', 'black', 'white') by mapping them to their hex equivalents, or
use a small parsing fallback that converts named colors to hex before parseInt
runs, then ensure the call site that logs "[setControllerLedColor] invalid color
format" uses the normalized value so generators/generators-scene.js can continue
to pass names without causing silent failures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant