@opsydyn/effect-three 0.3.0 → 0.6.4
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/CHANGELOG.md +56 -0
- package/README.md +15 -1
- package/dist/{index-8cf8t6by.js → index-re3rrfwd.js} +2935 -104
- package/dist/index-re3rrfwd.js.map +56 -0
- package/dist/index-ttwy0znv.js +145 -0
- package/dist/index-ttwy0znv.js.map +12 -0
- package/dist/index.js +557 -147
- package/dist/index.js.map +8 -6
- package/dist/kernel/bodies.d.ts +20 -1
- package/dist/kernel/bodies.d.ts.map +1 -1
- package/dist/kernel/boxSelect.d.ts +22 -0
- package/dist/kernel/boxSelect.d.ts.map +1 -0
- package/dist/kernel/build.d.ts +165 -7
- package/dist/kernel/build.d.ts.map +1 -1
- package/dist/kernel/cameraShake.d.ts.map +1 -1
- package/dist/kernel/describeScene.d.ts +50 -0
- package/dist/kernel/describeScene.d.ts.map +1 -0
- package/dist/kernel/description.d.ts +223 -1
- package/dist/kernel/description.d.ts.map +1 -1
- package/dist/kernel/diff.d.ts +15 -0
- package/dist/kernel/diff.d.ts.map +1 -1
- package/dist/kernel/equality.d.ts +11 -1
- package/dist/kernel/equality.d.ts.map +1 -1
- package/dist/kernel/gizmo.d.ts +69 -0
- package/dist/kernel/gizmo.d.ts.map +1 -0
- package/dist/kernel/history.d.ts +61 -0
- package/dist/kernel/history.d.ts.map +1 -0
- package/dist/kernel/index.d.ts +19 -6
- package/dist/kernel/index.d.ts.map +1 -1
- package/dist/kernel/index.js +124 -3
- package/dist/kernel/index.js.map +1 -1
- package/dist/kernel/inspect.d.ts +85 -0
- package/dist/kernel/inspect.d.ts.map +1 -0
- package/dist/kernel/lineGeometry.d.ts +25 -0
- package/dist/kernel/lineGeometry.d.ts.map +1 -0
- package/dist/kernel/lockstep.d.ts +114 -0
- package/dist/kernel/lockstep.d.ts.map +1 -0
- package/dist/kernel/loop.d.ts.map +1 -1
- package/dist/kernel/materials.d.ts.map +1 -1
- package/dist/kernel/paintOrder.d.ts +53 -0
- package/dist/kernel/paintOrder.d.ts.map +1 -0
- package/dist/kernel/physics.d.ts +39 -0
- package/dist/kernel/physics.d.ts.map +1 -1
- package/dist/kernel/pivot.d.ts +54 -0
- package/dist/kernel/pivot.d.ts.map +1 -0
- package/dist/kernel/pointBuffers.d.ts +17 -0
- package/dist/kernel/pointBuffers.d.ts.map +1 -0
- package/dist/kernel/pointer.d.ts +31 -1
- package/dist/kernel/pointer.d.ts.map +1 -1
- package/dist/kernel/preview.d.ts +32 -0
- package/dist/kernel/preview.d.ts.map +1 -0
- package/dist/kernel/renderKit.d.ts +21 -1
- package/dist/kernel/renderKit.d.ts.map +1 -1
- package/dist/kernel/renderer.d.ts +6 -0
- package/dist/kernel/renderer.d.ts.map +1 -1
- package/dist/kernel/sceneChanges.d.ts +87 -0
- package/dist/kernel/sceneChanges.d.ts.map +1 -0
- package/dist/kernel/sceneGraph.d.ts +9 -1
- package/dist/kernel/sceneGraph.d.ts.map +1 -1
- package/dist/kernel/sceneIndex.d.ts +5 -0
- package/dist/kernel/sceneIndex.d.ts.map +1 -1
- package/dist/kernel/seeded.d.ts +9 -0
- package/dist/kernel/seeded.d.ts.map +1 -0
- package/dist/kernel/shots.d.ts +26 -0
- package/dist/kernel/shots.d.ts.map +1 -0
- package/dist/kernel/tape.d.ts +38 -0
- package/dist/kernel/tape.d.ts.map +1 -0
- package/dist/kernel/timeline.d.ts +60 -0
- package/dist/kernel/timeline.d.ts.map +1 -0
- package/dist/kernel/trail.d.ts +31 -0
- package/dist/kernel/trail.d.ts.map +1 -0
- package/dist/kernel/viewportGizmo.d.ts +25 -0
- package/dist/kernel/viewportGizmo.d.ts.map +1 -0
- package/dist/runtime/Inspector.d.ts +20 -0
- package/dist/runtime/Inspector.d.ts.map +1 -0
- package/dist/runtime/SceneFile.d.ts +462 -0
- package/dist/runtime/SceneFile.d.ts.map +1 -0
- package/dist/runtime/SceneSchema.d.ts +404 -0
- package/dist/runtime/SceneSchema.d.ts.map +1 -1
- package/dist/runtime/errors.d.ts +9 -0
- package/dist/runtime/errors.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +3 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/webgl/index.d.ts.map +1 -1
- package/dist/webgl/index.js +228 -3
- package/dist/webgl/index.js.map +6 -4
- package/dist/webgl/line.d.ts +4 -0
- package/dist/webgl/line.d.ts.map +1 -0
- package/dist/webgl/points.d.ts +4 -0
- package/dist/webgl/points.d.ts.map +1 -0
- package/dist/webgpu/index.d.ts.map +1 -1
- package/dist/webgpu/index.js +206 -26
- package/dist/webgpu/index.js.map +6 -4
- package/dist/webgpu/line.d.ts +4 -0
- package/dist/webgpu/line.d.ts.map +1 -0
- package/dist/webgpu/points.d.ts +4 -0
- package/dist/webgpu/points.d.ts.map +1 -0
- package/package.json +4 -2
- package/src/kernel/bodies.ts +299 -17
- package/src/kernel/boxSelect.ts +73 -0
- package/src/kernel/build.ts +374 -1
- package/src/kernel/cameraShake.ts +3 -13
- package/src/kernel/describeScene.ts +224 -0
- package/src/kernel/description.ts +243 -0
- package/src/kernel/diff.ts +39 -0
- package/src/kernel/equality.ts +123 -0
- package/src/kernel/gizmo.ts +478 -0
- package/src/kernel/history.ts +118 -0
- package/src/kernel/index.ts +110 -1
- package/src/kernel/inspect.ts +214 -0
- package/src/kernel/lineGeometry.ts +75 -0
- package/src/kernel/lockstep.ts +237 -0
- package/src/kernel/loop.ts +7 -0
- package/src/kernel/materials.ts +3 -0
- package/src/kernel/paintOrder.ts +274 -0
- package/src/kernel/physics.ts +86 -1
- package/src/kernel/pivot.ts +418 -0
- package/src/kernel/pointBuffers.ts +115 -0
- package/src/kernel/pointer.ts +98 -17
- package/src/kernel/preview.ts +467 -0
- package/src/kernel/renderKit.ts +23 -1
- package/src/kernel/renderer.ts +6 -0
- package/src/kernel/sceneChanges.ts +265 -0
- package/src/kernel/sceneGraph.ts +354 -11
- package/src/kernel/sceneIndex.ts +8 -0
- package/src/kernel/seeded.ts +18 -0
- package/src/kernel/shots.ts +167 -0
- package/src/kernel/tape.ts +124 -0
- package/src/kernel/timeline.ts +93 -0
- package/src/kernel/trail.ts +170 -0
- package/src/kernel/viewportGizmo.ts +194 -0
- package/src/runtime/Inspector.ts +43 -0
- package/src/runtime/SceneFile.ts +46 -0
- package/src/runtime/SceneSchema.ts +319 -0
- package/src/runtime/errors.ts +6 -0
- package/src/runtime/index.ts +3 -1
- package/src/webgl/index.ts +4 -0
- package/src/webgl/line.ts +66 -0
- package/src/webgl/points.ts +205 -0
- package/src/webgpu/index.ts +4 -0
- package/src/webgpu/line.ts +67 -0
- package/src/webgpu/points.ts +193 -0
- package/dist/index-8cf8t6by.js.map +0 -41
package/src/kernel/pointer.ts
CHANGED
|
@@ -26,10 +26,15 @@ export type Modifiers = {
|
|
|
26
26
|
readonly alt: boolean;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
/** What pressed: `PointerEvent.pointerType`. A finger is less steady than a mouse or pen. */
|
|
30
|
+
export type PointerDevice = 'mouse' | 'pen' | 'touch';
|
|
31
|
+
|
|
29
32
|
/**
|
|
30
33
|
* Pointer input in normalised device coordinates. `button` follows `MouseEvent.button`.
|
|
31
34
|
* `pointer` is the input's `PointerEvent.pointerId` (0 when absent): with two pointers
|
|
32
|
-
* pressed (two fingers), the second only takes part in pinches.
|
|
35
|
+
* pressed (two fingers), the second only takes part in pinches. A press's `device` is
|
|
36
|
+
* what pressed (a mouse when absent); it decides how far a press may travel and still be
|
|
37
|
+
* a click on nothing.
|
|
33
38
|
*/
|
|
34
39
|
export type PointerInput =
|
|
35
40
|
| {
|
|
@@ -45,6 +50,7 @@ export type PointerInput =
|
|
|
45
50
|
readonly button: number;
|
|
46
51
|
readonly pointer?: number;
|
|
47
52
|
readonly modifiers?: Modifiers;
|
|
53
|
+
readonly device?: PointerDevice;
|
|
48
54
|
}
|
|
49
55
|
| {
|
|
50
56
|
readonly _tag: 'PointerUp';
|
|
@@ -209,6 +215,18 @@ export type SceneEvent =
|
|
|
209
215
|
}
|
|
210
216
|
/** A drag, wheel or pinch on the canvas, when the scene claims gestures. */
|
|
211
217
|
| { readonly _tag: 'Gesture'; readonly gesture: Gesture }
|
|
218
|
+
/**
|
|
219
|
+
* A gesture that moved has ended: released, or the pointer left. Only after a `Drag`
|
|
220
|
+
* or `Pinch`, with the press's button, modifiers, mesh and view: the moment to finish
|
|
221
|
+
* what the gesture drew, such as a selection box.
|
|
222
|
+
*/
|
|
223
|
+
| {
|
|
224
|
+
readonly _tag: 'GestureEnd';
|
|
225
|
+
readonly button: number;
|
|
226
|
+
readonly modifiers: Modifiers;
|
|
227
|
+
readonly key?: string;
|
|
228
|
+
readonly view?: string;
|
|
229
|
+
}
|
|
212
230
|
/**
|
|
213
231
|
* A gesture is about to begin on a camera that has turned by itself (`autoRotate`):
|
|
214
232
|
* where it got to, so the Model can keep it (`autoRotated(camera, detail)`) and the
|
|
@@ -273,6 +291,19 @@ export type SceneEvent =
|
|
|
273
291
|
readonly maxForceDirection: Vec3;
|
|
274
292
|
readonly maxForceMagnitude: number;
|
|
275
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* A world on `physics({ until })` reached that step and waits there: its run, its
|
|
296
|
+
* step count, and a checksum of every body's pose, which peers running the same inputs
|
|
297
|
+
* share (ADR-014). It comes after the collisions of the steps that led there. At
|
|
298
|
+
* `physics({ snapshotAt })` it carries a snapshot of the world, to start another `from`.
|
|
299
|
+
*/
|
|
300
|
+
| {
|
|
301
|
+
readonly _tag: 'PhysicsReached';
|
|
302
|
+
readonly run: number;
|
|
303
|
+
readonly step: number;
|
|
304
|
+
readonly checksum: string;
|
|
305
|
+
readonly snapshot?: string;
|
|
306
|
+
}
|
|
276
307
|
/**
|
|
277
308
|
* A measured label's laid-out size changed (`scene({ measure })`, after its glyphs are
|
|
278
309
|
* laid out): in its own units, before its scale, for sizing what goes behind it, as
|
|
@@ -405,14 +436,17 @@ export const createPicker = (graph: SceneGraph): Picker => {
|
|
|
405
436
|
const rayOrigin = new Vector3();
|
|
406
437
|
const rayDirection = new Vector3();
|
|
407
438
|
|
|
408
|
-
/**
|
|
409
|
-
|
|
439
|
+
/**
|
|
440
|
+
* The nearest keyed hit in `on` (the scene's graph or its HUD's) along the raycaster's
|
|
441
|
+
* ray, reporting `view` when there is one.
|
|
442
|
+
*/
|
|
443
|
+
const nearestHit = (on: SceneGraph, view: string | undefined): Hit | undefined => {
|
|
410
444
|
// Recursive, so an interactive group makes every mesh inside it pickable.
|
|
411
|
-
for (const intersection of raycaster.intersectObjects(
|
|
445
|
+
for (const intersection of raycaster.intersectObjects(on.interactiveObjects(), true)) {
|
|
412
446
|
// Hidden things are not hit: a level of detail not showing, as three's `LOD.raycast`.
|
|
413
447
|
if (!shown(intersection.object)) continue;
|
|
414
|
-
const owner = keyedOwner(
|
|
415
|
-
const key = owner === undefined ? undefined :
|
|
448
|
+
const owner = keyedOwner(on, intersection.object);
|
|
449
|
+
const key = owner === undefined ? undefined : on.keyOf(owner);
|
|
416
450
|
if (owner !== undefined && key !== undefined) {
|
|
417
451
|
normal.set(0, 0, 0);
|
|
418
452
|
if (intersection.face) {
|
|
@@ -421,13 +455,13 @@ export const createPicker = (graph: SceneGraph): Picker => {
|
|
|
421
455
|
const instance =
|
|
422
456
|
intersection.instanceId === undefined
|
|
423
457
|
? undefined
|
|
424
|
-
:
|
|
458
|
+
: on.instanceKeyOf(intersection.object, intersection.instanceId);
|
|
425
459
|
return {
|
|
426
460
|
key,
|
|
427
461
|
...(instance === undefined ? {} : { instance }),
|
|
428
462
|
...partOf(owner, intersection.object),
|
|
429
463
|
...(view === undefined ? {} : { view }),
|
|
430
|
-
path: pathOf(
|
|
464
|
+
path: pathOf(on, owner),
|
|
431
465
|
point: toVec3(intersection.point),
|
|
432
466
|
distance: intersection.distance,
|
|
433
467
|
normal: toVec3(normal),
|
|
@@ -439,6 +473,17 @@ export const createPicker = (graph: SceneGraph): Picker => {
|
|
|
439
473
|
return undefined;
|
|
440
474
|
};
|
|
441
475
|
|
|
476
|
+
/** A hit on the HUD's interactive meshes, which are over everything else. */
|
|
477
|
+
const hudHit = (x: number, y: number): Hit | undefined => {
|
|
478
|
+
const hud = graph.hud();
|
|
479
|
+
if (hud === undefined || hud.graph.interactiveObjects().length === 0) return undefined;
|
|
480
|
+
hud.graph.scene.updateMatrixWorld();
|
|
481
|
+
hud.graph.camera.updateMatrixWorld();
|
|
482
|
+
ndc.set(x, y);
|
|
483
|
+
raycaster.setFromCamera(ndc, hud.graph.camera);
|
|
484
|
+
return nearestHit(hud.graph, undefined);
|
|
485
|
+
};
|
|
486
|
+
|
|
442
487
|
const currentRay = (): Ray => ({
|
|
443
488
|
origin: toVec3(raycaster.ray.origin),
|
|
444
489
|
direction: toVec3(raycaster.ray.direction),
|
|
@@ -472,10 +517,12 @@ export const createPicker = (graph: SceneGraph): Picker => {
|
|
|
472
517
|
holdCameras: graph.holdCameras,
|
|
473
518
|
turned: graph.turned,
|
|
474
519
|
pick: (x, y) => {
|
|
520
|
+
const hud = hudHit(x, y);
|
|
521
|
+
if (hud !== undefined) return hud;
|
|
475
522
|
if (graph.interactiveObjects().length === 0) return undefined;
|
|
476
523
|
const view = aim(x, y);
|
|
477
524
|
if (view === false) return undefined;
|
|
478
|
-
return nearestHit(view);
|
|
525
|
+
return nearestHit(graph, view);
|
|
479
526
|
},
|
|
480
527
|
pickRay: (ray) => {
|
|
481
528
|
if (graph.interactiveObjects().length === 0) return undefined;
|
|
@@ -484,7 +531,7 @@ export const createPicker = (graph: SceneGraph): Picker => {
|
|
|
484
531
|
rayOrigin.fromArray(ray.origin),
|
|
485
532
|
rayDirection.fromArray(ray.direction).normalize(),
|
|
486
533
|
);
|
|
487
|
-
return nearestHit(undefined);
|
|
534
|
+
return nearestHit(graph, undefined);
|
|
488
535
|
},
|
|
489
536
|
viewport: graph.viewport,
|
|
490
537
|
};
|
|
@@ -502,14 +549,24 @@ export type PointerTracker = {
|
|
|
502
549
|
|
|
503
550
|
const none: ReadonlyArray<SceneEvent> = [];
|
|
504
551
|
|
|
505
|
-
/**
|
|
506
|
-
|
|
552
|
+
/**
|
|
553
|
+
* How far, in CSS pixels, a press on nothing may travel and still be a miss rather than a
|
|
554
|
+
* drag. React Three Fiber allows 2 (`events.ts`, `delta <= 2`, at pinned `d74622e`), but
|
|
555
|
+
* measures it on the browser's `click`, which a browser only synthesises from a tap that
|
|
556
|
+
* kept within its own, larger touch slop. This kernel works from pointer down and up, so
|
|
557
|
+
* it gives a finger its own allowance: a steady tap wanders a few pixels, a drag far more.
|
|
558
|
+
*/
|
|
559
|
+
const missTolerances = { mouse: 2, pen: 2, touch: 10 } as const satisfies Record<
|
|
560
|
+
PointerDevice,
|
|
561
|
+
number
|
|
562
|
+
>;
|
|
507
563
|
|
|
508
564
|
type Press = {
|
|
509
565
|
readonly key: string | undefined;
|
|
510
566
|
readonly button: number;
|
|
511
567
|
readonly x: number;
|
|
512
568
|
readonly y: number;
|
|
569
|
+
readonly device: PointerDevice;
|
|
513
570
|
};
|
|
514
571
|
|
|
515
572
|
/** The press a gesture began with: its button, modifiers, mesh and region. */
|
|
@@ -532,6 +589,8 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
532
589
|
const pressedPointers = new Map<number, Point>();
|
|
533
590
|
let primary: number | undefined;
|
|
534
591
|
let gesturePress: GesturePress | undefined;
|
|
592
|
+
// Whether the gesture press has moved: only then does its release end a gesture.
|
|
593
|
+
let gestureMoved = false;
|
|
535
594
|
let hovered: string | undefined;
|
|
536
595
|
// The latest press, kept after release: double-click and context-menu events follow it.
|
|
537
596
|
let press: Press | undefined;
|
|
@@ -569,7 +628,10 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
569
628
|
}
|
|
570
629
|
return;
|
|
571
630
|
}
|
|
572
|
-
if (
|
|
631
|
+
if (
|
|
632
|
+
from?.button === event.button &&
|
|
633
|
+
travel(from, event.x, event.y) <= missTolerances[from.device]
|
|
634
|
+
) {
|
|
573
635
|
events.push({ _tag: 'PointerMissed', button: event.button });
|
|
574
636
|
}
|
|
575
637
|
};
|
|
@@ -624,6 +686,7 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
624
686
|
pressedPointers.clear();
|
|
625
687
|
primary = id;
|
|
626
688
|
pressedPointers.set(id, { x: event.x, y: event.y });
|
|
689
|
+
gestureMoved = false;
|
|
627
690
|
const region = picker.region(event.x, event.y);
|
|
628
691
|
reportTurned(region, events);
|
|
629
692
|
// Cameras turning by themselves hold still while it is pressed, as `OrbitControls`.
|
|
@@ -641,6 +704,7 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
641
704
|
const from = pressedPointers.get(id);
|
|
642
705
|
if (from === undefined || gesturePress === undefined) return;
|
|
643
706
|
pressedPointers.set(id, to);
|
|
707
|
+
gestureMoved = true;
|
|
644
708
|
const { view, width, height, x, y } = gesturePress;
|
|
645
709
|
const region = { ...(view === undefined ? {} : { view }), width, height, x, y };
|
|
646
710
|
const moved = pixels(from, to);
|
|
@@ -680,11 +744,22 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
680
744
|
});
|
|
681
745
|
};
|
|
682
746
|
|
|
683
|
-
const endGestures = (): void => {
|
|
747
|
+
const endGestures = (events: Array<SceneEvent>): void => {
|
|
684
748
|
if (gesturePress !== undefined) picker.holdCameras(false);
|
|
749
|
+
if (gesturePress !== undefined && gestureMoved) {
|
|
750
|
+
const { button, modifiers, key, view } = gesturePress;
|
|
751
|
+
events.push({
|
|
752
|
+
_tag: 'GestureEnd',
|
|
753
|
+
button,
|
|
754
|
+
modifiers,
|
|
755
|
+
...(key === undefined ? {} : { key }),
|
|
756
|
+
...(view === undefined ? {} : { view }),
|
|
757
|
+
});
|
|
758
|
+
}
|
|
685
759
|
pressedPointers.clear();
|
|
686
760
|
primary = undefined;
|
|
687
761
|
gesturePress = undefined;
|
|
762
|
+
gestureMoved = false;
|
|
688
763
|
};
|
|
689
764
|
|
|
690
765
|
/**
|
|
@@ -714,7 +789,7 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
714
789
|
if (isSecondary(event, id)) return secondary(event, id);
|
|
715
790
|
const events: Array<SceneEvent> = [];
|
|
716
791
|
if (event._tag === 'PointerLeave') {
|
|
717
|
-
endGestures();
|
|
792
|
+
endGestures(events);
|
|
718
793
|
// A cancelled or abandoned press still ends its drag, at the last known position.
|
|
719
794
|
if (position !== undefined) endDrag(captured(), position.x, position.y, events);
|
|
720
795
|
dragged = false;
|
|
@@ -738,7 +813,13 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
738
813
|
moveGesture(id, event, events);
|
|
739
814
|
break;
|
|
740
815
|
case 'PointerDown':
|
|
741
|
-
press = {
|
|
816
|
+
press = {
|
|
817
|
+
key: hit?.key,
|
|
818
|
+
button: event.button,
|
|
819
|
+
x: event.x,
|
|
820
|
+
y: event.y,
|
|
821
|
+
device: event.device ?? 'mouse',
|
|
822
|
+
};
|
|
742
823
|
pressing = true;
|
|
743
824
|
dragged = false;
|
|
744
825
|
if (hit !== undefined) events.push({ _tag: 'PointerDown', button: event.button, ...hit });
|
|
@@ -748,7 +829,7 @@ export const createPointerTracker = (picker: Picker): PointerTracker => {
|
|
|
748
829
|
release(hit, event, events);
|
|
749
830
|
// Any release ends capture: a mouse's buttons share one pointer.
|
|
750
831
|
endDrag(drag, event.x, event.y, events);
|
|
751
|
-
endGestures();
|
|
832
|
+
endGestures(events);
|
|
752
833
|
break;
|
|
753
834
|
case 'DoubleClick':
|
|
754
835
|
if (hit !== undefined && pressed(hit)) {
|