@opsydyn/effect-three 0.0.0-stage → 0.2.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.
Files changed (166) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/LICENSE +21 -0
  3. package/README.md +189 -2
  4. package/dist/index-01kwfekm.js +5118 -0
  5. package/dist/index-01kwfekm.js.map +40 -0
  6. package/dist/index-4045wme0.js +129 -0
  7. package/dist/index-4045wme0.js.map +10 -0
  8. package/dist/index.d.ts +12 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +1361 -0
  11. package/dist/index.js.map +14 -0
  12. package/dist/kernel/animation.d.ts +14 -0
  13. package/dist/kernel/animation.d.ts.map +1 -0
  14. package/dist/kernel/behaviours.d.ts +16 -0
  15. package/dist/kernel/behaviours.d.ts.map +1 -0
  16. package/dist/kernel/bodies.d.ts +60 -0
  17. package/dist/kernel/bodies.d.ts.map +1 -0
  18. package/dist/kernel/bodySources.d.ts +47 -0
  19. package/dist/kernel/bodySources.d.ts.map +1 -0
  20. package/dist/kernel/build.d.ts +564 -0
  21. package/dist/kernel/build.d.ts.map +1 -0
  22. package/dist/kernel/cameraMotion.d.ts +39 -0
  23. package/dist/kernel/cameraMotion.d.ts.map +1 -0
  24. package/dist/kernel/clock.d.ts +17 -0
  25. package/dist/kernel/clock.d.ts.map +1 -0
  26. package/dist/kernel/contactShadowPasses.d.ts +47 -0
  27. package/dist/kernel/contactShadowPasses.d.ts.map +1 -0
  28. package/dist/kernel/description.d.ts +1120 -0
  29. package/dist/kernel/description.d.ts.map +1 -0
  30. package/dist/kernel/diff.d.ts +90 -0
  31. package/dist/kernel/diff.d.ts.map +1 -0
  32. package/dist/kernel/environmentPresets.d.ts +30 -0
  33. package/dist/kernel/environmentPresets.d.ts.map +1 -0
  34. package/dist/kernel/equality.d.ts +64 -0
  35. package/dist/kernel/equality.d.ts.map +1 -0
  36. package/dist/kernel/frames.d.ts +55 -0
  37. package/dist/kernel/frames.d.ts.map +1 -0
  38. package/dist/kernel/index.d.ts +37 -0
  39. package/dist/kernel/index.d.ts.map +1 -0
  40. package/dist/kernel/index.js +335 -0
  41. package/dist/kernel/index.js.map +9 -0
  42. package/dist/kernel/instances.d.ts +26 -0
  43. package/dist/kernel/instances.d.ts.map +1 -0
  44. package/dist/kernel/labels.d.ts +51 -0
  45. package/dist/kernel/labels.d.ts.map +1 -0
  46. package/dist/kernel/loop.d.ts +49 -0
  47. package/dist/kernel/loop.d.ts.map +1 -0
  48. package/dist/kernel/materials.d.ts +24 -0
  49. package/dist/kernel/materials.d.ts.map +1 -0
  50. package/dist/kernel/motion.d.ts +36 -0
  51. package/dist/kernel/motion.d.ts.map +1 -0
  52. package/dist/kernel/orbit.d.ts +127 -0
  53. package/dist/kernel/orbit.d.ts.map +1 -0
  54. package/dist/kernel/overlays.d.ts +16 -0
  55. package/dist/kernel/overlays.d.ts.map +1 -0
  56. package/dist/kernel/performance.d.ts +41 -0
  57. package/dist/kernel/performance.d.ts.map +1 -0
  58. package/dist/kernel/physics.d.ts +166 -0
  59. package/dist/kernel/physics.d.ts.map +1 -0
  60. package/dist/kernel/physicsDebug.d.ts +18 -0
  61. package/dist/kernel/physicsDebug.d.ts.map +1 -0
  62. package/dist/kernel/pointer.d.ts +357 -0
  63. package/dist/kernel/pointer.d.ts.map +1 -0
  64. package/dist/kernel/renderKit.d.ts +49 -0
  65. package/dist/kernel/renderKit.d.ts.map +1 -0
  66. package/dist/kernel/renderer.d.ts +83 -0
  67. package/dist/kernel/renderer.d.ts.map +1 -0
  68. package/dist/kernel/resources.d.ts +112 -0
  69. package/dist/kernel/resources.d.ts.map +1 -0
  70. package/dist/kernel/sceneGraph.d.ts +155 -0
  71. package/dist/kernel/sceneGraph.d.ts.map +1 -0
  72. package/dist/kernel/sceneIndex.d.ts +90 -0
  73. package/dist/kernel/sceneIndex.d.ts.map +1 -0
  74. package/dist/kernel/stage.d.ts +87 -0
  75. package/dist/kernel/stage.d.ts.map +1 -0
  76. package/dist/kernel/textLayout.d.ts +29 -0
  77. package/dist/kernel/textLayout.d.ts.map +1 -0
  78. package/dist/kernel/tween.d.ts +35 -0
  79. package/dist/kernel/tween.d.ts.map +1 -0
  80. package/dist/kernel/xrInput.d.ts +107 -0
  81. package/dist/kernel/xrInput.d.ts.map +1 -0
  82. package/dist/kernel/xrLocomotion.d.ts +38 -0
  83. package/dist/kernel/xrLocomotion.d.ts.map +1 -0
  84. package/dist/runtime/FrameSource.d.ts +29 -0
  85. package/dist/runtime/FrameSource.d.ts.map +1 -0
  86. package/dist/runtime/ResourceRegistry.d.ts +18 -0
  87. package/dist/runtime/ResourceRegistry.d.ts.map +1 -0
  88. package/dist/runtime/SceneRuntime.d.ts +68 -0
  89. package/dist/runtime/SceneRuntime.d.ts.map +1 -0
  90. package/dist/runtime/SceneSchema.d.ts +2536 -0
  91. package/dist/runtime/SceneSchema.d.ts.map +1 -0
  92. package/dist/runtime/errors.d.ts +19 -0
  93. package/dist/runtime/errors.d.ts.map +1 -0
  94. package/dist/runtime/index.d.ts +11 -0
  95. package/dist/runtime/index.d.ts.map +1 -0
  96. package/dist/webgl/contactShadows.d.ts +5 -0
  97. package/dist/webgl/contactShadows.d.ts.map +1 -0
  98. package/dist/webgl/index.d.ts +11 -0
  99. package/dist/webgl/index.d.ts.map +1 -0
  100. package/dist/webgl/index.js +239 -0
  101. package/dist/webgl/index.js.map +13 -0
  102. package/dist/webgl/shaderGrid.d.ts +27 -0
  103. package/dist/webgl/shaderGrid.d.ts.map +1 -0
  104. package/dist/webgl/sky.d.ts +4 -0
  105. package/dist/webgl/sky.d.ts.map +1 -0
  106. package/dist/webgpu/contactShadows.d.ts +5 -0
  107. package/dist/webgpu/contactShadows.d.ts.map +1 -0
  108. package/dist/webgpu/index.d.ts +10 -0
  109. package/dist/webgpu/index.d.ts.map +1 -0
  110. package/dist/webgpu/index.js +216 -0
  111. package/dist/webgpu/index.js.map +13 -0
  112. package/dist/webgpu/shaderGrid.d.ts +5 -0
  113. package/dist/webgpu/shaderGrid.d.ts.map +1 -0
  114. package/dist/webgpu/sky.d.ts +4 -0
  115. package/dist/webgpu/sky.d.ts.map +1 -0
  116. package/package.json +82 -4
  117. package/src/index.ts +11 -0
  118. package/src/kernel/animation.ts +24 -0
  119. package/src/kernel/behaviours.ts +36 -0
  120. package/src/kernel/bodies.ts +338 -0
  121. package/src/kernel/bodySources.ts +203 -0
  122. package/src/kernel/build.ts +1325 -0
  123. package/src/kernel/cameraMotion.ts +202 -0
  124. package/src/kernel/clock.ts +35 -0
  125. package/src/kernel/contactShadowPasses.ts +207 -0
  126. package/src/kernel/description.ts +1197 -0
  127. package/src/kernel/diff.ts +383 -0
  128. package/src/kernel/environmentPresets.ts +38 -0
  129. package/src/kernel/equality.ts +604 -0
  130. package/src/kernel/frames.ts +124 -0
  131. package/src/kernel/index.ts +274 -0
  132. package/src/kernel/instances.ts +97 -0
  133. package/src/kernel/labels.ts +54 -0
  134. package/src/kernel/loop.ts +248 -0
  135. package/src/kernel/materials.ts +258 -0
  136. package/src/kernel/motion.ts +75 -0
  137. package/src/kernel/orbit.ts +554 -0
  138. package/src/kernel/overlays.ts +130 -0
  139. package/src/kernel/performance.ts +101 -0
  140. package/src/kernel/physics.ts +361 -0
  141. package/src/kernel/physicsDebug.ts +68 -0
  142. package/src/kernel/pointer.ts +785 -0
  143. package/src/kernel/renderKit.ts +54 -0
  144. package/src/kernel/renderer.ts +136 -0
  145. package/src/kernel/resources.ts +504 -0
  146. package/src/kernel/sceneGraph.ts +1442 -0
  147. package/src/kernel/sceneIndex.ts +219 -0
  148. package/src/kernel/stage.ts +157 -0
  149. package/src/kernel/textLayout.ts +102 -0
  150. package/src/kernel/tween.ts +80 -0
  151. package/src/kernel/xrInput.ts +230 -0
  152. package/src/kernel/xrLocomotion.ts +72 -0
  153. package/src/runtime/FrameSource.ts +41 -0
  154. package/src/runtime/ResourceRegistry.ts +24 -0
  155. package/src/runtime/SceneRuntime.ts +229 -0
  156. package/src/runtime/SceneSchema.ts +983 -0
  157. package/src/runtime/errors.ts +18 -0
  158. package/src/runtime/index.ts +10 -0
  159. package/src/webgl/contactShadows.ts +67 -0
  160. package/src/webgl/index.ts +19 -0
  161. package/src/webgl/shaderGrid.ts +196 -0
  162. package/src/webgl/sky.ts +42 -0
  163. package/src/webgpu/contactShadows.ts +83 -0
  164. package/src/webgpu/index.ts +19 -0
  165. package/src/webgpu/shaderGrid.ts +158 -0
  166. package/src/webgpu/sky.ts +35 -0
