@graphty/graphty-element 2.3.1 → 2.4.1
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/AGENTS.md +4 -3
- package/dist/ai.js +3 -3
- package/dist/catalog.js +28 -27
- package/dist/chunks/{AiManager-BBmGJbH4.js → AiManager-DNJCoeTO.js} +5 -5
- package/dist/chunks/{DataSource-OeN3NeyD.js → DataSource-xL3Yn0Pa.js} +72 -61
- package/dist/chunks/{GraphSession-Bef1AYw9.js → GraphSession-PFm2tJ_j.js} +2942 -2822
- package/dist/chunks/{GraphtyLogger-5KEttFUo.js → GraphtyLogger-kbOx2zq3.js} +170 -222
- package/dist/chunks/{NodeStyle-DKj7HjMJ.js → NodeStyle-CtmA7dXi.js} +16 -14
- package/dist/chunks/{VoiceInputAdapter-Dr9Gcmds.js → VoiceInputAdapter-CDNKQgUK.js} +1 -1
- package/dist/chunks/{XRPivotCameraController-BbfgZWpS.js → XRPivotCameraController-JdlLBcD7.js} +146 -134
- package/dist/chunks/{algorithms-CpX56sUB.js → algorithms-B87OPYw4.js} +780 -635
- package/dist/chunks/{capability-check-Blhb2aBB.js → capability-check-B2oYf_30.js} +1 -1
- package/dist/chunks/{detect-Cqwshr9a.js → detect-tuYQLJbT.js} +2 -2
- package/dist/chunks/{format-detection-BXGO1lSn.js → format-detection-BG6CMwPO.js} +1 -1
- package/dist/chunks/{index-C0mIoumR.js → index-6GDfNfwJ.js} +3185 -2731
- package/dist/chunks/{optionsFromZod-17lkrAJs.js → optionsFromZod-DHLLiX_8.js} +275 -267
- package/dist/chunks/{paletteRegistry-x7WOEKZY.js → paletteRegistry-jg9uS7wo.js} +72 -70
- package/dist/chunks/pluginRegistry-MaTIDh6l.js +238 -0
- package/dist/chunks/{registry-CSba5QGJ.js → registry-DQeq4B2K.js} +8 -8
- package/dist/chunks/{scales-BRwl51k8.js → scales-BXHmwPXC.js} +572 -399
- package/dist/chunks/{types-B7bX5c0K.js → types-C_c53VgR.js} +31 -26
- package/dist/commands.d.ts +4 -0
- package/dist/custom-elements.json +1 -1
- package/dist/extend.js +8 -8
- package/dist/graphty-catalog.json +245 -12
- package/dist/graphty.bundle.js +37843 -36551
- package/dist/graphty.js +69 -65
- package/dist/index.d.ts +3 -0
- package/dist/logging.js +2 -2
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +42 -40
- package/dist/session.js +6 -6
- package/dist/src/Edge.d.ts +4 -4
- package/dist/src/Graph.d.ts +79 -7
- package/dist/src/acceleration/AccelerationController.d.ts +20 -3
- package/dist/src/acceleration/registry.d.ts +3 -0
- package/dist/src/acceleration/types.d.ts +85 -0
- package/dist/src/algorithms/Algorithm.d.ts +13 -0
- package/dist/src/algorithms/KCoreAlgorithm.d.ts +26 -0
- package/dist/src/algorithms/LinkPredictionAlgorithm.d.ts +41 -0
- package/dist/src/cameras/InputUtils.d.ts +67 -0
- package/dist/src/cameras/XRInputHandler.d.ts +0 -8
- package/dist/src/catalog/algorithms.d.ts +5 -5
- package/dist/src/catalog/index.d.ts +2 -2
- package/dist/src/catalog/layouts.d.ts +7 -6
- package/dist/src/catalog/pluginRegistry.d.ts +62 -0
- package/dist/src/catalog/registry.d.ts +7 -0
- package/dist/src/catalog/types.d.ts +77 -6
- package/dist/src/config/EdgeStyle.d.ts +35 -0
- package/dist/src/config/index.d.ts +1 -1
- package/dist/src/data/DataSource.d.ts +1 -1
- package/dist/src/data/GEXFDataSource.d.ts +23 -0
- package/dist/src/errors/codes.d.ts +16 -1
- package/dist/src/events.d.ts +30 -0
- package/dist/src/graphty-element.d.ts +66 -26
- package/dist/src/layout/GridLayoutEngine.d.ts +37 -0
- package/dist/src/layout/LayoutEngine.d.ts +7 -7
- package/dist/src/layout/NGraphLayoutEngine.d.ts +2 -0
- package/dist/src/layout/RadialLayoutEngine.d.ts +37 -0
- package/dist/src/layout/SimulationLayoutEngine.d.ts +12 -0
- package/dist/src/managers/DataManager.d.ts +69 -2
- package/dist/src/managers/EventManager.d.ts +10 -4
- package/dist/src/managers/GraphContext.d.ts +2 -1
- package/dist/src/managers/LayoutManager.d.ts +30 -3
- package/dist/src/meshes/CustomLineRenderer.d.ts +11 -9
- package/dist/src/meshes/EdgeMesh.d.ts +18 -9
- package/dist/src/meshes/FilledArrowRenderer.d.ts +61 -23
- package/dist/src/meshes/MeshCache.d.ts +18 -0
- package/dist/src/meshes/NodeEffects.d.ts +16 -11
- package/dist/src/meshes/NodeMesh.d.ts +2 -2
- package/dist/src/meshes/PatternedLineRenderer.d.ts +5 -37
- package/dist/src/meshes/PerSceneMaterials.d.ts +49 -0
- package/dist/src/meshes/RichTextParser.d.ts +26 -0
- package/dist/src/meshes/RichTextRenderer.d.ts +0 -1
- package/dist/src/session/cost/estimate.d.ts +1 -1
- package/dist/src/session/layout.d.ts +3 -3
- package/dist/src/session/runs/RunsApi.d.ts +1 -1
- package/dist/src/session/styles/StylesApi.d.ts +6 -0
- package/dist/src/session/styles/intern.d.ts +26 -5
- package/dist/src/session/styles/repaint.d.ts +2 -1
- package/dist/src/session/types.d.ts +6 -6
- package/dist/src/xr/XRSessionManager.d.ts +1 -1
- package/dist/webgpu.d.ts +8 -0
- package/dist/webgpu.js +2 -2
- package/package.json +6 -6
- package/dist/chunks/GraphtyError-BwcnblTH.js +0 -132
|
@@ -63,7 +63,7 @@ const u = {
|
|
|
63
63
|
"bottom",
|
|
64
64
|
"bottom-left",
|
|
65
65
|
"bottom-right"
|
|
66
|
-
]), d = t.enum(["left", "center", "right"]), _ = t.enum(["none", "pulse", "bounce", "shake", "glow", "fill"]),
|
|
66
|
+
]), d = t.enum(["left", "center", "right"]), _ = t.enum(["none", "pulse", "bounce", "shake", "glow", "fill"]), s = t.enum([
|
|
67
67
|
"notification",
|
|
68
68
|
"label",
|
|
69
69
|
"label-success",
|
|
@@ -73,7 +73,7 @@ const u = {
|
|
|
73
73
|
"icon",
|
|
74
74
|
"progress",
|
|
75
75
|
"dot"
|
|
76
|
-
]),
|
|
76
|
+
]), E = t.enum(["linear", "radial"]), O = t.enum(["vertical", "horizontal", "diagonal"]), R = t.enum(["round", "bevel", "miter"]), c = t.strictObject({
|
|
77
77
|
width: t.number(),
|
|
78
78
|
color: a,
|
|
79
79
|
spacing: t.number()
|
|
@@ -130,7 +130,7 @@ const u = {
|
|
|
130
130
|
// Background effects
|
|
131
131
|
backgroundPadding: t.number().default(0).optional(),
|
|
132
132
|
backgroundGradient: t.boolean().default(!1).optional(),
|
|
133
|
-
backgroundGradientType:
|
|
133
|
+
backgroundGradientType: E.default("linear").optional(),
|
|
134
134
|
backgroundGradientColors: t.array(a).optional(),
|
|
135
135
|
backgroundGradientDirection: O.default("vertical").optional(),
|
|
136
136
|
// Pointer/Arrow
|
|
@@ -144,7 +144,7 @@ const u = {
|
|
|
144
144
|
animation: _.default("none").optional(),
|
|
145
145
|
animationSpeed: t.number().default(1).optional(),
|
|
146
146
|
// Badge
|
|
147
|
-
badge:
|
|
147
|
+
badge: s.optional(),
|
|
148
148
|
icon: t.string().optional(),
|
|
149
149
|
iconPosition: t.enum(["left", "right"]).default("left").optional(),
|
|
150
150
|
progress: t.number().min(0).max(1).optional(),
|
|
@@ -205,7 +205,7 @@ const u = {
|
|
|
205
205
|
// Repeating wave period meshes
|
|
206
206
|
"zigzag"
|
|
207
207
|
// Repeating zigzag period meshes
|
|
208
|
-
]),
|
|
208
|
+
]), f = t.strictObject({
|
|
209
209
|
type: b.optional(),
|
|
210
210
|
animationSpeed: t.number().min(0).optional(),
|
|
211
211
|
width: t.number().positive().optional(),
|
|
@@ -234,7 +234,7 @@ const u = {
|
|
|
234
234
|
}), g = t.strictObject({
|
|
235
235
|
arrowHead: n.optional(),
|
|
236
236
|
arrowTail: n.optional(),
|
|
237
|
-
line:
|
|
237
|
+
line: f.optional(),
|
|
238
238
|
label: e.prefault({ location: "top" }).optional()
|
|
239
239
|
// effects: glow // https://playground.babylonjs.com/#H1LRZ3#35
|
|
240
240
|
}), S = {
|
|
@@ -250,7 +250,7 @@ const u = {
|
|
|
250
250
|
arrowHead: n.parse({
|
|
251
251
|
type: "normal"
|
|
252
252
|
})
|
|
253
|
-
},
|
|
253
|
+
}, m = t.enum([
|
|
254
254
|
"box",
|
|
255
255
|
"sphere",
|
|
256
256
|
"cylinder",
|
|
@@ -280,7 +280,7 @@ const u = {
|
|
|
280
280
|
shape: t.strictObject({
|
|
281
281
|
// 0 is legal and draws the smallest visible node; hide a node with `visible: false`.
|
|
282
282
|
size: t.number().nonnegative().optional(),
|
|
283
|
-
type:
|
|
283
|
+
type: m.optional()
|
|
284
284
|
// custom mesh https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/custom/custom
|
|
285
285
|
// import mesh https://doc.babylonjs.com/typedoc/functions/BABYLON.ImportMeshAsync
|
|
286
286
|
}).optional(),
|
|
@@ -334,14 +334,16 @@ const u = {
|
|
|
334
334
|
}
|
|
335
335
|
};
|
|
336
336
|
export {
|
|
337
|
-
|
|
338
|
-
|
|
337
|
+
I as E,
|
|
338
|
+
m as N,
|
|
339
339
|
r as P,
|
|
340
340
|
e as R,
|
|
341
341
|
L as S,
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
b as a,
|
|
343
|
+
g as b,
|
|
344
|
+
U as c,
|
|
345
345
|
S as d,
|
|
346
|
-
|
|
346
|
+
C as e,
|
|
347
|
+
T as f,
|
|
348
|
+
u as g
|
|
347
349
|
};
|
package/dist/chunks/{XRPivotCameraController-BbfgZWpS.js → XRPivotCameraController-JdlLBcD7.js}
RENAMED
|
@@ -1,15 +1,38 @@
|
|
|
1
|
-
import { Vector3 as f, Quaternion as E, Ray as
|
|
2
|
-
import { P as
|
|
1
|
+
import { Vector3 as f, Quaternion as E, Ray as N, WebXRState as D } from "@babylonjs/core";
|
|
2
|
+
import { P as I } from "./index-6GDfNfwJ.js";
|
|
3
3
|
import "@babylonjs/core/Culling/ray";
|
|
4
|
-
import { G as
|
|
5
|
-
function
|
|
6
|
-
if (Math.abs(
|
|
4
|
+
import { G as y } from "./GraphtyLogger-kbOx2zq3.js";
|
|
5
|
+
function x(c, t = 0.15) {
|
|
6
|
+
if (Math.abs(c) < t)
|
|
7
7
|
return 0;
|
|
8
|
-
const e = Math.sign(
|
|
8
|
+
const e = Math.sign(c), i = (Math.abs(c) - t) / (1 - t);
|
|
9
9
|
return e * Math.pow(i, 2);
|
|
10
10
|
}
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const P = 0.15, O = 0.04, k = 0.03, L = 0.08, w = 0.02, A = 2, _ = 0.04, X = 0.06, T = 1e-4;
|
|
12
|
+
function F(c, t) {
|
|
13
|
+
return c < (t ? X : _);
|
|
14
|
+
}
|
|
15
|
+
function z(c) {
|
|
16
|
+
return Math.max(0, 1 - c / _);
|
|
17
|
+
}
|
|
18
|
+
function G(c, t) {
|
|
19
|
+
const e = x(c.x, P), i = x(c.y, P), n = x(t.x, P), s = x(t.y, P), o = e * O, r = i * k, a = Math.abs(o) > T || Math.abs(r) > T;
|
|
20
|
+
return {
|
|
21
|
+
yaw: a ? o : 0,
|
|
22
|
+
pitch: a ? r : 0,
|
|
23
|
+
zoom: Math.abs(s) > T ? 1 + s * w : 1,
|
|
24
|
+
pan: Math.abs(n) > T ? n * L : 0
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function W(c, t, e, i) {
|
|
28
|
+
const n = 1 + (e - c) * A, s = 2 - Math.max(0.9, Math.min(1.1, n)), o = f.Cross(t, i), r = o.length();
|
|
29
|
+
if (r <= T)
|
|
30
|
+
return { zoom: s, axis: null, angle: 0 };
|
|
31
|
+
const a = Math.acos(Math.max(-1, Math.min(1, f.Dot(t, i))));
|
|
32
|
+
return { zoom: s, axis: o.scaleInPlace(1 / r), angle: -a };
|
|
33
|
+
}
|
|
34
|
+
const p = y.getLogger(["graphty", "camera", "xr", "input"]);
|
|
35
|
+
class V {
|
|
13
36
|
// Reference to scene for onBeforeRenderObservable and picking
|
|
14
37
|
/**
|
|
15
38
|
* Creates a new XRInputHandler instance.
|
|
@@ -17,7 +40,7 @@ class O {
|
|
|
17
40
|
* @param xr - The WebXR experience instance
|
|
18
41
|
*/
|
|
19
42
|
constructor(t, e) {
|
|
20
|
-
this.enabled = !1, this.setupControllers = /* @__PURE__ */ new Map(), this.controllerCleanup = /* @__PURE__ */ new Map(), this.gestureControllers = /* @__PURE__ */ new Map(), this.leftStick = { x: 0, y: 0 }, this.rightStick = { x: 0, y: 0 }, this.leftHand = null, this.rightHand = null, this.previousDistance = null, this.previousDirection = null, this.wasPinching = { left: !1, right: !1 }, this.handTrackingFeature = null, this.
|
|
43
|
+
this.enabled = !1, this.setupControllers = /* @__PURE__ */ new Map(), this.controllerCleanup = /* @__PURE__ */ new Map(), this.gestureControllers = /* @__PURE__ */ new Map(), this.leftStick = { x: 0, y: 0 }, this.rightStick = { x: 0, y: 0 }, this.leftHand = null, this.rightHand = null, this.previousDistance = null, this.previousDirection = null, this.wasPinching = { left: !1, right: !1 }, this.handTrackingFeature = null, this.lastControllerRemovedTime = 0, this.INPUT_SWITCH_DELAY_MS = 100, this.isDraggingNode = !1, this.draggedNodeHandler = null, this.dragHand = null, this.lastDragHandPosition = null, this.VELOCITY_SLOW_THRESHOLD = 5e-3, this.VELOCITY_FAST_THRESHOLD = 0.03, this.AMP_SLOW = 5, this._AMP_MEDIUM = 10, this.AMP_FAST = 20, this.lastDragTime = 0, this.SMOOTHING_FACTOR = 0.7, this.smoothedDelta = null, this.DRAG_THRESHOLD = 0.08, this.dragStartHandPosition = null, this.dragThresholdExceeded = !1, this.frameCount = 0, this.dragUpdateCount = 0, this.pivotController = t, this.xr = e, this.scene = e.baseExperience.sessionManager.scene;
|
|
21
44
|
}
|
|
22
45
|
/**
|
|
23
46
|
* Enable input handling.
|
|
@@ -27,10 +50,10 @@ class O {
|
|
|
27
50
|
this.enabled || (this.enabled = !0, this.enableHandTracking(), this.xr.input.onControllerAddedObservable.add((t) => {
|
|
28
51
|
const i = performance.now() - this.lastControllerRemovedTime;
|
|
29
52
|
if (i < this.INPUT_SWITCH_DELAY_MS && this.lastControllerRemovedTime > 0) {
|
|
30
|
-
const
|
|
53
|
+
const n = this.INPUT_SWITCH_DELAY_MS - i;
|
|
31
54
|
setTimeout(() => {
|
|
32
55
|
this.setupController(t), this.addGestureController(t);
|
|
33
|
-
},
|
|
56
|
+
}, n);
|
|
34
57
|
} else
|
|
35
58
|
this.setupController(t), this.addGestureController(t);
|
|
36
59
|
}), this.xr.input.onControllerRemovedObservable.add((t) => {
|
|
@@ -83,73 +106,73 @@ class O {
|
|
|
83
106
|
const { handedness: e } = t.inputSource, { uniqueId: i } = t;
|
|
84
107
|
if (this.setupControllers.has(i))
|
|
85
108
|
return;
|
|
86
|
-
const { inputSource:
|
|
87
|
-
if (
|
|
88
|
-
(
|
|
109
|
+
const { inputSource: n } = t;
|
|
110
|
+
if (n.profiles.some(
|
|
111
|
+
(a) => a.includes("hand") || a.includes("generic-trigger-touchpad")
|
|
89
112
|
))
|
|
90
113
|
return;
|
|
91
|
-
const
|
|
114
|
+
const o = (a) => {
|
|
92
115
|
if (this.setupControllers.has(i))
|
|
93
116
|
return;
|
|
94
|
-
const l =
|
|
117
|
+
const l = a.getComponent("xr-standard-thumbstick");
|
|
95
118
|
if (!l)
|
|
96
119
|
return;
|
|
97
120
|
this.setupControllers.set(i, !0);
|
|
98
|
-
const
|
|
99
|
-
let
|
|
100
|
-
const m = (
|
|
101
|
-
if (
|
|
121
|
+
const u = e === "left";
|
|
122
|
+
let v = !1;
|
|
123
|
+
const m = (b) => {
|
|
124
|
+
if (v)
|
|
102
125
|
return;
|
|
103
|
-
const { x:
|
|
104
|
-
|
|
105
|
-
},
|
|
126
|
+
const { x: S } = b, { y: R } = b;
|
|
127
|
+
u ? (this.leftStick.x = S, this.leftStick.y = R) : (this.rightStick.x = S, this.rightStick.y = R);
|
|
128
|
+
}, H = l.onAxisValueChangedObservable.add(m), C = this.scene;
|
|
106
129
|
let g = null;
|
|
107
|
-
const
|
|
108
|
-
if (
|
|
130
|
+
const M = () => {
|
|
131
|
+
if (v || !this.enabled)
|
|
109
132
|
return;
|
|
110
133
|
if (!this.setupControllers.has(i)) {
|
|
111
|
-
g && (
|
|
134
|
+
g && (C.onBeforeRenderObservable.remove(g), g = null);
|
|
112
135
|
return;
|
|
113
136
|
}
|
|
114
137
|
if (l._disposed) {
|
|
115
|
-
g && (
|
|
138
|
+
g && (C.onBeforeRenderObservable.remove(g), g = null);
|
|
116
139
|
return;
|
|
117
140
|
}
|
|
118
|
-
const
|
|
119
|
-
|
|
141
|
+
const b = l.axes.x, S = l.axes.y;
|
|
142
|
+
u ? (this.leftStick.x = b, this.leftStick.y = S) : (this.rightStick.x = b, this.rightStick.y = S);
|
|
120
143
|
};
|
|
121
|
-
g =
|
|
122
|
-
if (
|
|
144
|
+
g = C.onBeforeRenderObservable.add(M), this.controllerCleanup.set(i, () => {
|
|
145
|
+
if (v = !0, H)
|
|
123
146
|
try {
|
|
124
|
-
l.onAxisValueChangedObservable.remove(
|
|
147
|
+
l.onAxisValueChangedObservable.remove(H);
|
|
125
148
|
} catch {
|
|
126
149
|
}
|
|
127
150
|
if (g)
|
|
128
151
|
try {
|
|
129
|
-
|
|
152
|
+
C.onBeforeRenderObservable.remove(g);
|
|
130
153
|
} catch {
|
|
131
154
|
}
|
|
132
155
|
});
|
|
133
|
-
},
|
|
134
|
-
if (
|
|
135
|
-
|
|
156
|
+
}, r = t;
|
|
157
|
+
if (r.motionController)
|
|
158
|
+
o(r.motionController);
|
|
136
159
|
else {
|
|
137
|
-
|
|
138
|
-
|
|
160
|
+
r.onMotionControllerInitObservable.add((l) => {
|
|
161
|
+
o(l);
|
|
139
162
|
});
|
|
140
|
-
let
|
|
163
|
+
let a = 0;
|
|
141
164
|
const d = setInterval(() => {
|
|
142
|
-
if (
|
|
165
|
+
if (a++, this.setupControllers.has(i) || a > 20) {
|
|
143
166
|
clearInterval(d);
|
|
144
167
|
return;
|
|
145
168
|
}
|
|
146
|
-
|
|
169
|
+
r.motionController && (o(r.motionController), clearInterval(d));
|
|
147
170
|
}, 100);
|
|
148
171
|
}
|
|
149
172
|
}
|
|
150
173
|
cleanupController(t) {
|
|
151
|
-
const { uniqueId: e } = t, { handedness: i } = t.inputSource,
|
|
152
|
-
|
|
174
|
+
const { uniqueId: e } = t, { handedness: i } = t.inputSource, n = this.controllerCleanup.get(e);
|
|
175
|
+
n && (n(), this.controllerCleanup.delete(e)), this.setupControllers.delete(e), i === "left" ? this.leftStick = { x: 0, y: 0 } : i === "right" && (this.rightStick = { x: 0, y: 0 }), this.lastControllerRemovedTime = performance.now();
|
|
153
176
|
}
|
|
154
177
|
/**
|
|
155
178
|
* Process input each frame.
|
|
@@ -164,18 +187,8 @@ class O {
|
|
|
164
187
|
* Right stick: X = pan, Y = zoom
|
|
165
188
|
*/
|
|
166
189
|
processThumbsticks() {
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
return;
|
|
170
|
-
const l = r * this.YAW_SPEED, h = a * this.PITCH_SPEED;
|
|
171
|
-
if ((Math.abs(l) > 1e-4 || Math.abs(h) > 1e-4) && this.pivotController.rotate(l, h), Math.abs(n) > 1e-4) {
|
|
172
|
-
const u = 1 + n * this.ZOOM_SPEED;
|
|
173
|
-
this.pivotController.zoom(u);
|
|
174
|
-
}
|
|
175
|
-
if (Math.abs(o) > 1e-4) {
|
|
176
|
-
const u = o * this.PAN_SPEED;
|
|
177
|
-
this.pivotController.panViewRelative(u, 0);
|
|
178
|
-
}
|
|
190
|
+
const { yaw: t, pitch: e, zoom: i, pan: n } = G(this.leftStick, this.rightStick);
|
|
191
|
+
(t !== 0 || e !== 0) && this.pivotController.rotate(t, e), i !== 1 && this.pivotController.zoom(i), n !== 0 && this.pivotController.panViewRelative(n, 0);
|
|
179
192
|
}
|
|
180
193
|
/**
|
|
181
194
|
* Process two-hand gesture input for zoom and rotation.
|
|
@@ -185,19 +198,18 @@ class O {
|
|
|
185
198
|
processHandGesturesInternal() {
|
|
186
199
|
if (!this.leftHand?.isPinching || !this.rightHand?.isPinching)
|
|
187
200
|
return;
|
|
188
|
-
const t = this.leftHand.position, e = this.rightHand.position, i = f.Distance(t, e),
|
|
201
|
+
const t = this.leftHand.position, e = this.rightHand.position, i = f.Distance(t, e), s = e.subtract(t).normalize();
|
|
189
202
|
if (this.previousDistance === null || this.previousDirection === null) {
|
|
190
|
-
this.previousDistance = i, this.previousDirection =
|
|
203
|
+
this.previousDistance = i, this.previousDirection = s.clone();
|
|
191
204
|
return;
|
|
192
205
|
}
|
|
193
|
-
const o
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
this.previousDistance = i, this.previousDirection = r.clone();
|
|
206
|
+
const { zoom: o, axis: r, angle: a } = W(
|
|
207
|
+
this.previousDistance,
|
|
208
|
+
this.previousDirection,
|
|
209
|
+
i,
|
|
210
|
+
s
|
|
211
|
+
);
|
|
212
|
+
this.pivotController.zoom(o), r && this.pivotController.rotateAroundAxis(r, a), this.previousDistance = i, this.previousDirection = s.clone();
|
|
201
213
|
}
|
|
202
214
|
/**
|
|
203
215
|
* Update hand states from controllers (trigger) or hand tracking.
|
|
@@ -219,22 +231,22 @@ class O {
|
|
|
219
231
|
break;
|
|
220
232
|
}
|
|
221
233
|
if (e) {
|
|
222
|
-
const { controller: i } = e, { grip:
|
|
223
|
-
if (
|
|
234
|
+
const { controller: i } = e, { grip: n } = i, s = i;
|
|
235
|
+
if (n && s.motionController)
|
|
224
236
|
try {
|
|
225
|
-
const
|
|
226
|
-
if (isFinite(
|
|
227
|
-
const
|
|
228
|
-
if (
|
|
229
|
-
const
|
|
230
|
-
if (
|
|
231
|
-
return this.wasPinching[t] || p.debug("Trigger press", { handedness: t, value:
|
|
232
|
-
position:
|
|
233
|
-
rotation:
|
|
237
|
+
const o = n.position;
|
|
238
|
+
if (isFinite(o.x) && isFinite(o.y) && isFinite(o.z)) {
|
|
239
|
+
const r = s.motionController.getComponent("xr-standard-trigger");
|
|
240
|
+
if (r) {
|
|
241
|
+
const a = r.value ?? 0;
|
|
242
|
+
if (r.pressed === !0 || a > 0.5)
|
|
243
|
+
return this.wasPinching[t] || p.debug("Trigger press", { handedness: t, value: a }), this.wasPinching[t] = !0, {
|
|
244
|
+
position: o.clone(),
|
|
245
|
+
rotation: n.rotationQuaternion?.clone() ?? E.Identity(),
|
|
234
246
|
isPinching: !0,
|
|
235
|
-
pinchStrength:
|
|
247
|
+
pinchStrength: a
|
|
236
248
|
};
|
|
237
|
-
this.wasPinching[t] && (p.debug("Trigger release", { handedness: t, value:
|
|
249
|
+
this.wasPinching[t] && (p.debug("Trigger release", { handedness: t, value: a }), this.wasPinching[t] = !1, this.resetGestureState());
|
|
238
250
|
}
|
|
239
251
|
}
|
|
240
252
|
} catch {
|
|
@@ -242,19 +254,19 @@ class O {
|
|
|
242
254
|
}
|
|
243
255
|
if (this.handTrackingFeature)
|
|
244
256
|
try {
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
const
|
|
248
|
-
if (
|
|
249
|
-
if (!isFinite(
|
|
257
|
+
const n = this.handTrackingFeature.getHandByHandedness?.(t);
|
|
258
|
+
if (n) {
|
|
259
|
+
const s = n.getJointMesh("wrist"), o = n.getJointMesh("thumb-tip"), r = n.getJointMesh("index-finger-tip");
|
|
260
|
+
if (s && o && r) {
|
|
261
|
+
if (!isFinite(s.position.x) || !isFinite(o.position.x))
|
|
250
262
|
return null;
|
|
251
|
-
const
|
|
252
|
-
if (
|
|
263
|
+
const a = f.Distance(o.position, r.position), d = this.wasPinching[t], l = F(a, d);
|
|
264
|
+
if (l !== d && (p.debug(l ? "Pinch start" : "Pinch end", { handedness: t, distance: a }), l || this.resetGestureState()), this.wasPinching[t] = l, l)
|
|
253
265
|
return {
|
|
254
|
-
position:
|
|
255
|
-
rotation:
|
|
266
|
+
position: s.position.clone(),
|
|
267
|
+
rotation: s.rotationQuaternion?.clone() ?? E.Identity(),
|
|
256
268
|
isPinching: !0,
|
|
257
|
-
pinchStrength:
|
|
269
|
+
pinchStrength: z(a)
|
|
258
270
|
};
|
|
259
271
|
}
|
|
260
272
|
}
|
|
@@ -312,61 +324,61 @@ class O {
|
|
|
312
324
|
*/
|
|
313
325
|
tryStartNodeDrag(t, e) {
|
|
314
326
|
let i = null;
|
|
315
|
-
for (const
|
|
316
|
-
if (
|
|
317
|
-
({ controller: i } =
|
|
327
|
+
for (const u of this.gestureControllers.values())
|
|
328
|
+
if (u.handedness === t) {
|
|
329
|
+
({ controller: i } = u);
|
|
318
330
|
break;
|
|
319
331
|
}
|
|
320
332
|
if (!i)
|
|
321
333
|
return;
|
|
322
|
-
const
|
|
323
|
-
if (
|
|
324
|
-
|
|
334
|
+
const n = new N(f.Zero(), f.Forward(), 100), s = i;
|
|
335
|
+
if (s.getWorldPointerRayToRef)
|
|
336
|
+
s.getWorldPointerRayToRef(n);
|
|
325
337
|
else {
|
|
326
|
-
const
|
|
327
|
-
|
|
338
|
+
const u = i.grip ?? i.pointer;
|
|
339
|
+
n.origin = u.position.clone(), n.direction = u.forward.clone();
|
|
328
340
|
}
|
|
329
|
-
const
|
|
330
|
-
if (!
|
|
341
|
+
const o = this.scene.pickWithRay(n, (u) => u.isPickable && u.isEnabled());
|
|
342
|
+
if (!o?.hit || !o.pickedMesh)
|
|
331
343
|
return;
|
|
332
|
-
const
|
|
333
|
-
if (!
|
|
344
|
+
const r = this.findDragHandlerForMesh(o.pickedMesh);
|
|
345
|
+
if (!r)
|
|
334
346
|
return;
|
|
335
|
-
const d =
|
|
347
|
+
const d = r.getNode().mesh.position, { pickedPoint: l } = o;
|
|
336
348
|
p.debug("Drag start", {
|
|
337
349
|
handedness: t,
|
|
338
350
|
handPos: { x: e.x, y: e.y, z: e.z },
|
|
339
351
|
nodePos: { x: d.x, y: d.y, z: d.z },
|
|
340
352
|
pickPt: l ? { x: l.x, y: l.y, z: l.z } : null
|
|
341
|
-
}), this.isDraggingNode = !0, this.draggedNodeHandler =
|
|
353
|
+
}), this.isDraggingNode = !0, this.draggedNodeHandler = r, this.dragHand = t, this.lastDragHandPosition = e.clone(), this.dragStartHandPosition = e.clone(), this.dragThresholdExceeded = !1, this.lastDragTime = performance.now();
|
|
342
354
|
}
|
|
343
355
|
updateNodeDrag(t) {
|
|
344
356
|
if (!this.draggedNodeHandler || !this.lastDragHandPosition || !this.dragStartHandPosition)
|
|
345
357
|
return;
|
|
346
358
|
const e = performance.now();
|
|
347
359
|
if (!this.dragThresholdExceeded) {
|
|
348
|
-
const
|
|
349
|
-
if (
|
|
360
|
+
const H = f.Distance(t, this.dragStartHandPosition);
|
|
361
|
+
if (H < this.DRAG_THRESHOLD) {
|
|
350
362
|
this.lastDragHandPosition = t.clone(), this.lastDragTime = e;
|
|
351
363
|
return;
|
|
352
364
|
}
|
|
353
|
-
this.dragThresholdExceeded = !0, p.debug("Drag threshold exceeded", { distance:
|
|
354
|
-
const
|
|
355
|
-
this.draggedNodeHandler.onDragStart(
|
|
365
|
+
this.dragThresholdExceeded = !0, p.debug("Drag threshold exceeded", { distance: H });
|
|
366
|
+
const C = this.draggedNodeHandler.getNode();
|
|
367
|
+
this.draggedNodeHandler.onDragStart(C.mesh.position.clone()), this.lastDragHandPosition = t.clone(), this.lastDragTime = e;
|
|
356
368
|
return;
|
|
357
369
|
}
|
|
358
|
-
const i = t.subtract(this.lastDragHandPosition),
|
|
359
|
-
if (
|
|
370
|
+
const i = t.subtract(this.lastDragHandPosition), n = i.length();
|
|
371
|
+
if (n < 1e-4)
|
|
360
372
|
return;
|
|
361
373
|
this.dragUpdateCount++;
|
|
362
|
-
const
|
|
363
|
-
d.scaleInPlace(
|
|
374
|
+
const s = e - this.lastDragTime, o = Math.max(s / 1e3, 1e-3), r = n / o, a = this.calculateVelocityBasedGain(r), d = this.transformDeltaToSceneSpace(i);
|
|
375
|
+
d.scaleInPlace(a), this.smoothedDelta === null ? this.smoothedDelta = d.clone() : (this.smoothedDelta.scaleInPlace(this.SMOOTHING_FACTOR), this.smoothedDelta.addInPlace(d.scale(1 - this.SMOOTHING_FACTOR)));
|
|
364
376
|
const l = this.smoothedDelta.clone(), m = this.draggedNodeHandler.getNode().mesh.position.clone().add(l);
|
|
365
377
|
this.dragUpdateCount <= 5 && p.trace("Drag update", {
|
|
366
378
|
updateCount: this.dragUpdateCount,
|
|
367
379
|
delta: { x: i.x, y: i.y, z: i.z },
|
|
368
|
-
velocity:
|
|
369
|
-
amplification:
|
|
380
|
+
velocity: r,
|
|
381
|
+
amplification: a,
|
|
370
382
|
newPos: { x: m.x, y: m.y, z: m.z }
|
|
371
383
|
}), this.draggedNodeHandler.setPositionDirect(m), this.lastDragHandPosition = t.clone(), this.lastDragTime = e;
|
|
372
384
|
}
|
|
@@ -437,15 +449,15 @@ class O {
|
|
|
437
449
|
return this.isDraggingNode;
|
|
438
450
|
}
|
|
439
451
|
}
|
|
440
|
-
const
|
|
441
|
-
class
|
|
452
|
+
const h = y.getLogger(["graphty", "camera", "xr"]);
|
|
453
|
+
class q {
|
|
442
454
|
/**
|
|
443
455
|
* Creates a new XRPivotCameraController instance.
|
|
444
456
|
* @param scene - The Babylon.js scene
|
|
445
457
|
* @param xr - The WebXR experience instance
|
|
446
458
|
*/
|
|
447
459
|
constructor(t, e) {
|
|
448
|
-
this.frameCount = 0, this.scene = t, this.xr = e, this.pivotController = new
|
|
460
|
+
this.frameCount = 0, this.scene = t, this.xr = e, this.pivotController = new I(t), this.inputHandler = new V(this.pivotController, e), h.debug("Created"), this.setupXRListeners();
|
|
449
461
|
}
|
|
450
462
|
/**
|
|
451
463
|
* Setup listeners for XR state changes.
|
|
@@ -453,13 +465,13 @@ class A {
|
|
|
453
465
|
* When exiting XR, disables input and unparents camera.
|
|
454
466
|
*/
|
|
455
467
|
setupXRListeners() {
|
|
456
|
-
|
|
468
|
+
h.debug("Setting up XR state listeners");
|
|
457
469
|
const t = this.xr.baseExperience.state;
|
|
458
|
-
|
|
459
|
-
const i =
|
|
460
|
-
|
|
470
|
+
h.debug("Current XR state", { state: D[t] }), t === D.IN_XR && (h.debug("Already in XR, enabling immediately"), this.enableXRMode()), this.xr.baseExperience.onStateChangedObservable.add((e) => {
|
|
471
|
+
const i = D[e];
|
|
472
|
+
h.debug("XR state changed", { state: i }), e === D.IN_XR ? this.enableXRMode() : e === D.NOT_IN_XR && this.disableXRMode();
|
|
461
473
|
}), this.xr.baseExperience.onInitialXRPoseSetObservable.add((e) => {
|
|
462
|
-
|
|
474
|
+
h.debug("Initial XR pose set", {
|
|
463
475
|
cameraName: e.name,
|
|
464
476
|
position: { x: e.position.x, y: e.position.y, z: e.position.z }
|
|
465
477
|
});
|
|
@@ -470,10 +482,10 @@ class A {
|
|
|
470
482
|
*/
|
|
471
483
|
enableXRMode() {
|
|
472
484
|
const { camera: t } = this.xr.baseExperience;
|
|
473
|
-
t.parent = this.pivotController.pivot,
|
|
485
|
+
t.parent = this.pivotController.pivot, h.debug("XR camera parented to pivot", {
|
|
474
486
|
pivotName: this.pivotController.pivot.name,
|
|
475
487
|
cameraName: t.name
|
|
476
|
-
}), this.parentHandMeshesToPivot(), this.inputHandler.enable(),
|
|
488
|
+
}), this.parentHandMeshesToPivot(), this.inputHandler.enable(), h.debug("Input handler enabled");
|
|
477
489
|
}
|
|
478
490
|
/**
|
|
479
491
|
* Parent hand tracking joint meshes to the pivot.
|
|
@@ -484,26 +496,26 @@ class A {
|
|
|
484
496
|
try {
|
|
485
497
|
const { featuresManager: t } = this.xr.baseExperience, e = t.getEnabledFeature("xr-hand-tracking");
|
|
486
498
|
if (!e) {
|
|
487
|
-
|
|
499
|
+
h.debug("No hand tracking feature to parent");
|
|
488
500
|
return;
|
|
489
501
|
}
|
|
490
502
|
const i = e;
|
|
491
|
-
i.leftHand?.handMesh && (i.leftHand.handMesh.parent = this.pivotController.pivot,
|
|
492
|
-
const
|
|
493
|
-
if (
|
|
494
|
-
|
|
495
|
-
for (const
|
|
496
|
-
|
|
503
|
+
i.leftHand?.handMesh && (i.leftHand.handMesh.parent = this.pivotController.pivot, h.debug("Left hand mesh parented to pivot")), i.rightHand?.handMesh && (i.rightHand.handMesh.parent = this.pivotController.pivot, h.debug("Right hand mesh parented to pivot"));
|
|
504
|
+
const n = this.scene.meshes.filter((s) => s.name.includes("hand") || s.name.includes("Hand"));
|
|
505
|
+
if (n.length > 0) {
|
|
506
|
+
h.debug("Found hand-related meshes", { count: n.length });
|
|
507
|
+
for (const s of n)
|
|
508
|
+
s.parent || (s.parent = this.pivotController.pivot, h.debug("Parented mesh", { name: s.name }));
|
|
497
509
|
}
|
|
498
510
|
} catch (t) {
|
|
499
|
-
|
|
511
|
+
h.warn("Error parenting hand meshes", { error: String(t) });
|
|
500
512
|
}
|
|
501
513
|
}
|
|
502
514
|
/**
|
|
503
515
|
* Disable XR mode - unparent camera and disable input.
|
|
504
516
|
*/
|
|
505
517
|
disableXRMode() {
|
|
506
|
-
|
|
518
|
+
h.debug("Exiting XR, disabling input"), this.inputHandler.disable(), this.xr.baseExperience.camera.parent = null;
|
|
507
519
|
}
|
|
508
520
|
/**
|
|
509
521
|
* Update input handling.
|
|
@@ -512,7 +524,7 @@ class A {
|
|
|
512
524
|
update() {
|
|
513
525
|
if (this.frameCount++, this.frameCount % 300 === 0) {
|
|
514
526
|
const { camera: t } = this.xr.baseExperience, { pivot: e } = this.pivotController;
|
|
515
|
-
|
|
527
|
+
h.trace("Heartbeat", {
|
|
516
528
|
frame: this.frameCount,
|
|
517
529
|
inputEnabled: this.inputHandler.isEnabled(),
|
|
518
530
|
cameraParent: t.parent ? t.parent.name : "null",
|
|
@@ -558,5 +570,5 @@ class A {
|
|
|
558
570
|
}
|
|
559
571
|
}
|
|
560
572
|
export {
|
|
561
|
-
|
|
573
|
+
q as XRPivotCameraController
|
|
562
574
|
};
|