(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "three"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("three"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.three);
    global.MorphBlendMesh = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _three) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.MorphBlendMesh = void 0;

  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }

  function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

  function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

  var MorphBlendMesh = /*#__PURE__*/function (_Mesh) {
    _inherits(MorphBlendMesh, _Mesh);

    var _super = _createSuper(MorphBlendMesh);

    function MorphBlendMesh(geometry, material) {
      var _this;

      _classCallCheck(this, MorphBlendMesh);

      _this = _super.call(this, geometry, material);
      _this.animationsMap = {};
      _this.animationsList = []; // prepare default animation
      // (all frames played together in 1 second)

      var numFrames = Object.keys(_this.morphTargetDictionary).length;
      var name = '__default';
      var startFrame = 0;
      var endFrame = numFrames - 1;
      var fps = numFrames / 1;

      _this.createAnimation(name, startFrame, endFrame, fps);

      _this.setAnimationWeight(name, 1);

      return _this;
    }

    _createClass(MorphBlendMesh, [{
      key: "createAnimation",
      value: function createAnimation(name, start, end, fps) {
        var animation = {
          start: start,
          end: end,
          length: end - start + 1,
          fps: 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);
      }
    }, {
      key: "autoCreateAnimations",
      value: function autoCreateAnimations(fps) {
        var pattern = /([a-z]+)_?(\d+)/i;
        var firstAnimation;
        var frameRanges = {};
        var i = 0;

        for (var key in this.morphTargetDictionary) {
          var chunks = key.match(pattern);

          if (chunks && chunks.length > 1) {
            var name = chunks[1];
            if (!frameRanges[name]) frameRanges[name] = {
              start: Infinity,
              end: -Infinity
            };
            var range = frameRanges[name];
            if (i < range.start) range.start = i;
            if (i > range.end) range.end = i;
            if (!firstAnimation) firstAnimation = name;
          }

          i++;
        }

        for (var _name in frameRanges) {
          var _range = frameRanges[_name];
          this.createAnimation(_name, _range.start, _range.end, fps);
        }

        this.firstAnimation = firstAnimation;
      }
    }, {
      key: "setAnimationDirectionForward",
      value: function setAnimationDirectionForward(name) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.direction = 1;
          animation.directionBackwards = false;
        }
      }
    }, {
      key: "setAnimationDirectionBackward",
      value: function setAnimationDirectionBackward(name) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.direction = -1;
          animation.directionBackwards = true;
        }
      }
    }, {
      key: "setAnimationFPS",
      value: function setAnimationFPS(name, fps) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.fps = fps;
          animation.duration = (animation.end - animation.start) / animation.fps;
        }
      }
    }, {
      key: "setAnimationDuration",
      value: function setAnimationDuration(name, duration) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.duration = duration;
          animation.fps = (animation.end - animation.start) / animation.duration;
        }
      }
    }, {
      key: "setAnimationWeight",
      value: function setAnimationWeight(name, weight) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.weight = weight;
        }
      }
    }, {
      key: "setAnimationTime",
      value: function setAnimationTime(name, time) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.time = time;
        }
      }
    }, {
      key: "getAnimationTime",
      value: function getAnimationTime(name) {
        var time = 0;
        var animation = this.animationsMap[name];

        if (animation) {
          time = animation.time;
        }

        return time;
      }
    }, {
      key: "getAnimationDuration",
      value: function getAnimationDuration(name) {
        var duration = -1;
        var animation = this.animationsMap[name];

        if (animation) {
          duration = animation.duration;
        }

        return duration;
      }
    }, {
      key: "playAnimation",
      value: function playAnimation(name) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.time = 0;
          animation.active = true;
        } else {
          console.warn('THREE.MorphBlendMesh: animation[' + name + '] undefined in .playAnimation()');
        }
      }
    }, {
      key: "stopAnimation",
      value: function stopAnimation(name) {
        var animation = this.animationsMap[name];

        if (animation) {
          animation.active = false;
        }
      }
    }, {
      key: "update",
      value: function update(delta) {
        for (var i = 0, il = this.animationsList.length; i < il; i++) {
          var animation = this.animationsList[i];
          if (!animation.active) continue;
          var 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;
          }

          var keyframe = animation.start + _three.MathUtils.clamp(Math.floor(animation.time / frameTime), 0, animation.length - 1);

          var 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;
          }

          var 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;
          }
        }
      }
    }]);

    return MorphBlendMesh;
  }(_three.Mesh);

  _exports.MorphBlendMesh = MorphBlendMesh;
});