@needle-tools/three-animation-pointer 1.0.2 → 1.0.3

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,8 @@ 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.3] - 2025-09-11
8
+ - Fix: Handle undefined path if AnimationClip tracks have invalid/unexpected names. Fallback to default three implementation
9
+
7
10
  ## [1.0.1] - 2025-08-27
8
11
  - 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(r) {
17
- this.name = R, this.parser = r, this.animationPointerResolver = null;
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(r) {
23
- return this.animationPointerResolver = r, this;
22
+ setAnimationPointerResolver(a) {
23
+ return this.animationPointerResolver = a, this;
24
24
  }
25
25
  /* DUPLICATE of functionality in GLTFLoader */
26
- loadAnimationTargetFromChannel(r) {
27
- const s = r.target, a = s.node !== void 0 ? s.node : s.id;
28
- return this.parser.getDependency("node", a);
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(r) {
30
+ loadAnimationTargetFromChannelWithAnimationPointer(a) {
31
31
  var c;
32
32
  B();
33
- const s = r.target, a = s.extensions && s.extensions[R] && s.path && s.path === "pointer";
34
- if (!a) return null;
35
- let e, t = f.node, n;
36
- if (a) {
37
- const m = s.extensions[R];
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, s);
40
+ console.warn("Invalid path", m, t);
41
41
  return;
42
42
  }
43
- if (o.startsWith("/materials/") ? t = f.material : o.startsWith("/extensions/KHR_lights_punctual/lights/") ? t = f.light : o.startsWith("/cameras/") && (t = f.camera), n = this._tryResolveTargetId(o, t), n === null || isNaN(n)) {
44
- console.warn("Failed resolving animation node id: " + n, o);
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 (t) {
47
+ switch (n) {
48
48
  case f.material:
49
- const x = ("/materials/" + n.toString() + "/").length, h = o.substring(0, x);
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/" + n.toString() + "/").length, l = o.substring(0, u);
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";
@@ -151,7 +151,7 @@ class j {
151
151
  o = l + e;
152
152
  break;
153
153
  case f.light:
154
- const p = ("/extensions/KHR_lights_punctual/lights/" + n.toString() + "/").length;
154
+ const p = ("/extensions/KHR_lights_punctual/lights/" + s.toString() + "/").length;
155
155
  switch (e = o.substring(p), e) {
156
156
  case "color":
157
157
  break;
@@ -167,10 +167,10 @@ class j {
167
167
  e = "distance";
168
168
  break;
169
169
  }
170
- o = "/lights/" + n.toString() + "/" + e;
170
+ o = "/lights/" + s.toString() + "/" + e;
171
171
  break;
172
172
  case f.camera:
173
- const g = ("/cameras/" + n.toString() + "/").length, b = o.substring(0, g);
173
+ const g = ("/cameras/" + s.toString() + "/").length, b = o.substring(0, g);
174
174
  switch (e = o.substring(g), e) {
175
175
  case "perspective/yfov":
176
176
  e = "fov";
@@ -196,25 +196,25 @@ class j {
196
196
  o = b + e;
197
197
  break;
198
198
  }
199
- (c = this.animationPointerResolver) != null && c.resolvePath && (o = this.animationPointerResolver.resolvePath(o)), s.extensions[R].pointer = o;
199
+ (c = this.animationPointerResolver) != null && c.resolvePath && (o = this.animationPointerResolver.resolvePath(o)), t.extensions[R].pointer = o;
200
200
  }
201
- if (n == null || isNaN(n)) {
202
- console.warn("Failed resolving animation node id: " + n, s);
201
+ if (s == null || isNaN(s)) {
202
+ console.warn("Failed resolving animation node id: " + s, t);
203
203
  return;
204
204
  }
205
205
  let i;
206
- return t === f.node ? i = this.parser.getDependency("node", n) : t === f.material ? i = this.parser.getDependency("material", n) : t === f.light ? i = this.parser.getDependency("light", n) : t === f.camera ? i = this.parser.getDependency("camera", n) : console.error("Unhandled type", t), i;
206
+ 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
207
  }
208
- createAnimationTracksWithAnimationPointer(r, s, a, e, t) {
209
- if (!(t.extensions && t.extensions[R] && t.path && t.path === "pointer")) return null;
210
- let i = t.extensions[R].pointer;
208
+ createAnimationTracksWithAnimationPointer(a, t, r, e, n) {
209
+ if (!(n.extensions && n.extensions[R] && n.path && n.path === "pointer")) return null;
210
+ let i = n.extensions[R].pointer;
211
211
  if (!i) return null;
212
212
  const c = [];
213
213
  i = i.replaceAll("/", ".");
214
214
  const m = i.split(".");
215
- var x = r.name !== void 0 && r.name !== null ? r.name : r.uuid;
216
- if (m[2] = x, m[3] === "morphTargetInfluences" && r.type === "Group") {
217
- for (const u of r.children)
215
+ var x = a.name !== void 0 && a.name !== null ? a.name : a.uuid;
216
+ if (m[2] = x, m[3] === "morphTargetInfluences" && a.type === "Group") {
217
+ for (const u of a.children)
218
218
  u instanceof S && u.morphTargetInfluences && (m[3] = u.name, m[4] = "morphTargetInfluences", h(this.parser));
219
219
  return c;
220
220
  }
@@ -222,7 +222,7 @@ class j {
222
222
  function h(u) {
223
223
  i = m.join(".");
224
224
  let l;
225
- switch (a.itemSize) {
225
+ switch (r.itemSize) {
226
226
  case 1:
227
227
  l = O;
228
228
  break;
@@ -235,25 +235,25 @@ class j {
235
235
  break;
236
236
  }
237
237
  if (!l) {
238
- console.warn("Unsupported output accessor format", a);
238
+ console.warn("Unsupported output accessor format", r);
239
239
  return;
240
240
  }
241
241
  const p = e.interpolation !== void 0 ? U[e.interpolation] : F;
242
- let g = u._getArrayFromAccessor(a);
242
+ let g = u._getArrayFromAccessor(r);
243
243
  i.endsWith(".fov") && (g = g.map((k) => k / Math.PI * 180));
244
244
  const b = new l(
245
245
  i,
246
- s.array,
246
+ t.array,
247
247
  g,
248
248
  p
249
249
  );
250
- if (p === "CUBICSPLINE" && u._createCubicSplineTrackInterpolant(b), c.push(b), i && a.itemSize === 4 && i.startsWith(".materials.") && i.endsWith(".color")) {
250
+ if (p === "CUBICSPLINE" && u._createCubicSplineTrackInterpolant(b), c.push(b), i && r.itemSize === 4 && i.startsWith(".materials.") && i.endsWith(".color")) {
251
251
  const k = new Float32Array(g.length / 4);
252
252
  for (let T = 0, _ = g.length / 4; T < _; T += 1)
253
253
  k[T] = g[T * 4 + 3];
254
254
  const d = new l(
255
255
  i.replace(".color", ".opacity"),
256
- s.array,
256
+ t.array,
257
257
  k,
258
258
  p
259
259
  );
@@ -262,9 +262,9 @@ class j {
262
262
  }
263
263
  return c;
264
264
  }
265
- _tryResolveTargetId(r, s) {
266
- let a = "";
267
- return s === "node" ? a = r.substring(7) : s === "material" ? a = r.substring(11) : s === "light" ? a = r.substring(39) : s === "camera" && (a = r.substring(9)), a = a.substring(0, a.indexOf("/")), Number.parseInt(a);
265
+ _tryResolveTargetId(a, t) {
266
+ let r = "";
267
+ 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
268
  }
269
269
  /* MOSTLY DUPLICATE of GLTFLoader.loadAnimation, but also tries to resolve KHR_animation_pointer. */
270
270
  /**
@@ -272,12 +272,12 @@ class j {
272
272
  * @param {number} animationIndex
273
273
  * @return {Promise<AnimationClip>}
274
274
  */
275
- loadAnimation(r) {
276
- const s = this, a = this.parser.json, e = this.parser, t = a.animations[r], n = t.name ? t.name : "animation_" + r, i = [], c = [], m = [], o = [], x = [];
277
- for (let h = 0, u = t.channels.length; h < u; h++) {
278
- const l = t.channels[h], p = t.samplers[l.sampler], g = l.target, b = t.parameters !== void 0 ? t.parameters[p.input] : p.input, k = t.parameters !== void 0 ? t.parameters[p.output] : p.output;
279
- let d = s.loadAnimationTargetFromChannelWithAnimationPointer(l);
280
- d || (d = s.loadAnimationTargetFromChannel(l)), i.push(d), c.push(e.getDependency("accessor", b)), m.push(e.getDependency("accessor", k)), o.push(p), x.push(g);
275
+ loadAnimation(a) {
276
+ 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 = [];
277
+ for (let h = 0, u = n.channels.length; h < u; h++) {
278
+ 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;
279
+ let d = t.loadAnimationTargetFromChannelWithAnimationPointer(l);
280
+ 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
281
  }
282
282
  return Promise.all([
283
283
  Promise.all(i),
@@ -291,12 +291,12 @@ class j {
291
291
  const _ = u[d], v = l[d], A = p[d], N = g[d], K = b[d];
292
292
  if (_ === void 0) continue;
293
293
  _.updateMatrix && (_.updateMatrix(), _.matrixAutoUpdate = !0);
294
- let y = s.createAnimationTracksWithAnimationPointer(_, v, A, N, K);
294
+ let y = t.createAnimationTracksWithAnimationPointer(_, v, A, N, K);
295
295
  if (y || (y = e._createAnimationTracks(_, v, A, N, K)), y)
296
296
  for (let P = 0; P < y.length; P++)
297
297
  k.push(y[P]);
298
298
  }
299
- return new W(n, void 0, k);
299
+ return new W(s, void 0, k);
300
300
  });
301
301
  }
302
302
  }
@@ -305,36 +305,37 @@ function B() {
305
305
  if (H) return;
306
306
  H = !0;
307
307
  const I = z || (z = C.findNode);
308
- C.findNode = function(r, s) {
309
- if (s.startsWith(".materials.")) {
310
- const a = s.substring(11).substring(s.indexOf(".")), e = a.indexOf("."), t = e < 0 ? a : a.substring(0, e);
311
- let n = null;
312
- return r.traverse((i) => {
313
- n !== null || i.type !== "Mesh" && i.type !== "SkinnedMesh" || i.material && (i.material.uuid === t || i.material.name === t) && (n = i.material, n !== null && (a.endsWith(".map") ? n = n.map : a.endsWith(".emissiveMap") && (n = n.emissiveMap)));
314
- }), n;
315
- } else if (s.startsWith(".nodes.") || s.startsWith(".lights.") || s.startsWith(".cameras.")) {
316
- const a = s.split(".");
308
+ C.findNode = function(a, t) {
309
+ if (!t) return I(a, t);
310
+ if (t.startsWith(".materials.")) {
311
+ const r = t.substring(11).substring(t.indexOf(".")), e = r.indexOf("."), n = e < 0 ? r : r.substring(0, e);
312
+ let s = null;
313
+ return a.traverse((i) => {
314
+ 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)));
315
+ }), s;
316
+ } else if (t.startsWith(".nodes.") || t.startsWith(".lights.") || t.startsWith(".cameras.")) {
317
+ const r = t.split(".");
317
318
  let e;
318
- for (let t = 1; t < a.length; t++) {
319
- const n = a[t];
320
- if (n.length == 36)
321
- e = r.getObjectByProperty("uuid", n);
322
- else if (e && e[n]) {
323
- const c = Number.parseInt(n);
324
- let m = n;
319
+ for (let n = 1; n < r.length; n++) {
320
+ const s = r[n];
321
+ if (s.length == 36)
322
+ e = a.getObjectByProperty("uuid", s);
323
+ else if (e && e[s]) {
324
+ const c = Number.parseInt(s);
325
+ let m = s;
325
326
  c >= 0 && (m = c), e = e[m];
326
327
  } else {
327
- const c = r.getObjectByName(n);
328
+ const c = a.getObjectByName(s);
328
329
  c && (e = c);
329
330
  }
330
331
  }
331
332
  if (!e) {
332
- const t = I(r, a[2]);
333
- return t || console.warn(R + ": Property binding not found", s, r, r.name, a), t;
333
+ const n = I(a, r[2]);
334
+ return n || console.warn(R + ": Property binding not found", t, a, a.name, r), n;
334
335
  }
335
336
  return e;
336
337
  }
337
- return I(r, s);
338
+ return I(a, t);
338
339
  };
339
340
  }
340
341
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/three-animation-pointer",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "KHR_animation_pointer support for three.js",
5
5
  "type": "module",
6
6
  "main": "dist/three-animation-pointer.js",
@@ -657,6 +657,10 @@ function _ensurePropertyBindingPatch() {
657
657
  // "path" is the animated property path, just with translated material names.
658
658
  PropertyBinding.findNode = function (node, path) {
659
659
 
660
+ // if the binding is empty fallback to original
661
+ if (!path) return findNode(node, path);
662
+
663
+
660
664
  if (path.startsWith('.materials.')) {
661
665
 
662
666
  if (_animationPointerDebug) console.log('FIND', path);