@@ -0,0 +1,983 @@
1
+ /**
2
+ * Effect Schemas for scene descriptions.
3
+ *
4
+ * They validate untrusted descriptions at the boundary, type the Foldkit `scene`
5
+ * property and derive property-test generators. Each decoded `Type` is checked at compile
6
+ * time to be exactly the kernel's description type, so the two can't drift.
7
+ *
8
+ * @module
9
+ */
10
+ import { Schema } from 'effect';
11
+
12
+ import { handJoints, type SceneNode as KernelSceneNode } from '../kernel/description.ts';
13
+
14
+ const NonNegative = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0));
15
+ const Positive = Schema.Finite.check(Schema.isGreaterThan(0));
16
+ const UnitInterval = Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 1 }));
17
+
18
+ /** A three-component vector `[x, y, z]` of finite numbers. */
19
+ export const Vec3 = Schema.Tuple([Schema.Finite, Schema.Finite, Schema.Finite]);
20
+
21
+ /** A rotation axis. */
22
+ export const Axis = Schema.Literals(['x', 'y', 'z']);
23
+
24
+ /** A 24-bit RGB colour, for example `0x3366ff`. */
25
+ export const Rgb = Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 0xffffff }));
26
+
27
+ /** Model-owned Euler angles, or a spin behaviour that owns the rotation. */
28
+ export const Rotation = Schema.Union([
29
+ Schema.TaggedStruct('Fixed', { euler: Vec3 }),
30
+ Schema.TaggedStruct('Spin', {
31
+ axis: Axis,
32
+ radiansPerSecond: Schema.Finite,
33
+ phase: Schema.Finite,
34
+ }),
35
+ ]);
36
+
37
+ /** Box geometry parameters. */
38
+ export const BoxGeometry = Schema.TaggedStruct('Box', {
39
+ width: Positive,
40
+ height: Positive,
41
+ depth: Positive,
42
+ });
43
+
44
+ const Segments = Schema.Int.check(Schema.isGreaterThanOrEqualTo(3));
45
+
46
+ /** Sphere geometry parameters. */
47
+ export const SphereGeometry = Schema.TaggedStruct('Sphere', {
48
+ radius: Positive,
49
+ widthSegments: Segments,
50
+ heightSegments: Schema.Int.check(Schema.isGreaterThanOrEqualTo(2)),
51
+ });
52
+
53
+ /** Plane geometry parameters. */
54
+ export const PlaneGeometry = Schema.TaggedStruct('Plane', { width: Positive, height: Positive });
55
+
56
+ /** Cylinder geometry parameters. A zero radius makes a cone. */
57
+ export const CylinderGeometry = Schema.TaggedStruct('Cylinder', {
58
+ radiusTop: NonNegative,
59
+ radiusBottom: NonNegative,
60
+ height: Positive,
61
+ radialSegments: Segments,
62
+ });
63
+
64
+ /** Torus geometry parameters. */
65
+ export const TorusGeometry = Schema.TaggedStruct('Torus', {
66
+ radius: Positive,
67
+ tube: Positive,
68
+ radialSegments: Segments,
69
+ tubularSegments: Segments,
70
+ });
71
+
72
+ /** Cone geometry parameters. */
73
+ export const ConeGeometry = Schema.TaggedStruct('Cone', {
74
+ radius: Positive,
75
+ height: Positive,
76
+ radialSegments: Segments,
77
+ });
78
+
79
+ /** Capsule geometry parameters. */
80
+ export const CapsuleGeometry = Schema.TaggedStruct('Capsule', {
81
+ radius: Positive,
82
+ height: NonNegative,
83
+ capSegments: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
84
+ radialSegments: Segments,
85
+ });
86
+
87
+ /** Ring geometry parameters. */
88
+ export const RingGeometry = Schema.TaggedStruct('Ring', {
89
+ innerRadius: NonNegative,
90
+ outerRadius: Positive,
91
+ thetaSegments: Segments,
92
+ });
93
+
94
+ /** Circle geometry parameters. */
95
+ export const CircleGeometry = Schema.TaggedStruct('Circle', {
96
+ radius: Positive,
97
+ segments: Segments,
98
+ });
99
+
100
+ const Steps = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));
101
+
102
+ /** Text from a lent typeface font. */
103
+ export const TextGeometry = Schema.TaggedStruct('Text', {
104
+ text: Schema.String,
105
+ font: Schema.String,
106
+ size: Positive,
107
+ depth: NonNegative,
108
+ curveSegments: Steps,
109
+ bevel: Schema.NullOr(
110
+ Schema.Struct({
111
+ thickness: NonNegative,
112
+ size: NonNegative,
113
+ offset: Schema.Finite,
114
+ segments: Steps,
115
+ }),
116
+ ),
117
+ center: Schema.Boolean,
118
+ letterSpacing: Schema.Finite,
119
+ lineHeight: NonNegative,
120
+ align: Schema.Literals(['left', 'center', 'right']),
121
+ });
122
+
123
+ /** Any geometry shape. */
124
+ export const ShapeGeometry = Schema.Union([
125
+ TextGeometry,
126
+ BoxGeometry,
127
+ SphereGeometry,
128
+ PlaneGeometry,
129
+ CylinderGeometry,
130
+ TorusGeometry,
131
+ ConeGeometry,
132
+ CapsuleGeometry,
133
+ RingGeometry,
134
+ CircleGeometry,
135
+ ]);
136
+
137
+ /** A registered behaviour, by name, with numeric parameters. */
138
+ export const Behave = Schema.Struct({
139
+ name: Schema.String,
140
+ params: Schema.Record(Schema.String, Schema.Finite),
141
+ });
142
+
143
+ /** How a transition progresses. */
144
+ export const Easing = Schema.Literals(['linear', 'easeInOutCubic', 'easeOutCubic', 'easeOutBack']);
145
+
146
+ /** How position and scale changes are shown. */
147
+ export const Transition = Schema.Union([
148
+ Schema.TaggedStruct('Instant', {}),
149
+ Schema.TaggedStruct('Ease', { seconds: Positive, easing: Easing }),
150
+ ]);
151
+
152
+ /** Which faces a material draws. */
153
+ export const MaterialSide = Schema.Literals(['front', 'back', 'double']);
154
+
155
+ /** A texture lent to the store, by id, or `null` for none. */
156
+ const TextureId = Schema.NullOr(Schema.String);
157
+
158
+ const surface = {
159
+ opacity: UnitInterval,
160
+ transparent: Schema.Boolean,
161
+ side: MaterialSide,
162
+ wireframe: Schema.Boolean,
163
+ };
164
+
165
+ const shaded = { ...surface, flatShading: Schema.Boolean };
166
+
167
+ /** Unlit material parameters. */
168
+ export const BasicMaterial = Schema.TaggedStruct('Basic', {
169
+ color: Rgb,
170
+ map: TextureId,
171
+ ...surface,
172
+ });
173
+
174
+ /** Matte material parameters. */
175
+ export const LambertMaterial = Schema.TaggedStruct('Lambert', {
176
+ color: Rgb,
177
+ map: TextureId,
178
+ emissive: Rgb,
179
+ ...shaded,
180
+ });
181
+
182
+ /** Shiny material parameters. */
183
+ export const PhongMaterial = Schema.TaggedStruct('Phong', {
184
+ color: Rgb,
185
+ map: TextureId,
186
+ emissive: Rgb,
187
+ specular: Rgb,
188
+ shininess: NonNegative,
189
+ ...shaded,
190
+ });
191
+
192
+ const pbr = {
193
+ color: Rgb,
194
+ map: TextureId,
195
+ roughness: UnitInterval,
196
+ metalness: UnitInterval,
197
+ emissive: Rgb,
198
+ emissiveIntensity: NonNegative,
199
+ };
200
+
201
+ /** Standard (PBR) material parameters. */
202
+ export const StandardMaterial = Schema.TaggedStruct('Standard', { ...pbr, ...shaded });
203
+
204
+ /** Physical material parameters: index of refraction in [1, 2.333], the range three.js documents. */
205
+ export const PhysicalMaterial = Schema.TaggedStruct('Physical', {
206
+ ...pbr,
207
+ clearcoat: UnitInterval,
208
+ clearcoatRoughness: UnitInterval,
209
+ transmission: UnitInterval,
210
+ ior: Schema.Finite.check(Schema.isBetween({ minimum: 1, maximum: 2.333 })),
211
+ ...shaded,
212
+ });
213
+
214
+ /** Normal-coloured material parameters. */
215
+ export const NormalMaterial = Schema.TaggedStruct('Normal', shaded);
216
+
217
+ /** A shadow catcher: only the shadows cast onto it. */
218
+ export const ShadowMaterial = Schema.TaggedStruct('Shadow', { color: Rgb, opacity: UnitInterval });
219
+
220
+ /** Any material kind. */
221
+ export const SurfaceMaterial = Schema.Union([
222
+ ShadowMaterial,
223
+ BasicMaterial,
224
+ LambertMaterial,
225
+ PhongMaterial,
226
+ StandardMaterial,
227
+ PhysicalMaterial,
228
+ NormalMaterial,
229
+ ]);
230
+
231
+ /** An owned geometry or a reference to a shared one. */
232
+ export const GeometryRef = Schema.Union([
233
+ ...ShapeGeometry.members,
234
+ Schema.TaggedStruct('SharedGeometry', { id: Schema.String }),
235
+ Schema.TaggedStruct('LentGeometry', { id: Schema.String }),
236
+ ]);
237
+
238
+ /** An owned material or a reference to a shared one. */
239
+ export const MaterialRef = Schema.Union([
240
+ ...SurfaceMaterial.members,
241
+ Schema.TaggedStruct('SharedMaterial', { id: Schema.String }),
242
+ ]);
243
+
244
+ /** Shared resource definitions. */
245
+ export const ResourceDefinitions = Schema.Struct({
246
+ geometries: Schema.Array(Schema.Struct({ id: Schema.String, geometry: ShapeGeometry })),
247
+ materials: Schema.Array(Schema.Struct({ id: Schema.String, material: SurfaceMaterial })),
248
+ });
249
+
250
+ /** A renderable mesh. */
251
+ const Upright = { halfHeight: Positive, radius: Positive };
252
+
253
+ /** A collider of a body's own, placed in it. */
254
+ export const ColliderDescription = Schema.Struct({
255
+ shape: Schema.Union([
256
+ Schema.TaggedStruct('Cuboid', { halfExtents: Vec3 }),
257
+ Schema.TaggedStruct('Ball', { radius: Positive }),
258
+ Schema.TaggedStruct('Capsule', Upright),
259
+ Schema.TaggedStruct('Cylinder', Upright),
260
+ Schema.TaggedStruct('Cone', Upright),
261
+ ]),
262
+ position: Vec3,
263
+ rotation: Vec3,
264
+ name: Schema.NullOr(Schema.String),
265
+ });
266
+
267
+ const Group = Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 15 }));
268
+
269
+ /** Collision groups: those a body is in, and those it interacts with (null: all). */
270
+ export const InteractionGroups = Schema.Struct({
271
+ memberships: Schema.Array(Group),
272
+ filters: Schema.NullOr(Schema.Array(Group)),
273
+ });
274
+
275
+ /** A rigid body for a mesh, group, model or instances. */
276
+ export const Body = Schema.Struct({
277
+ type: Schema.Literals(['dynamic', 'fixed', 'kinematic']),
278
+ collider: Schema.Literals(['cuboid', 'ball', 'hull', 'trimesh']),
279
+ mass: Schema.NullOr(Positive),
280
+ friction: NonNegative,
281
+ restitution: NonNegative,
282
+ linearDamping: NonNegative,
283
+ angularDamping: NonNegative,
284
+ gravityScale: Schema.Finite,
285
+ ccd: Schema.Boolean,
286
+ sensor: Schema.Boolean,
287
+ linearVelocity: Vec3,
288
+ angularVelocity: Vec3,
289
+ impulse: Schema.NullOr(Schema.Struct({ id: Schema.Finite, impulse: Vec3 })),
290
+ colliders: Schema.NullOr(Schema.Array(ColliderDescription)),
291
+ contactForces: Schema.NullOr(NonNegative),
292
+ collisionGroups: Schema.NullOr(InteractionGroups),
293
+ solverGroups: Schema.NullOr(InteractionGroups),
294
+ });
295
+
296
+ /** A physics world. */
297
+ const Handedness = Schema.Literals(['left', 'right']);
298
+
299
+ /** A space an immersive session tracks, for a group to follow. */
300
+ export const XrSpace = Schema.Union([
301
+ Schema.TaggedStruct('Head', {}),
302
+ Schema.TaggedStruct('Joint', { hand: Handedness, joint: Schema.Literals(handJoints) }),
303
+ Schema.TaggedStruct('Controller', { hand: Handedness, space: Schema.Literals(['grip', 'ray']) }),
304
+ Schema.TaggedStruct('Anchor', { id: Schema.String }),
305
+ Schema.TaggedStruct('Plane', { id: Schema.String }),
306
+ Schema.TaggedStruct('Mesh', { id: Schema.String }),
307
+ ]);
308
+
309
+ /** A body a joint holds: a node's, or one instance's. */
310
+ export const BodyRef = Schema.Struct({
311
+ key: Schema.String,
312
+ instance: Schema.NullOr(Schema.String),
313
+ });
314
+
315
+ /** A joint's motor: a target position and velocity, and how hard it pursues each. */
316
+ export const JointMotor = Schema.Struct({
317
+ position: Schema.Finite,
318
+ velocity: Schema.Finite,
319
+ stiffness: NonNegative,
320
+ damping: NonNegative,
321
+ });
322
+
323
+ /** A joint's range of motion. */
324
+ export const JointLimits = Schema.Tuple([Schema.Finite, Schema.Finite]);
325
+
326
+ /** How a joint holds its bodies. */
327
+ export const JointKind = Schema.Union([
328
+ Schema.TaggedStruct('Fixed', { frameA: Vec3, frameB: Vec3 }),
329
+ Schema.TaggedStruct('Spherical', {}),
330
+ Schema.TaggedStruct('Revolute', {
331
+ axis: Vec3,
332
+ limits: Schema.NullOr(JointLimits),
333
+ motor: Schema.NullOr(JointMotor),
334
+ }),
335
+ Schema.TaggedStruct('Prismatic', {
336
+ axis: Vec3,
337
+ limits: Schema.NullOr(JointLimits),
338
+ motor: Schema.NullOr(JointMotor),
339
+ }),
340
+ Schema.TaggedStruct('Rope', { length: Schema.Finite }),
341
+ Schema.TaggedStruct('Spring', {
342
+ restLength: Schema.Finite,
343
+ stiffness: Schema.Finite,
344
+ damping: Schema.Finite,
345
+ }),
346
+ ]);
347
+
348
+ /** A joint between two bodies. */
349
+ export const Joint = Schema.Struct({
350
+ key: Schema.String,
351
+ a: BodyRef,
352
+ b: BodyRef,
353
+ anchorA: Vec3,
354
+ anchorB: Vec3,
355
+ kind: JointKind,
356
+ contacts: Schema.Boolean,
357
+ });
358
+
359
+ export const Physics = Schema.Struct({
360
+ gravity: Vec3,
361
+ paused: Schema.Boolean,
362
+ timeStep: Positive,
363
+ interpolate: Schema.Boolean,
364
+ debug: Schema.Boolean,
365
+ joints: Schema.Array(Joint),
366
+ });
367
+
368
+ export const MeshNode = Schema.TaggedStruct('Mesh', {
369
+ key: Schema.String,
370
+ position: Vec3,
371
+ rotation: Rotation,
372
+ scale: Vec3,
373
+ transition: Transition,
374
+ behaviour: Schema.NullOr(Behave),
375
+ geometry: GeometryRef,
376
+ material: MaterialRef,
377
+ interactive: Schema.Boolean,
378
+ castShadow: Schema.Boolean,
379
+ receiveShadow: Schema.Boolean,
380
+ body: Schema.NullOr(Body),
381
+ });
382
+
383
+ /** One instance of an instances node. */
384
+ export const Instance = Schema.Struct({
385
+ key: Schema.String,
386
+ position: Vec3,
387
+ rotation: Vec3,
388
+ scale: Vec3,
389
+ color: Rgb,
390
+ });
391
+
392
+ /** Many instances of one geometry and material. */
393
+ export const InstancesNode = Schema.TaggedStruct('Instances', {
394
+ key: Schema.String,
395
+ position: Vec3,
396
+ rotation: Rotation,
397
+ scale: Vec3,
398
+ transition: Transition,
399
+ behaviour: Schema.NullOr(Behave),
400
+ geometry: GeometryRef,
401
+ material: MaterialRef,
402
+ interactive: Schema.Boolean,
403
+ castShadow: Schema.Boolean,
404
+ receiveShadow: Schema.Boolean,
405
+ instances: Schema.Array(Instance),
406
+ body: Schema.NullOr(Body),
407
+ });
408
+
409
+ /** An application object lent to the store under `id`. */
410
+ export const Animation = Schema.Struct({
411
+ clip: Schema.String,
412
+ speed: Schema.Finite,
413
+ loop: Schema.Boolean,
414
+ });
415
+
416
+ export const BorrowedNode = Schema.TaggedStruct('Borrowed', {
417
+ key: Schema.String,
418
+ id: Schema.String,
419
+ animation: Schema.NullOr(Animation),
420
+ position: Vec3,
421
+ rotation: Rotation,
422
+ scale: Vec3,
423
+ transition: Transition,
424
+ behaviour: Schema.NullOr(Behave),
425
+ interactive: Schema.Boolean,
426
+ body: Schema.NullOr(Body),
427
+ });
428
+
429
+ /** Distance-field text. */
430
+ export const LabelNode = Schema.TaggedStruct('Label', {
431
+ key: Schema.String,
432
+ position: Vec3,
433
+ rotation: Rotation,
434
+ scale: Vec3,
435
+ transition: Transition,
436
+ behaviour: Schema.NullOr(Behave),
437
+ interactive: Schema.Boolean,
438
+ text: Schema.String,
439
+ font: Schema.NullOr(Schema.String),
440
+ fontSize: Positive,
441
+ color: Rgb,
442
+ fillOpacity: NonNegative,
443
+ anchorX: Schema.Union([Schema.Literals(['left', 'center', 'right']), Schema.Finite]),
444
+ anchorY: Schema.Union([
445
+ Schema.Literals(['top', 'top-baseline', 'middle', 'bottom-baseline', 'bottom']),
446
+ Schema.Finite,
447
+ ]),
448
+ maxWidth: Schema.NullOr(Positive),
449
+ lineHeight: Schema.NullOr(Positive),
450
+ letterSpacing: Schema.Finite,
451
+ textAlign: Schema.Literals(['left', 'right', 'center', 'justify']),
452
+ outlineWidth: NonNegative,
453
+ outlineColor: Rgb,
454
+ outlineOpacity: NonNegative,
455
+ outlineBlur: NonNegative,
456
+ colorRanges: Schema.Array(
457
+ Schema.Struct({ start: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), color: Rgb }),
458
+ ),
459
+ curveRadius: Schema.Finite,
460
+ material: Schema.NullOr(MaterialRef),
461
+ });
462
+
463
+ /** Uniform ambient light. */
464
+ export const AmbientLightNode = Schema.TaggedStruct('AmbientLight', {
465
+ key: Schema.String,
466
+ color: Rgb,
467
+ intensity: NonNegative,
468
+ });
469
+
470
+ /** Directional light. */
471
+ const isPowerOfTwo = (size: number) =>
472
+ Number.isInteger(Math.log2(size)) || 'expected a power of two';
473
+
474
+ /** Shadow map size: a power of two from 16 to 8192 texels. */
475
+ const ShadowMapSize = Schema.Int.check(
476
+ Schema.isBetween({ minimum: 16, maximum: 8192 }),
477
+ Schema.makeFilter(isPowerOfTwo),
478
+ );
479
+
480
+ export const DirectionalLightNode = Schema.TaggedStruct('DirectionalLight', {
481
+ key: Schema.String,
482
+ color: Rgb,
483
+ intensity: NonNegative,
484
+ position: Vec3,
485
+ castShadow: Schema.Boolean,
486
+ shadowMapSize: ShadowMapSize,
487
+ shadowBias: Schema.Finite,
488
+ shadowArea: Positive,
489
+ });
490
+
491
+ /** Point light. */
492
+ export const PointLightNode = Schema.TaggedStruct('PointLight', {
493
+ key: Schema.String,
494
+ color: Rgb,
495
+ intensity: NonNegative,
496
+ position: Vec3,
497
+ distance: NonNegative,
498
+ decay: NonNegative,
499
+ castShadow: Schema.Boolean,
500
+ shadowMapSize: ShadowMapSize,
501
+ shadowBias: Schema.Finite,
502
+ });
503
+
504
+ /** Spot light: `angle` in (0, π/2], `penumbra` in [0, 1]. */
505
+ export const SpotLightNode = Schema.TaggedStruct('SpotLight', {
506
+ key: Schema.String,
507
+ color: Rgb,
508
+ intensity: NonNegative,
509
+ position: Vec3,
510
+ target: Vec3,
511
+ distance: NonNegative,
512
+ angle: Schema.Finite.check(
513
+ Schema.isBetween({ minimum: 0, maximum: Math.PI / 2, exclusiveMinimum: true }),
514
+ ),
515
+ penumbra: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 1 })),
516
+ decay: NonNegative,
517
+ castShadow: Schema.Boolean,
518
+ shadowMapSize: ShadowMapSize,
519
+ shadowBias: Schema.Finite,
520
+ });
521
+
522
+ /** Hemisphere light. */
523
+ /** A grid of lines on the XZ plane. */
524
+ export const GridNode = Schema.TaggedStruct('Grid', {
525
+ key: Schema.String,
526
+ position: Vec3,
527
+ size: Positive,
528
+ divisions: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
529
+ color: Rgb,
530
+ centerColor: Rgb,
531
+ });
532
+
533
+ /** Drei's shader grid. */
534
+ export const ShaderGridNode = Schema.TaggedStruct('ShaderGrid', {
535
+ key: Schema.String,
536
+ position: Vec3,
537
+ rotation: Vec3,
538
+ size: Schema.Tuple([Positive, Positive]),
539
+ cellSize: Positive,
540
+ cellThickness: NonNegative,
541
+ cellColor: Rgb,
542
+ sectionSize: Positive,
543
+ sectionThickness: NonNegative,
544
+ sectionColor: Rgb,
545
+ infinite: Schema.Boolean,
546
+ followCamera: Schema.Boolean,
547
+ fadeDistance: Positive,
548
+ fadeStrength: NonNegative,
549
+ fadeFrom: Schema.Finite,
550
+ side: Schema.Literals(['front', 'back', 'double']),
551
+ });
552
+
553
+ export const HemisphereLightNode = Schema.TaggedStruct('HemisphereLight', {
554
+ key: Schema.String,
555
+ color: Rgb,
556
+ groundColor: Rgb,
557
+ intensity: NonNegative,
558
+ position: Vec3,
559
+ });
560
+
561
+ /** Any scene node. Groups nest recursively. */
562
+ export const SceneNode: Schema.Codec<KernelSceneNode> = Schema.Union([
563
+ Schema.TaggedStruct('Group', {
564
+ key: Schema.String,
565
+ position: Vec3,
566
+ rotation: Rotation,
567
+ scale: Vec3,
568
+ transition: Transition,
569
+ behaviour: Schema.NullOr(Behave),
570
+ interactive: Schema.Boolean,
571
+ children: Schema.Array(Schema.suspend((): Schema.Codec<KernelSceneNode> => SceneNode)),
572
+ body: Schema.NullOr(Body),
573
+ follow: Schema.NullOr(XrSpace),
574
+ }),
575
+ MeshNode,
576
+ InstancesNode,
577
+ BorrowedNode,
578
+ LabelNode,
579
+ ShaderGridNode,
580
+ AmbientLightNode,
581
+ DirectionalLightNode,
582
+ PointLightNode,
583
+ SpotLightNode,
584
+ HemisphereLightNode,
585
+ GridNode,
586
+ ]);
587
+
588
+ /** The fraction of the way a camera closes every sixtieth of a second: 0 jumps. */
589
+ const CameraDamping = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThan(1));
590
+
591
+ /** A perspective camera. */
592
+ export const PerspectiveCamera = Schema.TaggedStruct('Perspective', {
593
+ fov: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 180, exclusiveMinimum: true })),
594
+ near: Positive,
595
+ far: Positive,
596
+ position: Vec3,
597
+ lookAt: Vec3,
598
+ damping: CameraDamping,
599
+ autoRotate: Schema.Finite,
600
+ });
601
+
602
+ /** An orthographic camera; `zoom` is CSS pixels per world unit. */
603
+ export const OrthographicCamera = Schema.TaggedStruct('Orthographic', {
604
+ zoom: Positive,
605
+ near: Positive,
606
+ far: Positive,
607
+ position: Vec3,
608
+ lookAt: Vec3,
609
+ damping: CameraDamping,
610
+ autoRotate: Schema.Finite,
611
+ });
612
+
613
+ /** The active camera. */
614
+ export const Camera = Schema.Union([PerspectiveCamera, OrthographicCamera]);
615
+
616
+ const NonNegativeFinite = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0));
617
+
618
+ /** A post-processing effect. */
619
+ export const PostEffect = Schema.Union([
620
+ Schema.TaggedStruct('Bloom', {
621
+ strength: NonNegativeFinite,
622
+ radius: NonNegativeFinite,
623
+ threshold: NonNegativeFinite,
624
+ }),
625
+ Schema.TaggedStruct('Vignette', { offset: NonNegativeFinite, darkness: NonNegativeFinite }),
626
+ Schema.TaggedStruct('Film', { intensity: NonNegativeFinite, grayscale: Schema.Boolean }),
627
+ ]);
628
+
629
+ /** Scene-wide render settings. */
630
+ export const RenderSettings = Schema.Struct({
631
+ effects: Schema.Array(PostEffect),
632
+ frames: Schema.Literals(['always', 'demand', 'never']),
633
+ resolution: Schema.Finite.check(
634
+ Schema.isBetween({ minimum: 0, maximum: 1, exclusiveMinimum: true }),
635
+ ),
636
+ shadows: Schema.Literals(['off', 'basic', 'percentage', 'soft', 'variance']),
637
+ toneMapping: Schema.Literals(['none', 'linear', 'reinhard', 'cineon', 'aces', 'agx', 'neutral']),
638
+ exposure: Positive,
639
+ colorSpace: Schema.Literals(['srgb', 'linear']),
640
+ });
641
+
642
+ /** A view of the scene into part of the canvas. */
643
+ export const View = Schema.Struct({
644
+ key: Schema.String,
645
+ camera: Camera,
646
+ rect: Schema.Struct({
647
+ x: Schema.Finite,
648
+ y: Schema.Finite,
649
+ width: Schema.Finite.check(Schema.isGreaterThan(0)),
650
+ height: Schema.Finite.check(Schema.isGreaterThan(0)),
651
+ }),
652
+ });
653
+
654
+ /** A scene rendered into a texture lent under `id`. */
655
+ export const RenderTexture = Schema.Struct({
656
+ id: Schema.String,
657
+ width: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 8192 })),
658
+ height: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 8192 })),
659
+ camera: Camera,
660
+ background: Schema.NullOr(Rgb),
661
+ children: Schema.Array(SceneNode),
662
+ });
663
+
664
+ /** A complete scene description. */
665
+ /** A point to show HTML at. */
666
+ export const Overlay = Schema.Struct({
667
+ key: Schema.String,
668
+ node: Schema.NullOr(Schema.String),
669
+ position: Vec3,
670
+ center: Schema.Boolean,
671
+ distanceFactor: Schema.NullOr(Positive),
672
+ occlude: Schema.Boolean,
673
+ zIndexRange: Schema.Tuple([Schema.Int, Schema.Int]),
674
+ view: Schema.NullOr(Schema.String),
675
+ });
676
+
677
+ /** Image-based lighting and background. */
678
+ export const Environment = Schema.Struct({
679
+ map: Schema.NullOr(Schema.String),
680
+ background: Schema.Union([Schema.Boolean, Schema.Literal('only')]),
681
+ backgroundBlurriness: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 1 })),
682
+ backgroundIntensity: NonNegative,
683
+ environmentIntensity: NonNegative,
684
+ });
685
+
686
+ /** A daylight sky. */
687
+ export const Sky = Schema.Struct({
688
+ sunPosition: Vec3,
689
+ turbidity: NonNegative,
690
+ rayleigh: NonNegative,
691
+ mieCoefficient: NonNegative,
692
+ mieDirectionalG: UnitInterval,
693
+ clouds: UnitInterval,
694
+ distance: Positive,
695
+ });
696
+
697
+ /** Soft ground shadows. */
698
+ export const ContactShadows = Schema.Struct({
699
+ position: Vec3,
700
+ size: Schema.Tuple([Positive, Positive]),
701
+ near: Schema.Finite,
702
+ far: Positive,
703
+ blur: NonNegative,
704
+ smooth: Schema.Boolean,
705
+ opacity: UnitInterval,
706
+ color: Rgb,
707
+ resolution: Schema.Int.check(Schema.isBetween({ minimum: 16, maximum: 4096 })),
708
+ });
709
+
710
+ /** Immersive presentation. */
711
+ /** An anchor the description places in the scene. */
712
+ export const XrAnchor = Schema.Struct({ id: Schema.String, position: Vec3, rotation: Vec3 });
713
+
714
+ export const Xr = Schema.Struct({
715
+ origin: Vec3,
716
+ heading: Schema.Finite,
717
+ referenceSpace: Schema.Literals(['local-floor', 'local', 'bounded-floor']),
718
+ framebufferScale: Positive,
719
+ hitTest: Schema.Boolean,
720
+ showInputs: Schema.Boolean,
721
+ anchors: Schema.Array(XrAnchor),
722
+ planes: Schema.Boolean,
723
+ meshes: Schema.Boolean,
724
+ domOverlay: Schema.Boolean,
725
+ glide: Schema.NullOr(
726
+ Schema.Struct({
727
+ speed: NonNegative,
728
+ turn: Schema.Literals(['smooth', 'snap']),
729
+ turnSpeed: NonNegative,
730
+ snapDegrees: NonNegative,
731
+ }),
732
+ ),
733
+ });
734
+
735
+ /** Whether the scene claims the pointer's gestures from the page. */
736
+ export const Gestures = Schema.Literals(['page', 'scene']);
737
+
738
+ export const SceneDescription = Schema.Struct({
739
+ camera: Camera,
740
+ gestures: Gestures,
741
+ views: Schema.Array(View),
742
+ renderTextures: Schema.Array(RenderTexture),
743
+ overlays: Schema.Array(Overlay),
744
+ environment: Schema.NullOr(Environment),
745
+ sky: Schema.NullOr(Sky),
746
+ contactShadows: Schema.NullOr(ContactShadows),
747
+ physics: Schema.NullOr(Physics),
748
+ xr: Schema.NullOr(Xr),
749
+ measure: Schema.Array(Schema.String),
750
+ render: RenderSettings,
751
+ resources: ResourceDefinitions,
752
+ children: Schema.Array(SceneNode),
753
+ });
754
+
755
+ /** Detail of pointer-leave events: the interactive mesh's key. */
756
+ export const KeyDetail = Schema.Struct({ key: Schema.String });
757
+
758
+ /**
759
+ * Where the pointer met an interactive mesh: its key and ancestor path, the world-space
760
+ * hit point, the distance from the camera, the world-space face normal, the texture
761
+ * coordinates and the pointer's world-space ray.
762
+ */
763
+ export const HitDetail = Schema.Struct({
764
+ key: Schema.String,
765
+ instance: Schema.optionalKey(Schema.String),
766
+ part: Schema.optionalKey(Schema.String),
767
+ view: Schema.optionalKey(Schema.String),
768
+ path: Schema.Array(Schema.String),
769
+ point: Vec3,
770
+ distance: Schema.Finite,
771
+ normal: Vec3,
772
+ uv: Schema.Tuple([Schema.Finite, Schema.Finite]),
773
+ ray: Schema.Struct({ origin: Vec3, direction: Vec3 }),
774
+ });
775
+
776
+ /** Detail of button events: the hit plus `MouseEvent.button`. */
777
+ export const ButtonDetail = Schema.Struct({ ...HitDetail.fields, button: Schema.Int });
778
+
779
+ /** Detail of wheel events: the hit plus `WheelEvent.deltaX` and `deltaY`. */
780
+ export const WheelDetail = Schema.Struct({
781
+ ...HitDetail.fields,
782
+ deltaX: Schema.Finite,
783
+ deltaY: Schema.Finite,
784
+ });
785
+
786
+ /** Detail of a click that hit no interactive mesh. */
787
+ export const MissDetail = Schema.Struct({ button: Schema.Int });
788
+
789
+ /** A world-space ray: an origin and a unit direction. */
790
+ export const Ray = HitDetail.fields.ray;
791
+
792
+ /** Detail of drag events: the captured mesh, the pressed button and the pointer's ray. */
793
+ export const DragDetail = Schema.Struct({ key: Schema.String, button: Schema.Int, ray: Ray });
794
+
795
+ /** Detail of performance changes: the fps average and the new factor (0 to 1). */
796
+ export const PerformanceDetail = Schema.Struct({
797
+ fps: Schema.Finite,
798
+ factor: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 1 })),
799
+ });
800
+
801
+ /** Modifier keys held during an input. */
802
+ export const Modifiers = Schema.Struct({
803
+ shift: Schema.Boolean,
804
+ control: Schema.Boolean,
805
+ meta: Schema.Boolean,
806
+ alt: Schema.Boolean,
807
+ });
808
+
809
+ const regionFields = {
810
+ view: Schema.optionalKey(Schema.String),
811
+ width: Schema.Finite,
812
+ height: Schema.Finite,
813
+ x: Schema.Finite,
814
+ y: Schema.Finite,
815
+ };
816
+
817
+ /** A drag, wheel or pinch on the canvas: distances in CSS pixels since the last one. */
818
+ export const Gesture = Schema.Union([
819
+ Schema.TaggedStruct('Drag', {
820
+ button: Schema.Int,
821
+ modifiers: Modifiers,
822
+ key: Schema.optionalKey(Schema.String),
823
+ ...regionFields,
824
+ deltaX: Schema.Finite,
825
+ deltaY: Schema.Finite,
826
+ }),
827
+ Schema.TaggedStruct('Wheel', {
828
+ modifiers: Modifiers,
829
+ ...regionFields,
830
+ deltaX: Schema.Finite,
831
+ deltaY: Schema.Finite,
832
+ }),
833
+ Schema.TaggedStruct('Pinch', {
834
+ ...regionFields,
835
+ scale: Schema.Finite,
836
+ deltaX: Schema.Finite,
837
+ deltaY: Schema.Finite,
838
+ }),
839
+ ]);
840
+
841
+ /**
842
+ * Detail of collision events: the two bodies' keys (and instances', for bodies on
843
+ * instances), and whether they began touching.
844
+ */
845
+ export const CollisionDetail = Schema.Struct({
846
+ a: Schema.String,
847
+ aInstance: Schema.optionalKey(Schema.String),
848
+ aPart: Schema.optionalKey(Schema.String),
849
+ b: Schema.String,
850
+ bInstance: Schema.optionalKey(Schema.String),
851
+ bPart: Schema.optionalKey(Schema.String),
852
+ started: Schema.Boolean,
853
+ });
854
+
855
+ const XrHand = Schema.Literals(['left', 'right', 'none']);
856
+
857
+ /** Detail of XR stick events: a thumbstick pushed past halfway, or let back. */
858
+ export const XrStickDetail = Schema.Struct({
859
+ hand: XrHand,
860
+ direction: Schema.Literals(['center', 'left', 'right', 'forward', 'back']),
861
+ });
862
+
863
+ /** Detail of XR button events: a controller button pressed or released. */
864
+ export const XrButtonDetail = Schema.Struct({
865
+ hand: XrHand,
866
+ button: Schema.Literals(['trigger', 'squeeze', 'touchpad', 'thumbstick', 'primary', 'secondary']),
867
+ pressed: Schema.Boolean,
868
+ });
869
+
870
+ /** Detail of XR moved events: where gliding left the player. */
871
+ export const XrMovedDetail = Schema.Struct({ origin: Vec3, heading: Schema.Finite });
872
+
873
+ /** Detail of XR surface events: in AR, where a select met a real surface. */
874
+ export const XrSurfaceDetail = Schema.Struct({ hand: XrHand, point: Vec3, normal: Vec3 });
875
+
876
+ /** A detected plane, in the scene's space. */
877
+ export const XrPlane = Schema.Struct({
878
+ id: Schema.String,
879
+ orientation: Schema.Literals(['horizontal', 'vertical']),
880
+ label: Schema.String,
881
+ position: Vec3,
882
+ rotation: Vec3,
883
+ polygon: Schema.Array(Vec3),
884
+ });
885
+
886
+ /** Detail of XR planes events: every plane the session has detected, as it is now. */
887
+ export const XrPlanesDetail = Schema.Struct({ planes: Schema.Array(XrPlane) });
888
+
889
+ /** A detected mesh, in the scene's space: its geometry is lent for `xrMesh(id)`. */
890
+ export const XrMesh = Schema.Struct({
891
+ id: Schema.String,
892
+ label: Schema.String,
893
+ position: Vec3,
894
+ rotation: Vec3,
895
+ });
896
+
897
+ /** Detail of XR meshes events: every mesh the session has detected, as it is now. */
898
+ export const XrMeshesDetail = Schema.Struct({ meshes: Schema.Array(XrMesh) });
899
+
900
+ /** Detail of contact force events: the two bodies, and how hard they pushed. */
901
+ export const ContactForceDetail = Schema.Struct({
902
+ a: Schema.String,
903
+ aInstance: Schema.optionalKey(Schema.String),
904
+ aPart: Schema.optionalKey(Schema.String),
905
+ b: Schema.String,
906
+ bInstance: Schema.optionalKey(Schema.String),
907
+ bPart: Schema.optionalKey(Schema.String),
908
+ totalForce: Vec3,
909
+ totalForceMagnitude: Schema.Finite,
910
+ maxForceDirection: Vec3,
911
+ maxForceMagnitude: Schema.Finite,
912
+ });
913
+
914
+ const Rect = Schema.Tuple([Schema.Finite, Schema.Finite, Schema.Finite, Schema.Finite]);
915
+
916
+ /** Detail of label measured events: a label's laid-out size in its own units. */
917
+ export const LabelMeasuredDetail = Schema.Struct({
918
+ key: Schema.String,
919
+ block: Rect,
920
+ visible: Rect,
921
+ });
922
+
923
+ /** Detail of measured events: a node's world bounding box. */
924
+ export const MeasuredDetail = Schema.Struct({ key: Schema.String, min: Vec3, max: Vec3 });
925
+
926
+ /** Detail of auto-rotated events: where a camera turning by itself got to. */
927
+ export const AutoRotatedDetail = Schema.Struct({
928
+ view: Schema.optionalKey(Schema.String),
929
+ position: Vec3,
930
+ });
931
+
932
+ /** Detail of gesture events. */
933
+ export const GestureDetail = Schema.Struct({ gesture: Gesture });
934
+
935
+ /** A pointer interaction with an interactive mesh, or a miss. */
936
+ export const SceneEvent = Schema.Union([
937
+ Schema.TaggedStruct('PointerEnter', HitDetail.fields),
938
+ Schema.TaggedStruct('PointerLeave', KeyDetail.fields),
939
+ Schema.TaggedStruct('PointerMove', HitDetail.fields),
940
+ Schema.TaggedStruct('PointerDown', ButtonDetail.fields),
941
+ Schema.TaggedStruct('PointerUp', ButtonDetail.fields),
942
+ Schema.TaggedStruct('Click', ButtonDetail.fields),
943
+ Schema.TaggedStruct('DoubleClick', ButtonDetail.fields),
944
+ Schema.TaggedStruct('ContextMenu', HitDetail.fields),
945
+ Schema.TaggedStruct('Wheel', WheelDetail.fields),
946
+ Schema.TaggedStruct('PointerMissed', MissDetail.fields),
947
+ Schema.TaggedStruct('Drag', DragDetail.fields),
948
+ Schema.TaggedStruct('DragEnd', DragDetail.fields),
949
+ Schema.TaggedStruct('Gesture', GestureDetail.fields),
950
+ Schema.TaggedStruct('AutoRotated', AutoRotatedDetail.fields),
951
+ Schema.TaggedStruct('Collision', CollisionDetail.fields),
952
+ Schema.TaggedStruct('Measured', MeasuredDetail.fields),
953
+ Schema.TaggedStruct('LabelMeasured', LabelMeasuredDetail.fields),
954
+ Schema.TaggedStruct('ContactForce', ContactForceDetail.fields),
955
+ Schema.TaggedStruct('XrStick', XrStickDetail.fields),
956
+ Schema.TaggedStruct('XrButton', XrButtonDetail.fields),
957
+ Schema.TaggedStruct('XrSurface', XrSurfaceDetail.fields),
958
+ Schema.TaggedStruct('XrMoved', XrMovedDetail.fields),
959
+ Schema.TaggedStruct('XrPlanes', XrPlanesDetail.fields),
960
+ Schema.TaggedStruct('XrMeshes', XrMeshesDetail.fields),
961
+ Schema.TaggedStruct('PerformanceChanged', PerformanceDetail.fields),
962
+ ]);
963
+
964
+ /** Why a scene description was rejected. */
965
+ export const DescriptionError = Schema.Union([
966
+ Schema.TaggedStruct('DuplicateKey', { key: Schema.String }),
967
+ Schema.TaggedStruct('DuplicateResourceId', {
968
+ resource: Schema.Literals(['geometry', 'material']),
969
+ id: Schema.String,
970
+ }),
971
+ Schema.TaggedStruct('UnknownSharedGeometry', { nodeKey: Schema.String, id: Schema.String }),
972
+ Schema.TaggedStruct('UnknownSharedMaterial', { nodeKey: Schema.String, id: Schema.String }),
973
+ Schema.TaggedStruct('DuplicateInstanceKey', { nodeKey: Schema.String, key: Schema.String }),
974
+ Schema.TaggedStruct('UnknownBehaviour', { nodeKey: Schema.String, name: Schema.String }),
975
+ Schema.TaggedStruct('DuplicateViewKey', { key: Schema.String }),
976
+ Schema.TaggedStruct('DuplicateOverlayKey', { key: Schema.String }),
977
+ Schema.TaggedStruct('UnknownOverlayNode', { key: Schema.String, node: Schema.String }),
978
+ Schema.TaggedStruct('UnknownOverlayView', { key: Schema.String, view: Schema.String }),
979
+ Schema.TaggedStruct('UnknownMeasuredNode', { key: Schema.String }),
980
+ Schema.TaggedStruct('DuplicateJointKey', { key: Schema.String }),
981
+ Schema.TaggedStruct('UnknownJointBody', { joint: Schema.String, body: Schema.String }),
982
+ Schema.TaggedStruct('DuplicateRenderTextureId', { id: Schema.String }),
983
+ ]);