Ai_Assistant/client/node_modules/@pixiv/three-vrm-springbone/lib/three-vrm-springbone.module.js

1283 lines
168 KiB
JavaScript
Raw Permalink Normal View History

2026-05-24 13:31:30 +02:00
/*!
* @pixiv/three-vrm-springbone v3.4.1
* Spring bone module for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-springbone is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/helpers/VRMSpringBoneColliderHelper.ts
import * as THREE7 from "three";
// src/VRMSpringBoneColliderShapeCapsule.ts
import * as THREE from "three";
// src/VRMSpringBoneColliderShape.ts
var VRMSpringBoneColliderShape = class {
};
// src/VRMSpringBoneColliderShapeCapsule.ts
var _v3A = new THREE.Vector3();
var _v3B = new THREE.Vector3();
var VRMSpringBoneColliderShapeCapsule = class extends VRMSpringBoneColliderShape {
get type() {
return "capsule";
}
constructor(params) {
var _a, _b, _c, _d;
super();
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE.Vector3(0, 0, 0);
this.tail = (_b = params == null ? void 0 : params.tail) != null ? _b : new THREE.Vector3(0, 0, 0);
this.radius = (_c = params == null ? void 0 : params.radius) != null ? _c : 0;
this.inside = (_d = params == null ? void 0 : params.inside) != null ? _d : false;
}
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
_v3A.setFromMatrixPosition(colliderMatrix);
_v3B.subVectors(this.tail, this.offset).applyMatrix4(colliderMatrix);
_v3B.sub(_v3A);
const lengthSqCapsule = _v3B.lengthSq();
target.copy(objectPosition).sub(_v3A);
const dot = _v3B.dot(target);
if (dot <= 0) {
} else if (lengthSqCapsule <= dot) {
target.sub(_v3B);
} else {
_v3B.multiplyScalar(dot / lengthSqCapsule);
target.sub(_v3B);
}
const length = target.length();
const distance = this.inside ? this.radius - objectRadius - length : length - objectRadius - this.radius;
if (distance < 0) {
target.multiplyScalar(1 / length);
if (this.inside) {
target.negate();
}
}
return distance;
}
};
// src/VRMSpringBoneColliderShapePlane.ts
import * as THREE2 from "three";
var _v3A2 = new THREE2.Vector3();
var _mat3A = new THREE2.Matrix3();
var VRMSpringBoneColliderShapePlane = class extends VRMSpringBoneColliderShape {
get type() {
return "plane";
}
constructor(params) {
var _a, _b;
super();
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE2.Vector3(0, 0, 0);
this.normal = (_b = params == null ? void 0 : params.normal) != null ? _b : new THREE2.Vector3(0, 0, 1);
}
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
target.setFromMatrixPosition(colliderMatrix);
target.negate().add(objectPosition);
_mat3A.getNormalMatrix(colliderMatrix);
_v3A2.copy(this.normal).applyNormalMatrix(_mat3A).normalize();
const distance = target.dot(_v3A2) - objectRadius;
target.copy(_v3A2);
return distance;
}
};
// src/VRMSpringBoneColliderShapeSphere.ts
import * as THREE3 from "three";
var _v3A3 = new THREE3.Vector3();
var VRMSpringBoneColliderShapeSphere = class extends VRMSpringBoneColliderShape {
get type() {
return "sphere";
}
constructor(params) {
var _a, _b, _c;
super();
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE3.Vector3(0, 0, 0);
this.radius = (_b = params == null ? void 0 : params.radius) != null ? _b : 0;
this.inside = (_c = params == null ? void 0 : params.inside) != null ? _c : false;
}
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
target.subVectors(objectPosition, _v3A3.setFromMatrixPosition(colliderMatrix));
const length = target.length();
const distance = this.inside ? this.radius - objectRadius - length : length - objectRadius - this.radius;
if (distance < 0) {
target.multiplyScalar(1 / length);
if (this.inside) {
target.negate();
}
}
return distance;
}
};
// src/helpers/utils/ColliderShapeCapsuleBufferGeometry.ts
import * as THREE4 from "three";
var _v3A4 = new THREE4.Vector3();
var ColliderShapeCapsuleBufferGeometry = class extends THREE4.BufferGeometry {
constructor(shape) {
super();
this.worldScale = 1;
this._currentRadius = 0;
this._currentOffset = new THREE4.Vector3();
this._currentTail = new THREE4.Vector3();
this._shape = shape;
this._attrPos = new THREE4.BufferAttribute(new Float32Array(396), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE4.BufferAttribute(new Uint16Array(264), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
const radius = this._shape.radius / this.worldScale;
if (this._currentRadius !== radius) {
this._currentRadius = radius;
shouldUpdateGeometry = true;
}
if (!this._currentOffset.equals(this._shape.offset)) {
this._currentOffset.copy(this._shape.offset);
shouldUpdateGeometry = true;
}
const tail = _v3A4.copy(this._shape.tail).divideScalar(this.worldScale);
if (this._currentTail.distanceToSquared(tail) > 1e-10) {
this._currentTail.copy(tail);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
_v3A4.copy(this._currentTail).sub(this._currentOffset);
const l = _v3A4.length() / this._currentRadius;
for (let i = 0; i <= 16; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(i, -Math.sin(t), -Math.cos(t), 0);
this._attrPos.setXYZ(17 + i, l + Math.sin(t), Math.cos(t), 0);
this._attrPos.setXYZ(34 + i, -Math.sin(t), 0, -Math.cos(t));
this._attrPos.setXYZ(51 + i, l + Math.sin(t), 0, Math.cos(t));
}
for (let i = 0; i < 32; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(68 + i, 0, Math.sin(t), Math.cos(t));
this._attrPos.setXYZ(100 + i, l, Math.sin(t), Math.cos(t));
}
const theta = Math.atan2(_v3A4.y, Math.sqrt(_v3A4.x * _v3A4.x + _v3A4.z * _v3A4.z));
const phi = -Math.atan2(_v3A4.z, _v3A4.x);
this.rotateZ(theta);
this.rotateY(phi);
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 34; i++) {
const i1 = (i + 1) % 34;
this._attrIndex.setXY(i * 2, i, i1);
this._attrIndex.setXY(68 + i * 2, 34 + i, 34 + i1);
}
for (let i = 0; i < 32; i++) {
const i1 = (i + 1) % 32;
this._attrIndex.setXY(136 + i * 2, 68 + i, 68 + i1);
this._attrIndex.setXY(200 + i * 2, 100 + i, 100 + i1);
}
this._attrIndex.needsUpdate = true;
}
};
// src/helpers/utils/ColliderShapePlaneBufferGeometry.ts
import * as THREE5 from "three";
var ColliderShapePlaneBufferGeometry = class extends THREE5.BufferGeometry {
constructor(shape) {
super();
this.worldScale = 1;
this._currentOffset = new THREE5.Vector3();
this._currentNormal = new THREE5.Vector3();
this._shape = shape;
this._attrPos = new THREE5.BufferAttribute(new Float32Array(6 * 3), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE5.BufferAttribute(new Uint16Array(10), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
if (!this._currentOffset.equals(this._shape.offset)) {
this._currentOffset.copy(this._shape.offset);
shouldUpdateGeometry = true;
}
if (!this._currentNormal.equals(this._shape.normal)) {
this._currentNormal.copy(this._shape.normal);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
this._attrPos.setXYZ(0, -0.5, -0.5, 0);
this._attrPos.setXYZ(1, 0.5, -0.5, 0);
this._attrPos.setXYZ(2, 0.5, 0.5, 0);
this._attrPos.setXYZ(3, -0.5, 0.5, 0);
this._attrPos.setXYZ(4, 0, 0, 0);
this._attrPos.setXYZ(5, 0, 0, 0.25);
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
this.lookAt(this._currentNormal);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
this._attrIndex.setXY(0, 0, 1);
this._attrIndex.setXY(2, 1, 2);
this._attrIndex.setXY(4, 2, 3);
this._attrIndex.setXY(6, 3, 0);
this._attrIndex.setXY(8, 4, 5);
this._attrIndex.needsUpdate = true;
}
};
// src/helpers/utils/ColliderShapeSphereBufferGeometry.ts
import * as THREE6 from "three";
var ColliderShapeSphereBufferGeometry = class extends THREE6.BufferGeometry {
constructor(shape) {
super();
this.worldScale = 1;
this._currentRadius = 0;
this._currentOffset = new THREE6.Vector3();
this._shape = shape;
this._attrPos = new THREE6.BufferAttribute(new Float32Array(32 * 3 * 3), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE6.BufferAttribute(new Uint16Array(64 * 3), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
const radius = this._shape.radius / this.worldScale;
if (this._currentRadius !== radius) {
this._currentRadius = radius;
shouldUpdateGeometry = true;
}
if (!this._currentOffset.equals(this._shape.offset)) {
this._currentOffset.copy(this._shape.offset);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
for (let i = 0; i < 32; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0);
this._attrPos.setXYZ(32 + i, 0, Math.cos(t), Math.sin(t));
this._attrPos.setXYZ(64 + i, Math.sin(t), 0, Math.cos(t));
}
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 32; i++) {
const i1 = (i + 1) % 32;
this._attrIndex.setXY(i * 2, i, i1);
this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
}
this._attrIndex.needsUpdate = true;
}
};
// src/helpers/VRMSpringBoneColliderHelper.ts
var _v3A5 = new THREE7.Vector3();
var VRMSpringBoneColliderHelper = class extends THREE7.Group {
constructor(collider) {
super();
this.matrixAutoUpdate = false;
this.collider = collider;
if (this.collider.shape instanceof VRMSpringBoneColliderShapeSphere) {
this._geometry = new ColliderShapeSphereBufferGeometry(this.collider.shape);
} else if (this.collider.shape instanceof VRMSpringBoneColliderShapeCapsule) {
this._geometry = new ColliderShapeCapsuleBufferGeometry(this.collider.shape);
} else if (this.collider.shape instanceof VRMSpringBoneColliderShapePlane) {
this._geometry = new ColliderShapePlaneBufferGeometry(this.collider.shape);
} else {
throw new Error("VRMSpringBoneColliderHelper: Unknown collider shape type detected");
}
const material = new THREE7.LineBasicMaterial({
color: 16711935,
depthTest: false,
depthWrite: false
});
this._line = new THREE7.LineSegments(this._geometry, material);
this.add(this._line);
}
dispose() {
this._geometry.dispose();
}
updateMatrixWorld(force) {
this.collider.updateWorldMatrix(true, false);
this.matrix.copy(this.collider.matrixWorld);
const matrixWorldElements = this.matrix.elements;
this._geometry.worldScale = _v3A5.set(matrixWorldElements[0], matrixWorldElements[1], matrixWorldElements[2]).length();
this._geometry.update();
super.updateMatrixWorld(force);
}
};
// src/helpers/VRMSpringBoneJointHelper.ts
import * as THREE9 from "three";
// src/helpers/utils/SpringBoneBufferGeometry.ts
import * as THREE8 from "three";
var SpringBoneBufferGeometry = class extends THREE8.BufferGeometry {
constructor(springBone) {
super();
this.worldScale = 1;
this._currentRadius = 0;
this._currentTail = new THREE8.Vector3();
this._springBone = springBone;
this._attrPos = new THREE8.BufferAttribute(new Float32Array(294), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE8.BufferAttribute(new Uint16Array(194), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
const radius = this._springBone.settings.hitRadius / this.worldScale;
if (this._currentRadius !== radius) {
this._currentRadius = radius;
shouldUpdateGeometry = true;
}
if (!this._currentTail.equals(this._springBone.initialLocalChildPosition)) {
this._currentTail.copy(this._springBone.initialLocalChildPosition);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
for (let i = 0; i < 32; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0);
this._attrPos.setXYZ(32 + i, 0, Math.cos(t), Math.sin(t));
this._attrPos.setXYZ(64 + i, Math.sin(t), 0, Math.cos(t));
}
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
this.translate(this._currentTail.x, this._currentTail.y, this._currentTail.z);
this._attrPos.setXYZ(96, 0, 0, 0);
this._attrPos.setXYZ(97, this._currentTail.x, this._currentTail.y, this._currentTail.z);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 32; i++) {
const i1 = (i + 1) % 32;
this._attrIndex.setXY(i * 2, i, i1);
this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
}
this._attrIndex.setXY(192, 96, 97);
this._attrIndex.needsUpdate = true;
}
};
// src/helpers/VRMSpringBoneJointHelper.ts
var _v3A6 = new THREE9.Vector3();
var VRMSpringBoneJointHelper = class extends THREE9.Group {
constructor(springBone) {
super();
this.matrixAutoUpdate = false;
this.springBone = springBone;
this._geometry = new SpringBoneBufferGeometry(this.springBone);
const material = new THREE9.LineBasicMaterial({
color: 16776960,
depthTest: false,
depthWrite: false
});
this._line = new THREE9.LineSegments(this._geometry, material);
this.add(this._line);
}
dispose() {
this._geometry.dispose();
}
updateMatrixWorld(force) {
this.springBone.bone.updateWorldMatrix(true, false);
this.matrix.copy(this.springBone.bone.matrixWorld);
const matrixWorldElements = this.matrix.elements;
this._geometry.worldScale = _v3A6.set(matrixWorldElements[0], matrixWorldElements[1], matrixWorldElements[2]).length();
this._geometry.update();
super.updateMatrixWorld(force);
}
};
// src/VRMSpringBoneCollider.ts
import * as THREE10 from "three";
var VRMSpringBoneCollider = class extends THREE10.Object3D {
constructor(shape) {
super();
/**
* World space matrix for the collider shape used in collision calculations.
*/
this.colliderMatrix = new THREE10.Matrix4();
this.shape = shape;
}
updateWorldMatrix(updateParents, updateChildren) {
super.updateWorldMatrix(updateParents, updateChildren);
updateColliderMatrix(this.colliderMatrix, this.matrixWorld, this.shape.offset);
}
};
function updateColliderMatrix(colliderMatrix, matrixWorld, offset) {
const me = matrixWorld.elements;
colliderMatrix.copy(matrixWorld);
if (offset) {
colliderMatrix.elements[12] = me[0] * offset.x + me[4] * offset.y + me[8] * offset.z + me[12];
colliderMatrix.elements[13] = me[1] * offset.x + me[5] * offset.y + me[9] * offset.z + me[13];
colliderMatrix.elements[14] = me[2] * offset.x + me[6] * offset.y + me[10] * offset.z + me[14];
}
}
// src/VRMSpringBoneJoint.ts
import * as THREE13 from "three";
// src/utils/Matrix4InverseCache.ts
import * as THREE12 from "three";
// src/utils/mat4InvertCompat.ts
import * as THREE11 from "three";
var _matA = new THREE11.Matrix4();
function mat4InvertCompat(target) {
if (target.invert) {
target.invert();
} else {
target.getInverse(_matA.copy(target));
}
return target;
}
// src/utils/Matrix4InverseCache.ts
var Matrix4InverseCache = class {
constructor(matrix) {
/**
* A cache of inverse of current matrix.
*/
this._inverseCache = new THREE12.Matrix4();
/**
* A flag that makes it want to recalculate its {@link _inverseCache}.
* Will be set `true` when `elements` are mutated and be used in `getInverse`.
*/
this._shouldUpdateInverse = true;
this.matrix = matrix;
const handler = {
set: (obj, prop, newVal) => {
this._shouldUpdateInverse = true;
obj[prop] = newVal;
return true;
}
};
this._originalElements = matrix.elements;
matrix.elements = new Proxy(matrix.elements, handler);
}
/**
* Inverse of given matrix.
* Note that it will return its internal private instance.
* Make sure copying this before mutate this.
*/
get inverse() {
if (this._shouldUpdateInverse) {
mat4InvertCompat(this._inverseCache.copy(this.matrix));
this._shouldUpdateInverse = false;
}
return this._inverseCache;
}
revert() {
this.matrix.elements = this._originalElements;
}
};
// src/VRMSpringBoneJoint.ts
var IDENTITY_MATRIX4 = new THREE13.Matrix4();
var _v3A7 = new THREE13.Vector3();
var _v3B2 = new THREE13.Vector3();
var _worldSpacePosition = new THREE13.Vector3();
var _nextTail = new THREE13.Vector3();
var _matA2 = new THREE13.Matrix4();
var VRMSpringBoneJoint = class {
/**
* Create a new VRMSpringBone.
*
* @param bone An Object3D that will be attached to this bone
* @param child An Object3D that will be used as a tail of this spring bone. It can be null when the spring bone is imported from VRM 0.0
* @param settings Several parameters related to behavior of the spring bone
* @param colliderGroups Collider groups that will be collided with this spring bone
*/
constructor(bone, child, settings = {}, colliderGroups = []) {
/**
* Current position of child tail, in center unit. Will be used for verlet integration.
*/
this._currentTail = new THREE13.Vector3();
/**
* Previous position of child tail, in center unit. Will be used for verlet integration.
*/
this._prevTail = new THREE13.Vector3();
/**
* Initial axis of the bone, in local unit.
*/
this._boneAxis = new THREE13.Vector3();
/**
* Length of the bone in world unit.
* Will be used for normalization in update loop, will be updated by {@link _calcWorldSpaceBoneLength}.
*
* It's same as local unit length unless there are scale transformations in the world space.
*/
this._worldSpaceBoneLength = 0;
/**
* This springbone will be calculated based on the space relative from this object.
* If this is `null`, springbone will be calculated in world space.
*/
this._center = null;
/**
* Initial state of the local matrix of the bone.
*/
this._initialLocalMatrix = new THREE13.Matrix4();
/**
* Initial state of the rotation of the bone.
*/
this._initialLocalRotation = new THREE13.Quaternion();
/**
* Initial state of the position of its child.
*/
this._initialLocalChildPosition = new THREE13.Vector3();
var _a, _b, _c, _d, _e, _f;
this.bone = bone;
this.bone.matrixAutoUpdate = false;
this.child = child;
this.settings = {
hitRadius: (_a = settings.hitRadius) != null ? _a : 0,
stiffness: (_b = settings.stiffness) != null ? _b : 1,
gravityPower: (_c = settings.gravityPower) != null ? _c : 0,
gravityDir: (_e = (_d = settings.gravityDir) == null ? void 0 : _d.clone()) != null ? _e : new THREE13.Vector3(0, -1, 0),
dragForce: (_f = settings.dragForce) != null ? _f : 0.4
};
this.colliderGroups = colliderGroups;
}
/**
* 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;
}
get center() {
return this._center;
}
set center(center) {
var _a;
if ((_a = this._center) == null ? void 0 : _a.userData.inverseCacheProxy) {
this._center.userData.inverseCacheProxy.revert();
delete this._center.userData.inverseCacheProxy;
}
this._center = center;
if (this._center) {
if (!this._center.userData.inverseCacheProxy) {
this._center.userData.inverseCacheProxy = new Matrix4InverseCache(this._center.matrixWorld);
}
}
}
get initialLocalChildPosition() {
return this._initialLocalChildPosition;
}
/**
* Returns the world matrix of its parent object.
* Note that it returns a reference to the matrix. Don't mutate this directly!
*/
get _parentMatrixWorld() {
return this.bone.parent ? this.bone.parent.matrixWorld : IDENTITY_MATRIX4;
}
/**
* Set the initial state of this spring bone.
* You might want to call {@link VRMSpringBoneManager.setInitState} instead.
*/
setInitState() {
this._initialLocalMatrix.copy(this.bone.matrix);
this._initialLocalRotation.copy(this.bone.quaternion);
if (this.child) {
this._initialLocalChildPosition.copy(this.child.position);
} else {
this._initialLocalChildPosition.copy(this.bone.position).normalize().multiplyScalar(0.07);
}
const matrixWorldToCenter = this._getMatrixWorldToCenter();
this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(matrixWorldToCenter);
this._prevTail.copy(this._currentTail);
this._boneAxis.copy(this._initialLocalChildPosition).normalize();
}
/**
* Reset the state of this bone.
* You might want to call {@link VRMSpringBoneManager.reset} instead.
*/
reset() {
this.bone.quaternion.copy(this._initialLocalRotation);
this.bone.updateMatrix();
this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld, this.bone.matrix);
const matrixWorldToCenter = this._getMatrixWorldToCenter();
this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(matrixWorldToCenter);
this._prevTail.copy(this._currentTail);
}
/**
* Update the state of this bone.
* You might want to call {@link VRMSpringBoneManager.update} instead.
*
* @param delta deltaTime
*/
update(delta) {
if (delta <= 0) return;
this._calcWorldSpaceBoneLength();
const worldSpaceBoneAxis = _v3B2.copy(this._boneAxis).transformDirection(this._initialLocalMatrix).transformDirection(this._parentMatrixWorld);
_nextTail.copy(this._currentTail).add(_v3A7.subVectors(this._currentTail, this._prevTail).multiplyScalar(1 - this.settings.dragForce)).applyMatrix4(this._getMatrixCenterToWorld()).addScaledVector(worldSpaceBoneAxis, this.settings.stiffness * delta).addScaledVector(this.settings.gravityDir, this.settings.gravityPower * delta);
_worldSpacePosition.setFromMatrixPosition(this.bone.matrixWorld);
_nextTail.sub(_worldSpacePosition).normalize().multiplyScalar(this._worldSpaceBoneLength).add(_worldSpacePosition);
this._collision(_nextTail);
this._prevTail.copy(this._currentTail);
this._currentTail.copy(_nextTail).applyMatrix4(this._getMatrixWorldToCenter());
const worldSpaceInitialMatrixInv = _matA2.multiplyMatrices(this._parentMatrixWorld, this._initialLocalMatrix).invert();
this.bone.quaternion.setFromUnitVectors(this._boneAxis, _v3A7.copy(_nextTail).applyMatrix4(worldSpaceInitialMatrixInv).normalize()).premultiply(this._initialLocalRotation);
this.bone.updateMatrix();
this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld, this.bone.matrix);
}
/**
* Do collision math against every colliders attached to this bone.
*
* @param tail The tail you want to process
*/
_collision(tail) {
for (let cg = 0; cg < this.colliderGroups.length; cg++) {
for (let c = 0; c < this.colliderGroups[cg].colliders.length; c++) {
const collider = this.colliderGroups[cg].colliders[c];
const dist = collider.shape.calculateCollision(collider.colliderMatrix, tail, this.settings.hitRadius, _v3A7);
if (dist < 0) {
tail.addScaledVector(_v3A7, -dist);
tail.sub(_worldSpacePosition);
const length = tail.length();
tail.multiplyScalar(this._worldSpaceBoneLength / length).add(_worldSpacePosition);
}
}
}
}
/**
* Calculate the {@link _worldSpaceBoneLength}.
* Intended to be used in {@link update}.
*/
_calcWorldSpaceBoneLength() {
_v3A7.setFromMatrixPosition(this.bone.matrixWorld);
if (this.child) {
_v3B2.setFromMatrixPosition(this.child.matrixWorld);
} else {
_v3B2.copy(this._initialLocalChildPosition);
_v3B2.applyMatrix4(this.bone.matrixWorld);
}
this._worldSpaceBoneLength = _v3A7.sub(_v3B2).length();
}
/**
* Create a matrix that converts center space into world space.
*/
_getMatrixCenterToWorld() {
return this._center ? this._center.matrixWorld : IDENTITY_MATRIX4;
}
/**
* Create a matrix that converts world space into center space.
*/
_getMatrixWorldToCenter() {
return this._center ? this._center.userData.inverseCacheProxy.inverse : IDENTITY_MATRIX4;
}
};
// src/VRMSpringBoneLoaderPlugin.ts
import * as THREE14 from "three";
// src/utils/traverseAncestorsFromRoot.ts
function traverseAncestorsFromRoot(object, callback) {
const ancestors = [];
let head = object;
while (head !== null) {
ancestors.unshift(head);
head = head.parent;
}
ancestors.forEach((ancestor) => {
callback(ancestor);
});
}
// src/utils/traverseChildrenUntilConditionMet.ts
function traverseChildrenUntilConditionMet(object, callback) {
object.children.forEach((child) => {
const result = callback(child);
if (!result) {
traverseChildrenUntilConditionMet(child, callback);
}
});
}
// src/utils/lowestCommonAncestor.ts
function lowestCommonAncestor(objects) {
var _a;
const sharedAncestors = /* @__PURE__ */ new Map();
for (const object of objects) {
let current = object;
do {
const newValue = ((_a = sharedAncestors.get(current)) != null ? _a : 0) + 1;
if (newValue === objects.size) {
return current;
}
sharedAncestors.set(current, newValue);
current = current.parent;
} while (current !== null);
}
return null;
}
// src/VRMSpringBoneManager.ts
var VRMSpringBoneManager = class {
constructor() {
this._joints = /* @__PURE__ */ new Set();
this._sortedJoints = [];
this._hasWarnedCircularDependency = false;
/**
* An ordered list of ancestors of all the SpringBone joints. Before the
* SpringBone joints can be updated, the world matrices of these ancestors
* must be calculated. The first element is the lowest common ancestor, for
* which not only its world matrix but its ancestors' world matrices are
* updated as well.
*/
this._ancestors = [];
this._objectSpringBonesMap = /* @__PURE__ */ new Map();
this._isSortedJointsDirty = false;
this._relevantChildrenUpdated = this._relevantChildrenUpdated.bind(this);
}
get joints() {
return this._joints;
}
/**
* @deprecated Use {@link joints} instead.
*/
get springBones() {
console.warn("VRMSpringBoneManager: springBones is deprecated. use joints instead.");
return this._joints;
}
get colliderGroups() {
const set = /* @__PURE__ */ new Set();
this._joints.forEach((springBone) => {
springBone.colliderGroups.forEach((colliderGroup) => {
set.add(colliderGroup);
});
});
return Array.from(set);
}
get colliders() {
const set = /* @__PURE__ */ new Set();
this.colliderGroups.forEach((colliderGroup) => {
colliderGroup.colliders.forEach((collider) => {
set.add(collider);
});
});
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;
}
/**
* @deprecated Use {@link addJoint} instead.
*/
addSpringBone(joint) {
console.warn("VRMSpringBoneManager: addSpringBone() is deprecated. use addJoint() instead.");
this.addJoint(joint);
}
deleteJoint(joint) {
this._joints.delete(joint);
const objectSet = this._objectSpringBonesMap.get(joint.bone);
objectSet.delete(joint);
this._isSortedJointsDirty = true;
}
/**
* @deprecated Use {@link deleteJoint} instead.
*/
deleteSpringBone(joint) {
console.warn("VRMSpringBoneManager: deleteSpringBone() is deprecated. use deleteJoint() instead.");
this.deleteJoint(joint);
}
setInitState() {
this._sortJoints();
for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
springBone.bone.updateWorldMatrix(false, false);
springBone.setInitState();
}
}
reset() {
this._sortJoints();
for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
springBone.bone.updateWorldMatrix(false, false);
springBone.reset();
}
}
update(delta) {
this._sortJoints();
for (let i = 0; i < this._ancestors.length; i++) {
this._ancestors[i].updateWorldMatrix(i === 0, false);
}
for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
springBone.bone.updateWorldMatrix(false, false);
springBone.update(delta);
traverseChildrenUntilConditionMet(springBone.bone, this._relevantChildrenUpdated);
}
}
/**
* 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, _b;
if (((_b = (_a = this._objectSpringBonesMap.get(object)) == null ? void 0 : _a.size) != null ? _b : 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);
}
_relevantChildrenUpdated(object) {
var _a, _b;
if (((_b = (_a = this._objectSpringBonesMap.get(object)) == null ? void 0 : _a.size) != null ? _b : 0) > 0) {
return true;
}
object.updateWorldMatrix(false, false);
return false;
}
};
// src/VRMSpringBoneLoaderPlugin.ts
var EXTENSION_NAME_EXTENDED_COLLIDER = "VRMC_springBone_extended_collider";
var POSSIBLE_SPEC_VERSIONS = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var POSSIBLE_SPEC_VERSIONS_EXTENDED_COLLIDERS = /* @__PURE__ */ new Set(["1.0"]);
var _VRMSpringBoneLoaderPlugin = class _VRMSpringBoneLoaderPlugin {
get name() {
return _VRMSpringBoneLoaderPlugin.EXTENSION_NAME;
}
constructor(parser, options) {
var _a;
this.parser = parser;
this.jointHelperRoot = options == null ? void 0 : options.jointHelperRoot;
this.colliderHelperRoot = options == null ? void 0 : options.colliderHelperRoot;
this.useExtendedColliders = (_a = options == null ? void 0 : options.useExtendedColliders) != null ? _a : true;
}
afterRoot(gltf) {
return __async(this, null, function* () {
gltf.userData.vrmSpringBoneManager = yield this._import(gltf);
});
}
/**
* Import spring bones from a GLTF and return a {@link VRMSpringBoneManager}.
* It might return `null` instead when it does not need to be created or something go wrong.
*
* @param gltf A parsed result of GLTF taken from GLTFLoader
*/
_import(gltf) {
return __async(this, null, function* () {
const v1Result = yield this._v1Import(gltf);
if (v1Result != null) {
return v1Result;
}
const v0Result = yield this._v0Import(gltf);
if (v0Result != null) {
return v0Result;
}
return null;
});
}
_v1Import(gltf) {
return __async(this, null, function* () {
var _a, _b, _c, _d, _e;
const json = gltf.parser.json;
const isSpringBoneUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf(_VRMSpringBoneLoaderPlugin.EXTENSION_NAME)) !== -1;
if (!isSpringBoneUsed) {
return null;
}
const manager = new VRMSpringBoneManager();
const threeNodes = yield gltf.parser.getDependencies("node");
const extension = (_b = json.extensions) == null ? void 0 : _b[_VRMSpringBoneLoaderPlugin.EXTENSION_NAME];
if (!extension) {
return null;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS.has(specVersion)) {
console.warn(
`VRMSpringBoneLoaderPlugin: Unknown ${_VRMSpringBoneLoaderPlugin.EXTENSION_NAME} specVersion "${specVersion}"`
);
return null;
}
const colliders = (_c = extension.colliders) == null ? void 0 : _c.map((schemaCollider, iCollider) => {
var _a2, _b2, _c2, _d2, _e2, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
const node = threeNodes[schemaCollider.node];
if (node == null) {
console.warn(
`VRMSpringBoneLoaderPlugin: The collider #${iCollider} attempted to use the node #${schemaCollider.node} but not found`
);
return null;
}
const schemaShape = schemaCollider.shape;
const schemaExCollider = (_a2 = schemaCollider.extensions) == null ? void 0 : _a2[EXTENSION_NAME_EXTENDED_COLLIDER];
if (this.useExtendedColliders && schemaExCollider != null) {
const specVersionExCollider = schemaExCollider.specVersion;
if (!POSSIBLE_SPEC_VERSIONS_EXTENDED_COLLIDERS.has(specVersionExCollider)) {
console.warn(
`VRMSpringBoneLoaderPlugin: Unknown ${EXTENSION_NAME_EXTENDED_COLLIDER} specVersion "${specVersionExCollider}". Fallbacking to the ${_VRMSpringBoneLoaderPlugin.EXTENSION_NAME} definition`
);
} else {
const schemaExShape = schemaExCollider.shape;
if (schemaExShape.sphere) {
return this._importSphereCollider(node, {
offset: new THREE14.Vector3().fromArray((_b2 = schemaExShape.sphere.offset) != null ? _b2 : [0, 0, 0]),
radius: (_c2 = schemaExShape.sphere.radius) != null ? _c2 : 0,
inside: (_d2 = schemaExShape.sphere.inside) != null ? _d2 : false
});
} else if (schemaExShape.capsule) {
return this._importCapsuleCollider(node, {
offset: new THREE14.Vector3().fromArray((_e2 = schemaExShape.capsule.offset) != null ? _e2 : [0, 0, 0]),
radius: (_f = schemaExShape.capsule.radius) != null ? _f : 0,
tail: new THREE14.Vector3().fromArray((_g = schemaExShape.capsule.tail) != null ? _g : [0, 0, 0]),
inside: (_h = schemaExShape.capsule.inside) != null ? _h : false
});
} else if (schemaExShape.plane) {
return this._importPlaneCollider(node, {
offset: new THREE14.Vector3().fromArray((_i = schemaExShape.plane.offset) != null ? _i : [0, 0, 0]),
normal: new THREE14.Vector3().fromArray((_j = schemaExShape.plane.normal) != null ? _j : [0, 0, 1])
});
}
}
}
if (schemaShape.sphere) {
return this._importSphereCollider(node, {
offset: new THREE14.Vector3().fromArray((_k = schemaShape.sphere.offset) != null ? _k : [0, 0, 0]),
radius: (_l = schemaShape.sphere.radius) != null ? _l : 0,
inside: false
});
} else if (schemaShape.capsule) {
return this._importCapsuleCollider(node, {
offset: new THREE14.Vector3().fromArray((_m = schemaShape.capsule.offset) != null ? _m : [0, 0, 0]),
radius: (_n = schemaShape.capsule.radius) != null ? _n : 0,
tail: new THREE14.Vector3().fromArray((_o = schemaShape.capsule.tail) != null ? _o : [0, 0, 0]),
inside: false
});
}
throw new Error(`VRMSpringBoneLoaderPlugin: The collider #${iCollider} has no valid shape`);
});
const colliderGroups = (_d = extension.colliderGroups) == null ? void 0 : _d.map(
(schemaColliderGroup, iColliderGroup) => {
var _a2;
const cols = ((_a2 = schemaColliderGroup.colliders) != null ? _a2 : []).flatMap((iCollider) => {
const col = colliders == null ? void 0 : colliders[iCollider];
if (col == null) {
console.warn(
`VRMSpringBoneLoaderPlugin: The colliderGroup #${iColliderGroup} attempted to use a collider #${iCollider} but not found`
);
return [];
}
return col;
});
return {
colliders: cols,
name: schemaColliderGroup.name
};
}
);
(_e = extension.springs) == null ? void 0 : _e.forEach((schemaSpring, iSpring) => {
var _a2;
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 = schemaSpring.center != null ? threeNodes[schemaSpring.center] : void 0;
let prevSchemaJoint;
schemaJoints.forEach((schemaJoint) => {
if (prevSchemaJoint) {
const nodeIndex = prevSchemaJoint.node;
const node = threeNodes[nodeIndex];
const childIndex = schemaJoint.node;
const child = threeNodes[childIndex];
const setting = {
hitRadius: prevSchemaJoint.hitRadius,
dragForce: prevSchemaJoint.dragForce,
gravityPower: prevSchemaJoint.gravityPower,
stiffness: prevSchemaJoint.stiffness,
gravityDir: prevSchemaJoint.gravityDir != null ? new THREE14.Vector3().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) {
return __async(this, null, function* () {
var _a, _b, _c;
const json = gltf.parser.json;
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRM")) !== -1;
if (!isVRMUsed) {
return null;
}
const extension = (_b = json.extensions) == null ? void 0 : _b["VRM"];
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 threeNodes = yield gltf.parser.getDependencies("node");
const colliderGroups = (_c = schemaSecondaryAnimation.colliderGroups) == null ? void 0 : _c.map(
(schemaColliderGroup) => {
var _a2;
const node = threeNodes[schemaColliderGroup.node];
const colliders = ((_a2 = schemaColliderGroup.colliders) != null ? _a2 : []).map((schemaCollider, iCollider) => {
var _a3, _b2, _c2;
const offset = new THREE14.Vector3(0, 0, 0);
if (schemaCollider.offset) {
offset.set(
(_a3 = schemaCollider.offset.x) != null ? _a3 : 0,
(_b2 = schemaCollider.offset.y) != null ? _b2 : 0,
schemaCollider.offset.z ? -schemaCollider.offset.z : 0
// z is opposite in VRM0.0
);
}
return this._importSphereCollider(node, {
offset,
radius: (_c2 = schemaCollider.radius) != null ? _c2 : 0,
inside: false
});
});
return { colliders };
}
);
schemaBoneGroups == null ? void 0 : schemaBoneGroups.forEach((schemaBoneGroup, iBoneGroup) => {
const rootIndices = schemaBoneGroup.bones;
if (!rootIndices) {
return;
}
rootIndices.forEach((rootIndex) => {
var _a2, _b2, _c2, _d;
const root = threeNodes[rootIndex];
const gravityDir = new THREE14.Vector3();
if (schemaBoneGroup.gravityDir) {
gravityDir.set(
(_a2 = schemaBoneGroup.gravityDir.x) != null ? _a2 : 0,
(_b2 = schemaBoneGroup.gravityDir.y) != null ? _b2 : 0,
(_c2 = schemaBoneGroup.gravityDir.z) != null ? _c2 : 0
);
} else {
gravityDir.set(0, -1, 0);
}
const center = schemaBoneGroup.center != null ? threeNodes[schemaBoneGroup.center] : void 0;
const setting = {
hitRadius: schemaBoneGroup.hitRadius,
dragForce: schemaBoneGroup.dragForce,
gravityPower: schemaBoneGroup.gravityPower,
stiffness: schemaBoneGroup.stiffiness,
gravityDir
};
const colliderGroupsForSpring = (_d = schemaBoneGroup.colliderGroups) == null ? void 0 : _d.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.traverse((node) => {
var _a3;
const child = (_a3 = node.children[0]) != null ? _a3 : null;
const joint = this._importJoint(node, child, setting, colliderGroupsForSpring);
if (center) {
joint.center = center;
}
manager.addJoint(joint);
});
});
});
gltf.scene.updateMatrixWorld();
manager.setInitState();
return manager;
});
}
_importJoint(node, child, setting, colliderGroupsForSpring) {
const springBone = new VRMSpringBoneJoint(node, child, setting, colliderGroupsForSpring);
if (this.jointHelperRoot) {
const helper = new VRMSpringBoneJointHelper(springBone);
this.jointHelperRoot.add(helper);
helper.renderOrder = this.jointHelperRoot.renderOrder;
}
return springBone;
}
_importSphereCollider(destination, params) {
const shape = new VRMSpringBoneColliderShapeSphere(params);
const collider = new VRMSpringBoneCollider(shape);
destination.add(collider);
if (this.colliderHelperRoot) {
const helper = new VRMSpringBoneColliderHelper(collider);
this.colliderHelperRoot.add(helper);
helper.renderOrder = this.colliderHelperRoot.renderOrder;
}
return collider;
}
_importCapsuleCollider(destination, params) {
const shape = new VRMSpringBoneColliderShapeCapsule(params);
const collider = new VRMSpringBoneCollider(shape);
destination.add(collider);
if (this.colliderHelperRoot) {
const helper = new VRMSpringBoneColliderHelper(collider);
this.colliderHelperRoot.add(helper);
helper.renderOrder = this.colliderHelperRoot.renderOrder;
}
return collider;
}
_importPlaneCollider(destination, params) {
const shape = new VRMSpringBoneColliderShapePlane(params);
const collider = new VRMSpringBoneCollider(shape);
destination.add(collider);
if (this.colliderHelperRoot) {
const helper = new VRMSpringBoneColliderHelper(collider);
this.colliderHelperRoot.add(helper);
helper.renderOrder = this.colliderHelperRoot.renderOrder;
}
return collider;
}
};
_VRMSpringBoneLoaderPlugin.EXTENSION_NAME = "VRMC_springBone";
var VRMSpringBoneLoaderPlugin = _VRMSpringBoneLoaderPlugin;
export {
VRMSpringBoneCollider,
VRMSpringBoneColliderHelper,
VRMSpringBoneColliderShape,
VRMSpringBoneColliderShapeCapsule,
VRMSpringBoneColliderShapePlane,
VRMSpringBoneColliderShapeSphere,
VRMSpringBoneJoint,
VRMSpringBoneJointHelper,
VRMSpringBoneLoaderPlugin,
VRMSpringBoneManager
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2hlbHBlcnMvVlJNU3ByaW5nQm9uZUNvbGxpZGVySGVscGVyLnRzIiwgIi4uL3NyYy9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZUNhcHN1bGUudHMiLCAiLi4vc3JjL1ZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlLnRzIiwgIi4uL3NyYy9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZVBsYW5lLnRzIiwgIi4uL3NyYy9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZVNwaGVyZS50cyIsICIuLi9zcmMvaGVscGVycy91dGlscy9Db2xsaWRlclNoYXBlQ2Fwc3VsZUJ1ZmZlckdlb21ldHJ5LnRzIiwgIi4uL3NyYy9oZWxwZXJzL3V0aWxzL0NvbGxpZGVyU2hhcGVQbGFuZUJ1ZmZlckdlb21ldHJ5LnRzIiwgIi4uL3NyYy9oZWxwZXJzL3V0aWxzL0NvbGxpZGVyU2hhcGVTcGhlcmVCdWZmZXJHZW9tZXRyeS50cyIsICIuLi9zcmMvaGVscGVycy9WUk1TcHJpbmdCb25lSm9pbnRIZWxwZXIudHMiLCAiLi4vc3JjL2hlbHBlcnMvdXRpbHMvU3ByaW5nQm9uZUJ1ZmZlckdlb21ldHJ5LnRzIiwgIi4uL3NyYy9WUk1TcHJpbmdCb25lQ29sbGlkZXIudHMiLCAiLi4vc3JjL1ZSTVNwcmluZ0JvbmVKb2ludC50cyIsICIuLi9zcmMvdXRpbHMvTWF0cml4NEludmVyc2VDYWNoZS50cyIsICIuLi9zcmMvdXRpbHMvbWF0NEludmVydENvbXBhdC50cyIsICIuLi9zcmMvVlJNU3ByaW5nQm9uZUxvYWRlclBsdWdpbi50cyIsICIuLi9zcmMvdXRpbHMvdHJhdmVyc2VBbmNlc3RvcnNGcm9tUm9vdC50cyIsICIuLi9zcmMvdXRpbHMvdHJhdmVyc2VDaGlsZHJlblVudGlsQ29uZGl0aW9uTWV0LnRzIiwgIi4uL3NyYy91dGlscy9sb3dlc3RDb21tb25BbmNlc3Rvci50cyIsICIuLi9zcmMvVlJNU3ByaW5nQm9uZU1hbmFnZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB7IFZSTVNwcmluZ0JvbmVDb2xsaWRlciB9IGZyb20gJy4uL1ZSTVNwcmluZ0JvbmVDb2xsaWRlcic7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZUNhcHN1bGUgfSBmcm9tICcuLi9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZUNhcHN1bGUnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVQbGFuZSB9IGZyb20gJy4uL1ZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlUGxhbmUnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUgfSBmcm9tICcuLi9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZVNwaGVyZSc7XG5pbXBvcnQgeyBDb2xsaWRlclNoYXBlQnVmZmVyR2VvbWV0cnkgfSBmcm9tICcuL3V0aWxzL0NvbGxpZGVyU2hhcGVCdWZmZXJHZW9tZXRyeSc7XG5pbXBvcnQgeyBDb2xsaWRlclNoYXBlQ2Fwc3VsZUJ1ZmZlckdlb21ldHJ5IH0gZnJvbSAnLi91dGlscy9Db2xsaWRlclNoYXBlQ2Fwc3VsZUJ1ZmZlckdlb21ldHJ5JztcbmltcG9ydCB7IENvbGxpZGVyU2hhcGVQbGFuZUJ1ZmZlckdlb21ldHJ5IH0gZnJvbSAnLi91dGlscy9Db2xsaWRlclNoYXBlUGxhbmVCdWZmZXJHZW9tZXRyeSc7XG5pbXBvcnQgeyBDb2xsaWRlclNoYXBlU3BoZXJlQnVmZmVyR2VvbWV0cnkgfSBmcm9tICcuL3V0aWxzL0NvbGxpZGVyU2hhcGVTcGhlcmVCdWZmZXJHZW9tZXRyeSc7XG5cbmNvbnN0IF92M0EgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuXG5leHBvcnQgY2xhc3MgVlJNU3ByaW5nQm9uZUNvbGxpZGVySGVscGVyIGV4dGVuZHMgVEhSRUUuR3JvdXAge1xuICBwdWJsaWMgcmVhZG9ubHkgY29sbGlkZXI6IFZSTVNwcmluZ0JvbmVDb2xsaWRlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBfZ2VvbWV0cnk6IENvbGxpZGVyU2hhcGVCdWZmZXJHZW9tZXRyeTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbGluZTogVEhSRUUuTGluZVNlZ21lbnRzO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihjb2xsaWRlcjogVlJNU3ByaW5nQm9uZUNvbGxpZGVyKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLm1hdHJpeEF1dG9VcGRhdGUgPSBmYWxzZTtcblxuICAgIHRoaXMuY29sbGlkZXIgPSBjb2xsaWRlcjtcblxuICAgIGlmICh0aGlzLmNvbGxpZGVyLnNoYXBlIGluc3RhbmNlb2YgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUpIHtcbiAgICAgIHRoaXMuX2dlb21ldHJ5ID0gbmV3IENvbGxpZGVyU2hhcGVTcGhlcmVCdWZmZXJHZW9tZXRyeSh0aGlzLmNvbGxpZGVyLnNoYXBlKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY29sbGlkZXIuc2hhcGUgaW5zdGFuY2VvZiBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZUNhcHN1bGUpIHtcbiAgICAgIHRoaXMuX2dlb21ldHJ5ID0gbmV3IENvbGxpZGVyU2hhcGVDYXBzdWxlQnVmZmVyR2VvbWV0cnkodGhpcy5jb2xsaWRlci5zaGFwZSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmNvbGxpZGVyLnNoYXBlIGluc3RhbmNlb2YgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVQbGFuZSkge1xuICAgICAgdGhpcy5fZ2VvbWV0cnkgPSBuZXcgQ29sbGlkZXJTaGFwZVBsYW5lQnVmZmVyR2VvbWV0cnkodGhpcy5jb2xsaWRlci5zaGFwZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVlJNU3ByaW5nQm9uZUNvbGxpZGVySGVscGVyOiBVbmtub3duIGNvbGxpZGVyIHNoYXBlIHR5cGUgZGV0ZWN0ZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBtYXRlcmlhbCA9IG5ldyBUSFJFRS5MaW5lQmFzaWNNYXRlcmlhbCh7XG4gICAgICBjb2xvcjogMHhmZjAwZmYsXG4gICAgICBkZXB0aFRlc3Q6IGZhbHNlLFxuICAgICAgZGVwdGhXcml0ZTogZmFsc2UsXG4gICAgfSk7XG5cbiAgICB0aGlzLl9saW5lID0gbmV3IFRIUkVFLkxpbmVTZWdtZW50cyh0aGlzLl9nZW9tZXRyeSwgbWF0ZXJpYWwpO1xuICAgIHRoaXMuYWRkKHRoaXMuX2xpbmUpO1xuICB9XG5cbiAgcHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5fZ2VvbWV0cnkuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHVibGljIHVwZGF0ZU1hdHJpeFdvcmxkKGZvcmNlOiBib29sZWFuKTogdm9pZCB7XG4gICAgd