import { Mesh, MathUtils } from "three";
class MorphBlendMesh extends Mesh {
  constructor(geometry, material) {
    super(geometry, material);
    this.animationsMap = {};
    this.animationsList = [];
    const numFrames = Object.keys(this.morphTargetDictionary).length;
    const name = "__default";
    const startFrame = 0;
    const endFrame = numFrames - 1;
    const fps = numFrames / 1;
    this.createAnimation(name, startFrame, endFrame, fps);
    this.setAnimationWeight(name, 1);
  }
  createAnimation(name, start, end, fps) {
    const animation = {
      start,
      end,
      length: end - start + 1,
      fps,
      duration: (end - start) / fps,
      lastFrame: 0,
      currentFrame: 0,
      active: false,
      time: 0,
      direction: 1,
      weight: 1,
      directionBackwards: false,
      mirroredLoop: false
    };
    this.animationsMap[name] = animation;
    this.animationsList.push(animation);
  }
  autoCreateAnimations(fps) {
    const pattern = /([a-z]+)_?(\d+)/i;
    let firstAnimation;
    const frameRanges = {};
    let i = 0;
    for (const key in this.morphTargetDictionary) {
      const chunks = key.match(pattern);
      if (chunks && chunks.length > 1) {
        const name = chunks[1];
        if (!frameRanges[name])
          frameRanges[name] = { start: Infinity, end: -Infinity };
        const range = frameRanges[name];
        if (i < range.start)
          range.start = i;
        if (i > range.end)
          range.end = i;
        if (!firstAnimation)
          firstAnimation = name;
      }
      i++;
    }
    for (const name in frameRanges) {
      const range = frameRanges[name];
      this.createAnimation(name, range.start, range.end, fps);
    }
    this.firstAnimation = firstAnimation;
  }
  setAnimationDirectionForward(name) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.direction = 1;
      animation.directionBackwards = false;
    }
  }
  setAnimationDirectionBackward(name) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.direction = -1;
      animation.directionBackwards = true;
    }
  }
  setAnimationFPS(name, fps) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.fps = fps;
      animation.duration = (animation.end - animation.start) / animation.fps;
    }
  }
  setAnimationDuration(name, duration) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.duration = duration;
      animation.fps = (animation.end - animation.start) / animation.duration;
    }
  }
  setAnimationWeight(name, weight) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.weight = weight;
    }
  }
  setAnimationTime(name, time) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.time = time;
    }
  }
  getAnimationTime(name) {
    let time = 0;
    const animation = this.animationsMap[name];
    if (animation) {
      time = animation.time;
    }
    return time;
  }
  getAnimationDuration(name) {
    let duration = -1;
    const animation = this.animationsMap[name];
    if (animation) {
      duration = animation.duration;
    }
    return duration;
  }
  playAnimation(name) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.time = 0;
      animation.active = true;
    } else {
      console.warn("THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()");
    }
  }
  stopAnimation(name) {
    const animation = this.animationsMap[name];
    if (animation) {
      animation.active = false;
    }
  }
  update(delta) {
    for (let i = 0, il = this.animationsList.length; i < il; i++) {
      const animation = this.animationsList[i];
      if (!animation.active)
        continue;
      const frameTime = animation.duration / animation.length;
      animation.time += animation.direction * delta;
      if (animation.mirroredLoop) {
        if (animation.time > animation.duration || animation.time < 0) {
          animation.direction *= -1;
          if (animation.time > animation.duration) {
            animation.time = animation.duration;
            animation.directionBackwards = true;
          }
          if (animation.time < 0) {
            animation.time = 0;
            animation.directionBackwards = false;
          }
        }
      } else {
        animation.time = animation.time % animation.duration;
        if (animation.time < 0)
          animation.time += animation.duration;
      }
      const keyframe = animation.start + MathUtils.clamp(Math.floor(animation.time / frameTime), 0, animation.length - 1);
      const weight = animation.weight;
      if (keyframe !== animation.currentFrame) {
        this.morphTargetInfluences[animation.lastFrame] = 0;
        this.morphTargetInfluences[animation.currentFrame] = 1 * weight;
        this.morphTargetInfluences[keyframe] = 0;
        animation.lastFrame = animation.currentFrame;
        animation.currentFrame = keyframe;
      }
      let mix = animation.time % frameTime / frameTime;
      if (animation.directionBackwards)
        mix = 1 - mix;
      if (animation.currentFrame !== animation.lastFrame) {
        this.morphTargetInfluences[animation.currentFrame] = mix * weight;
        this.morphTargetInfluences[animation.lastFrame] = (1 - mix) * weight;
      } else {
        this.morphTargetInfluences[animation.currentFrame] = weight;
      }
    }
  }
}
export {
  MorphBlendMesh
};
//# sourceMappingURL=MorphBlendMesh.js.map
