@lovelace_lol/embody 0.0.9 → 0.0.10

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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as THREE3 from 'three';
2
- import { NoBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, Vector3, Box3, Timer, Matrix4, AnimationMixer, AdditiveAnimationBlendMode, NormalAnimationBlendMode, LoopOnce, LoopRepeat, LoopPingPong, PropertyBinding, Quaternion, AnimationUtils, InterpolateDiscrete, InterpolateLinear, MathUtils, Mesh, PlaneGeometry, ShadowMaterial, HemisphereLight, DirectionalLight, SRGBColorSpace, ACESFilmicToneMapping, WebGLRenderer, Scene, Color, PerspectiveCamera, PCFShadowMap, PCFSoftShadowMap, NumberKeyframeTrack, QuaternionKeyframeTrack, VectorKeyframeTrack, AnimationClip, PMREMGenerator, FloatType, Float32BufferAttribute, Euler, BufferAttribute, WebGPUCoordinateSystem, WebGLCoordinateSystem } from 'three';
2
+ import { NoBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, Vector3, Box3, Timer, Matrix4, AnimationMixer, AdditiveAnimationBlendMode, NormalAnimationBlendMode, LoopOnce, LoopRepeat, LoopPingPong, PropertyBinding, Euler, Quaternion, AnimationUtils, InterpolateDiscrete, InterpolateLinear, MathUtils, Mesh, PlaneGeometry, ShadowMaterial, HemisphereLight, DirectionalLight, SRGBColorSpace, ACESFilmicToneMapping, WebGLRenderer, Scene, Color, PerspectiveCamera, PCFShadowMap, PCFSoftShadowMap, NumberKeyframeTrack, QuaternionKeyframeTrack, VectorKeyframeTrack, AnimationClip, PMREMGenerator, FloatType, Float32BufferAttribute, BufferAttribute, WebGPUCoordinateSystem, WebGLCoordinateSystem } from 'three';
3
3
  import { CC4_HUMANOID_SKELETON_TEMPLATE, HUMANOID_SKELETON_TEMPLATES, DEFAULT_HAIR_COLOR_APPEARANCE, initEmbodyCore, requireInitializedEmbodyCore } from '@lovelace_lol/embody/wasm';
4
4
  export * from '@lovelace_lol/embody/wasm';
5
5
  export { CC4_HUMANOID_SKELETON_TEMPLATE, DEFAULT_AXIS_TO_CHANNEL, DEFAULT_BONE_MAX_DEGREES, DEFAULT_HAIR_COLOR_APPEARANCE, HAIR_COLOR_PRESETS, HUMANOID_SKELETON_TEMPLATES, JOINT_CONTROL_SECTION, VISEME_KEYS } from '@lovelace_lol/embody/wasm';
@@ -6733,8 +6733,30 @@ function bindModelReferencePose(model, referencePose) {
6733
6733
  if (index !== referencePose.nodes.length) throw new Error("Incompatible reference pose hierarchy: extra captured nodes");
6734
6734
  return bindings2;
6735
6735
  }
