const pc = window.pc;
var SystemName = /* @__PURE__ */ ((SystemName2) => {
  SystemName2["LocalPlayer"] = "localPlayer";
  SystemName2["Account"] = "account";
  SystemName2["Ui"] = "ui";
  SystemName2["Quest"] = "quest";
  SystemName2["Network"] = "network";
  return SystemName2;
})(SystemName || {});
var HardwareType = /* @__PURE__ */ ((HardwareType2) => {
  HardwareType2["Desktop"] = "desktop";
  HardwareType2["Mobile"] = "mobile";
  HardwareType2["Headset"] = "headset";
  HardwareType2["Unknown"] = "unknown";
  return HardwareType2;
})(HardwareType || {});
var OsType = /* @__PURE__ */ ((OsType2) => {
  OsType2["Ios"] = "ios";
  OsType2["Android"] = "android";
  OsType2["Macos"] = "macos";
  OsType2["Windows"] = "windows";
  OsType2["Linux"] = "linux";
  OsType2["Unknown"] = "unknown";
  return OsType2;
})(OsType || {});
var XrHeadsetType = /* @__PURE__ */ ((XrHeadsetType2) => {
  XrHeadsetType2["Vive"] = "vive";
  XrHeadsetType2["Oculus"] = "oculus";
  XrHeadsetType2["VisionPro"] = "visionPro";
  return XrHeadsetType2;
})(XrHeadsetType || {});
var ScreenOrientationType = /* @__PURE__ */ ((ScreenOrientationType2) => {
  ScreenOrientationType2["Landscape"] = "landscape";
  ScreenOrientationType2["Portrait"] = "portrait";
  return ScreenOrientationType2;
})(ScreenOrientationType || {});
var BillboardAxisAlignment = /* @__PURE__ */ ((BillboardAxisAlignment2) => {
  BillboardAxisAlignment2["None"] = "none";
  BillboardAxisAlignment2["X"] = "x";
  BillboardAxisAlignment2["Y"] = "y";
  BillboardAxisAlignment2["Z"] = "z";
  return BillboardAxisAlignment2;
})(BillboardAxisAlignment || {});
var ModuleName = /* @__PURE__ */ ((ModuleName2) => {
  ModuleName2["LocalAvatar"] = "localAvatar";
  ModuleName2["Camera"] = "camera";
  ModuleName2["Locomotion"] = "locomotion";
  ModuleName2["Xr"] = "xr";
  ModuleName2["Interaction"] = "interaction";
  ModuleName2["Auth"] = "auth";
  ModuleName2["Multiplayer"] = "multiplayer";
  return ModuleName2;
})(ModuleName || {});
const SceneEntityConstants = {
  LocalPlayer: "ViverseLocalPlayer",
  Camera: {
    FirstPerson: "FirstPersonCamera",
    ThirdPerson: "ThirdPersonCamera",
    Xr: "XrCamera"
  },
  NameTag: "NameTag",
  XrOrigin: "ViverseXrOrigin",
  XrDevice: {
    XrController: "XrController"
  }
};
const CameraEntityKeys = {
  FirstPerson: "first-person",
  ThirdPerson: "third-person",
  Xr: "xr"
};
const SceneScriptNames = {
  XrController: "viverseXrController"
};
var AvatarFacingMode = /* @__PURE__ */ ((AvatarFacingMode2) => {
  AvatarFacingMode2["Movement"] = "movement";
  AvatarFacingMode2["View"] = "view";
  return AvatarFacingMode2;
})(AvatarFacingMode || {});
var PostureType = /* @__PURE__ */ ((PostureType2) => {
  PostureType2["Idle"] = "idle";
  PostureType2["Forward"] = "forward";
  PostureType2["Backward"] = "backward";
  PostureType2["StrafeLeft"] = "strafeLeft";
  PostureType2["StrafeRight"] = "strafeRight";
  PostureType2["JumpingUp"] = "jumpingUp";
  PostureType2["JumpingLoop"] = "jumpingLoop";
  PostureType2["JumpingDown"] = "jumpingDown";
  PostureType2["Sprint"] = "sprint";
  PostureType2["FlyFloat"] = "flyFloat";
  PostureType2["FlyForward"] = "flyForward";
  PostureType2["FlyBackward"] = "flyBackward";
  PostureType2["FlyStrafeLeft"] = "flyStrafeLeft";
  PostureType2["FlyStrafeRight"] = "flyStrafeRight";
  PostureType2["FlyUp"] = "flyUp";
  PostureType2["FlyUpForward"] = "flyUpForward";
  PostureType2["FlyDown"] = "flyDown";
  PostureType2["FlyDownForward"] = "flyDownForward";
  PostureType2["FlyForwardSprint"] = "flyForwardSprint";
  PostureType2["FlyUpForwardSprint"] = "flyUpForwardSprint";
  PostureType2["FlyDownForwardSprint"] = "flyDownForwardSprint";
  return PostureType2;
})(PostureType || {});
var AvatarHorizontalDirection = /* @__PURE__ */ ((AvatarHorizontalDirection2) => {
  AvatarHorizontalDirection2["Stop"] = "stop";
  AvatarHorizontalDirection2["Forward"] = "forward";
  AvatarHorizontalDirection2["Backward"] = "backward";
  AvatarHorizontalDirection2["StrafeLeft"] = "strafeLeft";
  AvatarHorizontalDirection2["StrafeRight"] = "strafeRight";
  AvatarHorizontalDirection2["ForwardDiagonalLeft"] = "forwardDiagonalLeft";
  AvatarHorizontalDirection2["ForwardDiagonalRight"] = "forwardDiagonalRight";
  AvatarHorizontalDirection2["BackwardDiagonalLeft"] = "backwardDiagonalLeft";
  AvatarHorizontalDirection2["BackwardDiagonalRight"] = "backwardDiagonalRight";
  return AvatarHorizontalDirection2;
})(AvatarHorizontalDirection || {});
var AvatarVerticalState = /* @__PURE__ */ ((AvatarVerticalState2) => {
  AvatarVerticalState2["Neutral"] = "neutral";
  AvatarVerticalState2["Up"] = "up";
  AvatarVerticalState2["Down"] = "down";
  return AvatarVerticalState2;
})(AvatarVerticalState || {});
var LocomotionStateType = /* @__PURE__ */ ((LocomotionStateType2) => {
  LocomotionStateType2["Grounded"] = "grounded";
  LocomotionStateType2["Jumping"] = "jumping";
  LocomotionStateType2["Falling"] = "falling";
  LocomotionStateType2["Flying"] = "flying";
  LocomotionStateType2["Dead"] = "dead";
  LocomotionStateType2["Sitting"] = "sitting";
  return LocomotionStateType2;
})(LocomotionStateType || {});
var XrLocomotionType = /* @__PURE__ */ ((XrLocomotionType2) => {
  XrLocomotionType2["Teleport"] = "teleport";
  XrLocomotionType2["Smooth"] = "smooth";
  return XrLocomotionType2;
})(XrLocomotionType || {});
var XrInputDeviceType = /* @__PURE__ */ ((XrInputDeviceType2) => {
  XrInputDeviceType2["Controller"] = "controller";
  XrInputDeviceType2["Hand"] = "hand";
  return XrInputDeviceType2;
})(XrInputDeviceType || {});
var XrUiAnchorType = /* @__PURE__ */ ((XrUiAnchorType2) => {
  XrUiAnchorType2["Head"] = "head";
  XrUiAnchorType2["LeftHand"] = "leftHand";
  XrUiAnchorType2["RightHand"] = "rightHand";
  return XrUiAnchorType2;
})(XrUiAnchorType || {});
const VRMHumanBoneList = [
  "hips",
  "spine",
  "chest",
  "upperChest",
  "neck",
  "head",
  "leftEye",
  "rightEye",
  "jaw",
  "leftUpperLeg",
  "leftLowerLeg",
  "leftFoot",
  "leftToes",
  "rightUpperLeg",
  "rightLowerLeg",
  "rightFoot",
  "rightToes",
  "leftShoulder",
  "leftUpperArm",
  "leftLowerArm",
  "leftHand",
  "rightShoulder",
  "rightUpperArm",
  "rightLowerArm",
  "rightHand",
  "leftThumbMetacarpal",
  "leftThumbProximal",
  "leftThumbDistal",
  "leftIndexProximal",
  "leftIndexIntermediate",
  "leftIndexDistal",
  "leftMiddleProximal",
  "leftMiddleIntermediate",
  "leftMiddleDistal",
  "leftRingProximal",
  "leftRingIntermediate",
  "leftRingDistal",
  "leftLittleProximal",
  "leftLittleIntermediate",
  "leftLittleDistal",
  "rightThumbMetacarpal",
  "rightThumbProximal",
  "rightThumbDistal",
  "rightIndexProximal",
  "rightIndexIntermediate",
  "rightIndexDistal",
  "rightMiddleProximal",
  "rightMiddleIntermediate",
  "rightMiddleDistal",
  "rightRingProximal",
  "rightRingIntermediate",
  "rightRingDistal",
  "rightLittleProximal",
  "rightLittleIntermediate",
  "rightLittleDistal"
];
const VRMHumanBoneParentMap = {
  hips: null,
  spine: "hips",
  chest: "spine",
  upperChest: "chest",
  neck: "upperChest",
  head: "neck",
  leftEye: "head",
  rightEye: "head",
  jaw: "head",
  leftUpperLeg: "hips",
  leftLowerLeg: "leftUpperLeg",
  leftFoot: "leftLowerLeg",
  leftToes: "leftFoot",
  rightUpperLeg: "hips",
  rightLowerLeg: "rightUpperLeg",
  rightFoot: "rightLowerLeg",
  rightToes: "rightFoot",
  leftShoulder: "upperChest",
  leftUpperArm: "leftShoulder",
  leftLowerArm: "leftUpperArm",
  leftHand: "leftLowerArm",
  rightShoulder: "upperChest",
  rightUpperArm: "rightShoulder",
  rightLowerArm: "rightUpperArm",
  rightHand: "rightLowerArm",
  leftThumbMetacarpal: "leftHand",
  leftThumbProximal: "leftThumbMetacarpal",
  leftThumbDistal: "leftThumbProximal",
  leftIndexProximal: "leftHand",
  leftIndexIntermediate: "leftIndexProximal",
  leftIndexDistal: "leftIndexIntermediate",
  leftMiddleProximal: "leftHand",
  leftMiddleIntermediate: "leftMiddleProximal",
  leftMiddleDistal: "leftMiddleIntermediate",
  leftRingProximal: "leftHand",
  leftRingIntermediate: "leftRingProximal",
  leftRingDistal: "leftRingIntermediate",
  leftLittleProximal: "leftHand",
  leftLittleIntermediate: "leftLittleProximal",
  leftLittleDistal: "leftLittleIntermediate",
  rightThumbMetacarpal: "rightHand",
  rightThumbProximal: "rightThumbMetacarpal",
  rightThumbDistal: "rightThumbProximal",
  rightIndexProximal: "rightHand",
  rightIndexIntermediate: "rightIndexProximal",
  rightIndexDistal: "rightIndexIntermediate",
  rightMiddleProximal: "rightHand",
  rightMiddleIntermediate: "rightMiddleProximal",
  rightMiddleDistal: "rightMiddleIntermediate",
  rightRingProximal: "rightHand",
  rightRingIntermediate: "rightRingProximal",
  rightRingDistal: "rightRingIntermediate",
  rightLittleProximal: "rightHand",
  rightLittleIntermediate: "rightLittleProximal",
  rightLittleDistal: "rightLittleIntermediate"
};
const VRMRigMap = {
  hips: "hips",
  spine: "spine",
  chest: "chest",
  upperChest: "upperChest",
  neck: "neck",
  head: "head",
  leftEye: "leftEye",
  leftShoulder: "leftShoulder",
  leftUpperArm: "leftUpperArm",
  leftLowerArm: "leftLowerArm",
  leftHand: "leftHand",
  leftUpperLeg: "leftUpperLeg",
  leftLowerLeg: "leftLowerLeg",
  leftFoot: "leftFoot",
  leftToes: "leftToes",
  leftThumbMetacarpal: "leftThumbMetacarpal",
  leftThumbProximal: "leftThumbProximal",
  leftThumbDistal: "leftThumbDistal",
  leftIndexProximal: "leftIndexProximal",
  leftIndexIntermediate: "leftIndexIntermediate",
  leftIndexDistal: "leftIndexDistal",
  leftMiddleProximal: "leftMiddleProximal",
  leftMiddleIntermediate: "leftMiddleIntermediate",
  leftMiddleDistal: "leftMiddleDistal",
  leftRingProximal: "leftRingProximal",
  leftRingIntermediate: "leftRingIntermediate",
  leftRingDistal: "leftRingDistal",
  leftLittleProximal: "leftLittleProximal",
  leftLittleIntermediate: "leftLittleIntermediate",
  leftLittleDistal: "leftLittleDistal",
  rightEye: "rightEye",
  rightUpperArm: "rightUpperArm",
  rightShoulder: "rightShoulder",
  rightLowerArm: "rightLowerArm",
  rightHand: "rightHand",
  rightUpperLeg: "rightUpperLeg",
  rightLowerLeg: "rightLowerLeg",
  rightFoot: "rightFoot",
  rightToes: "rightToes",
  rightThumbMetacarpal: "rightThumbMetacarpal",
  rightThumbProximal: "rightThumbProximal",
  rightThumbDistal: "rightThumbDistal",
  rightIndexProximal: "rightIndexProximal",
  rightIndexIntermediate: "rightIndexIntermediate",
  rightIndexDistal: "rightIndexDistal",
  rightMiddleProximal: "rightMiddleProximal",
  rightMiddleIntermediate: "rightMiddleIntermediate",
  rightMiddleDistal: "rightMiddleDistal",
  rightRingProximal: "rightRingProximal",
  rightRingIntermediate: "rightRingIntermediate",
  rightRingDistal: "rightRingDistal",
  rightLittleProximal: "rightLittleProximal",
  rightLittleIntermediate: "rightLittleIntermediate",
  rightLittleDistal: "rightLittleDistal"
};
const thumbBoneNameMap = {
  leftThumbProximal: "leftThumbMetacarpal",
  leftThumbIntermediate: "leftThumbProximal",
  rightThumbProximal: "rightThumbMetacarpal",
  rightThumbIntermediate: "rightThumbProximal"
};
const v0v1PresetNameMap = {
  a: "aa",
  e: "ee",
  i: "ih",
  o: "oh",
  u: "ou",
  blink: "blink",
  joy: "happy",
  angry: "angry",
  sorrow: "sad",
  fun: "relaxed",
  lookup: "lookUp",
  lookdown: "lookDown",
  lookleft: "lookLeft",
  lookright: "lookRight",
  blink_l: "blinkLeft",
  blink_r: "blinkRight",
  neutral: "neutral"
};
const VRMExpressionPresetName = {
  Aa: "aa",
  Ih: "ih",
  Ou: "ou",
  Ee: "ee",
  Oh: "oh",
  Blink: "blink",
  Happy: "happy",
  Angry: "angry",
  Sad: "sad",
  Relaxed: "relaxed",
  LookUp: "lookUp",
  Surprised: "surprised",
  LookDown: "lookDown",
  LookLeft: "lookLeft",
  LookRight: "lookRight",
  BlinkLeft: "blinkLeft",
  BlinkRight: "blinkRight",
  Neutral: "neutral"
};
const POSSIBLE_SPEC_VERSIONS$1 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
const v0ExpressionMaterialColorMap = {
  _Color: "color",
  _EmissionColor: "emissionColor",
  _ShadeColor: "shadeColor",
  _RimColor: "rimColor",
  _OutlineColor: "outlineColor"
};
const expressionMateriaPropertyNameMapMap = {
  isMeshStandardMaterial: {
    color: "color",
    emissionColor: "emissive"
  },
  isMeshBasicMaterial: {
    color: "color"
  },
  isMToonMaterial: {
    color: "color",
    emissionColor: "emissive",
    outlineColor: "outlineColorFactor",
    matcapColor: "matcapFactor",
    rimColor: "parametricRimColorFactor",
    shadeColor: "shadeColorFactor"
  }
};
const VrmMapList = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  POSSIBLE_SPEC_VERSIONS: POSSIBLE_SPEC_VERSIONS$1,
  VRMExpressionPresetName,
  VRMHumanBoneList,
  VRMHumanBoneParentMap,
  VRMRigMap,
  expressionMateriaPropertyNameMapMap,
  thumbBoneNameMap,
  v0ExpressionMaterialColorMap,
  v0v1PresetNameMap
}, Symbol.toStringTag, { value: "Module" }));
class VRMAnimation {
  constructor(pcRef) {
    this.duration = 0;
    this.restHipsPosition = new pcRef.Vec3();
    this.humanoidTracks = {
      translation: /* @__PURE__ */ new Map(),
      rotation: /* @__PURE__ */ new Map()
    };
    this.expressionTracks = {
      preset: /* @__PURE__ */ new Map(),
      custom: /* @__PURE__ */ new Map()
    };
    this.lookAtTrack = null;
  }
}
function arrayChunk(array, every) {
  const N = array.length;
  const ret = [];
  let current = [];
  let remaining = 0;
  for (let i = 0; i < N; i++) {
    const el = array[i];
    if (remaining <= 0) {
      remaining = every;
      current = [];
      ret.push(current);
    }
    current.push(el);
    remaining--;
  }
  return ret;
}
function applyMatrix4(pcRef, v3, m) {
  const e = m.data;
  const w = 1 / (e[3] * v3.x + e[7] * v3.y + e[11] * v3.z + e[15]);
  const _x = (e[0] * v3.x + e[4] * v3.y + e[8] * v3.z + e[12]) * w;
  const _y = (e[1] * v3.x + e[5] * v3.y + e[9] * v3.z + e[13]) * w;
  const _z = (e[2] * v3.x + e[6] * v3.y + e[10] * v3.z + e[14]) * w;
  return new pcRef.Vec3(_x, _y, _z);
}
function cloneAnimTrack(pcRef, origAnimTrack) {
  const inputs = origAnimTrack.inputs.map(
    (input) => new pcRef.AnimData(input.components, input.data)
  );
  const outputs = origAnimTrack.outputs.map(
    (output) => new pcRef.AnimData(output.components, output.data)
  );
  const curves = origAnimTrack.curves.map((curve) => {
    const curvePaths = curve.paths.map((path) => {
      const morphCurvePath = path;
      return {
        component: morphCurvePath.component,
        entityPath: [...morphCurvePath.entityPath],
        propertyPath: [...morphCurvePath.propertyPath]
      };
    });
    return new pcRef.AnimCurve(curvePaths, curve.input, curve.output, curve.interpolation);
  });
  return new pcRef.AnimTrack(origAnimTrack.name, origAnimTrack.duration, inputs, outputs, curves);
}
const POSSIBLE_SPEC_VERSIONS = /* @__PURE__ */ new Set(["1.0", "1.0-draft"]);
const vrmExpressionPresetNameSet = new Set(Object.values(VRMExpressionPresetName));
class VRMAnimationLoader {
  constructor(pcRef) {
    this.pcRef = pcRef;
  }
  loadVRMA(vrmaAsset) {
    var _a, _b, _c;
    const resource = vrmaAsset.resource;
    const defGltf = resource.data.gltf;
    const defExtensionsUsed = defGltf.extensionsUsed;
    if (defExtensionsUsed == null || defExtensionsUsed.indexOf("VRMC_vrm_animation") == -1) {
      console.warn("CreateVRMAnimation: Please check. It is not a vrma.");
      return;
    }
    const defExtension = (_a = defGltf.extensions) == null ? void 0 : _a["VRMC_vrm_animation"];
    if (defExtension == null) {
      console.warn("CreateVRMAnimation: Please check. It is not a vrma.");
      return;
    }
    const specVersion = defExtension.specVersion;
    if (!POSSIBLE_SPEC_VERSIONS.has(specVersion)) {
      console.warn(`CreateVRMAnimation: Unknown VRMC_vrm_animation spec version: ${specVersion}`);
      return;
    }
    if (specVersion === "1.0-draft") {
      console.warn(
        "CreateVRMAnimation: Using a draft spec version: 1.0-draft. Some behaviors may be different. Consider updating the animation file."
      );
    }
    const pcNodes = resource.data.nodes;
    const nodeMap = this._createNodeMap(defGltf, defExtension);
    const worldMatrixMap = this._createBoneWorldMatrixMap(pcNodes, defExtension);
    const hipsNode = (_c = (_b = defExtension.humanoid) == null ? void 0 : _b.humanBones["hips"]) == null ? void 0 : _c.node;
    const hips = hipsNode != null ? pcNodes[hipsNode] : null;
    const restHipsPosition = hips ? hips.getPosition() : new this.pcRef.Vec3();
    const animTracks = resource.data.animations;
    const animations = animTracks.map((animTrack, index) => {
      const defAnimation = defGltf.animations[index];
      const animation = this._parseAnimation(animTrack, defAnimation, nodeMap, worldMatrixMap);
      animation.restHipsPosition = restHipsPosition;
      return animation;
    });
    return animations;
  }
  _createNodeMap(defGltf, defExtension) {
    var _a, _b, _c, _d;
    const origNameToHumanoidIndex = /* @__PURE__ */ new Map();
    const humanoidIndexToName = /* @__PURE__ */ new Map();
    const expressionsIndexToName = /* @__PURE__ */ new Map();
    const origNodes = defGltf.nodes;
    if (origNodes) {
      origNodes.forEach((value, index) => {
        if (value.name) {
          origNameToHumanoidIndex.set(value.name, index);
        }
      });
    }
    const humanBones = (_a = defExtension.humanoid) == null ? void 0 : _a.humanBones;
    if (humanBones) {
      Object.entries(humanBones).forEach(([name, bone]) => {
        const node = bone == null ? void 0 : bone.node;
        if (node != null) {
          humanoidIndexToName.set(node, name);
        }
      });
    }
    const preset = (_b = defExtension.expressions) == null ? void 0 : _b.preset;
    if (preset) {
      Object.entries(preset).forEach(([name, expression]) => {
        const node = expression == null ? void 0 : expression.node;
        if (node != null) {
          expressionsIndexToName.set(node, name);
        }
      });
    }
    const custom = (_c = defExtension.expressions) == null ? void 0 : _c.custom;
    if (custom) {
      Object.entries(custom).forEach(([name, expression]) => {
        const { node } = expression;
        expressionsIndexToName.set(node, name);
      });
    }
    const lookAtIndex = ((_d = defExtension.lookAt) == null ? void 0 : _d.node) ?? null;
    return { origNameToHumanoidIndex, humanoidIndexToName, expressionsIndexToName, lookAtIndex };
  }
  //In THREE, it's async
  _createBoneWorldMatrixMap(pcNodes, defExtension) {
    var _a;
    const worldMatrixMap = /* @__PURE__ */ new Map();
    if (defExtension.humanoid == null) {
      return worldMatrixMap;
    }
    for (const [boneName, humanBone] of Object.entries(defExtension.humanoid.humanBones)) {
      const node = humanBone == null ? void 0 : humanBone.node;
      if (node != null) {
        const pcNode = pcNodes[node];
        worldMatrixMap.set(boneName, pcNode.getWorldTransform());
        const MAT4_IDENTITY = new this.pcRef.Mat4();
        if (boneName === "hips") {
          worldMatrixMap.set("hipsParent", ((_a = pcNode.parent) == null ? void 0 : _a.getWorldTransform()) ?? MAT4_IDENTITY);
        }
      }
    }
    return worldMatrixMap;
  }
  _parseAnimation(animTrack, defAnimation, nodeMap, worldMatrixMap) {
    const { inputs, outputs, curves } = cloneAnimTrack(this.pcRef, animTrack);
    const defChannels = defAnimation.channels;
    const result = new VRMAnimation(this.pcRef);
    result.duration = animTrack.duration;
    defChannels.forEach((channel, index) => {
      const { node, path } = channel.target;
      const curve = curves[index];
      const input = inputs[curve.input];
      const output = outputs[curve.output];
      if (node == null) {
        return;
      }
      const boneName = nodeMap.humanoidIndexToName.get(node);
      if (boneName != null) {
        let parentBoneName = VRMHumanBoneParentMap[boneName];
        while (parentBoneName != null && worldMatrixMap.get(parentBoneName) == null) {
          parentBoneName = VRMHumanBoneParentMap[parentBoneName];
        }
        parentBoneName ?? (parentBoneName = "hipsParent");
        curve.paths.forEach((graph) => {
          const morphCurvePath = graph;
          const arrangedEntityPath = morphCurvePath.entityPath.map((path2) => {
            const nodeIndex = nodeMap.origNameToHumanoidIndex.get(path2);
            if (nodeIndex) {
              const _boneName = nodeMap.humanoidIndexToName.get(nodeIndex);
              return _boneName ? _boneName : boneName;
            } else {
              return boneName;
            }
          });
          morphCurvePath.entityPath = arrangedEntityPath;
        });
        if (path === "translation") {
          if (boneName !== "hips") {
            console.warn(
              `The loading animation contains a translation track for ${boneName}, which is not permitted in the VRMC_vrm_animation spec. ignoring the track`
            );
          } else {
            const hipsParentWorldMatrix = worldMatrixMap.get("hipsParent");
            const outputData = arrayChunk(output.data, 3).flatMap((v) => {
              let _vec3 = new this.pcRef.Vec3(v[0], v[1], v[2]);
              _vec3 = applyMatrix4(this.pcRef, _vec3, hipsParentWorldMatrix);
              return [_vec3.x, _vec3.y, _vec3.z];
            });
            const _outputData = new Float32Array(outputData);
            const _output = new this.pcRef.AnimData(output.components, _outputData);
            const vrmaTrack = { curve, input, output: _output };
            result.humanoidTracks.translation.set(boneName, vrmaTrack);
          }
        } else if (path === "rotation") {
          const worldMatrix = worldMatrixMap.get(boneName);
          const parentWorldMatrix = worldMatrixMap.get(parentBoneName);
          const worldMatrixQuat = new this.pcRef.Quat();
          worldMatrixQuat.setFromMat4(worldMatrix);
          worldMatrixQuat.invert();
          const parentWorldMatrixQuat = new this.pcRef.Quat();
          parentWorldMatrixQuat.setFromMat4(parentWorldMatrix);
          const outputData = arrayChunk(output.data, 4).flatMap((q) => {
            let _quat = new this.pcRef.Quat(q[0], q[1], q[2], q[3]);
            _quat = _quat.mul2(parentWorldMatrixQuat, _quat).mul(worldMatrixQuat);
            return [_quat.x, _quat.y, _quat.z, _quat.w];
          });
          const _outputData = new Float32Array(outputData);
          const _output = new this.pcRef.AnimData(output.components, _outputData);
          const vrmaTrack = { curve, input, output: _output };
          result.humanoidTracks.rotation.set(boneName, vrmaTrack);
        } else {
          throw new Error(`Invalid path "${path}"`);
        }
        return;
      }
      const expressionName = nodeMap.expressionsIndexToName.get(node);
      if (expressionName != null) {
        if (path === "translation") {
          const values = new Float32Array(output.data.length / 3);
          for (let i = 0; i < values.length; i++) {
            values[i] = output.data[3 * i];
          }
          const expressionConfig = {
            times: input.data,
            values,
            loop: true
          };
          if (vrmExpressionPresetNameSet.has(expressionName)) {
            result.expressionTracks.preset.set(
              expressionName,
              expressionConfig
            );
          } else {
            result.expressionTracks.custom.set(expressionName, expressionConfig);
          }
        } else {
          throw new Error(`Invalid path "${path}"`);
        }
        return;
      }
      if (node === nodeMap.lookAtIndex) {
        if (path === "rotation") {
          const lookAtTrack = { curve, input, output };
          result.lookAtTrack = lookAtTrack;
        } else {
          throw new Error(`Invalid path "${path}"`);
        }
      }
    });
    return result;
  }
}
class VRMAnimationTrack {
  constructor(pcRef, stateName, name, vrmAnimation, humanoid, metaVersion = "v0") {
    this.pcRef = pcRef;
    this.vrmAnimation = vrmAnimation;
    this.stateName = stateName;
    this.name = name;
    this.humanoid = humanoid;
    this.metaVersion = metaVersion;
  }
  get result() {
    return this.createVRMAnimTrack();
  }
  createVRMAnimTrack() {
    const inputs = [];
    const outputs = [];
    const curves = [];
    const vrmaTracks = [];
    const humanoidTracks = this._createHumanoidTracks();
    vrmaTracks.push(...humanoidTracks.translation.values());
    vrmaTracks.push(...humanoidTracks.rotation.values());
    const lookAtTracks = this._createLookAtTracks() ?? this._resetLookAtTrack(vrmaTracks[0].input);
    vrmaTracks.push(...lookAtTracks.values());
    for (let i = 0; i < vrmaTracks.length; i++) {
      inputs.push(vrmaTracks[i].input);
      outputs.push(vrmaTracks[i].output);
      const _curve = new this.pcRef.AnimCurve(
        vrmaTracks[i].curve.paths,
        i,
        i,
        vrmaTracks[i].curve.interpolation
      );
      curves.push(_curve);
      const vrmaCurve = vrmaTracks[i].curve;
      vrmaCurve.paths.forEach((graph) => {
        const morphCurvePath = graph;
        const entityPath = morphCurvePath.entityPath;
        entityPath.unshift("SkeletonRoot");
        const arrangedEntityPath = entityPath.map((path) => {
          var _a;
          const originalRigName = path;
          const vrmBoneName = VRMRigMap[originalRigName];
          const vrmNodeName = (_a = this.humanoid.getRawBoneNode(vrmBoneName)) == null ? void 0 : _a.name;
          if (!vrmBoneName || !vrmNodeName) {
            return path;
          }
          return vrmNodeName;
        });
        morphCurvePath.entityPath = arrangedEntityPath;
      });
    }
    const events = new this.pcRef.AnimEvents([
      { name: `anim-track:${this.stateName}-start`, time: 0 }
    ]);
    return new this.pcRef.AnimTrack(
      this.name,
      this.vrmAnimation.duration,
      inputs,
      outputs,
      curves,
      events
    );
  }
  _createHumanoidTracks() {
    var _a, _b, _c;
    const translation = /* @__PURE__ */ new Map();
    const rotation = /* @__PURE__ */ new Map();
    for (const [name, origTrack] of this.vrmAnimation.humanoidTracks.translation.entries()) {
      const nodeName = (_a = this.humanoid.getNormalizedBoneNode(name)) == null ? void 0 : _a.name;
      if (nodeName != null) {
        const animationY = this.vrmAnimation.restHipsPosition.y;
        const humanoidHipsPosition = ((_b = this.humanoid.normalizedHumanBones.hips) == null ? void 0 : _b.node.getLocalPosition()) || new this.pcRef.Vec3();
        const humanoidY = humanoidHipsPosition.y;
        const scale = humanoidY / animationY;
        const outputData = origTrack.output.data.map(
          (v, i) => (this.metaVersion === "v0" && i % 3 !== 1 ? -v : v) * scale
        );
        const _outputData = new Float32Array(outputData);
        const _output = new this.pcRef.AnimData(origTrack.output.components, _outputData);
        const vrmaTrack = {
          curve: origTrack.curve,
          input: origTrack.input,
          output: _output
        };
        translation.set(name, vrmaTrack);
      }
    }
    for (const [name, origTrack] of this.vrmAnimation.humanoidTracks.rotation.entries()) {
      const nodeName = (_c = this.humanoid.getNormalizedBoneNode(name)) == null ? void 0 : _c.name;
      if (nodeName != null) {
        const outputData = origTrack.output.data.map(
          (v, i) => this.metaVersion === "v0" && i % 2 === 0 ? -v : v
        );
        const _outputData = new Float32Array(outputData);
        const _output = new this.pcRef.AnimData(origTrack.output.components, _outputData);
        const vrmaTrack = {
          curve: origTrack.curve,
          input: origTrack.input,
          output: _output
        };
        rotation.set(name, vrmaTrack);
      }
    }
    return { translation, rotation };
  }
  _createLookAtTracks() {
    const origTrack = this.vrmAnimation.lookAtTrack;
    if (!origTrack)
      return null;
    const Tracks = /* @__PURE__ */ new Map();
    const eyes = ["leftEye", "rightEye"];
    const lookAtScale = (src, index) => {
      const indexOrder = index % 4;
      const w = origTrack.output.data[index + 3 - indexOrder];
      const _w = w === 0 ? 1 : w;
      switch (indexOrder) {
        case 0:
          return src / _w * 0.06;
        case 1:
          return src / _w * 0.08;
        default:
          return 1;
      }
    };
    const outputData = origTrack.output.data.map((v, i) => {
      const _v = (this.metaVersion === "v0" && i % 4 == 0 ? -v : v) * lookAtScale(v, i);
      return _v;
    });
    const _outputData = new Float32Array(outputData);
    const _output = new this.pcRef.AnimData(origTrack.output.components, _outputData);
    const vrmaCurve = origTrack.curve;
    vrmaCurve.paths.forEach((graph) => {
      const morphCurvePath = graph;
      eyes.forEach((eye) => {
        morphCurvePath.entityPath = [eye];
        const paths = [{ ...morphCurvePath }];
        const _curve = new this.pcRef.AnimCurve(
          paths,
          vrmaCurve.input,
          vrmaCurve.output,
          vrmaCurve.interpolation
        );
        const vrmaTrack = {
          curve: _curve,
          input: origTrack.input,
          output: _output
        };
        Tracks.set(eye, vrmaTrack);
      });
    });
    return Tracks;
  }
  _resetLookAtTrack(input) {
    const Tracks = /* @__PURE__ */ new Map();
    const eyes = ["leftEye", "rightEye"];
    const _outputData = new Float32Array(input.data.length * 4);
    for (let i = 0; i < _outputData.length; i++) {
      if (i % 4 === 3) {
        _outputData[i] = 1;
      }
    }
    const _output = new this.pcRef.AnimData(4, _outputData);
    eyes.forEach((eye) => {
      const path = {
        entityPath: [eye],
        component: "graph",
        propertyPath: ["localRotation"]
      };
      const _curve = new this.pcRef.AnimCurve([{ ...path }], 0, 0, 1);
      const vrmaTrack = {
        curve: _curve,
        input,
        output: _output
      };
      Tracks.set(eye, vrmaTrack);
    });
    return Tracks;
  }
}
class VRMViverseAnimationTrack {
  constructor(pcRef, animationAsset, humanoid, metaVersion = "v0", extraSettings, origAnimTrack) {
    this.pcRef = pcRef;
    this.animationAsset = animationAsset;
    this.humanoid = humanoid;
    this.metaVersion = metaVersion;
    this.extraSettings = extraSettings;
    this.origAnimTrack = origAnimTrack;
  }
  get result() {
    return this.createViverseAnimTrack();
  }
  createViverseAnimTrack() {
    var _a;
    const vrmHipsPosition = ((_a = this.humanoid.rawHumanBones.hips) == null ? void 0 : _a.node.getPosition()) || new this.pcRef.Vec3();
    const vrmHipsY = vrmHipsPosition.y;
    const vrmHipsHeight = Math.abs(vrmHipsY - 0);
    const vrmHipsZ = vrmHipsPosition.z;
    const vrmHipsDeep = Math.abs(vrmHipsZ - 0);
    const hipPositionOutputIndexes = {};
    const scaleOutputIndexes = {};
    let { motionHipsHeight, negativeZAnimNames } = this.extraSettings;
    if (!negativeZAnimNames) {
      negativeZAnimNames = [];
    }
    const animTrack = cloneAnimTrack(this.pcRef, this.origAnimTrack);
    const isNegativeZAxis = negativeZAnimNames.includes(this.origAnimTrack.name);
    const needConvertVersion = isNegativeZAxis ? "v1" : "v0";
    let nodeMotionHipsHeight = 0;
    if (this.animationAsset.asset.type === "container") {
      const resource = this.animationAsset.asset.resource;
      const motionHipsNode = resource.data.nodes.find(
        (node) => node.name === VRMRigMap.hips
      );
      if (motionHipsNode) {
        nodeMotionHipsHeight = motionHipsNode.getLocalPosition().y;
      }
    }
    motionHipsHeight = motionHipsHeight || nodeMotionHipsHeight || 0.855;
    const hipsPositionScaleY = vrmHipsHeight / motionHipsHeight;
    animTrack.curves.forEach((curve) => {
      curve.paths.forEach((graph) => {
        const morphCurvePath = graph;
        const isPosition = morphCurvePath.propertyPath.find((path) => path === "localPosition");
        const isHipsTarget = morphCurvePath.entityPath[morphCurvePath.entityPath.length - 1] === VRMRigMap["hips"];
        if (isPosition && isHipsTarget && !hipPositionOutputIndexes[curve.output]) {
          hipPositionOutputIndexes[curve.output] = true;
        }
      });
    });
    animTrack.curves.forEach((curve) => {
      let isLocalScale = false;
      curve.paths.forEach((graph) => {
        const morphCurvePath = graph;
        const arrangedEntityPath = morphCurvePath.entityPath.map((path) => {
          var _a2;
          const originalRigName = path;
          const vrmBoneName = VRMRigMap[originalRigName];
          const vrmNodeName = (_a2 = this.humanoid.getRawBoneNode(vrmBoneName)) == null ? void 0 : _a2.name;
          if (!vrmBoneName || !vrmNodeName) {
            return path;
          }
          return vrmNodeName;
        });
        morphCurvePath.entityPath = arrangedEntityPath;
        if (morphCurvePath.propertyPath.find((path) => path === "localScale")) {
          isLocalScale = true;
        }
      });
      if (isLocalScale && !scaleOutputIndexes[curve.output]) {
        scaleOutputIndexes[curve.output] = true;
      }
    });
    animTrack.outputs.forEach((output, outputIndex) => {
      const isScaleOutput = scaleOutputIndexes[outputIndex];
      if (output.components === 3) {
        if (!isScaleOutput) {
          const newData = output.data.map((v, index) => {
            let value = v;
            if (this.metaVersion === needConvertVersion && index % 3 !== 1) {
              value *= -1;
            }
            if (hipPositionOutputIndexes[outputIndex] && index % 3 === 1) {
              if (this.animationAsset.removeY) {
                return vrmHipsHeight;
              }
              if (this.animationAsset.removeUpperY && v * hipsPositionScaleY > vrmHipsHeight) {
                return vrmHipsHeight;
              }
            }
            if (hipPositionOutputIndexes[outputIndex] && index % 3 === 2) {
              if (this.animationAsset.removeZ) {
                return vrmHipsDeep;
              }
            }
            return value * hipsPositionScaleY;
          });
          output._data = newData;
        }
      } else if (output.components === 4) {
        const newData = output.data.map((v, index) => {
          if (this.metaVersion === needConvertVersion && index % 2 === 0) {
            return -v;
          } else {
            return v;
          }
        });
        output._data = newData;
      }
    });
    const events = new this.pcRef.AnimEvents([
      { name: `anim-track:${this.animationAsset.stateName}-start`, time: 0 }
    ]);
    animTrack.events = events;
    return animTrack;
  }
}
class VRMAExpression {
  constructor(vrmAnimation) {
    this.preset = vrmAnimation.expressionTracks.preset;
    this.custom = vrmAnimation.expressionTracks.custom;
  }
  createCustomExpression() {
    console.log(this.custom);
  }
}
function createVRMAnimation(pcRef, animationAssets, asset, humanoid, {
  motionHipsHeight,
  negativeZAnimNames
} = {}) {
  const extraSettings = { motionHipsHeight, negativeZAnimNames };
  console.warn(
    "Warning: createVRMAnimation is deprecated. Please use createVRMAnimResources instead."
  );
  return createVRMAnimResources(pcRef, animationAssets, asset, humanoid, extraSettings);
}
function createVRMAnimResources(pcRef, animationAssets, vrmAsset, humanoid, extraSettings = {}) {
  var _a, _b;
  if (!vrmAsset) {
    console.error('CreateVRMAnimResources: Please provide "vrm asset".');
    return;
  }
  if (!animationAssets) {
    console.error('CreateVRMAnimResources: Please provide "animation assets".');
    return;
  }
  if (!humanoid) {
    console.error('CreateVRMAnimResources: Please provide "humanoid" or "asset and entity".');
    return;
  }
  const resource = vrmAsset.resource;
  const isV1Used = (_a = resource.data.gltf.extensions) == null ? void 0 : _a.VRMC_vrm;
  const isV0Used = (_b = resource.data.gltf.extensions) == null ? void 0 : _b.VRM;
  const version = isV1Used ? "v1" : isV0Used ? "v0" : null;
  const checkAnimType = (assetType, extensionsUsed) => {
    if (assetType == "animation") {
      return false;
    } else if (assetType == "container") {
      if (extensionsUsed && extensionsUsed.includes("VRMC_vrm_animation") && extensionsUsed.indexOf("VRMC_vrm_animation") !== -1) {
        return true;
      } else {
        return false;
      }
    }
    return false;
  };
  const resources = [];
  animationAssets.forEach((animationAsset) => {
    var _a2;
    const assetResource = animationAsset.asset.resource;
    const assetType = animationAsset.asset.type;
    let resource2;
    if (!assetResource) {
      resource2 = null;
      console.warn(
        `createVRMAnimResources: loadAnimation can't find available resource from ${animationAsset.stateName} asset.`
      );
    } else {
      const extensionsUsed = (_a2 = assetResource.data) == null ? void 0 : _a2.gltf.extensionsUsed;
      const isVRMA = checkAnimType(assetType, extensionsUsed);
      if (isVRMA) {
        resource2 = createVRMAResource(pcRef, animationAsset, humanoid, version);
      } else {
        resource2 = createViverseAnimResource(
          pcRef,
          animationAsset,
          humanoid,
          version,
          extraSettings
        );
      }
    }
    if (resource2) {
      resources.push(resource2);
    }
  });
  return resources;
}
const assignAnimation = (entity, resource) => {
  if (entity.anim) {
    entity.anim.assignAnimation(
      resource.name,
      resource.resource,
      resource.setting && resource.setting.layerName !== void 0 ? resource.setting.layerName : void 0,
      resource.setting && resource.setting.speed !== void 0 ? resource.setting.speed : 1,
      resource.setting && resource.setting.loop !== void 0 ? resource.setting.loop : true
    );
  } else {
    console.error("AssignAnimation: Please set the anim component on the entity.");
  }
};
function bindVRMAExpression(entity, resource, animEntity) {
  const listenerEntity = animEntity ?? entity;
  const vrmAnim = listenerEntity.anim;
  if (vrmAnim) {
    vrmAnim.on(`anim-track:${resource.name}-start`, () => {
      var _a, _b, _c;
      if (!vrmAnim)
        return;
      let activeState;
      if (vrmAnim.vrmaExpressionLayerName) {
        const targetLayer = vrmAnim.layers.find(
          (layer) => layer.name === vrmAnim.vrmaExpressionLayerName
        );
        activeState = targetLayer == null ? void 0 : targetLayer.activeState;
      } else {
        activeState = (_a = vrmAnim.baseLayer) == null ? void 0 : _a.activeState;
      }
      if (activeState !== resource.name)
        return;
      const hasCustom = (((_b = resource.expression) == null ? void 0 : _b.custom.size) ?? 0) > 0;
      const hasPreset = (((_c = resource.expression) == null ? void 0 : _c.preset.size) ?? 0) > 0;
      const hasExpression = hasCustom || hasPreset;
      if (hasExpression) {
        entity.fire(`vrm-expression:vrma-start`, resource.expression);
      } else {
        entity.fire(`vrm-expression:vrma-reset`);
      }
    });
  }
}
function createVRMAResource(pcRef, animationAsset, humanoid, version) {
  var _a, _b, _c, _d;
  const vrmaLoader = new VRMAnimationLoader(pcRef);
  const vrmAnimations = vrmaLoader.loadVRMA(animationAsset.asset);
  const resource = animationAsset.asset.resource;
  let name = (_d = (_c = (_b = (_a = resource.data.gltf.animations) == null ? void 0 : _a[0]) == null ? void 0 : _b.resources) == null ? void 0 : _c[0]) == null ? void 0 : _d.name;
  if (!name)
    name = "";
  if (vrmAnimations) {
    const animTrack = new VRMAnimationTrack(
      pcRef,
      animationAsset.stateName,
      name,
      vrmAnimations[0],
      humanoid,
      version
    ).result;
    const expression = new VRMAExpression(vrmAnimations[0]);
    return {
      name: animationAsset.stateName,
      resource: animTrack,
      expression,
      ...animationAsset.setting && { setting: animationAsset.setting }
    };
  }
  return null;
}
function createViverseAnimResource(pcRef, animationAsset, humanoid, version, extraSettings) {
  var _a, _b;
  const resource = animationAsset.asset.resource;
  const origAnimTrack = animationAsset.asset.type === "container" ? (_b = (_a = resource.animations) == null ? void 0 : _a[0]) == null ? void 0 : _b.resource : animationAsset.asset.resource;
  if (origAnimTrack) {
    const animTrack = new VRMViverseAnimationTrack(
      pcRef,
      animationAsset,
      humanoid,
      version,
      extraSettings,
      origAnimTrack
    ).result;
    const parsedAnimAsset = {
      name: animationAsset.stateName,
      resource: animTrack,
      ...animationAsset.setting && {
        setting: animationAsset.setting
      }
    };
    return parsedAnimAsset;
  } else {
    console.error(
      `CreateViverseAnimResource: loadAnimation can't find valid resource from ${animationAsset.stateName} asset.`
    );
    return null;
  }
}
const VrmAnimation = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  assignAnimation,
  bindVRMAExpression,
  createVRMAnimResources,
  createVRMAnimation
}, Symbol.toStringTag, { value: "Module" }));
class Timer {
  constructor(name) {
    this.name = name;
    this._timers = {};
    this._nextFreeId = 0;
    this.timer = {};
    this.handle = null;
    this.isPausing = true;
  }
  add(durationSecs, callback, scope) {
    if (durationSecs > 0) {
      this.isPausing = false;
      const handle = { id: this._nextFreeId };
      this._timers[this._nextFreeId] = {
        secsLeft: durationSecs,
        callback,
        scope
      };
      this._nextFreeId += 1;
      this.handle = handle;
    } else {
      this.handle = null;
    }
  }
  pause() {
    this.isPausing = true;
    this.handle = null;
    this._timers = {};
  }
  update(dt) {
    for (let property in this._timers) {
      const targetTimer = this._timers[property];
      if (targetTimer.secsLeft !== void 0) {
        targetTimer.secsLeft -= dt;
        if (targetTimer.secsLeft <= 0) {
          delete this._timers[property];
          if (targetTimer.callback)
            targetTimer.callback.call(targetTimer.scope);
        }
      }
    }
  }
}
function saturate(value) {
  return Math.max(Math.min(value, 1), 0);
}
function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min) + min);
}
function getRandom(min, max) {
  return Math.random() * (max - min) + min;
}
class VRMExpressionManager {
  constructor() {
    this.managerName = "expression";
    this.blinkExpressionNames = /* @__PURE__ */ new Set(["blink", "blinkLeft", "blinkRight"]);
    this.lookAtExpressionNames = /* @__PURE__ */ new Set(["lookLeft", "lookRight", "lookUp", "lookDown"]);
    this.mouthExpressionNames = /* @__PURE__ */ new Set(["aa", "ee", "ih", "oh", "ou"]);
    this.emotionExpressionNames = /* @__PURE__ */ new Set([
      "neutral",
      "happy",
      "angry",
      "sad",
      "relaxed",
      "surprised"
    ]);
    this._expressions = [];
    this._expressionMap = {};
    this.talkExpressions = [];
    this.previousTalkName = "";
    this.isBackToBlink = false;
  }
  registerExpression(expression) {
    this._expressions.push(expression);
    this._expressionMap[expression.expressionName] = expression;
  }
  getExpression(name) {
    return this._expressionMap[name] ?? null;
  }
  getTalkingExpression() {
    const aExpression = this.getExpression("aa");
    const eExpression = this.getExpression("ee");
    const iExpression = this.getExpression("ih");
    const oExpression = this.getExpression("oh");
    const uExpression = this.getExpression("ou");
    return [aExpression, eExpression, iExpression, oExpression, uExpression].filter(
      (expression) => expression
    );
  }
  setValue(name, weight) {
    const expression = this.getExpression(name);
    if (expression) {
      expression.weight = saturate(weight);
    }
  }
  // Specific expression animations
  startBlink(blinkInterval, config) {
    const blinkConfig = config || {
      times: [0, blinkInterval - 0.2, blinkInterval - 0.1, blinkInterval],
      values: [0, 0, 1, 0]
    };
    const expression = this.getExpression("blink");
    if (!expression)
      return;
    expression.animatedMorph = blinkConfig;
    expression.isPausing = false;
    this.clearAllAppliedWeight(true);
  }
  stopBlink() {
    const expression = this.getExpression("blink");
    if (!expression)
      return;
    expression.stop();
  }
  startEmotion(name, config) {
    const emotionConfig = config || {
      times: [0, 1, 2.5, 3],
      values: [0, 1, 1, 0]
    };
    const expression = this.getExpression(name);
    if (!expression)
      return;
    expression.animatedMorph = emotionConfig;
    expression.isPausing = false;
    this.clearAllAppliedWeight(true);
  }
  stopEmotions(names) {
    names.forEach((name) => {
      const expression = this.getExpression(name);
      if (expression)
        expression.stop();
    });
  }
  stopAllEmotions() {
    this._expressions.forEach((expression) => {
      expression.stop();
    });
  }
  getNextTalking() {
    if (this.talkExpressions.length === 0)
      return null;
    const expressionIndex = getRandomInt(0, this.talkExpressions.length - 1);
    if (this.talkExpressions[expressionIndex].name === this.previousTalkName && this.talkExpressions.length > 1) {
      return this.getNextTalking();
    }
    this.previousTalkName = this.talkExpressions[expressionIndex].expressionName;
    return this.talkExpressions[expressionIndex];
  }
  startTalking(times, values) {
    if (this.talkExpressions.length === 0) {
      this.talkExpressions = this.getTalkingExpression();
    }
    const talkExpression = this.getNextTalking();
    if (!talkExpression)
      return;
    talkExpression.animatedMorph = {
      times,
      values
    };
  }
  stopTalking() {
    this.talkExpressions.forEach((expression) => {
      if (expression)
        expression.stop();
    });
  }
  clearAllAppliedWeight(isAllToZero) {
    for (const expression of this._expressions) {
      expression.clearAppliedWeight(isAllToZero);
    }
  }
  update(dt) {
    for (const expression of this._expressions) {
      expression.updateBlendShape(dt);
    }
    const weightMultipliers = this._calculateWeightMultipliers();
    this.clearAllAppliedWeight();
    this.isBackToBlink = true;
    for (const expression of this._expressions) {
      let multiplier = 1;
      const name = expression.expressionName;
      if (this.blinkExpressionNames.has(name)) {
        multiplier *= weightMultipliers.blink;
      }
      if (this.lookAtExpressionNames.has(name)) {
        multiplier *= weightMultipliers.lookAt;
      }
      if (this.mouthExpressionNames.has(name)) {
        multiplier *= weightMultipliers.mouth;
      }
      expression.applyWeight({ multiplier });
      if (expression.weight !== 0) {
        this.isBackToBlink = false;
      }
    }
  }
  /**
   * Calculate sum of override amounts to see how much we should multiply weights of certain expressions.
   */
  _calculateWeightMultipliers() {
    let blink = 1;
    let lookAt = 1;
    let mouth = 1;
    this._expressions.forEach((expression) => {
      blink -= expression.overrideBlinkAmount;
      lookAt -= expression.overrideLookAtAmount;
      mouth -= expression.overrideMouthAmount;
    });
    blink = Math.max(0, blink);
    lookAt = Math.max(0, lookAt);
    mouth = Math.max(0, mouth);
    return { blink, lookAt, mouth };
  }
}
class VRMExpression {
  constructor(expressionName) {
    this._binds = [];
    this.overrideLookAt = "none";
    this.overrideMouth = "none";
    this.name = `VRMExpression_${expressionName}`;
    this.expressionName = expressionName;
    this.type = "VRMExpression";
    this.isBinary = false;
    this.weight = 0;
    this._animatedMorph = null;
    this.time = 0;
    this.currentValue = 0;
    this.currentTimeIndex = null;
    this.isPausing = false;
    this._binds = [];
    this.overrideBlink = "none";
    this.overrideLookAt = "none";
    this.overrideMouth = "none";
  }
  get animatedMorph() {
    return this._animatedMorph;
  }
  set animatedMorph(input) {
    this.resetAnimatedMorph();
    this._animatedMorph = input;
  }
  addBind(bind) {
    this._binds.push(bind);
  }
  applyWeight({ multiplier }) {
    let actualWeight = this.isBinary ? this.weight <= 0.5 ? 0 : 1 : this.weight;
    actualWeight *= multiplier ?? 1;
    this._binds.forEach((bind) => bind.applyWeight(actualWeight));
  }
  /**
   * Clear previously assigned blend shapes.
   */
  clearAppliedWeight(isAllToZero) {
    if (isAllToZero)
      this.weight = 0;
    this._binds.forEach((bind) => bind.clearAppliedWeight());
  }
  /**
   * A value represents how much it should override blink expressions.
   * `0.0` == no override at all, `1.0` == completely block the expressions.
   */
  get overrideBlinkAmount() {
    if (this.overrideBlink === "block") {
      return 0 < this.weight ? 1 : 0;
    } else if (this.overrideBlink === "blend") {
      return this.weight;
    } else {
      return 0;
    }
  }
  /**
   * A value represents how much it should override lookAt expressions.
   * `0.0` == no override at all, `1.0` == completely block the expressions.
   */
  get overrideLookAtAmount() {
    if (this.overrideLookAt === "block") {
      return 0 < this.weight ? 1 : 0;
    } else if (this.overrideLookAt === "blend") {
      return this.weight;
    } else {
      return 0;
    }
  }
  /**
   * A value represents how much it should override mouth expressions.
   * `0.0` == no override at all, `1.0` == completely block the expressions.
   */
  get overrideMouthAmount() {
    if (this.overrideMouth === "block") {
      return 0 < this.weight ? 1 : 0;
    } else if (this.overrideMouth === "blend") {
      return this.weight;
    } else {
      return 0;
    }
  }
  setValue(weight) {
    this.currentValue = weight;
    this.weight = saturate(weight);
  }
  resetAnimatedMorph() {
    this.time = 0;
    this._animatedMorph = null;
    this.currentTimeIndex = null;
  }
  stop() {
    this.resetAnimatedMorph();
  }
  pause() {
    this.isPausing = true;
  }
  play() {
    this.isPausing = false;
  }
  _findTimeIndex(time, times) {
    if (time < times[1])
      return 0;
    for (let i = 1; i < times.length - 1; i++) {
      if (times[i - 1] < time && times[i + 1] > time) {
        return i;
      }
    }
    return -1;
  }
  updateBlendShape(dt) {
    if (!this._animatedMorph || this.isPausing)
      return;
    const { times, values } = this._animatedMorph;
    if (this.time === 0 && this.currentTimeIndex === null) {
      const initialValue = values[0];
      this.setValue(initialValue);
    }
    if (this.time >= times[times.length - 1]) {
      this.resetAnimatedMorph();
      const lastValue = values[values.length - 1];
      this.setValue(lastValue);
      return;
    }
    this.time += dt;
    const timeIndex = this._findTimeIndex(this.time, times);
    if (timeIndex !== -1) {
      if (this.currentTimeIndex !== timeIndex) {
        this.currentValue = values[timeIndex];
      }
      this.currentTimeIndex = timeIndex;
      const targetValue = values[this.currentTimeIndex + 1];
      const duration = times[this.currentTimeIndex] - times[this.currentTimeIndex + 1];
      const valueRange = values[this.currentTimeIndex] - values[this.currentTimeIndex + 1];
      const eachSecondValue = valueRange / duration;
      const newValue = this.currentValue + eachSecondValue * dt;
      if (eachSecondValue > 0 && newValue >= targetValue || eachSecondValue < 0 && targetValue >= newValue) {
        this.setValue(targetValue);
      } else {
        this.setValue(newValue);
      }
    }
  }
}
class VRMExpressionMorphTargetBind {
  constructor({
    primitives,
    targetIndex,
    weight
  }) {
    this.primitives = primitives;
    this.targetIndex = targetIndex;
    this.weight = weight;
  }
  applyWeight(weight) {
    this.primitives.forEach((mesh) => {
      var _a;
      if (((_a = mesh.morphInstance) == null ? void 0 : _a.morph.targets[this.targetIndex]) != null) {
        let currentWeight = mesh.morphInstance.getWeight(this.targetIndex);
        mesh.morphInstance.setWeight(this.targetIndex, currentWeight += this.weight * weight);
      }
    });
  }
  clearAppliedWeight() {
    this.primitives.forEach((mesh) => {
      var _a;
      if (((_a = mesh.morphInstance) == null ? void 0 : _a.morph.targets[this.targetIndex]) != null) {
        mesh.morphInstance.setWeight(this.targetIndex, 0);
      }
    });
  }
}
class VRMExpressionLoaderPlugin {
  constructor(asset, meshInstances) {
    this.asset = asset;
    this.meshInstances = meshInstances;
  }
  import() {
    const resource = this.asset.resource;
    const gltf = resource.data.gltf;
    const v1Result = this._v1Import(gltf);
    if (v1Result) {
      return v1Result;
    }
    const v0Result = this._v0Import(gltf);
    if (v0Result) {
      return v0Result;
    }
    return null;
  }
  _v1Import(gltf) {
    var _a;
    const isVRMUsed = (gltf == null ? void 0 : gltf.extensionsUsed.indexOf("VRMC_vrm")) !== -1;
    if (!isVRMUsed) {
      return null;
    }
    const extension = (_a = gltf == null ? void 0 : gltf.extensions) == null ? void 0 : _a.VRMC_vrm;
    if (!extension) {
      return null;
    }
    const schemaExpressions = extension.expressions;
    if (!schemaExpressions) {
      return null;
    }
    const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
    const nameSchemaExpressionMap = /* @__PURE__ */ new Map();
    if (schemaExpressions.preset != null) {
      Object.entries(schemaExpressions.preset).forEach(([name, schemaExpression]) => {
        if (schemaExpression == null) {
          return;
        }
        if (!presetNameSet.has(name)) {
          console.warn(
            `VRMExpressionLoaderPlugin: Unknown preset name "${name}" detected. Ignoring the expression`
          );
          return;
        }
        nameSchemaExpressionMap.set(name, schemaExpression);
      });
    }
    if (schemaExpressions.custom != null) {
      Object.entries(schemaExpressions.custom).forEach(([name, schemaExpression]) => {
        if (presetNameSet.has(name)) {
          console.warn(
            `VRMExpressionLoaderPlugin: Custom expression cannot have preset name "${name}". Ignoring the expression`
          );
          return;
        }
        nameSchemaExpressionMap.set(name, schemaExpression);
      });
    }
    const manager = new VRMExpressionManager();
    Array.from(nameSchemaExpressionMap.entries()).map(([name, schemaExpression]) => {
      const expression = new VRMExpression(name);
      expression.isBinary = schemaExpression.isBinary ?? false;
      expression.overrideBlink = schemaExpression.overrideBlink ?? "none";
      expression.overrideLookAt = schemaExpression.overrideLookAt ?? "none";
      expression.overrideMouth = schemaExpression.overrideMouth ?? "none";
      if (schemaExpression.morphTargetBinds) {
        schemaExpression.morphTargetBinds.forEach((bind) => {
          if (bind.node === void 0 || bind.index === void 0) {
            return;
          }
          const primitives = this.meshInstances.filter((meshInstance) => {
            return meshInstance.node.tags.has(`node_${bind.node}`);
          });
          const morphTargetIndex = bind.index;
          expression.addBind(
            new VRMExpressionMorphTargetBind({
              primitives,
              targetIndex: morphTargetIndex,
              weight: bind.weight ?? 1
            })
          );
        });
      }
      manager.registerExpression(expression);
    });
    return manager;
  }
  _v0Import(gltf) {
    var _a, _b;
    const isVRMUsed = ((_a = gltf.extensionsUsed) == null ? void 0 : _a.indexOf("VRM")) !== -1;
    if (!isVRMUsed) {
      return null;
    }
    const vrmExt = (_b = gltf.extensions) == null ? void 0 : _b.VRM;
    if (!vrmExt) {
      return null;
    }
    const schemaBlendShape = vrmExt.blendShapeMaster;
    if (!schemaBlendShape) {
      return null;
    }
    const manager = new VRMExpressionManager();
    const schemaBlendShapeGroups = schemaBlendShape.blendShapeGroups;
    if (!schemaBlendShapeGroups) {
      return manager;
    }
    const blendShapeNameSet = /* @__PURE__ */ new Set();
    schemaBlendShapeGroups.map((schemaGroup) => {
      const v0PresetName = schemaGroup.presetName;
      const v1PresetName = v0PresetName != null && v0v1PresetNameMap[v0PresetName] || null;
      const name = v1PresetName ?? schemaGroup.name;
      if (name == null) {
        console.warn(
          "VRMExpressionLoaderPlugin: One of custom expressions has no name. Ignoring the expression"
        );
        return;
      }
      if (blendShapeNameSet.has(name)) {
        console.warn(
          `VRMExpressionLoaderPlugin: An expression preset ${v0PresetName} has duplicated entries. Ignoring the expression`
        );
        return;
      }
      blendShapeNameSet.add(name);
      const expression = new VRMExpression(name);
      expression.isBinary = schemaGroup.isBinary ?? false;
      if (schemaGroup.binds) {
        schemaGroup.binds.forEach((bind) => {
          if (bind.mesh === void 0 || bind.index === void 0) {
            return;
          }
          const nodesUsingMesh = [];
          gltf.nodes.forEach((node, index) => {
            if (node.mesh === bind.mesh) {
              nodesUsingMesh.push({ gltfNode: node, index });
            }
          });
          const morphTargetIndex = bind.index;
          nodesUsingMesh.map((node) => {
            const primitives = this.meshInstances.filter((meshInstance) => {
              return meshInstance.node.tags.has(`node_${node.index}`);
            });
            expression.addBind(
              new VRMExpressionMorphTargetBind({
                primitives,
                targetIndex: morphTargetIndex,
                weight: 0.01 * (bind.weight ?? 100)
                // narrowing the range from [ 0.0 - 100.0 ] to [ 0.0 - 1.0 ]
              })
            );
          });
        });
        manager.registerExpression(expression);
      }
    });
    return manager;
  }
}
const collectMeshInstances = (entity) => {
  const meshInstances = [];
  if (entity) {
    const components = entity.findComponents("render");
    for (let i = 0; i < components.length; i++) {
      const render = components[i];
      if (render.meshInstances) {
        for (let m = 0; m < render.meshInstances.length; m++) {
          const meshInstance = render.meshInstances[m];
          meshInstances.push(meshInstance);
        }
      }
    }
  }
  return meshInstances;
};
const importScript$2 = (pcRef) => {
  class VrmExpression2 extends pcRef.ScriptType {
    constructor() {
      super(...arguments);
      this.previousTalkName = "";
      this.vrmaEmotionWasPlaying = false;
    }
    initialize() {
      const meshInstances = collectMeshInstances(this.entity);
      const loaderPlugin = new VRMExpressionLoaderPlugin(this.asset, meshInstances);
      this.expressionManager = loaderPlugin.import();
      this.blinkTimer = new Timer("blink");
      this.talkTimer = new Timer("talk");
      this.startBlink();
      this.entity.on("vrm-expression:start-emotion", this.startEmotion, this);
      this.entity.on("vrm-expression:vrma-start", this._startVRMAExpression, this);
      this.entity.on("vrm-expression:talking-state-changed", this.onTalkingStateChanged, this);
      this.entity.on("audio:is-talking-change", this.onTalkingStateChanged, this);
      this.on("destroy", () => {
        this.entity.off("vrm-expression:start-emotion", this.startEmotion, this);
        this.entity.off("vrm-expression:vrma-start", this._startVRMAExpression, this);
        this.entity.off("vrm-expression:vrma-reset", this._resetVRMAExpression, this);
        this.entity.off("vrm-expression:talking-state-changed", this.onTalkingStateChanged, this);
        this.entity.off("audio:is-talking-change", this.onTalkingStateChanged, this);
      });
    }
    // Specific Automatic Start Expressions
    startBlink(config) {
      if (!this.expressionManager)
        return;
      this.expressionManager.startBlink(1, config);
      const randomValue = getRandom(1, 5);
      this.blinkTimer.add(randomValue, this.startBlink, this);
    }
    stopBlink() {
      if (!this.expressionManager)
        return;
      this.blinkTimer.pause();
      this.expressionManager.stopBlink();
    }
    startEmotion(name, config) {
      var _a;
      (_a = this.expressionManager) == null ? void 0 : _a.startEmotion(name, config);
    }
    startTalking(speed = 0.25) {
      if (!this.expressionManager)
        return;
      const time1 = Math.random() * 0.5;
      const time2 = Math.random() * 0.5 + 0.5;
      const valueMiddle = getRandom(0.5, 1);
      const value1 = getRandom(0.4, 0.6) * valueMiddle;
      const value2 = getRandom(0.4, 0.6) * valueMiddle;
      const times = [0, time1, 0.5, time2, 1].map((time) => time * speed);
      const values = [0, value1, valueMiddle, value2, 0];
      const timerRandomValue = getRandom(0.5, 1);
      this.expressionManager.startTalking(times, values);
      this.talkTimer.add(timerRandomValue, this.startTalking, this);
    }
    stopTalking(restartSecond) {
      this.talkTimer.pause();
      if (restartSecond) {
        this.talkTimer.add(restartSecond, this.startTalking, this);
      }
    }
    onTalkingStateChanged(state) {
      const timerAvailable = this.talkTimer.isPausing || !this.talkTimer.handle;
      if (state && timerAvailable) {
        this.startTalking();
      } else {
        this.stopTalking();
      }
    }
    update(dt) {
      if (!this.expressionManager)
        return;
      this.expressionManager.update(dt);
      this.blinkTimer.update(dt);
      this.talkTimer.update(dt);
    }
    _startVRMAExpression(vrmaExpression) {
      if (!this.expressionManager)
        return;
      this.stopBlink();
      this.expressionManager.stopAllEmotions();
      for (const [name, config] of vrmaExpression.preset.entries()) {
        this.startEmotion(name, config);
      }
      if (!this.entity.hasEvent("vrm-expression:vrma-reset")) {
        this.entity.once("vrm-expression:vrma-reset", this._resetVRMAExpression, this);
      }
      this.vrmaEmotionWasPlaying = true;
    }
    _resetVRMAExpression() {
      var _a;
      if (!this.vrmaEmotionWasPlaying)
        return;
      (_a = this.expressionManager) == null ? void 0 : _a.stopAllEmotions();
      this.startBlink();
      this.vrmaEmotionWasPlaying = false;
    }
  }
  pcRef.registerScript(VrmExpression2, "vrmExpression");
  VrmExpression2.attributes.add("asset", {
    type: "asset",
    description: "Set the container asset loaded from vrm avatar."
  });
};
const VrmExpression = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  importScript: importScript$2
}, Symbol.toStringTag, { value: "Module" }));
function lowestCommonAncestor(objects) {
  const sharedAncestors = /* @__PURE__ */ new Map();
  for (const object of objects) {
    let current = object;
    do {
      const newValue = (sharedAncestors.get(current) ?? 0) + 1;
      if (newValue === objects.size) {
        return current;
      }
      sharedAncestors.set(current, newValue);
      current = current.parent;
    } while (current !== null);
  }
  return null;
}
function traverseAncestorsFromRoot(object, callback) {
  const ancestors = [];
  let head = object;
  while (head !== null) {
    ancestors.unshift(head);
    head = head.parent;
  }
  ancestors.forEach((ancestor) => {
    callback(ancestor);
  });
}
function traverseChildrenUntilConditionMet(object, callback) {
  object.children.forEach((child) => {
    const result = callback(child);
    if (!result) {
      traverseChildrenUntilConditionMet(child, callback);
    }
  });
}
class VRMSpringBoneManager {
  constructor() {
    this.managerName = "springBone";
    this._joints = /* @__PURE__ */ new Set();
    this._hasWarnedCircularDependency = false;
    this._sortedJoints = [];
    this._limitedStrength = 0.3;
    this._normalStrength = 1;
    this._ancestors = [];
    this._objectSpringBonesMap = /* @__PURE__ */ new Map();
    this._isSortedJointsDirty = false;
  }
  get joints() {
    return this._joints;
  }
  get limitedStrength() {
    return this._limitedStrength;
  }
  get normalStrength() {
    return this._normalStrength;
  }
  get colliderGroups() {
    const set = /* @__PURE__ */ new Set();
    this._joints.forEach((springBone) => {
      springBone.colliderGroups.forEach((colliderGroup) => {
        set.add(colliderGroup);
      });
    });
    return Array.from(set);
  }
  addJoint(joint) {
    this._joints.add(joint);
    let objectSet = this._objectSpringBonesMap.get(joint.bone);
    if (objectSet == null) {
      objectSet = /* @__PURE__ */ new Set();
      this._objectSpringBonesMap.set(joint.bone, objectSet);
    }
    objectSet.add(joint);
    this._isSortedJointsDirty = true;
  }
  setInitState() {
    this._sortJoints();
    for (let i = 0; i < this._sortedJoints.length; i++) {
      const springBone = this._sortedJoints[i];
      springBone.setInitState();
    }
  }
  reset() {
    this._sortJoints();
    for (let i = 0; i < this._sortedJoints.length; i++) {
      const springBone = this._sortedJoints[i];
      springBone.reset();
    }
  }
  /**
   * Sorts the joints ensuring they are updated in the correct order taking dependencies into account.
   *
   * This method updates {@link _sortedJoints} and {@link _ancestors}.
   * Make sure to call this before using them.
   */
  _sortJoints() {
    if (!this._isSortedJointsDirty) {
      return;
    }
    const springBoneOrder = [];
    const springBonesTried = /* @__PURE__ */ new Set();
    const springBonesDone = /* @__PURE__ */ new Set();
    const ancestors = /* @__PURE__ */ new Set();
    for (const springBone of this._joints) {
      this._insertJointSort(
        springBone,
        springBonesTried,
        springBonesDone,
        springBoneOrder,
        ancestors
      );
    }
    this._sortedJoints = springBoneOrder;
    const lca = lowestCommonAncestor(ancestors);
    this._ancestors = [];
    if (lca) {
      this._ancestors.push(lca);
      traverseChildrenUntilConditionMet(lca, (object) => {
        var _a;
        if ((((_a = this._objectSpringBonesMap.get(object)) == null ? void 0 : _a.size) ?? 0) > 0) {
          return true;
        }
        this._ancestors.push(object);
        return false;
      });
    }
    this._isSortedJointsDirty = false;
  }
  _insertJointSort(springBone, springBonesTried, springBonesDone, springBoneOrder, ancestors) {
    if (springBonesDone.has(springBone)) {
      return;
    }
    if (springBonesTried.has(springBone)) {
      if (!this._hasWarnedCircularDependency) {
        console.warn("VRMSpringBoneManager: Circular dependency detected");
        this._hasWarnedCircularDependency = true;
      }
      return;
    }
    springBonesTried.add(springBone);
    const depObjects = springBone.dependencies;
    for (const depObject of depObjects) {
      let encounteredSpringBone = false;
      let ancestor = null;
      traverseAncestorsFromRoot(depObject, (depObjectAncestor) => {
        const objectSet = this._objectSpringBonesMap.get(depObjectAncestor);
        if (objectSet) {
          for (const depSpringBone of objectSet) {
            encounteredSpringBone = true;
            this._insertJointSort(
              depSpringBone,
              springBonesTried,
              springBonesDone,
              springBoneOrder,
              ancestors
            );
          }
        } else if (!encounteredSpringBone) {
          ancestor = depObjectAncestor;
        }
      });
      if (ancestor) {
        ancestors.add(ancestor);
      }
    }
    springBoneOrder.push(springBone);
    springBonesDone.add(springBone);
  }
  update(delta, isLimited = false) {
    this._sortJoints();
    const currentStrength = isLimited ? this._limitedStrength : this._normalStrength;
    for (let i = 0; i < this._sortedJoints.length; i++) {
      const springBone = this._sortedJoints[i];
      springBone.update(delta, currentStrength);
    }
  }
}
class VRMSpringBoneColliderShapeSphere {
  constructor(pcRef, params) {
    this.offset = (params == null ? void 0 : params.offset) ?? new pcRef.Vec3();
    this.radius = (params == null ? void 0 : params.radius) ?? 0;
    this.inside = (params == null ? void 0 : params.inside) ?? false;
  }
  get type() {
    return "sphere";
  }
  calculateCollision(colliderMatrix, objectPosition, objectRadius, target, reference) {
    target.sub2(objectPosition, colliderMatrix.getTranslation(reference));
    const length = target.length();
    const distance = this.inside ? this.radius - objectRadius - length : length - objectRadius - this.radius;
    if (distance < 0) {
      target.mulScalar(1 / length);
      if (this.inside) {
        target.mulScalar(-1);
      }
    }
    return distance;
  }
}
class VRMSpringBoneColliderShapeCapsule {
  constructor(pcRef, params = {}) {
    this.offset = (params == null ? void 0 : params.offset) ?? new pcRef.Vec3();
    this.tail = (params == null ? void 0 : params.tail) ?? new pcRef.Vec3();
    this.radius = (params == null ? void 0 : params.radius) ?? 0;
    this._v3A = new pcRef.Vec3();
    this._v3B = new pcRef.Vec3();
    this.inside = (params == null ? void 0 : params.inside) ?? false;
  }
  get type() {
    return "capsule";
  }
  calculateCollision(colliderMatrix, objectPosition, objectRadius, target, reference) {
    this._v3A.copy(colliderMatrix.getTranslation(reference));
    colliderMatrix.transformPoint(reference.sub2(this.tail, this.offset), this._v3B);
    this._v3B.sub(this._v3A);
    const lengthSqCapsule = this._v3B.lengthSq();
    target.copy(objectPosition).sub(this._v3A);
    const dot = this._v3B.dot(target);
    if (dot <= 0)
      ;
    else if (lengthSqCapsule <= dot) {
      target.sub(this._v3B);
    } else {
      this._v3B.mulScalar(dot / lengthSqCapsule);
      target.sub(this._v3B);
    }
    const length = target.length();
    const distance = this.inside ? this.radius - objectRadius - length : length - objectRadius - this.radius;
    if (distance < 0) {
      target.mulScalar(1 / length);
      if (this.inside) {
        target.mulScalar(-1);
      }
    }
    return distance;
  }
}
class VRMSpringBoneJoint {
  constructor(pcRef, bone, child, settings = {}, colliderGroups = []) {
    var _a;
    this.id = crypto.randomUUID();
    this._center = null;
    this._worldSpaceBoneLength = 0;
    this._pcRef = pcRef;
    this._v3A = new this._pcRef.Vec3();
    this._v3B = new this._pcRef.Vec3();
    this._nextTail = new this._pcRef.Vec3();
    this._quatA = new this._pcRef.Quat();
    this._quatB = new this._pcRef.Quat();
    this._quatC = new this._pcRef.Quat();
    this._quatD = new this._pcRef.Quat();
    this._matA = new this._pcRef.Mat4();
    this._identityMat4 = new this._pcRef.Mat4();
    this._worldSpacePosition = new this._pcRef.Vec3();
    this._worldSpaceBoneLength = 0;
    this.bone = bone;
    this.child = child;
    this.settings = {
      hitRadius: settings.hitRadius ?? 0,
      stiffness: settings.stiffness ?? 1,
      gravityPower: settings.gravityPower ?? 0,
      gravityDir: ((_a = settings.gravityDir) == null ? void 0 : _a.clone()) ?? new this._pcRef.Vec3(0, -1, 0),
      dragForce: settings.dragForce ?? 0.4
    };
    this.colliderGroups = colliderGroups;
    this._initialLocalMatrix = new this._pcRef.Mat4();
    this._initialLocalRotation = new this._pcRef.Quat();
    this._initialLocalChildPosition = new this._pcRef.Vec3();
    this._currentTail = new this._pcRef.Vec3();
    this._prevTail = new this._pcRef.Vec3();
    this._boneAxis = new this._pcRef.Vec3();
    this._center = null;
  }
  get center() {
    return this._center;
  }
  set center(center) {
    this._center = center;
  }
  get _parentMatrixWorld() {
    return this.bone.parent ? this.bone.parent.getWorldTransform() : this._identityMat4;
  }
  /**
   * Set of dependencies that need to be updated before this joint.
   */
  get dependencies() {
    const set = /* @__PURE__ */ new Set();
    const parent = this.bone.parent;
    if (parent) {
      set.add(parent);
    }
    for (let cg = 0; cg < this.colliderGroups.length; cg++) {
      for (let c = 0; c < this.colliderGroups[cg].colliders.length; c++) {
        set.add(this.colliderGroups[cg].colliders[c]);
      }
    }
    return set;
  }
  _calcWorldSpaceBoneLength() {
    const matrixWorld = this.bone.getWorldTransform();
    matrixWorld.getTranslation(this._v3A);
    if (this.child) {
      const childMatrixWorld = this.child.getWorldTransform();
      childMatrixWorld.getTranslation(this._v3B);
    } else {
      this._v3B.copy(this._initialLocalChildPosition);
      matrixWorld.transformPoint(this._v3B, this._v3B);
    }
    this._worldSpaceBoneLength = this._v3A.sub(this._v3B).length();
  }
  setInitState() {
    this._initialLocalMatrix.copy(this.bone.getLocalTransform());
    this._initialLocalRotation.copy(this.bone.getLocalRotation());
    if (this.child) {
      this._initialLocalChildPosition.copy(this.child.getLocalPosition());
    } else {
      this._initialLocalChildPosition.copy(this.bone.getLocalPosition()).normalize().mulScalar(0.07);
    }
    const worldTransform = this.bone.getWorldTransform();
    worldTransform.transformPoint(
      this._currentTail.copy(this._initialLocalChildPosition),
      this._currentTail
    );
    this._transformPointWorldToCenter(this._currentTail);
    this._prevTail.copy(this._currentTail);
    this._boneAxis.copy(this._initialLocalChildPosition).normalize();
  }
  reset() {
    this.bone.setLocalRotation(this._initialLocalRotation);
    const worldTransform = this.bone.getWorldTransform();
    worldTransform.transformPoint(
      this._currentTail.copy(this._initialLocalChildPosition),
      this._currentTail
    );
    this._transformPointWorldToCenter(this._currentTail);
    this._prevTail.copy(this._currentTail);
  }
  update(dt, strength = 1) {
    if (dt <= 0)
      return;
    this._calcWorldSpaceBoneLength();
    const worldSpaceBoneAxis = this._v3A.copy(this._boneAxis);
    this._initialLocalMatrix.transformVector(worldSpaceBoneAxis, worldSpaceBoneAxis);
    worldSpaceBoneAxis.normalize();
    this._parentMatrixWorld.transformVector(worldSpaceBoneAxis, worldSpaceBoneAxis);
    worldSpaceBoneAxis.normalize();
    this._nextTail.copy(this._currentTail).add(
      this._v3B.sub2(this._currentTail, this._prevTail).mulScalar(1 - this.settings.dragForce)
    );
    this._transformPointCenterToWorld(this._nextTail);
    this._nextTail.add(this._v3B.copy(worldSpaceBoneAxis).mulScalar(this.settings.stiffness * dt));
    this._nextTail.add(
      this._v3B.copy(this.settings.gravityDir).mulScalar(this.settings.gravityPower * dt)
    );
    this._worldSpacePosition.copy(this.bone.getPosition());
    this._nextTail.sub(this._worldSpacePosition).normalize().mulScalar(this._worldSpaceBoneLength).add(this._worldSpacePosition);
    this._collision(this._nextTail);
    this._prevTail.copy(this._currentTail);
    this._currentTail.copy(this._nextTail);
    this._transformPointWorldToCenter(this._currentTail);
    const to = this._v3A.copy(this._nextTail).sub(this._worldSpacePosition).normalize();
    const parentRotation = this.bone.parent ? this.bone.parent.getRotation() : this._quatC.set(0, 0, 0, 1);
    const restPoseRotation = this._quatD.mul2(parentRotation, this._initialLocalRotation);
    restPoseRotation.invert().transformVector(to, to);
    to.normalize();
    const applyRotation = this._quatA.setFromDirections(this._boneAxis, to);
    if (strength !== 1) {
      const identityQuat = this._quatC.set(0, 0, 0, 1);
      const tempQuat = this._quatD.copy(applyRotation);
      applyRotation.slerp(identityQuat, tempQuat, strength);
    }
    const rotation = this._quatB.mul2(this._initialLocalRotation, applyRotation);
    this.bone.setLocalRotation(rotation);
  }
  _transformPointCenterToWorld(target) {
    if (!this._center)
      return;
    this._center.getWorldTransform().transformPoint(target, target);
  }
  _transformPointWorldToCenter(target) {
    if (!this._center)
      return;
    this._matA.copy(this._center.getWorldTransform()).invert();
    this._matA.transformPoint(target, target);
  }
  _collision(tail) {
    if (!this.colliderGroups)
      return;
    for (let i = 0; i < this.colliderGroups.length; i++) {
      const colliderGroup = this.colliderGroups[i];
      const colliders = colliderGroup.colliders;
      for (let j = 0; j < colliders.length; j++) {
        const collider = colliders[j];
        const dist = collider.shape.calculateCollision(
          collider.getWorldTransform(),
          tail,
          this.settings.hitRadius,
          this._v3A,
          this._v3B
        );
        if (dist < 0) {
          tail.add(this._v3A.mulScalar(-dist));
          tail.sub(this._worldSpacePosition);
          const length = tail.length();
          tail.mulScalar(this._worldSpaceBoneLength / length).add(this._worldSpacePosition);
        }
      }
    }
  }
}
function createVRMSpringBoneCollider(pcRef, shape) {
  const collider = new pcRef.Entity();
  collider.shape = shape;
  collider.setLocalPosition(shape.offset);
  return collider;
}
const _VRMSpringBoneLoaderPlugin = class _VRMSpringBoneLoaderPlugin2 {
  constructor(pcRef, asset, entity) {
    this.asset = asset;
    this.entity = entity;
    this._pcRef = pcRef;
  }
  import() {
    const resource = this.asset.resource;
    const gltf = resource.data.gltf;
    const data = resource.data;
    if (!gltf) {
      return null;
    }
    const v1Result = this._v1Import(gltf);
    if (v1Result) {
      return v1Result;
    }
    const v0Result = this._v0Import(gltf, data);
    if (v0Result) {
      return v0Result;
    }
    return null;
  }
  _v1Import(gltf) {
    var _a, _b, _c;
    const isSpringBoneUsed = ((_a = gltf.extensionsUsed) == null ? void 0 : _a.indexOf(_VRMSpringBoneLoaderPlugin2.EXTENSION_NAME)) !== -1;
    if (!isSpringBoneUsed) {
      return null;
    }
    const isVRMUsed = ((_b = gltf == null ? void 0 : gltf.extensionsUsed) == null ? void 0 : _b.indexOf("VRMC_vrm")) !== -1;
    if (!isVRMUsed) {
      return null;
    }
    const manager = new VRMSpringBoneManager();
    const extension = (_c = gltf.extensions) == null ? void 0 : _c[_VRMSpringBoneLoaderPlugin2.EXTENSION_NAME];
    if (!extension) {
      return null;
    }
    const specVersion = extension.specVersion;
    if (!POSSIBLE_SPEC_VERSIONS$1.has(specVersion)) {
      console.warn(
        `VRMSpringBoneLoaderPlugin: Unknown ${_VRMSpringBoneLoaderPlugin2.EXTENSION_NAME} specVersion "${specVersion}"`
      );
      return null;
    }
    const extensionColliders = extension.colliders || [];
    const colliders = extensionColliders == null ? void 0 : extensionColliders.map((schemaCollider, iCollider) => {
      var _a2;
      const node = (_a2 = this.entity.findByTag(`node_${schemaCollider.node}`)) == null ? void 0 : _a2[0];
      const schemaShape = schemaCollider.shape;
      if (!node) {
        console.error(
          "VRMSpringBoneLoaderPlugin Error: Did not find the node map to schemaColliderGroup"
        );
        return;
      }
      if (schemaShape) {
        if (schemaShape.sphere) {
          return this._importSphereCollider(node, {
            offset: new this._pcRef.Vec3().fromArray(schemaShape.sphere.offset ?? [0, 0, 0]),
            radius: schemaShape.sphere.radius ?? 0
          });
        } else if (schemaShape.capsule) {
          return this._importCapsuleCollider(node, {
            offset: new this._pcRef.Vec3().fromArray(schemaShape.capsule.offset ?? [0, 0, 0]),
            radius: schemaShape.capsule.radius ?? 0,
            tail: new this._pcRef.Vec3().fromArray(schemaShape.capsule.tail ?? [0, 0, 0])
          });
        }
      }
      throw new Error(`VRMSpringBoneLoaderPlugin: The collider #${iCollider} has no valid shape`);
    });
    const extensionColliderGroups = extension.colliderGroups || [];
    const colliderGroups = extensionColliderGroups == null ? void 0 : extensionColliderGroups.map((schemaColliderGroup, iColliderGroup) => {
      const cols = (schemaColliderGroup.colliders ?? []).map((iCollider) => {
        const col = colliders == null ? void 0 : colliders[iCollider];
        if (col == null) {
          throw new Error(
            `VRMSpringBoneLoaderPlugin: The colliderGroup #${iColliderGroup} attempted to use a collider #${iCollider} but not found`
          );
        }
        return col;
      });
      return {
        colliders: cols,
        name: schemaColliderGroup.name
      };
    });
    const extensionSprings = extension.springs || [];
    extensionSprings.forEach((schemaSpring, iSpring) => {
      var _a2, _b2;
      const schemaJoints = schemaSpring.joints;
      const colliderGroupsForSpring = (_a2 = schemaSpring.colliderGroups) == null ? void 0 : _a2.map((iColliderGroup) => {
        const group = colliderGroups == null ? void 0 : colliderGroups[iColliderGroup];
        if (group == null) {
          throw new Error(
            `VRMSpringBoneLoaderPlugin: The spring #${iSpring} attempted to use a colliderGroup ${iColliderGroup} but not found`
          );
        }
        return group;
      });
      const center = (_b2 = this.entity.findByTag(`node_${schemaSpring.center}`)) == null ? void 0 : _b2[0];
      let prevSchemaJoint;
      schemaJoints.forEach((schemaJoint) => {
        var _a3, _b3;
        if (prevSchemaJoint) {
          const nodeIndex = prevSchemaJoint.node;
          const node = (_a3 = this.entity.findByTag(`node_${nodeIndex}`)) == null ? void 0 : _a3[0];
          const childIndex = schemaJoint.node;
          const child = (_b3 = this.entity.findByTag(`node_${childIndex}`)) == null ? void 0 : _b3[0];
          const setting = {
            hitRadius: prevSchemaJoint.hitRadius,
            dragForce: prevSchemaJoint.dragForce,
            gravityPower: prevSchemaJoint.gravityPower,
            stiffness: prevSchemaJoint.stiffness,
            gravityDir: prevSchemaJoint.gravityDir != null ? new this._pcRef.Vec3().fromArray(prevSchemaJoint.gravityDir) : void 0
          };
          const joint = this._importJoint(node, child, setting, colliderGroupsForSpring);
          if (center) {
            joint.center = center;
          }
          manager.addJoint(joint);
        }
        prevSchemaJoint = schemaJoint;
      });
    });
    manager.setInitState();
    return manager;
  }
  _v0Import(gltf, resourceData) {
    var _a, _b, _c;
    const extension = (_a = gltf.extensions) == null ? void 0 : _a.VRM;
    const isVRMUsed = ((_b = gltf.extensionsUsed) == null ? void 0 : _b.indexOf("VRM")) !== -1;
    if (!isVRMUsed) {
      return null;
    }
    const schemaSecondaryAnimation = extension == null ? void 0 : extension.secondaryAnimation;
    if (!schemaSecondaryAnimation) {
      return null;
    }
    const schemaBoneGroups = schemaSecondaryAnimation == null ? void 0 : schemaSecondaryAnimation.boneGroups;
    if (!schemaBoneGroups) {
      return null;
    }
    const manager = new VRMSpringBoneManager();
    const colliderGroups = (_c = schemaSecondaryAnimation.colliderGroups) == null ? void 0 : _c.map((schemaColliderGroup) => {
      var _a2;
      const node = (_a2 = this.entity.findByTag(`node_${schemaColliderGroup.node}`)) == null ? void 0 : _a2[0];
      if (!node) {
        console.error(
          "VRMSpringBoneLoaderPlugin Error: Did not find the node map to schemaColliderGroup"
        );
        return;
      }
      const colliders = (schemaColliderGroup.colliders ?? []).map((schemaCollider) => {
        const offset = new this._pcRef.Vec3(0, 0, 0);
        if (schemaCollider.offset) {
          offset.set(
            schemaCollider.offset.x ?? 0,
            schemaCollider.offset.y ?? 0,
            schemaCollider.offset.z ? -schemaCollider.offset.z : 0
            // z is opposite in VRM0.0
          );
        }
        return this._importSphereCollider(node, {
          offset,
          radius: schemaCollider.radius ?? 0
        });
      });
      return { colliders };
    });
    schemaBoneGroups == null ? void 0 : schemaBoneGroups.forEach((schemaBoneGroup, iBoneGroup) => {
      const rootIndices = schemaBoneGroup.bones;
      if (!rootIndices) {
        return;
      }
      rootIndices.forEach((rootIndex) => {
        var _a2, _b2;
        const root = (_a2 = this.entity.findByTag(`node_${rootIndex}`)) == null ? void 0 : _a2[0];
        if (!root) {
          console.error(
            "VRMSpringBoneLoaderPlugin Error: Did not find the node map to schemaColliderGroup"
          );
          return;
        }
        const gravityDir = new this._pcRef.Vec3();
        if (schemaBoneGroup.gravityDir) {
          gravityDir.set(
            schemaBoneGroup.gravityDir.x ?? 0,
            schemaBoneGroup.gravityDir.y ?? 0,
            schemaBoneGroup.gravityDir.z ?? 0
          );
        } else {
          gravityDir.set(0, -1, 0);
        }
        const center = schemaBoneGroup.center != null ? resourceData.nodes[schemaBoneGroup.center] : void 0;
        const setting = {
          hitRadius: schemaBoneGroup.hitRadius,
          dragForce: schemaBoneGroup.dragForce,
          gravityPower: schemaBoneGroup.gravityPower,
          stiffness: schemaBoneGroup.stiffiness,
          gravityDir
        };
        const colliderGroupsForSpring = (_b2 = schemaBoneGroup.colliderGroups) == null ? void 0 : _b2.map((iColliderGroup) => {
          const group = colliderGroups == null ? void 0 : colliderGroups[iColliderGroup];
          if (group == null) {
            throw new Error(
              `VRMSpringBoneLoaderPlugin: The spring #${iBoneGroup} attempted to use a colliderGroup ${iColliderGroup} but not found`
            );
          }
          return group;
        });
        root.forEach((node) => {
          const child = node.children[0] ?? null;
          const joint = this._importJoint(node, child, setting, colliderGroupsForSpring);
          if (center) {
            joint.center = center;
          }
          manager.addJoint(joint);
        });
      });
    });
    manager.setInitState();
    return manager;
  }
  _importSphereCollider(destination, { offset, radius }) {
    const shape = new VRMSpringBoneColliderShapeSphere(this._pcRef, { offset, radius });
    const collider = createVRMSpringBoneCollider(this._pcRef, shape);
    destination.addChild(collider);
    return collider;
  }
  _importCapsuleCollider(destination, { offset, radius, tail }) {
    const shape = new VRMSpringBoneColliderShapeCapsule(this._pcRef, {
      offset,
      radius,
      tail
    });
    const collider = createVRMSpringBoneCollider(this._pcRef, shape);
    destination.addChild(collider);
    return collider;
  }
  _importJoint(node, child, setting, colliderGroupsForSpring) {
    const springBone = new VRMSpringBoneJoint(
      this._pcRef,
      node,
      child,
      setting,
      colliderGroupsForSpring
    );
    return springBone;
  }
};
_VRMSpringBoneLoaderPlugin.EXTENSION_NAME = "VRMC_springBone";
let VRMSpringBoneLoaderPlugin = _VRMSpringBoneLoaderPlugin;
const importScript$1 = (pcRef) => {
  class VrmSpringBone2 extends pcRef.ScriptType {
    constructor() {
      super(...arguments);
      this.activeSpringBone = true;
      this.isLimitedStrength = false;
      this.updateInterval = 1 / 90;
      this.timeSinceLastUpdate = 0;
    }
    initialize() {
      const springBoneLoader = new VRMSpringBoneLoaderPlugin(pcRef, this.asset, this.entity);
      this.springBoneManager = springBoneLoader.import();
      this.isLimitedStrength = false;
      this.entity.on("vrm-spring-bone:set-enabled ", this.setEnabled, this);
      this.entity.on("toggle-spring-bone", this.setEnabled, this);
      this.entity.on("vrm-spring-bone:set-strength-limit", this.setStrengthLimit, this);
      this.on("destroy", () => {
        this.entity.on("vrm-spring-bone:set-enabled ", this.setEnabled, this);
        this.entity.off("toggle-spring-bone", this.setEnabled, this);
        this.entity.off("vrm-spring-bone:set-strength-limit", this.setStrengthLimit, this);
      });
    }
    setEnabled(enabled) {
      this.activeSpringBone = enabled;
    }
    setStrengthLimit(limited) {
      this.isLimitedStrength = limited;
    }
    update(dt) {
      if (!this.springBoneManager || !this.activeSpringBone)
        return;
      this.timeSinceLastUpdate += dt;
      if (this.timeSinceLastUpdate < this.updateInterval)
        return;
      this.springBoneManager.update(dt, this.isLimitedStrength);
      this.timeSinceLastUpdate = 0;
    }
  }
  pcRef.registerScript(VrmSpringBone2, "vrmSpringBone");
  VrmSpringBone2.attributes.add("activeSpringBone", {
    type: "boolean",
    default: true
  });
  VrmSpringBone2.attributes.add("asset", {
    type: "asset",
    description: "Set the container asset loaded from vrm avatar."
  });
  VrmSpringBone2.attributes.add("updateInterval", {
    type: "number",
    default: 1 / 90
    // 90 FPS
  });
};
const VrmSpringBone = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  importScript: importScript$1
}, Symbol.toStringTag, { value: "Module" }));
const gammaEOTF = (e) => {
  return Math.pow(e, 2.2);
};
const updateTextureMatrix = (pcRef, mat3, textureTransform) => {
  if (!textureTransform)
    return;
  const offset = new pcRef.Vec2(0, 0);
  const repeat = new pcRef.Vec2(1, 1);
  const center = new pcRef.Vec2(0.5, 0.5);
  let rotation = 0;
  if (textureTransform.scale) {
    repeat.x = textureTransform.scale[0];
    repeat.y = textureTransform.scale[1];
  }
  if (textureTransform.offset) {
    offset.x = textureTransform.offset[0];
    offset.y = 1 - repeat.y - textureTransform.offset[1];
  }
  if (textureTransform.rotation) {
    rotation = textureTransform.rotation;
  }
  setUvTransform(mat3, offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y);
  return mat3;
};
const setUvTransform = (mat3, tx, ty, sx, sy, rotation, cx, cy) => {
  const c = Math.cos(rotation);
  const s = Math.sin(rotation);
  mat3.set([
    sx * c,
    sx * s,
    -sx * (c * cx + s * cy) + cx + tx,
    -sy * s,
    sy * c,
    -sy * (-s * cx + c * cy) + cy + ty,
    0,
    0,
    1
  ]);
};
class VRMMaterialsV0CompatPlugin {
  constructor(pcRef, asset) {
    this._pcRef = pcRef;
    this.asset = asset;
    this._renderQueueMapTransparent = /* @__PURE__ */ new Map();
    this._renderQueueMapTransparentZWrite = /* @__PURE__ */ new Map();
  }
  parseMaterials() {
    var _a, _b;
    const resource = this.asset.resource;
    const gltf = (_a = resource == null ? void 0 : resource.data) == null ? void 0 : _a.gltf;
    if (!gltf) {
      console.error("VRMMaterialsV0CompatPlugin: gltf data is undefined");
      return;
    }
    const v0VRMExtension = (_b = gltf == null ? void 0 : gltf.extensions) == null ? void 0 : _b["VRM"];
    const v0MaterialProperties = v0VRMExtension == null ? void 0 : v0VRMExtension.materialProperties;
    if (!v0MaterialProperties) {
      return;
    }
    this._populateRenderQueueMap(v0MaterialProperties);
    v0MaterialProperties.forEach((materialProperties, materialIndex) => {
      var _a2;
      if (!gltf.materials) {
        console.error("parseMaterials: gltf.materials is undefined");
        return;
      }
      const materialDef = gltf.materials[materialIndex];
      if (!materialDef) {
        console.warn(
          `VRMMaterialsV0CompatPlugin: Attempt to use materials[${materialIndex}] of glTF but the material doesn't exist`
        );
        return;
      }
      if (materialProperties.shader === "VRM/MToon") {
        const material = this._parseV0MToonProperties(materialProperties, materialDef);
        gltf.materials[materialIndex] = material;
      } else if ((_a2 = materialProperties.shader) == null ? void 0 : _a2.startsWith("VRM/Unlit"))
        ;
      else if (materialProperties.shader === "VRM_USE_GLTFSHADER")
        ;
      else {
        console.warn(`parseMaterials: Unknown shader: ${materialProperties.shader}`);
      }
    });
  }
  _parseV0MToonProperties(materialProperties, schemaMaterial) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H;
    if (schemaMaterial.v0Compat)
      return schemaMaterial;
    const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) ?? false;
    const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1;
    const transparentWithZWrite = enabledZWrite && isTransparent;
    const renderQueueOffsetNumber = this._v0ParseRenderQueue(materialProperties);
    const isCutoff = ((_c = materialProperties.keywordMap) == null ? void 0 : _c["_ALPHATEST_ON"]) ?? false;
    const alphaMode = isTransparent ? "BLEND" : isCutoff ? "MASK" : "OPAQUE";
    const alphaCutoff = isCutoff ? ((_d = materialProperties.floatProperties) == null ? void 0 : _d["_Cutoff"]) ?? 0.5 : void 0;
    const cullMode = ((_e = materialProperties.floatProperties) == null ? void 0 : _e["_CullMode"]) ?? 2;
    const doubleSided = cullMode === 0;
    const textureTransformExt = this._portTextureTransform(materialProperties);
    const baseColorFactor = (((_f = materialProperties.vectorProperties) == null ? void 0 : _f["_Color"]) ?? [1, 1, 1, 1]).map(
      (v, i) => i === 3 ? v : gammaEOTF(v)
      // alpha channel is stored in linear
    );
    const baseColorTextureIndex = (_g = materialProperties.textureProperties) == null ? void 0 : _g["_MainTex"];
    const baseColorTexture = baseColorTextureIndex != null ? {
      index: baseColorTextureIndex,
      extensions: {
        ...textureTransformExt
      }
    } : void 0;
    const normalTextureScale = ((_h = materialProperties.floatProperties) == null ? void 0 : _h["_BumpScale"]) ?? 1;
    const normalTextureIndex = (_i = materialProperties.textureProperties) == null ? void 0 : _i["_BumpMap"];
    const normalTexture = normalTextureIndex != null ? {
      index: normalTextureIndex,
      scale: normalTextureScale,
      extensions: {
        ...textureTransformExt
      }
    } : void 0;
    const emissiveFactor = (_k = (_j = materialProperties.vectorProperties) == null ? void 0 : _j["_EmissionColor"]) == null ? void 0 : _k.map(gammaEOTF);
    const emissiveTextureIndex = (_l = materialProperties.textureProperties) == null ? void 0 : _l["_EmissionMap"];
    const emissiveTexture = emissiveTextureIndex != null ? {
      index: emissiveTextureIndex,
      extensions: {
        ...textureTransformExt
      }
    } : void 0;
    const shadeColorFactor = (_n = (_m = materialProperties.vectorProperties) == null ? void 0 : _m["_ShadeColor"]) == null ? void 0 : _n.map(gammaEOTF);
    const shadeMultiplyTextureIndex = (_o = materialProperties.textureProperties) == null ? void 0 : _o["_ShadeTexture"];
    const shadeMultiplyTexture = shadeMultiplyTextureIndex != null ? {
      index: shadeMultiplyTextureIndex,
      extensions: {
        ...textureTransformExt
      }
    } : void 0;
    let shadingShiftFactor = ((_p = materialProperties.floatProperties) == null ? void 0 : _p["_ShadeShift"]) ?? 0;
    let shadingToonyFactor = ((_q = materialProperties.floatProperties) == null ? void 0 : _q["_ShadeToony"]) ?? 0.9;
    shadingToonyFactor = this._pcRef.math.lerp(
      shadingToonyFactor,
      1,
      0.5 + 0.5 * shadingShiftFactor
    );
    shadingShiftFactor = -shadingShiftFactor - (1 - shadingToonyFactor);
    const giIntensityFactor = ((_r = materialProperties.floatProperties) == null ? void 0 : _r["_IndirectLightIntensity"]) ?? 0.1;
    const giEqualizationFactor = giIntensityFactor ? 1 - giIntensityFactor : void 0;
    const matcapTextureIndex = (_s = materialProperties.textureProperties) == null ? void 0 : _s["_SphereAdd"];
    const matcapFactor = matcapTextureIndex != null ? [1, 1, 1] : void 0;
    const matcapTexture = matcapTextureIndex != null ? {
      index: matcapTextureIndex
    } : void 0;
    const rimLightingMixFactor = ((_t = materialProperties.floatProperties) == null ? void 0 : _t["_RimLightingMix"]) ?? 0;
    const rimMultiplyTextureIndex = (_u = materialProperties.textureProperties) == null ? void 0 : _u["_RimTexture"];
    const rimMultiplyTexture = rimMultiplyTextureIndex != null ? {
      index: rimMultiplyTextureIndex,
      extensions: {
        ...textureTransformExt
      }
    } : void 0;
    const parametricRimColorFactor = (((_v = materialProperties.vectorProperties) == null ? void 0 : _v["_RimColor"]) ?? [0, 0, 0, 1]).map(gammaEOTF);
    const parametricRimFresnelPowerFactor = ((_w = materialProperties.floatProperties) == null ? void 0 : _w["_RimFresnelPower"]) ?? 1;
    const parametricRimLiftFactor = ((_x = materialProperties.floatProperties) == null ? void 0 : _x["_RimLift"]) ?? 0;
    const outlineWidthMode = ["none", "worldCoordinates", "screenCoordinates"][((_y = materialProperties.floatProperties) == null ? void 0 : _y["_OutlineWidthMode"]) ?? 0];
    let outlineWidthFactor = ((_z = materialProperties.floatProperties) == null ? void 0 : _z["_OutlineWidth"]) ?? 0;
    outlineWidthFactor = 0.01 * outlineWidthFactor;
    const outlineWidthMultiplyTextureIndex = (_A = materialProperties.textureProperties) == null ? void 0 : _A["_OutlineWidthTexture"];
    const outlineWidthMultiplyTexture = outlineWidthMultiplyTextureIndex != null ? {
      index: outlineWidthMultiplyTextureIndex,
      extensions: {
        ...textureTransformExt
      }
    } : void 0;
    const outlineColorFactor = (((_B = materialProperties.vectorProperties) == null ? void 0 : _B["_OutlineColor"]) ?? [0, 0, 0]).map(gammaEOTF);
    const outlineColorMode = ((_C = materialProperties.floatProperties) == null ? void 0 : _C["_OutlineColorMode"]) ?? 0;
    const outlineLightingMixFactor = outlineColorMode === 1 ? ((_D = materialProperties.floatProperties) == null ? void 0 : _D["_OutlineLightingMix"]) ?? 1 : 0;
    const uvAnimationMaskTextureIndex = (_E = materialProperties.textureProperties) == null ? void 0 : _E["_UvAnimMaskTexture"];
    const uvAnimationMaskTexture = uvAnimationMaskTextureIndex != null ? {
      index: uvAnimationMaskTextureIndex,
      extensions: {
        ...textureTransformExt
      }
    } : void 0;
    const uvAnimationScrollXSpeedFactor = ((_F = materialProperties.floatProperties) == null ? void 0 : _F["_UvAnimScrollX"]) ?? 0;
    let uvAnimationScrollYSpeedFactor = ((_G = materialProperties.floatProperties) == null ? void 0 : _G["_UvAnimScrollY"]) ?? 0;
    if (uvAnimationScrollYSpeedFactor != null) {
      uvAnimationScrollYSpeedFactor = -uvAnimationScrollYSpeedFactor;
    }
    const uvAnimationRotationSpeedFactor = ((_H = materialProperties.floatProperties) == null ? void 0 : _H["_UvAnimRotation"]) ?? 0;
    const mtoonExtension = {
      specVersion: "1.0",
      transparentWithZWrite,
      renderQueueOffsetNumber,
      shadeColorFactor,
      shadeMultiplyTexture,
      shadingShiftFactor,
      shadingToonyFactor,
      giEqualizationFactor,
      matcapFactor,
      matcapTexture,
      rimLightingMixFactor,
      rimMultiplyTexture,
      parametricRimColorFactor,
      parametricRimFresnelPowerFactor,
      parametricRimLiftFactor,
      outlineWidthMode,
      outlineWidthFactor,
      outlineWidthMultiplyTexture,
      outlineColorFactor,
      outlineLightingMixFactor,
      uvAnimationMaskTexture,
      uvAnimationScrollXSpeedFactor,
      uvAnimationScrollYSpeedFactor,
      uvAnimationRotationSpeedFactor
    };
    schemaMaterial.v0Compat = true;
    return {
      ...schemaMaterial,
      pbrMetallicRoughness: {
        baseColorFactor,
        baseColorTexture
      },
      normalTexture,
      emissiveTexture,
      emissiveFactor,
      alphaMode,
      alphaCutoff,
      doubleSided,
      extensions: {
        VRMC_materials_mtoon: mtoonExtension
      }
    };
  }
  _portTextureTransform(materialProperties) {
    var _a;
    const textureTransform = (_a = materialProperties.vectorProperties) == null ? void 0 : _a["_MainTex"];
    if (textureTransform == null) {
      return {};
    }
    const offset = [(textureTransform == null ? void 0 : textureTransform[0]) ?? 0, (textureTransform == null ? void 0 : textureTransform[1]) ?? 0];
    const scale = [(textureTransform == null ? void 0 : textureTransform[2]) ?? 1, (textureTransform == null ? void 0 : textureTransform[3]) ?? 1];
    offset[1] = 1 - scale[1] - offset[1];
    return {
      // eslint-disable-next-line @typescript-eslint/naming-convention
      KHR_texture_transform: { offset, scale }
    };
  }
  /**
   * Convert v0 render order into v1 render order.
   * This uses a map from v0 render queue to v1 compliant render queue offset which is generated in {@link _populateRenderQueueMap}.
   */
  _v0ParseRenderQueue(materialProperties) {
    var _a, _b;
    const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) ?? false;
    const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1;
    let offset = 0;
    if (isTransparent) {
      const v0Queue = materialProperties.renderQueue;
      if (v0Queue != null) {
        if (enabledZWrite) {
          offset = this._renderQueueMapTransparentZWrite.get(v0Queue);
        } else {
          offset = this._renderQueueMapTransparent.get(v0Queue);
        }
      }
    }
    return offset;
  }
  /**
   * Create a map which maps v0 render queue to v1 compliant render queue offset.
   * This lists up all render queues the model use and creates a map to new render queue offsets in the same order.
   */
  _populateRenderQueueMap(materialPropertiesList) {
    const renderQueuesTransparent = /* @__PURE__ */ new Set();
    const renderQueuesTransparentZWrite = /* @__PURE__ */ new Set();
    materialPropertiesList.forEach((materialProperties) => {
      var _a, _b;
      const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) ?? false;
      const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1;
      if (isTransparent) {
        const v0Queue = materialProperties.renderQueue;
        if (v0Queue != null) {
          if (enabledZWrite) {
            renderQueuesTransparentZWrite.add(v0Queue);
          } else {
            renderQueuesTransparent.add(v0Queue);
          }
        }
      }
    });
    if (renderQueuesTransparent.size > 10) {
      console.warn(
        `VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparent.size} render queues for Transparent materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
      );
    }
    if (renderQueuesTransparentZWrite.size > 10) {
      console.warn(
        `VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparentZWrite.size} render queues for TransparentZWrite materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
      );
    }
    Array.from(renderQueuesTransparent).sort().forEach((queue, i) => {
      const newQueueOffset = Math.min(Math.max(i - renderQueuesTransparent.size + 1, -9), 0);
      this._renderQueueMapTransparent.set(queue, newQueueOffset);
    });
    Array.from(renderQueuesTransparentZWrite).sort().forEach((queue, i) => {
      const newQueueOffset = Math.min(Math.max(i, 0), 9);
      this._renderQueueMapTransparentZWrite.set(queue, newQueueOffset);
    });
  }
}
const EXTENSION_VRMC_MATERIALS_MTOON = "VRMC_materials_mtoon";
const MToonMaterialOutlineWidthMode = {
  None: "none",
  WorldCoordinates: "worldCoordinates",
  ScreenCoordinates: "screenCoordinates"
};
const litUserDeclarationVS = (
  /* glsl */
  `
#ifdef FORWARD_PASS
  varying vec3 vViewPosition;
  varying vec3 vViewDirection;
  varying vec3 vNormal;

  // engine supplied uniforms
  uniform vec3 view_position;

  #ifdef OUTLINE
    uniform float outlineWidthFactor;

    #ifdef USE_OUTLINEWIDTHMULTIPLYTEXTURE
      uniform sampler2D outlineWidthMultiplyTexture;
      uniform mat3 outlineWidthMultiplyTextureUvTransform;
    #endif
  #endif

#endif
`
);
const litUserMainEndVS = (
  /* glsl */
  `
#ifdef FORWARD_PASS
    vec4 worldPosition = vec4(vPositionW, 1.0);
    vViewDirection = normalize(view_position - worldPosition.xyz);
    vViewPosition = -worldPosition.xyz;

    vec3 objectNormal = vec3(0.0, 0.0, 1.0);
    vec3 transformedNormal = vec3(0.0, 0.0, 1.0);

    #ifdef NORMALS
        objectNormal = vertex_normal;
        objectNormal = normalize( objectNormal );
        transformedNormal = vNormalW;
    #endif

    vNormal = transformedNormal;

    #ifdef OUTLINE
        float outlineTex = 1.0;
        
        #ifdef USE_OUTLINEWIDTHMULTIPLYTEXTURE
            #ifdef UV0
                vec2 outlineWidthMultiplyTextureUv = ( outlineWidthMultiplyTextureUvTransform * vec3( vUv0, 1 ) ).xy;
                outlineTex = texture2D( outlineWidthMultiplyTexture, outlineWidthMultiplyTextureUv ).g;
            #endif
        #endif

        #ifdef OUTLINE_WIDTH_WORLD
            float worldNormalLength = length( transformedNormal );
            vec3 outlineOffset = outlineWidthFactor * outlineTex * worldNormalLength * objectNormal;
            vec3 localPos = getLocalPosition(vertex_position.xyz);

            // From playcanvas transform.js vertex shader
            #ifdef MORPHING
            #ifdef MORPHING_POS03
            localPos.xyz += morph_weights_a[0] * morph_pos0;
            localPos.xyz += morph_weights_a[1] * morph_pos1;
            localPos.xyz += morph_weights_a[2] * morph_pos2;
            localPos.xyz += morph_weights_a[3] * morph_pos3;
            #endif // MORPHING_POS03
            #ifdef MORPHING_POS47
            localPos.xyz += morph_weights_b[0] * morph_pos4;
            localPos.xyz += morph_weights_b[1] * morph_pos5;
            localPos.xyz += morph_weights_b[2] * morph_pos6;
            localPos.xyz += morph_weights_b[3] * morph_pos7;
            #endif // MORPHING_POS47
            #endif // MORPHING

            #ifdef MORPHING_TEXTURE_BASED_POSITION
                vec2 morphUV = getTextureMorphCoords();
                    vec3 morphPos = texture2D(morphPositionTex, morphUV).xyz;
                localPos += morphPos;
            #endif

            gl_Position = matrix_viewProjection * getModelMatrix() * vec4( localPos + outlineOffset, 1.0 );
        #endif

        #ifdef OUTLINE_WIDTH_SCREEN
            // TODO: Wait until an avatar containing this information is found before proceeding with the implementation.
        #endif

        gl_Position.z += 1E-6 * gl_Position.w; // anti-artifact magic
    #endif
#endif
`
);
const litUserDeclarationPS = (
  /* glsl */
  `
#ifdef FORWARD_PASS
    #define RECIPROCAL_PI 0.3183098861837907

    uniform vec3 shadeColorFactor;
    uniform vec3 ambientLightColor;

    varying vec3 vNormal;
    varying vec3 vViewDirection;

    #ifdef USE_SHADEMULTIPLYTEXTURE
        uniform sampler2D shadeMultiplyTexture;
        uniform mat3 shadeMultiplyTextureUvTransform;
    #endif

    uniform float shadingShiftFactor;
    uniform float shadingToonyFactor;

    #ifdef USE_SHADINGSHIFTTEXTURE
        uniform sampler2D shadingShiftTexture;
        uniform mat3 shadingShiftTextureUvTransform;
        uniform float shadingShiftTextureScale;
    #endif

    uniform float giEqualizationFactor;
    uniform vec3 parametricRimColorFactor;
    #ifdef USE_RIMMULTIPLYTEXTURE
        uniform sampler2D rimMultiplyTexture;
        uniform mat3 rimMultiplyTextureUvTransform;
    #endif

    uniform float rimLightingMixFactor;
    uniform float parametricRimFresnelPowerFactor;
    uniform float parametricRimLiftFactor;

    #ifdef USE_MATCAPTEXTURE
        uniform vec3 matcapFactor;
        uniform sampler2D matcapTexture;
        uniform mat3 matcapTextureUvTransform;
    #endif

    uniform vec3 emissive;
    uniform float emissiveIntensity;

    uniform vec3 outlineColorFactor;
    uniform float outlineLightingMixFactor;


    uniform mat3 mapUvTransform;
    uniform mat3 emissiveMapUvTransform;

    varying vec3 vViewPosition;

    struct MToonMaterial {
        vec3 diffuseColor;
        vec3 shadeColor;
        float shadingShift;
    };

    struct GeometricContext {
	    vec3 position;
	    vec3 normal;
	    vec3 viewDir;
    };
    
    float linearstep( float a, float b, float t ) {
        return clamp( ( t - a ) / ( b - a ), 0.0, 1.0 );
    }

    vec3 BRDF_Lambert( const in vec3 diffuseColor ) {
        return RECIPROCAL_PI * diffuseColor;
    }

    /**
    * Convert NdotL into toon shading factor using shadingShift and shadingToony
    */
    float getShading(
        const in float dotNL,
        const in float shadow,
        const in float shadingShift
    ) {
        float shading = dotNL;
        shading = shading + shadingShift;
        shading = linearstep( -1.0 + shadingToonyFactor, 1.0 - shadingToonyFactor, shading );
        shading *= shadow;
        return shading;
    }

    vec3 getDiffuse(
        const in MToonMaterial material,
        const in float shading,
            in vec3 lightColor
    ) {
        vec3 col = lightColor * BRDF_Lambert( mix( material.shadeColor, material.diffuseColor, shading ) );
        
        // The "comment out if you want to PBR absolutely" line
        #ifdef V0_COMPAT_SHADE
            col = min( col, material.diffuseColor );
        #endif
        
        return col;
    }


    #ifdef USE_NORMALMAP
        uniform sampler2D normalMap;
        uniform mat3 normalMapUvTransform;
        uniform vec2 normalScale;
    #endif

    uniform mat3 normalMatrix;


    mat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {

        vec3 q0 = dFdx( eye_pos.xyz );
        vec3 q1 = dFdy( eye_pos.xyz );
        vec2 st0 = dFdx( uv.st );
        vec2 st1 = dFdy( uv.st );

        vec3 N = surf_norm;

        vec3 q1perp = cross( q1, N );
        vec3 q0perp = cross( N, q0 );

        vec3 T = q1perp * st0.x + q0perp * st1.x;
        vec3 B = q1perp * st0.y + q0perp * st1.y;

        float det = max( dot( T, T ), dot( B, B ) );
        float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );

        return mat3( T * scale, B * scale, N );
    }


    struct ReflectedLight {
	    vec3 directDiffuse;
	    vec3 directSpecular;
	    vec3 indirectDiffuse;
	    vec3 indirectSpecular;
    };

    struct IncidentLight {
	    vec3 color;
	    vec3 direction;
	    bool visible;
    };


    void RE_Direct_MToon( const in IncidentLight directLight, const in GeometricContext geometry, const in MToonMaterial material, const in float shadow, inout ReflectedLight reflectedLight ) {
        float dotNL = clamp( dot( geometry.normal, directLight.direction ), -1.0, 1.0 );
        vec3 irradiance = directLight.color;

        // directSpecular will be used for rim lighting, not an actual specular
        reflectedLight.directSpecular += irradiance;

        irradiance *= dotNL;

        float shading = getShading( dotNL, shadow, material.shadingShift );

        // toon shaded diffuse
        reflectedLight.directDiffuse += getDiffuse( material, shading, directLight.color );
    }

    void RE_IndirectDiffuse_MToon( const in vec3 irradiance, const in GeometricContext geometry, const in MToonMaterial material, inout ReflectedLight reflectedLight ) {
        // indirect diffuse will use diffuseColor, no shadeColor involved
        reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );

        // directSpecular will be used for rim lighting, not an actual specular
        reflectedLight.directSpecular += irradiance;
    }

    #define RE_Direct RE_Direct_MToon
    #define RE_IndirectDiffuse RE_IndirectDiffuse_MToon

    vec3 perturbNormal2Arb( vec2 uv, vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {
        vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );
        vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );
        vec2 st0 = dFdx( uv.st );
        vec2 st1 = dFdy( uv.st );

        vec3 N = normalize( surf_norm );

        vec3 q1perp = cross( q1, N );
        vec3 q0perp = cross( N, q0 );

        vec3 T = q1perp * st0.x + q0perp * st1.x;
        vec3 B = q1perp * st0.y + q0perp * st1.y;

        // From three-vrm specific change: Workaround for the issue that happens when delta of uv = 0.0
        // TODO: Is this still required? Or shall I make a PR about it?
        if ( length( T ) == 0.0 || length( B ) == 0.0 ) {
          return surf_norm;
        }

        float det = max( dot( T, T ), dot( B, B ) );
        float scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );

        return normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );
    }
#endif


#ifdef USE_UVANIMATIONMASKTEXTURE
    uniform sampler2D uvAnimationMaskTexture;
    uniform mat3 uvAnimationMaskTextureUvTransform;
#endif

uniform float uvAnimationScrollXOffset;
uniform float uvAnimationScrollYOffset;
uniform float uvAnimationRotationPhase;

// Apply UV Animation to a given UV coordinate
vec2 applyUvAnimation(vec2 uv) {
    #ifdef USE_UVANIMATIONMASKTEXTURE
        vec2 uvAnimationMaskTextureUv = ( uvAnimationMaskTextureUvTransform * vec3( uv, 1 ) ).xy;
        float uvAnimMask = texture2D( uvAnimationMaskTexture, uvAnimationMaskTextureUv ).b;
    #else
        float uvAnimMask = 1.0;
    #endif

    float uvRotCos = cos( uvAnimationRotationPhase * uvAnimMask );
    float uvRotSin = sin( uvAnimationRotationPhase * uvAnimMask );
    uv = mat2( uvRotCos, -uvRotSin, uvRotSin, uvRotCos ) * ( uv - 0.5 ) + 0.5;
    uv = uv + vec2( uvAnimationScrollXOffset, uvAnimationScrollYOffset ) * uvAnimMask;
    
    return uv;
}
`
);
const lightPS = (
  /* glsl */
  `
#ifdef FORWARD_PASS
    float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {
	    return smoothstep( coneCosine, penumbraCosine, angleCosine );
    }

    float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
		// based upon Frostbite 3 Moving to Physically-based Rendering
		// page 32, equation 26: E[window1]
		// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
		float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );

		if ( cutoffDistance > 0.0 ) {
            distanceFalloff *= pow( saturate( 1.0 - pow( lightDistance / cutoffDistance, 4.0 ) ), 2.0 );
		};

		return distanceFalloff;
    }

	vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
        vec3 irradiance = ambientLightColor;
		return irradiance;
	}
	vec3 getIBLIrradiance( const in vec3 envMapColor ) {
        return envMapColor.rgb;
	}

    // Point Lights
    #ifdef USE_POINT_LIGHTS
    #ifndef NUM_POINT_LIGHTS
    #define NUM_POINT_LIGHTS 0
    #endif
    struct PointLight {
        vec3 position;
        vec3 color;
        float distance;
        float decay;
    };
    #if NUM_POINT_LIGHTS > 0
    uniform PointLight pointLights[NUM_POINT_LIGHTS];
    #endif

    void getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {
        vec3 lVector = pointLight.position - geometry.position;
        light.direction = normalize( lVector );
        float lightDistance = length( lVector );
        light.color = pointLight.color;
        light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );

        light.visible = ( light.color != vec3( 0.0 ) );
    }
    #endif

    // Spot Lights
    #ifdef USE_SPOT_LIGHTS
    #ifndef NUM_SPOT_LIGHTS
    #define NUM_SPOT_LIGHTS 0
    #endif
    struct SpotLight {
        vec3 position;
        vec3 direction;
        vec3 color;
        float distance;
        float decay;
        float coneCos;
        float penumbraCos;
    };
    #if NUM_SPOT_LIGHTS > 0
    uniform SpotLight spotLights[NUM_SPOT_LIGHTS];
    #endif

    void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {
        vec3 lVector = spotLight.position - geometry.position;
        light.direction = normalize( lVector );
        float angleCos = dot( light.direction, spotLight.direction );
        float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );

        if ( spotAttenuation > 0.0 ) {
            float lightDistance = length( lVector );
            light.color = spotLight.color * spotAttenuation;
            light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );

            light.visible = ( light.color != vec3( 0.0 ) );
        } else {
            light.color = vec3( 0.0 );
            light.visible = false;
        }
    }
    #endif

    // Directional Lights
    #ifdef USE_DIR_LIGHTS
    #ifndef NUM_DIR_LIGHTS
    #define NUM_DIR_LIGHTS 0
    #endif
    struct DirectionalLight {
        vec3 direction;
        vec3 color;
    };
    #if NUM_DIR_LIGHTS > 0
        uniform DirectionalLight directionalLights[NUM_DIR_LIGHTS];
    #endif

    void getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {
        light.color = directionalLight.color;

        light.direction = directionalLight.direction;
        light.visible = true;
    }
    #endif
    
#endif
`
);
const litUserMainEndPS = (
  /* glsl */
  `
#ifdef FORWARD_PASS

    vec2 uv = vec2(0.5, 0.5);
    #ifdef VARYING_VUV0
        uv = vUv0;
        uv = applyUvAnimation(uv);
    #endif

    float finalOpacity = gl_FragColor.a; // result from "outputAlphaPS"
    vec4 diffuseColor = vec4( material_diffuse, finalOpacity );
    #if LIT_BLEND_TYPE == PREMULTIPLIED
        diffuseColor.rgb *= litArgs_opacity; // get premultiplied rgb
    #endif

    #ifdef STD_DIFFUSE_TEXTURE
        vec2 colorMapUv = ( mapUvTransform * vec3( uv, 1 ) ).xy;
        vec3 albedoTexture = {STD_DIFFUSE_TEXTURE_DECODE}(texture2DBias({STD_DIFFUSE_TEXTURE_NAME}, colorMapUv, textureBias)).{STD_DIFFUSE_TEXTURE_CHANNEL};
        diffuseColor.rgb *= albedoTexture;
    #endif

    float faceDirection = gl_FrontFacing ? 1.0 : -1.0;
    vec3 normal = normalize( vNormal );
    normal *= faceDirection;

    #ifdef OUTLINE
        normal *= -1.0;
    #endif

    #ifdef USE_NORMALMAP
        vec2 normalMapUv = ( normalMapUvTransform * vec3( uv, 1 ) ).xy;

        #ifdef SHADERDEF_TANGENTS
            mat3 tbn = mat3( normalize( vTangentW ), normalize( vBinormalW ), normal );
        #else
            mat3 tbn = getTangentFrame( - vViewPosition, normal, normalMapUv );
        #endif

        vec3 mapN = texture2D( normalMap, normalMapUv ).xyz * 2.0 - 1.0;
        mapN.xy *= normalScale;

        #if defined(SHADERDEF_TANGENTS)
            normal = normalize( tbn * mapN );
        #else
            normal = perturbNormal2Arb( uv, -vViewPosition, normal, mapN, faceDirection );
        #endif
    #endif

    vec3 totalEmissiveRadiance = material_emissive * material_emissiveIntensity;
    #ifdef STD_EMISSIVE_TEXTURE
        vec2 emissiveMapUv = (emissiveMapUvTransform * vec3( uv, 1 )).xy;
        vec3 emissiveTexture = {STD_EMISSIVE_TEXTURE_DECODE}(texture2DBias({STD_EMISSIVE_TEXTURE_NAME}, emissiveMapUv, textureBias)).{STD_EMISSIVE_TEXTURE_CHANNEL};
        totalEmissiveRadiance *= emissiveTexture;
    #endif


    // -- MToon: lighting --------------------------------------------------------
    MToonMaterial material;
    material.diffuseColor = diffuseColor.rgb;
    material.shadeColor = shadeColorFactor;

    #ifdef USE_SHADEMULTIPLYTEXTURE
        vec2 shadeMultiplyTextureUv = ( shadeMultiplyTextureUvTransform * vec3( uv, 1 ) ).xy;
        vec3 shadeMultiply = texture2D( shadeMultiplyTexture, shadeMultiplyTextureUv ).rgb;
        shadeMultiply = decodeGamma(shadeMultiply); // convert to linear
        material.shadeColor *= shadeMultiply;
    #endif

    material.shadingShift = shadingShiftFactor;
    #ifdef USE_SHADINGSHIFTTEXTURE
        vec2 shadingShiftTextureUv = ( shadingShiftTextureUvTransform * vec3( uv, 1 ) ).xy;
        material.shadingShift += texture2D( shadingShiftTexture, shadingShiftTextureUv ).r * shadingShiftTextureScale;
    #endif    


    GeometricContext geometry;
    geometry.position = - vViewPosition;
    geometry.normal = normal;
    geometry.viewDir = normalize( vViewPosition );

    ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
    IncidentLight directLight;
    // since these variables will be used in unrolled loop, we have to define in prior
    float shadow = 1.0;

    // Point Lights - loop controlled by define
    #ifdef USE_POINT_LIGHTS
    #if NUM_POINT_LIGHTS > 0
    {
        PointLight pointLight;
        for ( int i = 0; i < NUM_POINT_LIGHTS; i++ ) {
            pointLight = pointLights[i];
            getPointLightInfo( pointLight, geometry, directLight );
            RE_Direct( directLight, geometry, material, shadow, reflectedLight );
        }
    }
    #endif
    #endif

    // Spot Lights - loop controlled by define
    #ifdef USE_SPOT_LIGHTS
    #if NUM_SPOT_LIGHTS > 0
    {
        SpotLight spotLight;
        for ( int i = 0; i < NUM_SPOT_LIGHTS; i++ ) {
            spotLight = spotLights[i];
            getSpotLightInfo( spotLight, geometry, directLight );
            RE_Direct( directLight, geometry, material, shadow, reflectedLight );
        }
    }
    #endif
    #endif

    // Directional Lights - loop controlled by define
    #ifdef USE_DIR_LIGHTS
    #if NUM_DIR_LIGHTS > 0
    {
        DirectionalLight directionalLight;
        for ( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {
            directionalLight = directionalLights[i];
            getDirectionalLightInfo( directionalLight, directLight );  
            RE_Direct( directLight, geometry, material, shadow, reflectedLight );
        }
    }
    #endif
    #endif 

    // -- MToon: Ambient --------------------------------------------------------
    vec3 iblIrradiance = vec3( 0.0 );
    vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );


    // From three.js #include <lights_fragment_maps>
    // -- MToon: Environment --------------------------------------------------------
	#ifdef USE_ENV_LIGHTS
		vec3 dir = normalize(cubeMapRotate(vNormal) * vec3(-1.0, 1.0, 1.0));
        vec2 envuv = mapUv(toSphericalUv(dir), vec4(128.0, 256.0 + 128.0, 64.0, 32.0) / atlasSize);
        vec4 raw = texture2D(texture_envAtlas, envuv);
        vec3 linear = decodeLinear(raw);
        irradiance += getIBLIrradiance(linear);
	#endif


    // From three.js #include <lights_fragment_end>
    RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );

    float directDiffuseIntensity = 2.5; // Boost the effect of direct light
    reflectedLight.directDiffuse *= directDiffuseIntensity;
    vec3 col = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;
    col = min( col, material.diffuseColor * 1.2 ); // Slightly boost the cap to allow brighter lighting

 
    // -- MToon: rim lighting -----------------------------------------
    vec3 viewDir = normalize( vViewDirection );

    vec3 rimMix = mix( vec3( 1.0 ), reflectedLight.directSpecular, rimLightingMixFactor );
    vec3 rim = parametricRimColorFactor * pow( saturate( 1.0 - dot( viewDir, normal ) + parametricRimLiftFactor ), parametricRimFresnelPowerFactor );

    #ifdef USE_MATCAPTEXTURE
        {
          vec3 x = normalize( vec3( viewDir.z, 0.0, -viewDir.x ) );
          vec3 y = cross( viewDir, x ); // guaranteed to be normalized
          vec2 sphereUv = vec2(dot(x, normal), dot(y, normal)) * 0.5 + 0.5;
          sphereUv = ( matcapTextureUvTransform * vec3( sphereUv, 1 ) ).xy;
          vec3 matcap = texture2D( matcapTexture, sphereUv ).rgb;
          matcap = decodeGamma(matcap); // convert to linear
          rim += matcapFactor * matcap;
        }
    #endif


    #ifdef USE_RIMMULTIPLYTEXTURE
        vec2 rimMultiplyTextureUv = ( rimMultiplyTextureUvTransform * vec3( uv, 1 ) ).xy;
        vec3 rimMultiply = texture2D( rimMultiplyTexture, rimMultiplyTextureUv ).rgb;
        rimMultiply = decodeGamma(rimMultiply); // convert to linear
        rim *= rimMultiply;
    #endif


    col += rimMix * rim;

    // -- MToon: Emission --------------------------------------------------------
    col += totalEmissiveRadiance;

    // -- MToon: Outline --------------------------------------------------------
    #ifdef OUTLINE
        col = outlineColorFactor.rgb * mix( vec3( 1.0 ), col, outlineLightingMixFactor );
    #endif

    gl_FragColor = vec4( col, diffuseColor.a );
    gl_FragColor.rgb = addFog(gl_FragColor.rgb);
    gl_FragColor.rgb = toneMap(gl_FragColor.rgb);
    gl_FragColor.rgb = gammaCorrectOutput(gl_FragColor.rgb);
#endif
`
);
const opacityPS = (
  /* glsl */
  `
uniform float material_opacity;

void getOpacity() {
    dAlpha = material_opacity;

    #ifdef STD_OPACITY_TEXTURE
    vec2 opacityUv = {STD_OPACITY_TEXTURE_UV};
    opacityUv = applyUvAnimation(opacityUv);

    dAlpha *= texture2DBias({STD_OPACITY_TEXTURE_NAME}, opacityUv, textureBias).{STD_OPACITY_TEXTURE_CHANNEL};
    #endif

    #ifdef STD_OPACITY_VERTEX
    dAlpha *= clamp(vVertexColor.{STD_OPACITY_VERTEX_CHANNEL}, 0.0, 1.0);
    #endif
}
`
);
const litUserCodePS = `${lightPS}`;
const shaderChunksMtoon = {
  litUserDeclarationVS,
  litUserMainEndVS,
  litUserDeclarationPS,
  litUserCodePS,
  litUserMainEndPS,
  opacityPS
};
class RenderStates {
  constructor(pcRef) {
    this._pcRef = pcRef;
    this._app = null;
    this.lightStateInfo = null;
    this.defaultInfoSetting = {
      directionalLight: {
        direction: new pcRef.Vec3(0, 0, 0),
        color: new pcRef.Color(0, 0, 0)
      },
      spotLight: {
        position: new pcRef.Vec3(0, 0, 0),
        direction: new pcRef.Vec3(0, 0, 0),
        color: new pcRef.Color(0, 0, 0),
        distance: 0,
        decay: 0,
        coneCos: 0,
        penumbraCos: 0
      },
      pointLight: {
        position: new pcRef.Vec3(0, 0, 0),
        color: new pcRef.Color(0, 0, 0),
        distance: 0,
        decay: 0
      }
    };
  }
  _updateLightInfo(lights) {
    this.lightStateInfo = this.convertLightStateInfo(lights);
  }
  setApp(app) {
    if (this._app)
      return;
    this._app = app;
  }
  convertLightStateInfo(lights) {
    const directionalLights = lights[this._pcRef.LIGHTTYPE_DIRECTIONAL];
    const spotLights = lights[this._pcRef.LIGHTTYPE_SPOT];
    const pointLights = lights[this._pcRef.LIGHTTYPE_POINT];
    const info = {
      directionalLights: [],
      spotLights: [],
      pointLights: [],
      ...this._app && {
        scene: {
          envAtlas: this._app.scene.envAtlas || null,
          ambientLight: this._app.scene.ambientLight
        }
      }
    };
    info.directionalLights = directionalLights.map((light) => {
      if (light._node === null) {
        return this.defaultInfoSetting.directionalLight;
      }
      const component = light._node.light;
      const color = new this._pcRef.Color(
        component.color.r * component.intensity,
        component.color.g * component.intensity,
        component.color.b * component.intensity
      );
      return {
        direction: light._direction,
        color
      };
    });
    info.spotLights = spotLights.map((light) => {
      if (light._node === null) {
        return this.defaultInfoSetting.spotLight;
      }
      const component = light._node.light;
      const color = new this._pcRef.Color(
        component.color.r * component.intensity,
        component.color.g * component.intensity,
        component.color.b * component.intensity
      );
      return {
        position: light._node.getPosition(),
        direction: light._node.forward,
        color,
        distance: component.range,
        decay: light.falloffMode === this._pcRef.LIGHTFALLOFF_LINEAR ? 1 : 2,
        coneCos: Math.cos(component.innerConeAngle),
        penumbraCos: Math.cos(component.outerConeAngle)
      };
    });
    info.pointLights = pointLights.map((light) => {
      if (light._node === null) {
        return this.defaultInfoSetting.pointLight;
      }
      const component = light._node.light;
      const color = new this._pcRef.Color(
        component.color.r * component.intensity,
        component.color.g * component.intensity,
        component.color.b * component.intensity
      );
      return {
        position: light._node.getPosition(),
        color,
        distance: component.range,
        decay: light.falloffMode === this._pcRef.LIGHTFALLOFF_LINEAR ? 1 : 2
      };
    });
    return info;
  }
  update() {
    if (!this._app)
      return;
    const worldLayer = this._app.scene.layers.getLayerById(this._pcRef.LAYERID_WORLD);
    if (worldLayer) {
      const lights = worldLayer.splitLights;
      this._updateLightInfo(lights);
    }
  }
}
class MaterialPreprocessor {
  /**
   * Applies preprocessed material settings to the given PlayCanvas material.
   * Reference: playcanvas glb-parser.js implementation
   *
   * Note: Playcanvas dose not have beforeRoot timing to remove this extension like three.js,
   * only way is to restore here as a workaround.
   */
  static applyToMaterial(pcMaterial, gltfMaterial, gltf, pcRef) {
    var _a, _b;
    const hasUnlitExtension = ((_a = gltfMaterial == null ? void 0 : gltfMaterial.extensions) == null ? void 0 : _a.KHR_materials_unlit) !== void 0 || ((_b = gltf.extensionsUsed) == null ? void 0 : _b.includes("KHR_materials_unlit"));
    if (hasUnlitExtension) {
      pcMaterial.diffuseMap = pcMaterial.emissiveMap;
      pcMaterial.diffuseMapUv = pcMaterial.emissiveMapUv;
      pcMaterial.diffuseMapTiling.copy(pcMaterial.emissiveMapTiling);
      pcMaterial.diffuseMapOffset.copy(pcMaterial.emissiveMapOffset);
      pcMaterial.diffuseMapRotation = pcMaterial.emissiveMapRotation;
      pcMaterial.diffuseMapChannel = pcMaterial.emissiveMapChannel;
      pcMaterial.diffuse.copy(pcMaterial.emissive);
      if (gltfMaterial.hasOwnProperty("pbrMetallicRoughness")) {
        const pbrData = gltfMaterial.pbrMetallicRoughness;
        if (pbrData && pbrData.hasOwnProperty("baseColorFactor")) {
          const [r, g, b, a] = pbrData.baseColorFactor;
          pcMaterial.diffuse.set(r, g, b).gamma();
          pcMaterial.opacity = a;
        }
      }
      if (gltfMaterial.hasOwnProperty("emissiveFactor")) {
        const [r, g, b] = gltfMaterial.emissiveFactor.map((v) => Math.max(1e-4, v));
        pcMaterial.emissive.set(r, g, b).gamma();
      }
    }
    if (gltfMaterial.hasOwnProperty("alphaMode")) {
      switch (gltfMaterial.alphaMode) {
        case "MASK":
          pcMaterial.blendType = pcRef.BLEND_NONE;
          if (gltfMaterial.hasOwnProperty("alphaCutoff")) {
            pcMaterial.alphaTest = gltfMaterial.alphaCutoff;
          } else {
            pcMaterial.alphaTest = 0.5;
          }
          break;
        case "BLEND":
          pcMaterial.blendType = pcRef.BLEND_NORMAL;
          pcMaterial.depthWrite = false;
          break;
        default:
        case "OPAQUE":
          pcMaterial.blendType = pcRef.BLEND_NONE;
          break;
      }
    } else {
      pcMaterial.blendType = pcRef.BLEND_NONE;
    }
    if (gltfMaterial.hasOwnProperty("doubleSided") && gltfMaterial.doubleSided !== void 0) {
      pcMaterial.twoSidedLighting = gltfMaterial.doubleSided;
      pcMaterial.cull = gltfMaterial.doubleSided ? pcRef.CULLFACE_NONE : pcRef.CULLFACE_BACK;
    } else {
      pcMaterial.twoSidedLighting = false;
      pcMaterial.cull = pcRef.CULLFACE_BACK;
    }
  }
}
const textureTransformExtensionName = "KHR_texture_transform";
function createVRMCMtoonMaterial(options) {
  const { pcApp, pcRef, asset, isOutline = false } = options;
  const material = new pcRef.StandardMaterial();
  material.isMtoonMaterial = true;
  material.isOutline = isOutline;
  material.mapUvTransform = new pcRef.Mat3();
  material.normalMapUvTransform = new pcRef.Mat3();
  material.normalScale = new pcRef.Vec2(1, 1);
  material.emissiveMapUvTransform = new pcRef.Mat3();
  material.shadeColorFactor = new pcRef.Color(0, 0, 0, 1);
  material.shadeMultiplyTexture = null;
  material.shadeMultiplyTextureUvTransform = new pcRef.Mat3();
  material.shadingShiftFactor = 0;
  material.shadingShiftTexture = null;
  material.shadingShiftTextureUvTransform = new pcRef.Mat3();
  material.shadingShiftTextureScale = 1;
  material.shadingToonyFactor = 0.9;
  material.giEqualizationFactor = 0;
  material.matcapFactor = new pcRef.Color(1, 1, 1, 1);
  material.matcapTexture = null;
  material.matcapTextureUvTransform = new pcRef.Mat3();
  material.parametricRimColorFactor = new pcRef.Color(0, 0, 0, 1);
  material.rimMultiplyTexture = null;
  material.rimMultiplyTextureUvTransform = new pcRef.Mat3();
  material.rimLightingMixFactor = 0;
  material.parametricRimFresnelPowerFactor = 5;
  material.parametricRimLiftFactor = 0;
  material.uvAnimationMaskTexture = null;
  material.uvAnimationMaskTextureUvTransform = new pcRef.Mat3();
  material.uvAnimationScrollXOffset = 0;
  material.uvAnimationScrollYOffset = 0;
  material.uvAnimationRotationPhase = 0;
  material.uvAnimationScrollXSpeed = 0;
  material.uvAnimationScrollYSpeed = 0;
  material.uvAnimationRotationSpeed = 0;
  material.v0CompatShade = false;
  material.outlineWidthMode = MToonMaterialOutlineWidthMode.None;
  material.outlineWidthMultiplyTexture = null;
  material.outlineWidthMultiplyTextureUvTransform = new pcRef.Mat3();
  material.outlineWidthFactor = 0.02;
  material.outlineColorFactor = new pcRef.Color(1, 0.5, 0, 1);
  material.outlineLightingMixFactor = 0;
  material._asset = asset;
  material._vec3A = new pcRef.Vec3();
  material._currentDirLights = 0;
  material._currentSpotLights = 0;
  material._currentPointLights = 0;
  material._pcApp = pcApp;
  material._renderStates = new RenderStates(pcRef);
  material.parse = function() {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
    const { gltfMaterial, gltf, sourceMaterial, isOutline: isOutline2 } = options;
    material.copy(sourceMaterial);
    if (isOutline2) {
      this.name = sourceMaterial.name + "_outline";
    }
    MaterialPreprocessor.applyToMaterial(this, gltfMaterial, gltf, pcRef);
    const extension = (_a = gltfMaterial == null ? void 0 : gltfMaterial.extensions) == null ? void 0 : _a[EXTENSION_VRMC_MATERIALS_MTOON];
    const {
      shadeColorFactor,
      shadeMultiplyTexture: shadeMultiplyTextureInfo,
      shadingShiftFactor,
      shadingToonyFactor,
      parametricRimColorFactor,
      rimLightingMixFactor,
      parametricRimFresnelPowerFactor,
      parametricRimLiftFactor,
      shadingShiftTexture: shadingShiftTextureInfo,
      giEqualizationFactor,
      rimMultiplyTexture: rimMultiplyTextureInfo,
      matcapTexture: matcapTextureInfo,
      matcapFactor,
      outlineWidthFactor,
      outlineColorFactor,
      outlineLightingMixFactor,
      outlineWidthMode,
      outlineWidthMultiplyTexture: outlineWidthMultiplyTextureInfo,
      transparentWithZWrite,
      v0CompatShade,
      uvAnimationMaskTexture,
      uvAnimationScrollXSpeedFactor,
      uvAnimationScrollYSpeedFactor,
      uvAnimationRotationSpeedFactor
    } = extension;
    if (v0CompatShade !== void 0) {
      this.v0CompatShade = v0CompatShade;
    }
    if (uvAnimationScrollXSpeedFactor !== void 0) {
      this.uvAnimationScrollXSpeed = uvAnimationScrollXSpeedFactor;
    }
    if (uvAnimationScrollYSpeedFactor !== void 0) {
      this.uvAnimationScrollYSpeed = uvAnimationScrollYSpeedFactor;
    }
    if (uvAnimationRotationSpeedFactor !== void 0) {
      this.uvAnimationRotationSpeed = uvAnimationRotationSpeedFactor;
    }
    if (giEqualizationFactor !== void 0) {
      this.giEqualizationFactor = giEqualizationFactor;
    }
    if (shadeColorFactor) {
      this.shadeColorFactor = new pcRef.Color(
        shadeColorFactor[0],
        shadeColorFactor[1],
        shadeColorFactor[2],
        1
      );
    }
    if (shadeMultiplyTextureInfo !== void 0) {
      const resource = this._asset.resource;
      const texture = (_c = (_b = resource == null ? void 0 : resource.textures) == null ? void 0 : _b[shadeMultiplyTextureInfo.index]) == null ? void 0 : _c.resource;
      if (texture) {
        this.shadeMultiplyTexture = texture;
        updateTextureMatrix(
          pcRef,
          this.shadeMultiplyTextureUvTransform,
          (_d = shadeMultiplyTextureInfo.extensions) == null ? void 0 : _d[textureTransformExtensionName]
        );
      }
    }
    if (rimMultiplyTextureInfo !== void 0) {
      const resource = this._asset.resource;
      const texture = (_f = (_e = resource == null ? void 0 : resource.textures) == null ? void 0 : _e[rimMultiplyTextureInfo.index]) == null ? void 0 : _f.resource;
      if (texture) {
        this.rimMultiplyTexture = texture;
        updateTextureMatrix(
          pcRef,
          this.rimMultiplyTextureUvTransform,
          (_g = rimMultiplyTextureInfo.extensions) == null ? void 0 : _g[textureTransformExtensionName]
        );
      }
    }
    if (matcapTextureInfo !== void 0) {
      const resource = this._asset.resource;
      const texture = (_i = (_h = resource == null ? void 0 : resource.textures) == null ? void 0 : _h[matcapTextureInfo.index]) == null ? void 0 : _i.resource;
      if (texture) {
        this.matcapTexture = texture;
      }
    }
    if (shadingShiftTextureInfo !== void 0) {
      const resource = this._asset.resource;
      const texture = (_k = (_j = resource == null ? void 0 : resource.textures) == null ? void 0 : _j[shadingShiftTextureInfo.index]) == null ? void 0 : _k.resource;
      if (texture) {
        this.shadingShiftTexture = texture;
        updateTextureMatrix(
          pcRef,
          this.shadingShiftTextureUvTransform,
          (_l = shadingShiftTextureInfo.extensions) == null ? void 0 : _l[textureTransformExtensionName]
        );
      }
      if (shadingShiftTextureInfo.scale !== void 0) {
        this.shadingShiftTextureScale = shadingShiftTextureInfo.scale;
      }
    }
    if (matcapFactor) {
      this.matcapFactor = new pcRef.Color(matcapFactor[0], matcapFactor[1], matcapFactor[2], 1);
    }
    this.shadingShiftFactor = shadingShiftFactor;
    this.shadingToonyFactor = shadingToonyFactor;
    if (parametricRimColorFactor) {
      this.parametricRimColorFactor = new pcRef.Color(
        parametricRimColorFactor[0],
        parametricRimColorFactor[1],
        parametricRimColorFactor[2],
        1
      );
    }
    this.rimLightingMixFactor = rimLightingMixFactor;
    this.parametricRimFresnelPowerFactor = parametricRimFresnelPowerFactor;
    this.parametricRimLiftFactor = parametricRimLiftFactor;
    if (transparentWithZWrite) {
      this.depthWrite = true;
    }
    if (outlineWidthFactor !== void 0) {
      this.outlineWidthFactor = outlineWidthFactor;
    }
    if (outlineColorFactor) {
      this.outlineColorFactor = new pcRef.Color(
        outlineColorFactor[0],
        outlineColorFactor[1],
        outlineColorFactor[2],
        1
      );
    }
    if (outlineWidthMode) {
      this.outlineWidthMode = outlineWidthMode;
    }
    if (outlineWidthMultiplyTextureInfo !== void 0) {
      const resource = this._asset.resource;
      const texture = (_n = (_m = resource == null ? void 0 : resource.textures) == null ? void 0 : _m[outlineWidthMultiplyTextureInfo.index]) == null ? void 0 : _n.resource;
      if (texture) {
        this.outlineWidthMultiplyTexture = texture;
        updateTextureMatrix(
          pcRef,
          this.outlineWidthMultiplyTextureUvTransform,
          (_o = outlineWidthMultiplyTextureInfo.extensions) == null ? void 0 : _o[textureTransformExtensionName]
        );
      }
    }
    if (outlineLightingMixFactor !== void 0) {
      this.outlineLightingMixFactor = outlineLightingMixFactor;
    }
    if (this.isOutline)
      this.cull = pcRef.CULLFACE_FRONT;
    this._setShaderChunks();
    this._setShaderUniforms();
    this._setRenderStateUpdater();
    this.update();
  };
  material._setRenderStateUpdater = function() {
    this._renderStates.setApp(this._pcApp);
    this._updateCallback = (dt) => {
      this._renderStates.update();
      const lightStateInfo = this._renderStates.lightStateInfo;
      if (lightStateInfo)
        this.updateLightState(lightStateInfo);
      this.updateUvAnimation(dt);
    };
    this._pcApp.on("update", this._updateCallback);
    this._updateCallback(0);
  };
  material.onUpdateShader = function(options2) {
    if (this.shadeMultiplyTexture) {
      options2.defines.set("USE_SHADEMULTIPLYTEXTURE", "");
    }
    if (this.normalMap) {
      options2.defines.set("USE_NORMALMAP", "");
    }
    if (this.matcapTexture) {
      options2.defines.set("USE_MATCAPTEXTURE", "");
    }
    if (this.v0CompatShade) {
      options2.defines.set("V0_COMPAT_SHADE", "");
    }
    const USE_RIMMULTIPLYTEXTURE = this.rimMultiplyTexture;
    if (USE_RIMMULTIPLYTEXTURE) {
      options2.defines.set("USE_RIMMULTIPLYTEXTURE", "");
    }
    const USE_UVANIMATIONMASKTEXTURE = this.uvAnimationMaskTexture !== null;
    if (USE_UVANIMATIONMASKTEXTURE) {
      options2.defines.set("USE_UVANIMATIONMASKTEXTURE", "");
    }
    const USE_OUTLINEWIDTHMULTIPLYTEXTURE = this.outlineWidthMultiplyTexture !== null;
    if (USE_OUTLINEWIDTHMULTIPLYTEXTURE) {
      options2.defines.set("USE_OUTLINEWIDTHMULTIPLYTEXTURE", "");
    }
    const OUTLINE_WIDTH_WORLD = this.outlineWidthMode === MToonMaterialOutlineWidthMode.WorldCoordinates;
    if (OUTLINE_WIDTH_WORLD) {
      options2.defines.set("OUTLINE_WIDTH_WORLD", "");
    }
    const OUTLINE_WIDTH_SCREEN = this.outlineWidthMode === MToonMaterialOutlineWidthMode.ScreenCoordinates;
    if (OUTLINE_WIDTH_SCREEN) {
      options2.defines.set("OUTLINE_WIDTH_SCREEN", "");
    }
    if (this.isOutline) {
      options2.defines.set("OUTLINE", "");
    }
    if (this.envAtlas) {
      options2.defines.set("USE_ENV_LIGHTS", "");
    }
    options2.defines.set("NUM_DIR_LIGHTS", this._currentDirLights.toString());
    options2.defines.set("NUM_SPOT_LIGHTS", this._currentSpotLights.toString());
    options2.defines.set("NUM_POINT_LIGHTS", this._currentPointLights.toString());
    if (this._currentDirLights > 0) {
      options2.defines.set("USE_DIR_LIGHTS", "");
    }
    if (this._currentSpotLights > 0) {
      options2.defines.set("USE_SPOT_LIGHTS", "");
    }
    if (this._currentPointLights > 0) {
      options2.defines.set("USE_POINT_LIGHTS", "");
    }
    return options2;
  };
  material._setShaderChunks = function() {
    this.shaderChunksVersion = "2.8";
    const glsl = pcRef.SHADERLANGUAGE_GLSL;
    this.getShaderChunks(glsl).set("litUserDeclarationVS", shaderChunksMtoon.litUserDeclarationVS);
    this.getShaderChunks(glsl).set("litUserMainEndVS", shaderChunksMtoon.litUserMainEndVS);
    this.getShaderChunks(glsl).set("litUserDeclarationPS", shaderChunksMtoon.litUserDeclarationPS);
    this.getShaderChunks(glsl).set("litUserCodePS", shaderChunksMtoon.litUserCodePS);
    this.getShaderChunks(glsl).set("litUserMainEndPS", shaderChunksMtoon.litUserMainEndPS);
    this.getShaderChunks(glsl).set("opacityPS", shaderChunksMtoon.opacityPS);
  };
  material._setShaderUniforms = function() {
    this.setParameters("giEqualizationFactor", this.giEqualizationFactor);
    this.setParameter("shadeColorFactor", [
      this.shadeColorFactor.r,
      this.shadeColorFactor.g,
      this.shadeColorFactor.b
    ]);
    if (this.shadeMultiplyTexture) {
      this.setParameter("shadeMultiplyTexture", this.shadeMultiplyTexture);
      this.setParameter(
        "shadeMultiplyTextureUvTransform",
        this.shadeMultiplyTextureUvTransform.data
      );
    }
    if (this.matcapTexture) {
      this.setParameter("matcapTexture", this.matcapTexture);
      this.setParameter("matcapTextureUvTransform", this.matcapTextureUvTransform.data);
    }
    this.setParameter("matcapFactor", [
      this.matcapFactor.r,
      this.matcapFactor.g,
      this.matcapFactor.b
    ]);
    if (this.shadingShiftTexture) {
      this.setParameter("shadingShiftTexture", this.shadingShiftTexture);
    }
    this.setParameter("shadingShiftTextureUvTransform", this.shadingShiftTextureUvTransform.data);
    this.setParameter("mapUvTransform", this.mapUvTransform.data);
    this.setParameter("shadingShiftFactor", this.shadingShiftFactor);
    this.setParameter("shadingToonyFactor", this.shadingToonyFactor);
    this.setParameter("parametricRimColorFactor", [
      this.parametricRimColorFactor.r,
      this.parametricRimColorFactor.g,
      this.parametricRimColorFactor.b
    ]);
    this.setParameter("rimLightingMixFactor", this.rimLightingMixFactor);
    this.setParameter("parametricRimFresnelPowerFactor", this.parametricRimFresnelPowerFactor);
    this.setParameter("parametricRimLiftFactor", this.parametricRimLiftFactor);
    if (this.normalMap) {
      this.setParameter("normalMap", this.normalMap);
      this.setParameter("normalScale", [this.normalScale.x, this.normalScale.y]);
    }
    this.setParameter("normalMapUvTransform", this.normalMapUvTransform.data);
    this.setParameter("emissiveMapUvTransform", this.emissiveMapUvTransform.data);
    this.setParameter("shadingShiftTextureScale", this.shadingShiftTextureScale);
    if (this.matcapTexture) {
      this.setParameter("matcapTexture", this.matcapTexture);
    }
    if (this.rimMultiplyTexture) {
      this.setParameter("rimMultiplyTexture", this.rimMultiplyTexture);
      this.setParameter("rimMultiplyTextureUvTransform", this.rimMultiplyTextureUvTransform.data);
    }
    if (this.outlineWidthMultiplyTexture) {
      this.setParameter("outlineWidthMultiplyTexture", this.outlineWidthMultiplyTexture);
      this.setParameter(
        "outlineWidthMultiplyTextureUvTransform",
        this.outlineWidthMultiplyTextureUvTransform.data
      );
    }
    this.setParameter("outlineWidthFactor", this.outlineWidthFactor);
    this.setParameter("outlineLightingMixFactor", this.outlineLightingMixFactor);
    this.setParameter("outlineColorFactor", [
      this.outlineColorFactor.r,
      this.outlineColorFactor.g,
      this.outlineColorFactor.b
    ]);
    this.setParameter("uvAnimationScrollXOffset", this.uvAnimationScrollXOffset);
    this.setParameter("uvAnimationScrollYOffset", this.uvAnimationScrollYOffset);
    this.setParameter("uvAnimationRotationPhase", this.uvAnimationRotationPhase);
  };
  material.updateLightState = function(lightStateInfo) {
    const { directionalLights, spotLights, pointLights, scene } = lightStateInfo;
    this._updateIndirectLightUniforms(scene);
    directionalLights.forEach((info, i) => {
      const direction = info.direction;
      this._vec3A.copy(direction);
      this._vec3A.mulScalar(-1);
      this._vec3A.normalize();
      const color = info.color;
      this.setParameter(`directionalLights[${i}].color`, [color.r, color.g, color.b]);
      this.setParameter(`directionalLights[${i}].direction`, [
        this._vec3A.x,
        this._vec3A.y,
        this._vec3A.z
      ]);
    });
    spotLights.forEach((info, i) => {
      const position = info.position;
      const direction = info.direction;
      const color = info.color;
      const distance = info.distance;
      const decay = info.decay;
      const coneCos = info.coneCos;
      const penumbraCos = info.penumbraCos;
      this.setParameter(`spotLights[${i}].position`, [position.x, position.y, position.z]);
      this.setParameter(`spotLights[${i}].direction`, [direction.x, direction.y, direction.z]);
      this.setParameter(`spotLights[${i}].color`, [color.r, color.g, color.b]);
      this.setParameter(`spotLights[${i}].distance`, distance);
      this.setParameter(`spotLights[${i}].decay`, decay);
      this.setParameter(`spotLights[${i}].coneCos`, coneCos);
      this.setParameter(`spotLights[${i}].penumbraCos`, penumbraCos);
    });
    pointLights.forEach((info, i) => {
      const position = info.position;
      const color = info.color;
      const distance = info.distance;
      const decay = info.decay;
      this.setParameter(`pointLights[${i}].position`, [position.x, position.y, position.z]);
      this.setParameter(`pointLights[${i}].color`, [color.r, color.g, color.b]);
      this.setParameter(`pointLights[${i}].distance`, distance);
      this.setParameter(`pointLights[${i}].decay`, decay);
    });
    const dirNum = directionalLights.length;
    const spotNum = spotLights.length;
    const pointNum = pointLights.length;
    const lightsChanged = dirNum !== this._currentDirLights || spotNum !== this._currentSpotLights || pointNum !== this._currentPointLights;
    if (lightsChanged) {
      this._currentDirLights = dirNum;
      this._currentSpotLights = spotNum;
      this._currentPointLights = pointNum;
      this.update();
    }
  };
  material._updateIndirectLightUniforms = function(scene) {
    if (!scene)
      return;
    if (!this.envAtlas && scene.envAtlas) {
      this.envAtlas = scene.envAtlas;
    }
    if (this.envAtlas) {
      this.setParameter("ambientLightColor", [0, 0, 0]);
    } else {
      this.ambient.copy(scene.ambientLight);
      this.setParameter("ambientLightColor", [this.ambient.r, this.ambient.g, this.ambient.b]);
    }
  };
  material.updateUvAnimation = function(deltaTime) {
    this.uvAnimationScrollXOffset += this.uvAnimationScrollXSpeed * deltaTime;
    this.setParameter("uvAnimationScrollXOffset", this.uvAnimationScrollXOffset);
    this.uvAnimationScrollYOffset += this.uvAnimationScrollYSpeed * deltaTime;
    this.setParameter("uvAnimationScrollYOffset", this.uvAnimationScrollYOffset);
    this.uvAnimationRotationPhase += this.uvAnimationRotationSpeed * deltaTime;
    this.setParameter("uvAnimationRotationPhase", this.uvAnimationRotationPhase);
  };
  material.destroy = function() {
    pcRef.StandardMaterial.prototype.destroy.call(this);
    if (this._updateCallback) {
      this._pcApp.off("update", this._updateCallback);
      this._updateCallback = void 0;
    }
  };
  material.clone = function() {
    const cloned = createVRMCMtoonMaterial(options);
    return cloned;
  };
  material.parse();
  return material;
}
const extensionVRMCName = EXTENSION_VRMC_MATERIALS_MTOON;
class VRMMtoonLoader {
  constructor(app, pcRef, asset) {
    this._pcApp = app;
    this._pcRef = pcRef;
    this.asset = asset;
  }
  instantiated(entity) {
    var _a;
    const resource = this.asset.resource;
    if (!((_a = resource == null ? void 0 : resource.data) == null ? void 0 : _a.gltf)) {
      console.error("applyMaterialMtoon: gltf is undefined");
      return [];
    }
    const gltf = resource.data.gltf;
    const materialMappings = [];
    this._applyVRMCOutlineShader(entity, gltf, materialMappings);
    this._applyVRMCMtoonShader(entity, gltf, materialMappings);
    return materialMappings;
  }
  _applyVRMCOutlineShader(entity, gltf, materialMappings) {
    const renders = entity.findComponents("render");
    const outlineShaderMaterials = /* @__PURE__ */ new Map();
    renders.forEach((renderComponent) => {
      const render = renderComponent;
      const meshInstances = render.meshInstances;
      meshInstances.forEach((meshInstance) => {
        var _a, _b, _c;
        const material = meshInstance.material;
        let shaderMaterial = outlineShaderMaterials.get(material);
        if (!shaderMaterial) {
          const index = ((_a = material.userId.split("_")) == null ? void 0 : _a[1]) ?? -1;
          const parsedIndex = parseInt(index);
          if (parsedIndex === -1) {
            return;
          }
          const gltfMaterial = (_b = gltf.materials) == null ? void 0 : _b[parsedIndex];
          if (!gltfMaterial) {
            console.error("applyVRMCOutlineShader: gltfMaterial is undefined");
            return;
          }
          const extension = (_c = gltfMaterial == null ? void 0 : gltfMaterial.extensions) == null ? void 0 : _c[extensionVRMCName];
          if (!extension) {
            return;
          }
          if (extension.outlineWidthMode === MToonMaterialOutlineWidthMode.None) {
            return;
          }
          shaderMaterial = createVRMCMtoonMaterial({
            pcApp: this._pcApp,
            pcRef: this._pcRef,
            asset: this.asset,
            isOutline: true,
            sourceMaterial: material,
            gltfMaterial,
            gltf
          });
          outlineShaderMaterials.set(material, shaderMaterial);
        }
        const shaderMeshInstance = new this._pcRef.MeshInstance(
          meshInstance.mesh,
          shaderMaterial,
          render.entity
        );
        if (meshInstance.morphInstance) {
          const morphInstance = meshInstance.morphInstance.clone();
          shaderMeshInstance.morphInstance = morphInstance;
        }
        meshInstances.push(shaderMeshInstance);
        materialMappings.push({
          meshInstance: shaderMeshInstance,
          sourceMaterial: material,
          shaderMaterial
        });
      });
    });
  }
  _applyVRMCMtoonShader(entity, gltf, materialMappings) {
    const shaderMaterials = /* @__PURE__ */ new Map();
    const renders = entity.findComponents("render");
    renders.forEach((renderComponent) => {
      const render = renderComponent;
      const meshInstances = render.meshInstances;
      meshInstances.forEach((meshInstance) => {
        var _a, _b, _c;
        if (meshInstance.material.isMtoonMaterial) {
          return;
        }
        const material = meshInstance.material;
        let shaderMaterial = shaderMaterials.get(material);
        const index = ((_a = material.userId.split("_")) == null ? void 0 : _a[1]) ?? -1;
        const parsedIndex = parseInt(index);
        if (parsedIndex === -1) {
          return;
        }
        const gltfMaterial = (_b = gltf.materials) == null ? void 0 : _b[parsedIndex];
        if (!gltfMaterial) {
          console.error("applyVRMCMtoonShader: gltfMaterial is undefined");
          return;
        }
        const extension = (_c = gltfMaterial == null ? void 0 : gltfMaterial.extensions) == null ? void 0 : _c[extensionVRMCName];
        if (!extension) {
          return;
        }
        if (!shaderMaterial) {
          shaderMaterial = createVRMCMtoonMaterial({
            pcApp: this._pcApp,
            pcRef: this._pcRef,
            asset: this.asset,
            sourceMaterial: material,
            gltfMaterial,
            gltf
          });
          shaderMaterials.set(material, shaderMaterial);
        }
        materialMappings.push({
          meshInstance,
          sourceMaterial: material,
          shaderMaterial
        });
        meshInstance.material = shaderMaterial;
      });
    });
  }
}
const importScript = (pcRef) => {
  class VrmMtoon2 extends pcRef.ScriptType {
    constructor() {
      super(...arguments);
      this.autoInitialize = true;
      this.materialMappings = [];
    }
    initialize() {
      this._initializeMtoon();
      this._setEnabled(this.autoInitialize);
      this.entity.on("vrm-mtoon:set-enabled", this._setEnabled, this);
      this.on("destroy", () => {
        this.entity.off("vrm-mtoon:set-enabled", this._setEnabled, this);
      });
    }
    _initializeMtoon() {
      this._convertVRMMtoonMaterials(pcRef, this.asset);
      const mtoonLoader = new VRMMtoonLoader(this.app, pcRef, this.asset);
      const materialMappings = mtoonLoader.instantiated(this.entity);
      this.materialMappings = materialMappings;
    }
    _setEnabled(enabled) {
      if (enabled) {
        this._activateMtoon();
      } else {
        this._deactivateMtoon();
      }
      this.entity.fire("vrm-mtoon:materials-changed", enabled);
    }
    _activateMtoon() {
      this.materialMappings.forEach(({ meshInstance, shaderMaterial }) => {
        meshInstance.material = shaderMaterial;
        meshInstance.material.update();
        if (shaderMaterial.isOutline)
          meshInstance.visible = true;
      });
    }
    _deactivateMtoon() {
      this.materialMappings.forEach(({ meshInstance, sourceMaterial, shaderMaterial }) => {
        meshInstance.material = sourceMaterial;
        meshInstance.material.update();
        if (shaderMaterial.isOutline)
          meshInstance.visible = false;
      });
    }
    _convertVRMMtoonMaterials(pcRef2, asset) {
      var _a, _b;
      const v0CompatPlugin = new VRMMaterialsV0CompatPlugin(pcRef2, asset);
      v0CompatPlugin.parseMaterials();
      const resource = asset.resource;
      (_b = (_a = resource == null ? void 0 : resource.data) == null ? void 0 : _a.materials) == null ? void 0 : _b.forEach((material, index) => {
        material.userId = `material_${index}`;
      });
    }
  }
  pcRef.registerScript(VrmMtoon2, "vrmMtoon");
  VrmMtoon2.attributes.add("asset", {
    type: "asset",
    description: "Set the container asset loaded from vrm avatar."
  });
  VrmMtoon2.attributes.add("autoInitialize", {
    type: "boolean",
    description: "Initialize MToon materials on script initialization.",
    default: true
  });
};
const VrmMtoon = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  importScript
}, Symbol.toStringTag, { value: "Module" }));
class VRMRig {
  constructor(humanBones) {
    this.humanBones = humanBones;
  }
  /**
   * Return a bone bound to a specified {@link VRMHumanBoneName}, as a {@link VRMHumanBone}.
   *
   * @param name Name of the bone you want
   */
  getBone(name) {
    return this.humanBones[name] ?? void 0;
  }
  getBoneNode(name) {
    var _a;
    return ((_a = this.humanBones[name]) == null ? void 0 : _a.node) ?? null;
  }
}
class VRMHumanoidRig extends VRMRig {
  static _setupTransforms(pcRef, modelRig) {
    const root = new pcRef.Entity();
    root.name = "VRMHumanoidRig";
    const boneWorldPositions = {};
    const boneRotations = {};
    const parentWorldRotations = {};
    VRMHumanBoneList.forEach((boneName) => {
      const boneNode = modelRig.getBoneNode(boneName);
      if (boneNode) {
        boneWorldPositions[boneName] = boneNode.getPosition().clone();
        boneNode.getRotation().clone();
        boneRotations[boneName] = boneNode.getLocalRotation().clone();
        const parentWorldRotation = new pcRef.Quat();
        if (boneNode.parent) {
          parentWorldRotation.copy(boneNode.parent.getRotation());
        }
        parentWorldRotations[boneName] = parentWorldRotation;
      }
    });
    const rigBones = {};
    VRMHumanBoneList.forEach((boneName) => {
      var _a;
      const boneNode = modelRig.getBoneNode(boneName);
      if (boneNode) {
        const boneWorldPosition = boneWorldPositions[boneName];
        let currentBoneName = boneName;
        let parentBoneWorldPosition;
        while (parentBoneWorldPosition == null) {
          currentBoneName = VRMHumanBoneParentMap[currentBoneName];
          if (currentBoneName == null) {
            break;
          }
          parentBoneWorldPosition = boneWorldPositions[currentBoneName];
        }
        const rigBoneNode = new pcRef.Entity();
        rigBoneNode.name = boneNode.name;
        const parentRigBoneNode = currentBoneName ? (_a = rigBones[currentBoneName]) == null ? void 0 : _a.node : root;
        parentRigBoneNode.addChild(rigBoneNode);
        const localPosition = new pcRef.Vec3().copy(boneWorldPosition);
        if (parentBoneWorldPosition) {
          localPosition.sub(parentBoneWorldPosition);
        }
        rigBoneNode.setLocalPosition(localPosition);
        rigBones[boneName] = { node: rigBoneNode };
      }
    });
    return {
      rigBones,
      root,
      parentWorldRotations,
      boneRotations
    };
  }
  constructor(pcRef, humanoid) {
    const { rigBones, root, parentWorldRotations, boneRotations } = VRMHumanoidRig._setupTransforms(
      pcRef,
      humanoid
    );
    super(rigBones);
    this.pcRef = pcRef;
    this.original = humanoid;
    this.root = root;
    this._parentWorldRotations = parentWorldRotations;
    this._boneRotations = boneRotations;
    this._quatA = new pcRef.Quat();
    this._quatB = new pcRef.Quat();
    this._vec3A = new pcRef.Vec3();
    this._mat4A = new pcRef.Mat4();
  }
  applyMatrix4(position, m) {
    const x = position.x, y = position.y, z = position.z;
    const e = m.data;
    const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
    position.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w;
    position.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w;
    position.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w;
    return position;
  }
  update() {
    VRMHumanBoneList.forEach((boneName) => {
      var _a;
      const boneNode = (_a = this.original.humanBones[boneName]) == null ? void 0 : _a.entity;
      const rigBoneNode = this.getBoneNode(boneName);
      if (boneNode != null && rigBoneNode) {
        const parentWorldRotation = this._parentWorldRotations[boneName];
        const invParentWorldRotation = this._quatB.copy(parentWorldRotation).invert();
        const boneRotation = this._boneRotations[boneName];
        this._quatA.copy(rigBoneNode.getLocalRotation());
        this._quatA.mul(parentWorldRotation);
        this._quatA.copy(invParentWorldRotation.mul(this._quatA));
        this._quatA.mul(boneRotation);
        boneNode.setLocalRotation(this._quatA);
        if (boneName === "hips") {
          const boneWorldPosition = this._vec3A.copy(rigBoneNode.getPosition());
          const parentWorldMatrix = this._mat4A.copy(boneNode.parent.getWorldTransform());
          const localPosition = this.applyMatrix4(boneWorldPosition, parentWorldMatrix.invert());
          boneNode.setLocalPosition(localPosition);
        }
      }
    });
  }
}
class VRMHumanoid {
  constructor(pcRef, humanBones, options) {
    this.autoUpdateHumanBones = (options == null ? void 0 : options.autoUpdateHumanBones) ?? true;
    this._rawHumanBones = new VRMRig(humanBones);
    this._normalizedHumanBones = new VRMHumanoidRig(pcRef, this._rawHumanBones);
  }
  get humanBones() {
    return this._rawHumanBones.humanBones;
  }
  get rawHumanBones() {
    return this._rawHumanBones.humanBones;
  }
  get normalizedHumanBones() {
    return this._normalizedHumanBones.humanBones;
  }
  get normalizedHumanBonesRoot() {
    return this._normalizedHumanBones.root;
  }
  get animatedEntity() {
    return this.normalizedHumanBonesRoot;
  }
  /**
   * Return a raw {@link VRMHumanBone} bound to a specified {@link VRMHumanBoneName}.
   *
   * @param name Name of the bone you want
   */
  getRawBone(name) {
    return this._rawHumanBones.getBone(name);
  }
  /**
   * Return a normalized {@link VRMHumanBone} bound to a specified {@link VRMHumanBoneName}.
   *
   * @param name Name of the bone you want
   */
  getNormalizedBone(name) {
    return this._normalizedHumanBones.getBone(name);
  }
  /**
   * Return a raw bone as a `THREE.Object3D` bound to a specified {@link VRMHumanBoneName}.
   *
   * @param name Name of the bone you want
   */
  getRawBoneNode(name) {
    return this._rawHumanBones.getBoneNode(name);
  }
  /**
   * Return a normalized bone as a `THREE.Object3D` bound to a specified {@link VRMHumanBoneName}.
   *
   * @param name Name of the bone you want
   */
  getNormalizedBoneNode(name) {
    return this._normalizedHumanBones.getBoneNode(name);
  }
  getBoneEntity(name) {
    var _a;
    return ((_a = this._rawHumanBones.humanBones[name]) == null ? void 0 : _a.entity) || null;
  }
  /**
   * Update the humanoid component.
   *
   * If {@link autoUpdateHumanBones} is `true`, it transfers the pose of normalized human bones to raw human bones.
   * Default is `true` to follow the animation set to normalized human bones
   */
  update() {
    if (this.autoUpdateHumanBones) {
      this._normalizedHumanBones.update();
    }
  }
}
function createVRMHumanBones(schemaHumanoid, glbAsset, entity) {
  const schemaHumanBones = schemaHumanoid.humanBones;
  const humanBones = {};
  if (schemaHumanoid.humanBones != null) {
    Object.entries(schemaHumanBones).map(([, schemaHumanBone]) => {
      var _a;
      let boneName = schemaHumanBone.bone;
      const index = schemaHumanBone.node;
      if (boneName == null || index == null) {
        return;
      }
      const resource = glbAsset.resource;
      const node = resource.data.nodes[index];
      if (node == null) {
        console.warn(
          `A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`
        );
        return;
      }
      humanBones[boneName] = {
        node,
        entity: ((_a = entity.findByTag(`node_${index}`)) == null ? void 0 : _a[0]) || null
      };
    });
  }
  return humanBones;
}
function createVRMCHumanBones(schemaHumanoid, glbAsset, entity) {
  var _a;
  const humanBones = {};
  const existsPreviousThumbName = schemaHumanoid.humanBones.leftThumbIntermediate != null || schemaHumanoid.humanBones.rightThumbIntermediate != null;
  if (schemaHumanoid.humanBones) {
    for (const property in schemaHumanoid.humanBones) {
      let boneName = property;
      const index = schemaHumanoid.humanBones[property].node;
      const resource = glbAsset.resource;
      const node = resource.data.nodes[index];
      if (existsPreviousThumbName) {
        const thumbBoneName = thumbBoneNameMap[boneName];
        if (thumbBoneName != null) {
          boneName = thumbBoneName;
        }
      }
      if (node == null) {
        console.warn(
          `A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`
        );
        return null;
      }
      humanBones[boneName] = {
        node,
        entity: ((_a = entity.findByTag(`node_${index}`)) == null ? void 0 : _a[0]) || null
      };
    }
  }
  return humanBones;
}
function createFormattedVRMHumanoid(pcRef, vrmAsset, renderEntity, options) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
  const resource = vrmAsset.resource;
  const VRM = (_b = (_a = resource.data.gltf) == null ? void 0 : _a.extensions) == null ? void 0 : _b.VRM;
  const VRMC_vrm = (_d = (_c = resource.data.gltf) == null ? void 0 : _c.extensions) == null ? void 0 : _d.VRMC_vrm;
  if (!VRM && !VRMC_vrm) {
    console.warn("CreateFormattedVRMHumanoid: Please check. It is not a vrm avatar.");
    return null;
  }
  let humanBones = null;
  if (VRM) {
    const schemaHumanoid = (_g = (_f = (_e = resource.data.gltf) == null ? void 0 : _e.extensions) == null ? void 0 : _f.VRM) == null ? void 0 : _g.humanoid;
    humanBones = createVRMHumanBones(schemaHumanoid, vrmAsset, renderEntity);
  } else if (VRMC_vrm) {
    const specVersion = VRMC_vrm.specVersion;
    if (!POSSIBLE_SPEC_VERSIONS$1.has(specVersion)) {
      console.warn(`Unknown VRMC_vrm specVersion "${specVersion}"`);
      return null;
    }
    const schemaHumanoid = (_j = (_i = (_h = resource.data.gltf) == null ? void 0 : _h.extensions) == null ? void 0 : _i.VRMC_vrm) == null ? void 0 : _j.humanoid;
    humanBones = createVRMCHumanBones(schemaHumanoid, vrmAsset, renderEntity);
  }
  if (humanBones) {
    const autoUpdateHumanBones = (options == null ? void 0 : options.autoUpdateHumanBones) ?? true;
    const humanoid = new VRMHumanoid(pcRef, humanBones, { autoUpdateHumanBones });
    renderEntity.addChild(humanoid.normalizedHumanBonesRoot);
    return humanoid;
  }
  return null;
}
const addIndexToNodeTags = (asset) => {
  if (!asset.resource) {
    console.error("addIndexToNodeTags Error: asset.resource is not available");
    return;
  }
  const resource = asset.resource;
  if (!(resource.data && resource.data.gltf)) {
    console.error("addIndexToNodeTags Error: asset.resource.data.gltf is not available");
    return;
  }
  const assetData = resource.data;
  const nodes = assetData.nodes;
  nodes.forEach((node, index) => {
    node.tags.add(`node_${index}`);
  });
};
const getVersion = (asset) => {
  var _a, _b;
  const resource = asset.resource;
  const isV1Used = (_a = resource.data.gltf.extensions) == null ? void 0 : _a.VRMC_vrm;
  const isV0Used = (_b = resource.data.gltf.extensions) == null ? void 0 : _b.VRM;
  return isV1Used ? "v1" : isV0Used ? "v0" : null;
};
window.VRMLoader = {
  VrmAnimation,
  VrmExpression,
  VrmSpringBone,
  VrmMtoon,
  VrmMapList,
  createFormattedVRMHumanoid,
  addIndexToNodeTags,
  getVersion
};
const AvatarBoneName = {
  Chest: "chest",
  Head: "head",
  Hips: "hips",
  Jaw: "jaw",
  LeftEye: "leftEye",
  LeftFoot: "leftFoot",
  LeftHand: "leftHand",
  LeftIndexDistal: "leftIndexDistal",
  LeftIndexIntermediate: "leftIndexIntermediate",
  LeftIndexProximal: "leftIndexProximal",
  LeftLittleDistal: "leftLittleDistal",
  LeftLittleIntermediate: "leftLittleIntermediate",
  LeftLittleProximal: "leftLittleProximal",
  LeftLowerArm: "leftLowerArm",
  LeftLowerLeg: "leftLowerLeg",
  LeftMiddleDistal: "leftMiddleDistal",
  LeftMiddleIntermediate: "leftMiddleIntermediate",
  LeftMiddleProximal: "leftMiddleProximal",
  LeftRingDistal: "leftRingDistal",
  LeftRingIntermediate: "leftRingIntermediate",
  LeftRingProximal: "leftRingProximal",
  LeftShoulder: "leftShoulder",
  LeftThumbDistal: "leftThumbDistal",
  LeftThumbMetacarpal: "leftThumbMetacarpal",
  LeftThumbProximal: "leftThumbProximal",
  LeftToes: "leftToes",
  LeftUpperArm: "leftUpperArm",
  LeftUpperLeg: "leftUpperLeg",
  Neck: "neck",
  RightEye: "rightEye",
  RightFoot: "rightFoot",
  RightHand: "rightHand",
  RightIndexDistal: "rightIndexDistal",
  RightIndexIntermediate: "rightIndexIntermediate",
  RightIndexProximal: "rightIndexProximal",
  RightLittleDistal: "rightLittleDistal",
  RightLittleIntermediate: "rightLittleIntermediate",
  RightLittleProximal: "rightLittleProximal",
  RightLowerArm: "rightLowerArm",
  RightLowerLeg: "rightLowerLeg",
  RightMiddleDistal: "rightMiddleDistal",
  RightMiddleIntermediate: "rightMiddleIntermediate",
  RightMiddleProximal: "rightMiddleProximal",
  RightRingDistal: "rightRingDistal",
  RightRingIntermediate: "rightRingIntermediate",
  RightRingProximal: "rightRingProximal",
  RightShoulder: "rightShoulder",
  RightThumbDistal: "rightThumbDistal",
  RightThumbMetacarpal: "rightThumbMetacarpal",
  RightThumbProximal: "rightThumbProximal",
  RightToes: "rightToes",
  RightUpperArm: "rightUpperArm",
  RightUpperLeg: "rightUpperLeg",
  Spine: "spine",
  UpperChest: "upperChest"
};
var CompletionType = /* @__PURE__ */ ((CompletionType2) => {
  CompletionType2["Simple"] = "simple";
  CompletionType2["Progress"] = "progress";
  return CompletionType2;
})(CompletionType || {});
var MessageType = /* @__PURE__ */ ((MessageType2) => {
  MessageType2["System"] = "system";
  MessageType2["Custom"] = "custom";
  return MessageType2;
})(MessageType || {});
var PostEffectType = /* @__PURE__ */ ((PostEffectType2) => {
  PostEffectType2["BlendEffect"] = "blendEffect";
  PostEffectType2["BloomEffect"] = "bloomEffect";
  PostEffectType2["BrightnessContrastEffect"] = "brightnessContrastEffect";
  PostEffectType2["EdgeDetectEffect"] = "edgeDetectEffect";
  PostEffectType2["FxaaEffect"] = "fxaaEffect";
  PostEffectType2["HorizontalTiltShiftEffect"] = "horizontalTiltShiftEffect";
  PostEffectType2["HueSaturationEffect"] = "hueSaturationEffect";
  PostEffectType2["SSAOEffect"] = "sSAOEffect";
  PostEffectType2["VerticalTiltShiftEffect"] = "verticalTiltShiftEffect";
  PostEffectType2["VignetteEffect"] = "vignetteEffect";
  return PostEffectType2;
})(PostEffectType || {});
var TriggerEventType = /* @__PURE__ */ ((TriggerEventType2) => {
  TriggerEventType2["OnSelect"] = "onSelect";
  TriggerEventType2["OnCollision"] = "onCollision";
  TriggerEventType2["OnAnimation"] = "onAnimation";
  TriggerEventType2["OnNotificationEvent"] = "onNotificationEvent";
  TriggerEventType2["OnInteractionExecuting"] = "onInteractionExecuting";
  TriggerEventType2["OnSeatStateChanged"] = "onSeatStateChanged";
  return TriggerEventType2;
})(TriggerEventType || {});
var TriggerCollisionEvent = /* @__PURE__ */ ((TriggerCollisionEvent2) => {
  TriggerCollisionEvent2["TriggerEnter"] = "triggerenter";
  TriggerCollisionEvent2["TriggerLeave"] = "triggerleave";
  TriggerCollisionEvent2["CollisionStart"] = "collisionstart";
  TriggerCollisionEvent2["CollisionEnd"] = "collisionend";
  return TriggerCollisionEvent2;
})(TriggerCollisionEvent || {});
var TriggerCollisionFilter = /* @__PURE__ */ ((TriggerCollisionFilter2) => {
  TriggerCollisionFilter2["Any"] = "any";
  TriggerCollisionFilter2["Player"] = "player";
  TriggerCollisionFilter2["Tag"] = "tag";
  TriggerCollisionFilter2["PlayerAndTag"] = "playerAndTag";
  return TriggerCollisionFilter2;
})(TriggerCollisionFilter || {});
var TriggerAnimEvent = /* @__PURE__ */ ((TriggerAnimEvent2) => {
  TriggerAnimEvent2["Start"] = "start";
  TriggerAnimEvent2["End"] = "end";
  TriggerAnimEvent2["CustomEvent"] = "customEvent";
  return TriggerAnimEvent2;
})(TriggerAnimEvent || {});
var TriggerSeatState = /* @__PURE__ */ ((TriggerSeatState2) => {
  TriggerSeatState2["Occupied"] = "occupied";
  TriggerSeatState2["Vacated"] = "vacated";
  return TriggerSeatState2;
})(TriggerSeatState || {});
var ActionType = /* @__PURE__ */ ((ActionType2) => {
  ActionType2["ToggleEntities"] = "toggleEntities";
  ActionType2["ToggleComponent"] = "toggleComponent";
  ActionType2["DestroyEntities"] = "destroyEntities";
  ActionType2["FadeTransition"] = "fadeTransition";
  ActionType2["PublishNotification"] = "publishNotification";
  ActionType2["TeleportPlayer"] = "teleportPlayer";
  ActionType2["PushEntity"] = "pushEntity";
  ActionType2["SoundControl"] = "soundControl";
  ActionType2["AnimationControl"] = "animationControl";
  ActionType2["ParticleSystemControl"] = "particleSystemControl";
  ActionType2["Quest"] = "quest";
  ActionType2["SetSpawnPoint"] = "setSpawnPoint";
  ActionType2["ShowToastMessage"] = "showToastMessage";
  ActionType2["Seat"] = "seat";
  ActionType2["OpenLink"] = "openLink";
  ActionType2["FireEntityEvent"] = "fireEntityEvent";
  return ActionType2;
})(ActionType || {});
var ActionToggleOption = /* @__PURE__ */ ((ActionToggleOption2) => {
  ActionToggleOption2["Enable"] = "enable";
  ActionToggleOption2["Disable"] = "disable";
  ActionToggleOption2["Toggle"] = "toggle";
  return ActionToggleOption2;
})(ActionToggleOption || {});
var ActionEntityFilterOption = /* @__PURE__ */ ((ActionEntityFilterOption2) => {
  ActionEntityFilterOption2["Self"] = "self";
  ActionEntityFilterOption2["Tag"] = "tag";
  ActionEntityFilterOption2["TargetEntity"] = "targetEntity";
  return ActionEntityFilterOption2;
})(ActionEntityFilterOption || {});
var ActionFadeTransitionOption = /* @__PURE__ */ ((ActionFadeTransitionOption2) => {
  ActionFadeTransitionOption2["FadeIn"] = "fadeIn";
  ActionFadeTransitionOption2["FadeOut"] = "fadeOut";
  return ActionFadeTransitionOption2;
})(ActionFadeTransitionOption || {});
var ActionPlaybackOption = /* @__PURE__ */ ((ActionPlaybackOption2) => {
  ActionPlaybackOption2["Play"] = "play";
  ActionPlaybackOption2["Stop"] = "stop";
  return ActionPlaybackOption2;
})(ActionPlaybackOption || {});
var ActionCommandOption = /* @__PURE__ */ ((ActionCommandOption2) => {
  ActionCommandOption2["Collision"] = "collision";
  ActionCommandOption2["RigidBody"] = "rigidbody";
  return ActionCommandOption2;
})(ActionCommandOption || {});
var ActionQuestCommandOption = /* @__PURE__ */ ((ActionQuestCommandOption2) => {
  ActionQuestCommandOption2["StartQuest"] = "startQuest";
  ActionQuestCommandOption2["ResetQuest"] = "resetQuest";
  ActionQuestCommandOption2["CompleteTask"] = "completeTask";
  ActionQuestCommandOption2["AddTaskProgress"] = "addTaskProgress";
  return ActionQuestCommandOption2;
})(ActionQuestCommandOption || {});
var ActionSeatCommandOption = /* @__PURE__ */ ((ActionSeatCommandOption2) => {
  ActionSeatCommandOption2["Sit"] = "sit";
  ActionSeatCommandOption2["Leave"] = "leave";
  return ActionSeatCommandOption2;
})(ActionSeatCommandOption || {});
var BillboardTargetType = /* @__PURE__ */ ((BillboardTargetType2) => {
  BillboardTargetType2["ViverseCamera"] = "viverseCamera";
  BillboardTargetType2["Entity"] = "entity";
  BillboardTargetType2["Position"] = "position";
  return BillboardTargetType2;
})(BillboardTargetType || {});
export {
  ActionCommandOption,
  ActionEntityFilterOption,
  ActionFadeTransitionOption,
  ActionPlaybackOption,
  ActionQuestCommandOption,
  ActionSeatCommandOption,
  ActionToggleOption,
  ActionType,
  AvatarBoneName,
  AvatarFacingMode,
  AvatarHorizontalDirection,
  AvatarVerticalState,
  BillboardAxisAlignment,
  BillboardTargetType,
  CameraEntityKeys,
  CompletionType,
  HardwareType,
  LocomotionStateType,
  MessageType,
  ModuleName,
  OsType,
  PostEffectType,
  PostureType,
  SceneEntityConstants,
  SceneScriptNames,
  ScreenOrientationType,
  SystemName,
  TriggerAnimEvent,
  TriggerCollisionEvent,
  TriggerCollisionFilter,
  TriggerEventType,
  TriggerSeatState,
  XrHeadsetType,
  XrInputDeviceType,
  XrLocomotionType,
  XrUiAnchorType
};
