@needle-tools/three-animation-pointer 1.0.2 → 1.0.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
CHANGED
|
@@ -4,5 +4,11 @@ All notable changes to this package will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.0.4] - 2025-10-08
|
|
8
|
+
- Add: KHR_node_visibility extension
|
|
9
|
+
|
|
10
|
+
## [1.0.3] - 2025-09-11
|
|
11
|
+
- Fix: Handle undefined path if AnimationClip tracks have invalid/unexpected names. Fallback to default three implementation
|
|
12
|
+
|
|
7
13
|
## [1.0.1] - 2025-08-27
|
|
8
14
|
- Initial release
|
|
@@ -13,40 +13,40 @@ const f = {
|
|
|
13
13
|
};
|
|
14
14
|
class j {
|
|
15
15
|
/** @type {import("three/examples/jsm/loaders/GLTFLoader").GLTFParser} */
|
|
16
|
-
constructor(
|
|
17
|
-
this.name = R, this.parser =
|
|
16
|
+
constructor(a) {
|
|
17
|
+
this.name = R, this.parser = a, this.animationPointerResolver = null;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* @param {import("..").AnimationPointerResolver | null} animationPointerResolver
|
|
21
21
|
*/
|
|
22
|
-
setAnimationPointerResolver(
|
|
23
|
-
return this.animationPointerResolver =
|
|
22
|
+
setAnimationPointerResolver(a) {
|
|
23
|
+
return this.animationPointerResolver = a, this;
|
|
24
24
|
}
|
|
25
25
|
/* DUPLICATE of functionality in GLTFLoader */
|
|
26
|
-
loadAnimationTargetFromChannel(
|
|
27
|
-
const
|
|
28
|
-
return this.parser.getDependency("node",
|
|
26
|
+
loadAnimationTargetFromChannel(a) {
|
|
27
|
+
const t = a.target, r = t.node !== void 0 ? t.node : t.id;
|
|
28
|
+
return this.parser.getDependency("node", r);
|
|
29
29
|
}
|
|
30
|
-
loadAnimationTargetFromChannelWithAnimationPointer(
|
|
30
|
+
loadAnimationTargetFromChannelWithAnimationPointer(a) {
|
|
31
31
|
var c;
|
|
32
32
|
B();
|
|
33
|
-
const
|
|
34
|
-
if (!
|
|
35
|
-
let e,
|
|
36
|
-
if (
|
|
37
|
-
const m =
|
|
33
|
+
const t = a.target, r = t.extensions && t.extensions[R] && t.path && t.path === "pointer";
|
|
34
|
+
if (!r) return null;
|
|
35
|
+
let e, n = f.node, s;
|
|
36
|
+
if (r) {
|
|
37
|
+
const m = t.extensions[R];
|
|
38
38
|
let o = m.pointer;
|
|
39
39
|
if (!o) {
|
|
40
|
-
console.warn("Invalid path", m,
|
|
40
|
+
console.warn("Invalid path", m, t);
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
|
-
if (o.startsWith("/materials/") ?
|
|
44
|
-
console.warn("Failed resolving animation node id: " +
|
|
43
|
+
if (o.startsWith("/materials/") ? n = f.material : o.startsWith("/extensions/KHR_lights_punctual/lights/") ? n = f.light : o.startsWith("/cameras/") && (n = f.camera), s = this._tryResolveTargetId(o, n), s === null || isNaN(s)) {
|
|
44
|
+
console.warn("Failed resolving animation node id: " + s, o);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
switch (
|
|
47
|
+
switch (n) {
|
|
48
48
|
case f.material:
|
|
49
|
-
const x = ("/materials/" +
|
|
49
|
+
const x = ("/materials/" + s.toString() + "/").length, h = o.substring(0, x);
|
|
50
50
|
switch (e = o.substring(x), e) {
|
|
51
51
|
case "pbrMetallicRoughness/baseColorFactor":
|
|
52
52
|
e = "color";
|
|
@@ -133,7 +133,7 @@ class j {
|
|
|
133
133
|
o = h + e;
|
|
134
134
|
break;
|
|
135
135
|
case f.node:
|
|
136
|
-
const u = ("/nodes/" +
|
|
136
|
+
const u = ("/nodes/" + s.toString() + "/").length, l = o.substring(0, u);
|
|
137
137
|
switch (e = o.substring(u), e) {
|
|
138
138
|
case "translation":
|
|
139
139
|
e = "position";
|
|
@@ -147,11 +147,14 @@ class j {
|
|
|
147
147
|
case "weights":
|
|
148
148
|
e = "morphTargetInfluences";
|
|
149
149
|
break;
|
|
150
|
+
case "KHR_node_visibility/visible":
|
|
151
|
+
e = "visible";
|
|
152
|
+
break;
|
|
150
153
|
}
|
|
151
154
|
o = l + e;
|
|
152
155
|
break;
|
|
153
156
|
case f.light:
|
|
154
|
-
const p = ("/extensions/KHR_lights_punctual/lights/" +
|
|
157
|
+
const p = ("/extensions/KHR_lights_punctual/lights/" + s.toString() + "/").length;
|
|
155
158
|
switch (e = o.substring(p), e) {
|
|
156
159
|
case "color":
|
|
157
160
|
break;
|
|
@@ -167,10 +170,10 @@ class j {
|
|
|
167
170
|
e = "distance";
|
|
168
171
|
break;
|
|
169
172
|
}
|
|
170
|
-
o = "/lights/" +
|
|
173
|
+
o = "/lights/" + s.toString() + "/" + e;
|
|
171
174
|
break;
|
|
172
175
|
case f.camera:
|
|
173
|
-
const g = ("/cameras/" +
|
|
176
|
+
const g = ("/cameras/" + s.toString() + "/").length, b = o.substring(0, g);
|
|
174
177
|
switch (e = o.substring(g), e) {
|
|
175
178
|
case "perspective/yfov":
|
|
176
179
|
e = "fov";
|
|
@@ -196,25 +199,25 @@ class j {
|
|
|
196
199
|
o = b + e;
|
|
197
200
|
break;
|
|
198
201
|
}
|
|
199
|
-
(c = this.animationPointerResolver) != null && c.resolvePath && (o = this.animationPointerResolver.resolvePath(o)),
|
|
202
|
+
(c = this.animationPointerResolver) != null && c.resolvePath && (o = this.animationPointerResolver.resolvePath(o)), t.extensions[R].pointer = o;
|
|
200
203
|
}
|
|
201
|
-
if (
|
|
202
|
-
console.warn("Failed resolving animation node id: " +
|
|
204
|
+
if (s == null || isNaN(s)) {
|
|
205
|
+
console.warn("Failed resolving animation node id: " + s, t);
|
|
203
206
|
return;
|
|
204
207
|
}
|
|
205
208
|
let i;
|
|
206
|
-
return
|
|
209
|
+
return n === f.node ? i = this.parser.getDependency("node", s) : n === f.material ? i = this.parser.getDependency("material", s) : n === f.light ? i = this.parser.getDependency("light", s) : n === f.camera ? i = this.parser.getDependency("camera", s) : console.error("Unhandled type", n), i;
|
|
207
210
|
}
|
|
208
|
-
createAnimationTracksWithAnimationPointer(
|
|
209
|
-
if (!(
|
|
210
|
-
let i =
|
|
211
|
+
createAnimationTracksWithAnimationPointer(a, t, r, e, n) {
|
|
212
|
+
if (!(n.extensions && n.extensions[R] && n.path && n.path === "pointer")) return null;
|
|
213
|
+
let i = n.extensions[R].pointer;
|
|
211
214
|
if (!i) return null;
|
|
212
215
|
const c = [];
|
|
213
216
|
i = i.replaceAll("/", ".");
|
|
214
217
|
const m = i.split(".");
|
|
215
|
-
var x =
|
|
216
|
-
if (m[2] = x, m[3] === "morphTargetInfluences" &&
|
|
217
|
-
for (const u of
|
|
218
|
+
var x = a.name !== void 0 && a.name !== null ? a.name : a.uuid;
|
|
219
|
+
if (m[2] = x, m[3] === "morphTargetInfluences" && a.type === "Group") {
|
|
220
|
+
for (const u of a.children)
|
|
218
221
|
u instanceof S && u.morphTargetInfluences && (m[3] = u.name, m[4] = "morphTargetInfluences", h(this.parser));
|
|
219
222
|
return c;
|
|
220
223
|
}
|
|
@@ -222,7 +225,7 @@ class j {
|
|
|
222
225
|
function h(u) {
|
|
223
226
|
i = m.join(".");
|
|
224
227
|
let l;
|
|
225
|
-
switch (
|
|
228
|
+
switch (r.itemSize) {
|
|
226
229
|
case 1:
|
|
227
230
|
l = O;
|
|
228
231
|
break;
|
|
@@ -235,25 +238,25 @@ class j {
|
|
|
235
238
|
break;
|
|
236
239
|
}
|
|
237
240
|
if (!l) {
|
|
238
|
-
console.warn("Unsupported output accessor format",
|
|
241
|
+
console.warn("Unsupported output accessor format", r);
|
|
239
242
|
return;
|
|
240
243
|
}
|
|
241
244
|
const p = e.interpolation !== void 0 ? U[e.interpolation] : F;
|
|
242
|
-
let g = u._getArrayFromAccessor(
|
|
245
|
+
let g = u._getArrayFromAccessor(r);
|
|
243
246
|
i.endsWith(".fov") && (g = g.map((k) => k / Math.PI * 180));
|
|
244
247
|
const b = new l(
|
|
245
248
|
i,
|
|
246
|
-
|
|
249
|
+
t.array,
|
|
247
250
|
g,
|
|
248
251
|
p
|
|
249
252
|
);
|
|
250
|
-
if (p === "CUBICSPLINE" && u._createCubicSplineTrackInterpolant(b), c.push(b), i &&
|
|
253
|
+
if (p === "CUBICSPLINE" && u._createCubicSplineTrackInterpolant(b), c.push(b), i && r.itemSize === 4 && i.startsWith(".materials.") && i.endsWith(".color")) {
|
|
251
254
|
const k = new Float32Array(g.length / 4);
|
|
252
255
|
for (let T = 0, _ = g.length / 4; T < _; T += 1)
|
|
253
256
|
k[T] = g[T * 4 + 3];
|
|
254
257
|
const d = new l(
|
|
255
258
|
i.replace(".color", ".opacity"),
|
|
256
|
-
|
|
259
|
+
t.array,
|
|
257
260
|
k,
|
|
258
261
|
p
|
|
259
262
|
);
|
|
@@ -262,9 +265,9 @@ class j {
|
|
|
262
265
|
}
|
|
263
266
|
return c;
|
|
264
267
|
}
|
|
265
|
-
_tryResolveTargetId(
|
|
266
|
-
let
|
|
267
|
-
return
|
|
268
|
+
_tryResolveTargetId(a, t) {
|
|
269
|
+
let r = "";
|
|
270
|
+
return t === "node" ? r = a.substring(7) : t === "material" ? r = a.substring(11) : t === "light" ? r = a.substring(39) : t === "camera" && (r = a.substring(9)), r = r.substring(0, r.indexOf("/")), Number.parseInt(r);
|
|
268
271
|
}
|
|
269
272
|
/* MOSTLY DUPLICATE of GLTFLoader.loadAnimation, but also tries to resolve KHR_animation_pointer. */
|
|
270
273
|
/**
|
|
@@ -272,12 +275,12 @@ class j {
|
|
|
272
275
|
* @param {number} animationIndex
|
|
273
276
|
* @return {Promise<AnimationClip>}
|
|
274
277
|
*/
|
|
275
|
-
loadAnimation(
|
|
276
|
-
const
|
|
277
|
-
for (let h = 0, u =
|
|
278
|
-
const l =
|
|
279
|
-
let d =
|
|
280
|
-
d || (d =
|
|
278
|
+
loadAnimation(a) {
|
|
279
|
+
const t = this, r = this.parser.json, e = this.parser, n = r.animations[a], s = n.name ? n.name : "animation_" + a, i = [], c = [], m = [], o = [], x = [];
|
|
280
|
+
for (let h = 0, u = n.channels.length; h < u; h++) {
|
|
281
|
+
const l = n.channels[h], p = n.samplers[l.sampler], g = l.target, b = n.parameters !== void 0 ? n.parameters[p.input] : p.input, k = n.parameters !== void 0 ? n.parameters[p.output] : p.output;
|
|
282
|
+
let d = t.loadAnimationTargetFromChannelWithAnimationPointer(l);
|
|
283
|
+
d || (d = t.loadAnimationTargetFromChannel(l)), i.push(d), c.push(e.getDependency("accessor", b)), m.push(e.getDependency("accessor", k)), o.push(p), x.push(g);
|
|
281
284
|
}
|
|
282
285
|
return Promise.all([
|
|
283
286
|
Promise.all(i),
|
|
@@ -288,15 +291,15 @@ class j {
|
|
|
288
291
|
]).then(function(h) {
|
|
289
292
|
const u = h[0], l = h[1], p = h[2], g = h[3], b = h[4], k = [];
|
|
290
293
|
for (let d = 0, T = u.length; d < T; d++) {
|
|
291
|
-
const _ = u[d],
|
|
294
|
+
const _ = u[d], P = l[d], A = p[d], K = g[d], N = b[d];
|
|
292
295
|
if (_ === void 0) continue;
|
|
293
296
|
_.updateMatrix && (_.updateMatrix(), _.matrixAutoUpdate = !0);
|
|
294
|
-
let y =
|
|
295
|
-
if (y || (y = e._createAnimationTracks(_,
|
|
296
|
-
for (let
|
|
297
|
-
k.push(y[
|
|
297
|
+
let y = t.createAnimationTracksWithAnimationPointer(_, P, A, K, N);
|
|
298
|
+
if (y || (y = e._createAnimationTracks(_, P, A, K, N)), y)
|
|
299
|
+
for (let v = 0; v < y.length; v++)
|
|
300
|
+
k.push(y[v]);
|
|
298
301
|
}
|
|
299
|
-
return new W(
|
|
302
|
+
return new W(s, void 0, k);
|
|
300
303
|
});
|
|
301
304
|
}
|
|
302
305
|
}
|
|
@@ -305,36 +308,37 @@ function B() {
|
|
|
305
308
|
if (H) return;
|
|
306
309
|
H = !0;
|
|
307
310
|
const I = z || (z = C.findNode);
|
|
308
|
-
C.findNode = function(
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
311
|
+
C.findNode = function(a, t) {
|
|
312
|
+
if (!t) return I(a, t);
|
|
313
|
+
if (t.startsWith(".materials.")) {
|
|
314
|
+
const r = t.substring(11).substring(t.indexOf(".")), e = r.indexOf("."), n = e < 0 ? r : r.substring(0, e);
|
|
315
|
+
let s = null;
|
|
316
|
+
return a.traverse((i) => {
|
|
317
|
+
s !== null || i.type !== "Mesh" && i.type !== "SkinnedMesh" || i.material && (i.material.uuid === n || i.material.name === n) && (s = i.material, s !== null && (r.endsWith(".map") ? s = s.map : r.endsWith(".emissiveMap") && (s = s.emissiveMap)));
|
|
318
|
+
}), s;
|
|
319
|
+
} else if (t.startsWith(".nodes.") || t.startsWith(".lights.") || t.startsWith(".cameras.")) {
|
|
320
|
+
const r = t.split(".");
|
|
317
321
|
let e;
|
|
318
|
-
for (let
|
|
319
|
-
const
|
|
320
|
-
if (
|
|
321
|
-
e =
|
|
322
|
-
else if (e && e[
|
|
323
|
-
const c = Number.parseInt(
|
|
324
|
-
let m =
|
|
322
|
+
for (let n = 1; n < r.length; n++) {
|
|
323
|
+
const s = r[n];
|
|
324
|
+
if (s.length == 36)
|
|
325
|
+
e = a.getObjectByProperty("uuid", s);
|
|
326
|
+
else if (e && e[s]) {
|
|
327
|
+
const c = Number.parseInt(s);
|
|
328
|
+
let m = s;
|
|
325
329
|
c >= 0 && (m = c), e = e[m];
|
|
326
330
|
} else {
|
|
327
|
-
const c =
|
|
331
|
+
const c = a.getObjectByName(s);
|
|
328
332
|
c && (e = c);
|
|
329
333
|
}
|
|
330
334
|
}
|
|
331
335
|
if (!e) {
|
|
332
|
-
const
|
|
333
|
-
return
|
|
336
|
+
const n = I(a, r[2]);
|
|
337
|
+
return n || console.warn(R + ": Property binding not found", t, a, a.name, r), n;
|
|
334
338
|
}
|
|
335
339
|
return e;
|
|
336
340
|
}
|
|
337
|
-
return I(
|
|
341
|
+
return I(a, t);
|
|
338
342
|
};
|
|
339
343
|
}
|
|
340
344
|
export {
|
package/package.json
CHANGED
|
@@ -260,7 +260,9 @@ export class GLTFAnimationPointerExtension {
|
|
|
260
260
|
case 'weights':
|
|
261
261
|
targetProperty = 'morphTargetInfluences';
|
|
262
262
|
break;
|
|
263
|
-
|
|
263
|
+
case "KHR_node_visibility/visible":
|
|
264
|
+
targetProperty = 'visible';
|
|
265
|
+
break;
|
|
264
266
|
}
|
|
265
267
|
|
|
266
268
|
path = pathStartNode + targetProperty;
|
|
@@ -657,6 +659,10 @@ function _ensurePropertyBindingPatch() {
|
|
|
657
659
|
// "path" is the animated property path, just with translated material names.
|
|
658
660
|
PropertyBinding.findNode = function (node, path) {
|
|
659
661
|
|
|
662
|
+
// if the binding is empty fallback to original
|
|
663
|
+
if (!path) return findNode(node, path);
|
|
664
|
+
|
|
665
|
+
|
|
660
666
|
if (path.startsWith('.materials.')) {
|
|
661
667
|
|
|
662
668
|
if (_animationPointerDebug) console.log('FIND', path);
|