6736
-
6737
- // three/clipBindings.ts
6736
+ function withComponentTracks(clip) {
6737
+ let expanded = false;
6738
+ const tracks = clip.tracks.flatMap((track) => {
6739
+ const parsed = PropertyBinding.parseTrackName(track.name);
6740
+ const euler = parsed.propertyName === "rotation";
6741
+ if (!euler && !["morphTargetInfluences", "weights"].includes(parsed.propertyName) || parsed.propertyIndex !== void 0) return [track];
6742
+ const cubic = track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true;
6743
+ const parts = cubic ? 3 : 1;
6744
+ const width = track.getValueSize() / parts;
6745
+ if (!Number.isInteger(width) || width < 1 || euler && width !== 3) throw new Error(`Invalid component track ${JSON.stringify(track.name)}.`);
6746
+ expanded = true;
6747
+ return Array.from({ length: width }, (_, component) => {
6748
+ const scalar = track.clone();
6749
+ scalar.name = `${track.name}[${euler ? ["x", "y", "z"][component] : component}]`;
6750
+ scalar.values = track.values.slice(0, track.times.length * parts);
6751
+ for (let sample = 0; sample < scalar.values.length; sample += 1) scalar.values[sample] = track.values[sample * width + component];
6752
+ return scalar;
6753
+ });
6754
+ });
6755
+ if (!expanded) return clip;
6756
+ const indexed = clip.clone();
6757
+ indexed.tracks = tracks;
6758
+ return indexed;
6759
+ }
6738
6760
  function concreteTrackName(target, inspection) {
6739
6761
  if (!target) return void 0;
6740
6762
  if (target.kind === "morphTarget") {
@@ -6746,6 +6768,7 @@ function concreteTrackName(target, inspection) {
6746
6768
  const property = target.property ?? "rotation";
6747
6769
  if (!object) return void 0;
6748
6770
  if (property === "rotation" || property === "quaternion") return `${object.uuid}.quaternion`;
6771
+ if (property === "eulerX" || property === "eulerY" || property === "eulerZ") return `${object.uuid}.rotation[${property.slice(-1).toLowerCase()}]`;
6749
6772
  if (property === "position" || property === "scale") return `${object.uuid}.${property}`;
6750
6773
  }
6751
6774
  if (target.kind === "meshVisibility") {
@@ -6856,6 +6879,7 @@ var ThreeNativePlaybackConnector = class {
6856
6879
  */
6857
6880
  playNativeClip(clip, options = {}) {
6858
6881
  this.beforeOperation();
6882
+ clip = withComponentTracks(clip);
6859
6883
  const [ir] = serializeAnimationClips(this.binding.model, [clip], this.binding.inspection);
6860
6884
  if (ir.tracks.length !== clip.tracks.length) {
6861
6885
  throw new Error("Every native playback track must serialize against the bound model.");
@@ -6903,6 +6927,7 @@ var ThreeNativePlaybackConnector = class {
6903
6927
  /** Edit authored samples, retaining the native action and its loop/fade progress. */
6904
6928
  replaceClip(handle, clip) {
6905
6929
  this.beforeOperation();
6930
+ clip = withComponentTracks(clip);
6906
6931
  const resource = this.resources.get(handle);
6907
6932
  if (!resource) throw new Error("Unknown, foreign or stale playback handle.");
6908
6933
  const [ir] = serializeAnimationClips(this.binding.model, [clip], this.binding.inspection);
@@ -7411,10 +7436,17 @@ var Embody = class _Embody {
7411
7436
  switch (parsed.propertyName) {
7412
7437
  case "quaternion":
7413
7438
  return Object.values(reference.transform.rotation);
7439
+ case "rotation": {
7440
+ const rotation = reference.transform.rotation;
7441
+ const euler = reference.rotationEuler ?? new Euler().setFromQuaternion(new Quaternion(rotation.x, rotation.y, rotation.z, rotation.w), reference.rotationOrder);
7442
+ const axis = parsed.propertyIndex;
7443
+ return axis === "x" || axis === "y" || axis === "z" ? [euler[axis]] : [euler.x, euler.y, euler.z];
7444
+ }
7414
7445
  case "position":
7415
7446
  return Object.values(reference.transform.position);
7416
7447
  case "scale":
7417
7448
  return Object.values(reference.transform.scale);
7449
+ case "weights":
7418
7450
  case "morphTargetInfluences": {
7419
7451
  const mesh = object;
7420
7452
  const index = typeof parsed.propertyIndex === "string" && !/^\d+$/.test(parsed.propertyIndex) ? mesh.morphTargetDictionary?.[parsed.propertyIndex] : Number(parsed.propertyIndex);
@@ -7431,7 +7463,7 @@ var Embody = class _Embody {
7431
7463
  if (!nativeSource) {
7432
7464
  ir = this.compile(source, options);
7433
7465
  }
7434
- const clip = nativeSource ? source.clip.clone() : createAnimationClipFromClipIR(ir, this.inspection);
7466
+ const clip = nativeSource ? withComponentTracks(source.clip).clone() : createAnimationClipFromClipIR(ir, this.inspection);
7435
7467
  if (ir) {
7436
7468
  const predecessor = this.current.get(source.name);
7437
7469
  const outgoing = predecessor?.connector.getAction(predecessor.id);
@@ -9590,6 +9622,10 @@ function createAnimationClipFromClipIR(clip, inspection) {
9590
9622
  if (property === "rotation" || property === "quaternion") {
9591
9623
  if (track.inheritStart) object.quaternion.toArray(values, 0);
9592
9624
  tracks.push(new QuaternionKeyframeTrack(trackName, times, values, interpolation));
9625
+ } else if (property === "eulerX" || property === "eulerY" || property === "eulerZ") {
9626
+ const axis = property.slice(-1).toLowerCase();
9627
+ if (track.inheritStart) values[0] = object.rotation[axis];
9628
+ tracks.push(new NumberKeyframeTrack(trackName, times, values, interpolation));
9593
9629
  } else if (property === "position") {
9594
9630
  if (track.inheritStart) object.position.toArray(values, 0);
9595
9631
  tracks.push(new VectorKeyframeTrack(trackName, times, values, interpolation));
@@ -9623,7 +9659,7 @@ function serializeAnimationClips(model, clips, inspection) {
9623
9659
  channelKinds.set(kind, id);
9624
9660
  return id;
9625
9661
  };
9626
- clip.tracks.forEach((track, index) => {
9662
+ withComponentTracks(clip).tracks.forEach((track, index) => {
9627
9663
  const found = findTrackTarget(model, track);
9628
9664
  if (!found?.object) return;
9629
9665
  const { parsed, object } = found;
@@ -9638,7 +9674,7 @@ function serializeAnimationClips(model, clips, inspection) {
9638
9674
  } else if (property === "visible" && object.isMesh) {
9639
9675
  target = { kind: "meshVisibility", meshId: meshIds.get(object) };
9640
9676
  } else {
9641
- const transformProperty = property === "quaternion" || property === "rotation" ? "rotation" : property === "position" ? "position" : property === "scale" ? "scale" : null;
9677
+ const transformProperty = property === "rotation" && ["x", "y", "z"].includes(String(parsed.propertyIndex)) ? `euler${String(parsed.propertyIndex).toUpperCase()}` : property === "quaternion" ? "rotation" : property === "position" ? "position" : property === "scale" ? "scale" : null;
9642
9678
  if (transformProperty) {
9643
9679
  const boneId = boneIds.get(object);
9644
9680
  target = boneId ? { kind: "boneTransform", boneId, property: transformProperty } : { kind: "objectTransform", objectId: objectIds.get(object), property: transformProperty };