@kubohiroya/turbowarp-realtime-motion-capture 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,7 +35,7 @@ extension. The usual order is Camera Source, WebRTC, A-Frame, then Realtime Moti
35
35
  not used may be omitted. A version-pinned package URL is:
36
36
 
37
37
  ```text
38
- https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-realtime-motion-capture@0.2.0/dist/turbowarp-realtime-motion-capture.js
38
+ https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-realtime-motion-capture@0.3.0/dist/turbowarp-realtime-motion-capture.js
39
39
  ```
40
40
 
41
41
  The npm package distributes a standalone browser bundle, schemas, and documentation. It does not
@@ -5,6 +5,22 @@ export interface MultiviewPoseFeatureFlags {
5
5
  readonly cameraCalibrationV1: boolean;
6
6
  readonly avatarRetargetV1: boolean;
7
7
  readonly frameSyncPatternV1: boolean;
8
+ /**
9
+ * Hand the optical time path to turbowarp-time-space-sync.
10
+ *
11
+ * Independent of `cameraCalibrationV1` and its own delegation: during the
12
+ * move one path can be delegated while the other is not, and both states are
13
+ * legitimate.
14
+ */
15
+ readonly timeSpaceSyncDelegateV1: boolean;
16
+ /**
17
+ * Keep calibration profiles in Camera Source's shared registry.
18
+ *
19
+ * Only the profile half. Running a calibration stays here until
20
+ * turbowarp-camera-calibration publishes a way for another extension to ask
21
+ * it to.
22
+ */
23
+ readonly cameraCalibrationDelegateV1: boolean;
8
24
  readonly poseFusion3D: boolean;
9
25
  readonly glowStickMarkers: boolean;
10
26
  }
