@react-three-dom/core 0.4.0 → 0.6.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/dist/index.cjs +167 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +159 -2
- package/dist/index.d.ts +159 -2
- package/dist/index.js +164 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6,7 +6,7 @@ var fiber = require('@react-three/fiber');
|
|
|
6
6
|
var threeMeshBvh = require('three-mesh-bvh');
|
|
7
7
|
|
|
8
8
|
// src/version.ts
|
|
9
|
-
var version = "0.
|
|
9
|
+
var version = "0.5.0";
|
|
10
10
|
|
|
11
11
|
// src/debug.ts
|
|
12
12
|
var _enabled = false;
|
|
@@ -1525,6 +1525,7 @@ function findTrackingPair(obj) {
|
|
|
1525
1525
|
function registerSubtree(obj, store, mirror, instanceKey) {
|
|
1526
1526
|
obj.traverse((child) => {
|
|
1527
1527
|
if (!store.has(child) && shouldRegister(instanceKey, child)) {
|
|
1528
|
+
ensureAncestorChain(child, store, mirror);
|
|
1528
1529
|
store.register(child);
|
|
1529
1530
|
mirror.onObjectAdded(child);
|
|
1530
1531
|
}
|
|
@@ -2573,6 +2574,82 @@ function circlePath(center, radiusX, radiusY, steps = 36, pressure = 0.5) {
|
|
|
2573
2574
|
function sleep2(ms) {
|
|
2574
2575
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2575
2576
|
}
|
|
2577
|
+
var _v = new three.Vector3();
|
|
2578
|
+
function projectWorld(point, camera, size) {
|
|
2579
|
+
_v.set(point.x, point.y, point.z).project(camera);
|
|
2580
|
+
if (_v.z > 1) return null;
|
|
2581
|
+
return {
|
|
2582
|
+
x: (_v.x + 1) / 2 * size.width,
|
|
2583
|
+
y: (-_v.y + 1) / 2 * size.height
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
function clickAtWorld(point, _options = {}) {
|
|
2587
|
+
const camera = getCamera();
|
|
2588
|
+
const gl = getRenderer();
|
|
2589
|
+
const size = getCanvasSize();
|
|
2590
|
+
const canvas = gl.domElement;
|
|
2591
|
+
const screen = projectWorld(point, camera, size);
|
|
2592
|
+
if (!screen) {
|
|
2593
|
+
r3fLog("interaction", `clickAtWorld(${point.x}, ${point.y}, ${point.z}) \u2014 behind camera, skipped`);
|
|
2594
|
+
return { dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: true };
|
|
2595
|
+
}
|
|
2596
|
+
r3fLog("interaction", `clickAtWorld(${point.x}, ${point.y}, ${point.z}) \u2192 screen(${Math.round(screen.x)}, ${Math.round(screen.y)})`);
|
|
2597
|
+
dispatchClick(canvas, screen);
|
|
2598
|
+
return { dispatched: true, screenPoint: screen, behindCamera: false };
|
|
2599
|
+
}
|
|
2600
|
+
function doubleClickAtWorld(point, _options = {}) {
|
|
2601
|
+
const camera = getCamera();
|
|
2602
|
+
const gl = getRenderer();
|
|
2603
|
+
const size = getCanvasSize();
|
|
2604
|
+
const canvas = gl.domElement;
|
|
2605
|
+
const screen = projectWorld(point, camera, size);
|
|
2606
|
+
if (!screen) {
|
|
2607
|
+
r3fLog("interaction", `doubleClickAtWorld(${point.x}, ${point.y}, ${point.z}) \u2014 behind camera, skipped`);
|
|
2608
|
+
return { dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: true };
|
|
2609
|
+
}
|
|
2610
|
+
r3fLog("interaction", `doubleClickAtWorld(${point.x}, ${point.y}, ${point.z}) \u2192 screen(${Math.round(screen.x)}, ${Math.round(screen.y)})`);
|
|
2611
|
+
dispatchDoubleClick(canvas, screen);
|
|
2612
|
+
return { dispatched: true, screenPoint: screen, behindCamera: false };
|
|
2613
|
+
}
|
|
2614
|
+
function contextMenuAtWorld(point, _options = {}) {
|
|
2615
|
+
const camera = getCamera();
|
|
2616
|
+
const gl = getRenderer();
|
|
2617
|
+
const size = getCanvasSize();
|
|
2618
|
+
const canvas = gl.domElement;
|
|
2619
|
+
const screen = projectWorld(point, camera, size);
|
|
2620
|
+
if (!screen) {
|
|
2621
|
+
r3fLog("interaction", `contextMenuAtWorld(${point.x}, ${point.y}, ${point.z}) \u2014 behind camera, skipped`);
|
|
2622
|
+
return { dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: true };
|
|
2623
|
+
}
|
|
2624
|
+
r3fLog("interaction", `contextMenuAtWorld(${point.x}, ${point.y}, ${point.z}) \u2192 screen(${Math.round(screen.x)}, ${Math.round(screen.y)})`);
|
|
2625
|
+
dispatchContextMenu(canvas, screen);
|
|
2626
|
+
return { dispatched: true, screenPoint: screen, behindCamera: false };
|
|
2627
|
+
}
|
|
2628
|
+
function hoverAtWorld(point, _options = {}) {
|
|
2629
|
+
const camera = getCamera();
|
|
2630
|
+
const gl = getRenderer();
|
|
2631
|
+
const size = getCanvasSize();
|
|
2632
|
+
const canvas = gl.domElement;
|
|
2633
|
+
const screen = projectWorld(point, camera, size);
|
|
2634
|
+
if (!screen) {
|
|
2635
|
+
r3fLog("interaction", `hoverAtWorld(${point.x}, ${point.y}, ${point.z}) \u2014 behind camera, skipped`);
|
|
2636
|
+
return { dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: true };
|
|
2637
|
+
}
|
|
2638
|
+
r3fLog("interaction", `hoverAtWorld(${point.x}, ${point.y}, ${point.z}) \u2192 screen(${Math.round(screen.x)}, ${Math.round(screen.y)})`);
|
|
2639
|
+
dispatchHover(canvas, screen);
|
|
2640
|
+
return { dispatched: true, screenPoint: screen, behindCamera: false };
|
|
2641
|
+
}
|
|
2642
|
+
async function clickAtWorldSequence(points, options = {}) {
|
|
2643
|
+
const { delayMs = 50, ...interactionOpts } = options;
|
|
2644
|
+
const results = [];
|
|
2645
|
+
for (let i = 0; i < points.length; i++) {
|
|
2646
|
+
results.push(clickAtWorld(points[i], interactionOpts));
|
|
2647
|
+
if (delayMs > 0 && i < points.length - 1) {
|
|
2648
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
return results;
|
|
2652
|
+
}
|
|
2576
2653
|
|
|
2577
2654
|
// src/highlight/SelectionManager.ts
|
|
2578
2655
|
var SelectionManager = class {
|
|
@@ -2828,6 +2905,9 @@ var Highlighter = class {
|
|
|
2828
2905
|
this._hoverPollId = null;
|
|
2829
2906
|
this._lastHoveredUuid = null;
|
|
2830
2907
|
this._store = null;
|
|
2908
|
+
/** When true, the hover poll is paused and showHoverHighlight is blocked. */
|
|
2909
|
+
this._hoverPollSuppressed = false;
|
|
2910
|
+
this._suppressTimer = null;
|
|
2831
2911
|
}
|
|
2832
2912
|
// -----------------------------------------------------------------------
|
|
2833
2913
|
// Lifecycle
|
|
@@ -2850,6 +2930,11 @@ var Highlighter = class {
|
|
|
2850
2930
|
this._unsubscribe = null;
|
|
2851
2931
|
}
|
|
2852
2932
|
this._stopHoverPolling();
|
|
2933
|
+
if (this._suppressTimer) {
|
|
2934
|
+
clearTimeout(this._suppressTimer);
|
|
2935
|
+
this._suppressTimer = null;
|
|
2936
|
+
}
|
|
2937
|
+
this._hoverPollSuppressed = false;
|
|
2853
2938
|
this.clearHoverHighlight();
|
|
2854
2939
|
this._clearAllSelectionHighlights();
|
|
2855
2940
|
this._scene = null;
|
|
@@ -2877,6 +2962,7 @@ var Highlighter = class {
|
|
|
2877
2962
|
// -----------------------------------------------------------------------
|
|
2878
2963
|
/** Show a hover highlight on the given object (replaces any previous hover). */
|
|
2879
2964
|
showHoverHighlight(obj) {
|
|
2965
|
+
if (this._hoverPollSuppressed) return;
|
|
2880
2966
|
if (obj === this._hoverTarget) return;
|
|
2881
2967
|
this._clearHoverVisuals();
|
|
2882
2968
|
if (!this._scene) return;
|
|
@@ -2915,6 +3001,26 @@ var Highlighter = class {
|
|
|
2915
3001
|
this.clearHoverHighlight();
|
|
2916
3002
|
this._clearAllSelectionHighlights();
|
|
2917
3003
|
}
|
|
3004
|
+
/**
|
|
3005
|
+
* Stop the hover poll, clear all hover state, and restart after a delay.
|
|
3006
|
+
* This prevents the DevTools extension from re-applying highlights after
|
|
3007
|
+
* inspect mode is disabled (the extension polls `$0` every 200ms and
|
|
3008
|
+
* keeps writing `__r3fdom_hovered__`).
|
|
3009
|
+
*/
|
|
3010
|
+
suppressHoverPoll(durationMs = 1500) {
|
|
3011
|
+
this._hoverPollSuppressed = true;
|
|
3012
|
+
this._stopHoverPolling();
|
|
3013
|
+
this._clearHoverVisuals();
|
|
3014
|
+
this._lastHoveredUuid = null;
|
|
3015
|
+
window.__r3fdom_hovered__ = null;
|
|
3016
|
+
if (this._suppressTimer) clearTimeout(this._suppressTimer);
|
|
3017
|
+
this._suppressTimer = setTimeout(() => {
|
|
3018
|
+
this._hoverPollSuppressed = false;
|
|
3019
|
+
this._suppressTimer = null;
|
|
3020
|
+
window.__r3fdom_hovered__ = null;
|
|
3021
|
+
this._startHoverPolling();
|
|
3022
|
+
}, durationMs);
|
|
3023
|
+
}
|
|
2918
3024
|
// -----------------------------------------------------------------------
|
|
2919
3025
|
// Internal: selection highlights
|
|
2920
3026
|
// -----------------------------------------------------------------------
|
|
@@ -2997,6 +3103,16 @@ var Highlighter = class {
|
|
|
2997
3103
|
try {
|
|
2998
3104
|
const hoveredEl = window.__r3fdom_hovered__;
|
|
2999
3105
|
const uuid = hoveredEl?.getAttribute?.("data-uuid") ?? null;
|
|
3106
|
+
if (this._hoverPollSuppressed) {
|
|
3107
|
+
if (uuid) {
|
|
3108
|
+
window.__r3fdom_hovered__ = null;
|
|
3109
|
+
}
|
|
3110
|
+
if (this._hoverTarget) {
|
|
3111
|
+
this._clearHoverVisuals();
|
|
3112
|
+
}
|
|
3113
|
+
this._lastHoveredUuid = null;
|
|
3114
|
+
return;
|
|
3115
|
+
}
|
|
3000
3116
|
if (uuid === this._lastHoveredUuid) return;
|
|
3001
3117
|
this._lastHoveredUuid = uuid;
|
|
3002
3118
|
if (!uuid) {
|
|
@@ -3119,9 +3235,12 @@ var InspectController = class {
|
|
|
3119
3235
|
this._boundContextMenu = null;
|
|
3120
3236
|
this._hoveredObject = null;
|
|
3121
3237
|
this._cancelHoverReveal();
|
|
3122
|
-
this._highlighter.
|
|
3238
|
+
this._highlighter.clearAll();
|
|
3239
|
+
this._highlighter.suppressHoverPoll();
|
|
3240
|
+
this._selectionManager.clearSelection();
|
|
3241
|
+
window.__r3fdom_hovered__ = null;
|
|
3123
3242
|
window.__r3fdom_selected_element__ = null;
|
|
3124
|
-
r3fLog("inspect", "InspectController disabled");
|
|
3243
|
+
r3fLog("inspect", "InspectController disabled \u2014 highlights and selection cleared");
|
|
3125
3244
|
}
|
|
3126
3245
|
/** Disable and release all resources. */
|
|
3127
3246
|
dispose() {
|
|
@@ -3359,6 +3478,21 @@ function shouldRegister(instanceKey, obj) {
|
|
|
3359
3478
|
if (filter) return filter(obj);
|
|
3360
3479
|
return true;
|
|
3361
3480
|
}
|
|
3481
|
+
function ensureAncestorChain(obj, store, mirror) {
|
|
3482
|
+
const chain = [];
|
|
3483
|
+
let cursor = obj.parent;
|
|
3484
|
+
while (cursor) {
|
|
3485
|
+
if (store.has(cursor)) break;
|
|
3486
|
+
chain.push(cursor);
|
|
3487
|
+
cursor = cursor.parent;
|
|
3488
|
+
}
|
|
3489
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
3490
|
+
const ancestor = chain[i];
|
|
3491
|
+
store.register(ancestor);
|
|
3492
|
+
mirror.onObjectAdded(ancestor);
|
|
3493
|
+
mirror.materialize(ancestor.uuid);
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3362
3496
|
function getStore2(canvasId = "") {
|
|
3363
3497
|
return _stores.get(canvasId) ?? null;
|
|
3364
3498
|
}
|
|
@@ -3430,6 +3564,11 @@ function exposeGlobalAPI(store, gl, cameraRef, selMgr, inspCtrl, mirror, canvasI
|
|
|
3430
3564
|
const result = await drawPath(points, options);
|
|
3431
3565
|
return { eventCount: result.eventCount, pointCount: result.pointCount };
|
|
3432
3566
|
},
|
|
3567
|
+
clickAtWorld: (point, options) => clickAtWorld(point, options),
|
|
3568
|
+
doubleClickAtWorld: (point, options) => doubleClickAtWorld(point, options),
|
|
3569
|
+
contextMenuAtWorld: (point, options) => contextMenuAtWorld(point, options),
|
|
3570
|
+
hoverAtWorld: (point, options) => hoverAtWorld(point, options),
|
|
3571
|
+
clickAtWorldSequence: (points, options) => clickAtWorldSequence(points, options),
|
|
3433
3572
|
select: (idOrUuid) => {
|
|
3434
3573
|
const obj = store.getObject3D(idOrUuid);
|
|
3435
3574
|
if (obj && selMgr) selMgr.select(obj);
|
|
@@ -3518,10 +3657,17 @@ function exposeGlobalAPI(store, gl, cameraRef, selMgr, inspCtrl, mirror, canvasI
|
|
|
3518
3657
|
return;
|
|
3519
3658
|
}
|
|
3520
3659
|
obj.userData.__r3fdom_manual = true;
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3660
|
+
ensureAncestorChain(obj, store, mirror);
|
|
3661
|
+
let count = 0;
|
|
3662
|
+
obj.traverse((child) => {
|
|
3663
|
+
if (!store.has(child)) {
|
|
3664
|
+
store.register(child);
|
|
3665
|
+
mirror?.onObjectAdded(child);
|
|
3666
|
+
mirror?.materialize(child.uuid);
|
|
3667
|
+
count++;
|
|
3668
|
+
}
|
|
3669
|
+
});
|
|
3670
|
+
r3fLog("bridge", `r3fRegister: "${obj.userData?.testId || obj.name || obj.uuid.slice(0, 8)}" (${obj.type}) \u2014 ${count} objects`);
|
|
3525
3671
|
},
|
|
3526
3672
|
r3fUnregister: (obj) => {
|
|
3527
3673
|
if (!store.has(obj)) return;
|
|
@@ -3646,6 +3792,11 @@ function createStubBridge(error, canvasId) {
|
|
|
3646
3792
|
pointerMiss: () => {
|
|
3647
3793
|
},
|
|
3648
3794
|
drawPath: async () => ({ eventCount: 0, pointCount: 0 }),
|
|
3795
|
+
clickAtWorld: () => ({ dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: false }),
|
|
3796
|
+
doubleClickAtWorld: () => ({ dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: false }),
|
|
3797
|
+
contextMenuAtWorld: () => ({ dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: false }),
|
|
3798
|
+
hoverAtWorld: () => ({ dispatched: false, screenPoint: { x: 0, y: 0 }, behindCamera: false }),
|
|
3799
|
+
clickAtWorldSequence: async () => [],
|
|
3649
3800
|
select: () => {
|
|
3650
3801
|
},
|
|
3651
3802
|
clearSelection: () => {
|
|
@@ -3778,8 +3929,12 @@ function ThreeDom({
|
|
|
3778
3929
|
if (mode === "auto") {
|
|
3779
3930
|
if (filter) {
|
|
3780
3931
|
store.addTrackedRoot(scene);
|
|
3932
|
+
store.register(scene);
|
|
3933
|
+
mirror.onObjectAdded(scene);
|
|
3781
3934
|
scene.traverse((obj) => {
|
|
3935
|
+
if (obj === scene) return;
|
|
3782
3936
|
if (filter(obj)) {
|
|
3937
|
+
ensureAncestorChain(obj, store, mirror);
|
|
3783
3938
|
store.register(obj);
|
|
3784
3939
|
mirror.onObjectAdded(obj);
|
|
3785
3940
|
}
|
|
@@ -3971,8 +4126,11 @@ exports.ThreeElement = ThreeElement;
|
|
|
3971
4126
|
exports.applyAttributes = applyAttributes;
|
|
3972
4127
|
exports.circlePath = circlePath;
|
|
3973
4128
|
exports.click3D = click3D;
|
|
4129
|
+
exports.clickAtWorld = clickAtWorld;
|
|
4130
|
+
exports.clickAtWorldSequence = clickAtWorldSequence;
|
|
3974
4131
|
exports.computeAttributes = computeAttributes;
|
|
3975
4132
|
exports.contextMenu3D = contextMenu3D;
|
|
4133
|
+
exports.contextMenuAtWorld = contextMenuAtWorld;
|
|
3976
4134
|
exports.createFlatSnapshot = createFlatSnapshot;
|
|
3977
4135
|
exports.createSnapshot = createSnapshot;
|
|
3978
4136
|
exports.curvePath = curvePath;
|
|
@@ -3985,6 +4143,7 @@ exports.dispatchPointerMiss = dispatchPointerMiss;
|
|
|
3985
4143
|
exports.dispatchUnhover = dispatchUnhover;
|
|
3986
4144
|
exports.dispatchWheel = dispatchWheel;
|
|
3987
4145
|
exports.doubleClick3D = doubleClick3D;
|
|
4146
|
+
exports.doubleClickAtWorld = doubleClickAtWorld;
|
|
3988
4147
|
exports.drag3D = drag3D;
|
|
3989
4148
|
exports.drawPath = drawPath;
|
|
3990
4149
|
exports.enableDebug = enableDebug;
|
|
@@ -3997,6 +4156,7 @@ exports.getSelectionManager = getSelectionManager;
|
|
|
3997
4156
|
exports.getStore = getStore2;
|
|
3998
4157
|
exports.getTagForType = getTagForType;
|
|
3999
4158
|
exports.hover3D = hover3D;
|
|
4159
|
+
exports.hoverAtWorld = hoverAtWorld;
|
|
4000
4160
|
exports.isDebugEnabled = isDebugEnabled;
|
|
4001
4161
|
exports.isInFrustum = isInFrustum;
|
|
4002
4162
|
exports.isPatched = isPatched;
|