parseAnimation static method

dynamic parseAnimation(
  1. dynamic animation,
  2. dynamic bones
)

Implementation

static parseAnimation(animation, bones) {
  if (!animation) {
    print('three.AnimationClip: No animation in JSONLoader data.');
    return null;
  }

  addNonemptyTrack(String trackType, trackName, animationKeys, propertyName, destTracks) {
    // only return track if there are actually keys.
    if (animationKeys.length != 0) {
      const times = [];
      const values = [];

      AnimationUtils.flattenJSON(animationKeys, times, values, propertyName);

      // empty keys are filtered out, so check again
      if (times.isNotEmpty) {
        if (trackType == "VectorKeyframeTrack") {
          destTracks.add(VectorKeyframeTrack(trackName, times, values, null));
        } else if (trackType == "QuaternionKeyframeTrack") {
          destTracks.add(QuaternionKeyframeTrack(trackName, times, values, null));
        } else {
          throw ("AnimationClip. addNonemptyTrack trackType: $trackType is not support ");
        }
      }
    }
  }

  var tracks = <KeyframeTrack>[];

  var clipName = animation.name ?? 'default';
  var fps = animation.fps ?? 30;
  var blendMode = animation.blendMode;

  // automatic length determination in AnimationClip.
  var duration = animation.length ?? -1;

  var hierarchyTracks = animation.hierarchy ?? [];

  for (var h = 0; h < hierarchyTracks.length; h++) {
    var animationKeys = hierarchyTracks[h].keys;

    // skip empty tracks
    if (!animationKeys || animationKeys.length == 0) continue;

    // process morph targets
    if (animationKeys[0].morphTargets) {
      // figure out all morph targets used in this track
      var morphTargetNames = {};

      int k;

      for (k = 0; k < animationKeys.length; k++) {
        if (animationKeys[k].morphTargets) {
          for (var m = 0; m < animationKeys[k].morphTargets.length; m++) {
            morphTargetNames[animationKeys[k].morphTargets[m]] = -1;
          }
        }
      }

      // create a track for each morph target with all zero
      // morphTargetInfluences except for the keys in which
      // the morphTarget is named.
      // for ( var morphTargetName in morphTargetNames ) {
      morphTargetNames.forEach((morphTargetName, value) {
        List<num> times = [];
        List<num> values = [];

        for (var m = 0; m != animationKeys[k].morphTargets.length; ++m) {
          var animationKey = animationKeys[k];

          times.add(animationKey.time);
          values.add((animationKey.morphTarget == morphTargetName) ? 1 : 0);
        }

        tracks.add(NumberKeyframeTrack('.morphTargetInfluence[$morphTargetName]', times, values, null));
      });

      duration = morphTargetNames.length * (fps ?? 1.0);
    } else {
      // ...assume skeletal animation

      var boneName = '.bones[${bones[h].name}]';

      addNonemptyTrack("VectorKeyframeTrack", '$boneName.position', animationKeys, 'pos', tracks);

      addNonemptyTrack("QuaternionKeyframeTrack", '$boneName.quaternion', animationKeys, 'rot', tracks);

      addNonemptyTrack("VectorKeyframeTrack", '$boneName.scale', animationKeys, 'scl', tracks);
    }
  }

  if (tracks.isEmpty) {
    return null;
  }

  var clip = AnimationClip(clipName, duration, tracks, blendMode);

  return clip;
}