@@ -15,6 +31,43 @@ interface FeatureFlagGlobal {
15
31
 
16
32
  const overrides = (globalThis as FeatureFlagGlobal).__TWMP_FEATURE_FLAGS__;
17
33
 
34
+ /**
35
+ * Pairs where one flag runs the old path and the other hands it away.
36
+ *
37
+ * Turning both on runs two implementations of the same thing at once: two
38
+ * leases on one camera, two overlays covering the screen, two corrections
39
+ * applied to the same observation. None of those announce themselves -- a
40
+ * second lease is granted, a second overlay is drawn on top of the first, a
41
+ * doubled correction is a plausible number -- so the combination is refused
42
+ * before anything starts rather than diagnosed afterwards.
43
+ */
44
+ const exclusivePairs: ReadonlyArray<
45
+ readonly [keyof MultiviewPoseFeatureFlags, keyof MultiviewPoseFeatureFlags]
46
+ > = [
47
+ ["frameSyncPatternV1", "timeSpaceSyncDelegateV1"],
48
+ ["cameraCalibrationV1", "cameraCalibrationDelegateV1"],
49
+ ];
50
+
51
+ /**
52
+ * Refuses a combination that would run two implementations of one thing.
53
+ *
54
+ * Called when the extension is built rather than when this module loads: a
55
+ * throw during module evaluation gives TurboWarp nothing to show the operator,
56
+ * and the message is the only thing that explains what to change.
57
+ */
58
+ export function requireConsistentFeatureFlags(
59
+ flags: MultiviewPoseFeatureFlags = featureFlags,
60
+ ): MultiviewPoseFeatureFlags {
61
+ for (const [older, delegate] of exclusivePairs) {
62
+ if (flags[older] && flags[delegate]) {
63
+ throw new Error(
64
+ `${older} and ${delegate} are both on. One runs the path here and the other hands it to another extension; together they lease the same camera twice and draw two overlays. Turn off ${older} to delegate, or ${delegate} to keep the path here.`,
65
+ );
66
+ }
67
+ }
68
+ return flags;
69
+ }
70
+
18
71
  /** Startup-fixed flags. Experimental QR and pose paths stay independently opt-in. */
19
72
  export const featureFlags: MultiviewPoseFeatureFlags = Object.freeze({
20
73
  qrCourierPairing: overrides?.qrCourierPairing === true,
@@ -23,6 +76,8 @@ export const featureFlags: MultiviewPoseFeatureFlags = Object.freeze({
23
76
  cameraCalibrationV1: overrides?.cameraCalibrationV1 === true,
24
77
  avatarRetargetV1: overrides?.avatarRetargetV1 === true,
25
78
  frameSyncPatternV1: overrides?.frameSyncPatternV1 === true,
79
+ timeSpaceSyncDelegateV1: overrides?.timeSpaceSyncDelegateV1 === true,
80
+ cameraCalibrationDelegateV1: overrides?.cameraCalibrationDelegateV1 === true,
26
81
  poseFusion3D: overrides?.poseFusion3D === true,
27
82
  glowStickMarkers: overrides?.glowStickMarkers === true,
28
83
  });
@@ -2,6 +2,11 @@
2
2
  "formatVersion": 1,
3
3
  "id": "kubohiroyarealtimemotioncapture",
4
4
  "blocks": [
5
+ {
6
+ "opcode": "acknowledgeFrameSyncFlashing",
7
+ "blockType": "COMMAND",
8
+ "arguments": []
9
+ },
5
10
  {
6
11
  "opcode": "addCameraCalibrationSample",
7
12
  "blockType": "COMMAND",
@@ -312,6 +317,16 @@
312
317
  }
313
318
  ]
314
319
  },
320
+ {
321
+ "opcode": "inferPoseCameraAtFrameTime",
322
+ "blockType": "COMMAND",
323
+ "arguments": [
324
+ {
325
+ "id": "CAMERA_ID",
326
+ "type": "STRING"
327
+ }
328
+ ]
329
+ },
315
330
  {
316
331
  "opcode": "latestPoseFrame2D",
317
332
  "blockType": "REPORTER",
@@ -372,6 +387,26 @@
372
387
  "blockType": "REPORTER",
373
388
  "arguments": []
374
389
  },
390
+ {
391
+ "opcode": "poseCameraFrame2D",
392
+ "blockType": "REPORTER",
393
+ "arguments": [
394
+ {
395
+ "id": "CAMERA_ID",
396
+ "type": "STRING"
397
+ }
398
+ ]
399
+ },
400
+ {
401
+ "opcode": "poseCameraStatusJson",
402
+ "blockType": "REPORTER",
403
+ "arguments": [
404
+ {
405
+ "id": "CAMERA_ID",
406
+ "type": "STRING"
407
+ }
408
+ ]
409
+ },
375
410
  {
376
411
  "opcode": "poseError",
377
412
  "blockType": "REPORTER",
@@ -500,6 +535,16 @@
500
535
  "blockType": "COMMAND",
501
536
  "arguments": []
502
537
  },
538
+ {
539
+ "opcode": "setFrameSyncDisplayRefresh",
540
+ "blockType": "COMMAND",
541
+ "arguments": [
542
+ {
543
+ "id": "REFRESH_US",
544
+ "type": "NUMBER"
545
+ }
546
+ ]
547
+ },
503
548
  {
504
549
  "opcode": "setPerformerGlowStick",
505
550
  "blockType": "COMMAND",
@@ -583,6 +628,24 @@
583
628
  }
584
629
  ]
585
630
  },
631
+ {
632
+ "opcode": "startPoseCamera",
633
+ "blockType": "COMMAND",
634
+ "arguments": [
635
+ {
636
+ "id": "CALIBRATION_ID",
637
+ "type": "STRING"
638
+ },
639
+ {
640
+ "id": "CAMERA_ID",
641
+ "type": "STRING"
642
+ },
643
+ {
644
+ "id": "PEER_ID",
645
+ "type": "STRING"
646
+ }
647
+ ]
648
+ },
586
649
  {
587
650
  "opcode": "startPoseFusion",
588
651
  "blockType": "COMMAND",
@@ -619,11 +682,26 @@
619
682
  }
620
683
  ]
621
684
  },
685
+ {
686
+ "opcode": "stopAllPoseCameras",
687
+ "blockType": "COMMAND",
688
+ "arguments": []
689
+ },
622
690
  {
623
691
  "opcode": "stopFrameSyncDecoder",
624
692
  "blockType": "COMMAND",
625
693
  "arguments": []
626
694
  },
695
+ {
696
+ "opcode": "stopPoseCamera",
697
+ "blockType": "COMMAND",
698
+ "arguments": [
699
+ {
700
+ "id": "CAMERA_ID",
701
+ "type": "STRING"
702
+ }
703
+ ]
704
+ },
627
705
  {
628
706
  "opcode": "stopPoseFusion",
629
707
  "blockType": "COMMAND",