From 971cfdc9097e1c0452932ce29e0924944c183ac5 Mon Sep 17 00:00:00 2001 From: Patrick Gidich Date: Fri, 4 Sep 2026 18:45:26 -0400 Subject: [PATCH 1/2] feat(iwsdk): add MPFB radial pulse interaction evidence --- apps/arena/ui-xr-iwsdk-spike/src/main.ts | 89 +- .../src/mpfb-radial-pulse-patient.ts | 76 + .../src/radial-pulse-scene.ts | 215 + .../src/radial-pulse-state.test.ts | 120 + .../src/radial-pulse-state.ts | 234 + .../src/sidecar-state.test.ts | 10 +- apps/arena/ui-xr-iwsdk-spike/src/styles.css | 46 +- .../ui-xr-iwsdk-spike/src/xr-input-models.ts | 48 + ...b-radial-pulse-interaction-2026-09-04.json | 6691 +++++++++++++++++ ...ial-pulse-publication-review-2026-09-04.md | 64 + ...b-radial-pulse-interaction-2026-09-04.webm | Bin 0 -> 79162 bytes ...al-pulse-interaction-poster-2026-09-04.png | Bin 0 -> 156432 bytes package.json | 1 + .../iwsdk-radial-pulse-video-capture.test.ts | 85 + .../iwsdk-radial-pulse-video-capture.ts | 238 + 15 files changed, 7870 insertions(+), 47 deletions(-) create mode 100644 apps/arena/ui-xr-iwsdk-spike/src/mpfb-radial-pulse-patient.ts create mode 100644 apps/arena/ui-xr-iwsdk-spike/src/radial-pulse-scene.ts create mode 100644 apps/arena/ui-xr-iwsdk-spike/src/radial-pulse-state.test.ts create mode 100644 apps/arena/ui-xr-iwsdk-spike/src/radial-pulse-state.ts create mode 100644 apps/arena/ui-xr-iwsdk-spike/src/xr-input-models.ts create mode 100644 docs/openclinxr/evidence/iwsdk-mpfb-radial-pulse-interaction-2026-09-04.json create mode 100644 docs/openclinxr/radial-pulse-publication-review-2026-09-04.md create mode 100644 docs/openclinxr/videos/iwsdk-mpfb-radial-pulse-interaction-2026-09-04.webm create mode 100644 docs/openclinxr/videos/iwsdk-mpfb-radial-pulse-interaction-poster-2026-09-04.png create mode 100644 tools/openclinxr/evidence/iwsdk-radial-pulse-video-capture.test.ts create mode 100644 tools/openclinxr/evidence/iwsdk-radial-pulse-video-capture.ts diff --git a/apps/arena/ui-xr-iwsdk-spike/src/main.ts b/apps/arena/ui-xr-iwsdk-spike/src/main.ts index fb80190ce..fd2ad64e1 100644 --- a/apps/arena/ui-xr-iwsdk-spike/src/main.ts +++ b/apps/arena/ui-xr-iwsdk-spike/src/main.ts @@ -1,6 +1,5 @@ import { BoxGeometry, - BufferGeometry, CanvasTexture, CapsuleGeometry, Color, @@ -9,8 +8,6 @@ import { DoubleSide, Group, HemisphereLight, - Line, - LineBasicMaterial, Mesh, MeshBasicMaterial, MeshStandardMaterial, @@ -21,14 +18,15 @@ import { Vector3, WebGLRenderer, } from "three"; -import { XRControllerModelFactory } from "three/addons/webxr/XRControllerModelFactory.js"; -import { XRHandModelFactory } from "three/addons/webxr/XRHandModelFactory.js"; import { buildMixedRealitySupportState, hasApprovedMixedRealityOperatorGate, type MixedRealitySupportState, mixedRealityOptionalFeatures, } from "./mixed-reality-state.js"; +import { loadMpfbRadialPulsePatient } from "./mpfb-radial-pulse-patient.js"; +import { createRadialPulseSceneInteraction } from "./radial-pulse-scene.js"; +import { hasRadialPulseDemo, shouldHydrateOptionalIwsdkPackages, shouldInstallUikitmlSpatialTextPanel } from "./radial-pulse-state.js"; import { buildIwsdkSidecarFrameStats, buildIwsdkSidecarRuntimeEvidence, @@ -42,7 +40,6 @@ import { type IwsdkSidecarRuntimeState, type IwsdkSidecarXrEntryEvidence, type IwsdkSidecarXrEntryStatus, - iwsdkSidecarPrimitiveHandModelProfile, iwsdkSidecarSceneObjectNames, recordIwsdkSidecarXrEntryEvidence, summarizeIwsdkSidecarReadiness, @@ -53,6 +50,7 @@ import { type UikitmlSpatialTextEvidence, type UikitmlSpatialTextRuntimePanel, } from "./uikitml-spatial-text.js"; +import { addControllerAffordances, addHandModels } from "./xr-input-models.js"; import "./styles.css"; type NavigatorWithXr = Navigator & { @@ -233,6 +231,8 @@ function requireElement(selector: string): TElement { const bootStartedAtMs = performance.now(); const iwerAutoEnterVrQueryFlag = "iwerAutoEnterVr=true"; const iwerEvidenceViewWideQueryFlag = "iwerEvidenceView=wide"; +const radialPulseDemoEnabled = hasRadialPulseDemo(window.location.search); +document.body.classList.toggle("radial-pulse-demo", radialPulseDemoEnabled); function recordBootPhase(phase: string, error?: unknown): void { const current: OpenClinXrBootEvidence = window.__openClinXrBootEvidence ?? { app: "ui-xr-iwsdk-spike", events: [] }; @@ -283,6 +283,10 @@ app.innerHTML = `
+
+ Consent / assent checked + Stop immediately if discomfort is reported. +
Full VR checking @@ -294,6 +298,7 @@ app.innerHTML = `
IWSDK evidence pending Trace 0/${state.requiredTraceTags.length} + Radial pulse ready