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

431 lines
56 KiB
JavaScript
Raw Permalink Normal View History

2026-05-24 13:31:30 +02:00
/*!
* @pixiv/three-vrm-node-constraint v3.4.1
* Node constraint module for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-node-constraint 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/VRMNodeConstraintHelper.ts
import * as THREE from "three";
var _v3A = new THREE.Vector3();
var VRMNodeConstraintHelper = class extends THREE.Group {
constructor(constraint) {
super();
this._attrPosition = new THREE.BufferAttribute(new Float32Array([0, 0, 0, 0, 0, 0]), 3);
this._attrPosition.setUsage(THREE.DynamicDrawUsage);
const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", this._attrPosition);
const material = new THREE.LineBasicMaterial({
color: 16711935,
depthTest: false,
depthWrite: false
});
this._line = new THREE.Line(geometry, material);
this.add(this._line);
this.constraint = constraint;
}
updateMatrixWorld(force) {
_v3A.setFromMatrixPosition(this.constraint.destination.matrixWorld);
this._attrPosition.setXYZ(0, _v3A.x, _v3A.y, _v3A.z);
if (this.constraint.source) {
_v3A.setFromMatrixPosition(this.constraint.source.matrixWorld);
}
this._attrPosition.setXYZ(1, _v3A.x, _v3A.y, _v3A.z);
this._attrPosition.needsUpdate = true;
super.updateMatrixWorld(force);
}
};
// src/VRMAimConstraint.ts
import * as THREE3 from "three";
// src/utils/decomposePosition.ts
function decomposePosition(matrix, target) {
return target.set(matrix.elements[12], matrix.elements[13], matrix.elements[14]);
}
// src/utils/decomposeRotation.ts
import * as THREE2 from "three";
var _v3A2 = new THREE2.Vector3();
var _v3B = new THREE2.Vector3();
function decomposeRotation(matrix, target) {
matrix.decompose(_v3A2, target, _v3B);
return target;
}
// src/utils/quatInvertCompat.ts
function quatInvertCompat(target) {
if (target.invert) {
target.invert();
} else {
target.inverse();
}
return target;
}
// src/VRMNodeConstraint.ts
var VRMNodeConstraint = class {
/**
* @param destination The destination object
* @param source The source object
*/
constructor(destination, source) {
this.destination = destination;
this.source = source;
this.weight = 1;
}
};
// src/VRMAimConstraint.ts
var _v3A3 = new THREE3.Vector3();
var _v3B2 = new THREE3.Vector3();
var _v3C = new THREE3.Vector3();
var _quatA = new THREE3.Quaternion();
var _quatB = new THREE3.Quaternion();
var _quatC = new THREE3.Quaternion();
var VRMAimConstraint = class extends VRMNodeConstraint {
/**
* The aim axis of the constraint.
*/
get aimAxis() {
return this._aimAxis;
}
/**
* The aim axis of the constraint.
*/
set aimAxis(aimAxis) {
this._aimAxis = aimAxis;
this._v3AimAxis.set(
aimAxis === "PositiveX" ? 1 : aimAxis === "NegativeX" ? -1 : 0,
aimAxis === "PositiveY" ? 1 : aimAxis === "NegativeY" ? -1 : 0,
aimAxis === "PositiveZ" ? 1 : aimAxis === "NegativeZ" ? -1 : 0
);
}
get dependencies() {
const set = /* @__PURE__ */ new Set([this.source]);
if (this.destination.parent) {
set.add(this.destination.parent);
}
return set;
}
constructor(destination, source) {
super(destination, source);
this._aimAxis = "PositiveX";
this._v3AimAxis = new THREE3.Vector3(1, 0, 0);
this._dstRestQuat = new THREE3.Quaternion();
}
setInitState() {
this._dstRestQuat.copy(this.destination.quaternion);
}
update() {
this.destination.updateWorldMatrix(true, false);
this.source.updateWorldMatrix(true, false);
const dstParentWorldQuat = _quatA.identity();
const invDstParentWorldQuat = _quatB.identity();
if (this.destination.parent) {
decomposeRotation(this.destination.parent.matrixWorld, dstParentWorldQuat);
quatInvertCompat(invDstParentWorldQuat.copy(dstParentWorldQuat));
}
const a0 = _v3A3.copy(this._v3AimAxis).applyQuaternion(this._dstRestQuat).applyQuaternion(dstParentWorldQuat);
const a1 = decomposePosition(this.source.matrixWorld, _v3B2).sub(decomposePosition(this.destination.matrixWorld, _v3C)).normalize();
const targetQuat = _quatC.setFromUnitVectors(a0, a1).premultiply(invDstParentWorldQuat).multiply(dstParentWorldQuat).multiply(this._dstRestQuat);
this.destination.quaternion.copy(this._dstRestQuat).slerp(targetQuat, this.weight);
}
};
// src/utils/traverseAncestorsFromRoot.ts
function traverseAncestorsFromRoot(object, callback) {
const ancestors = [object];
let head = object.parent;
while (head !== null) {
ancestors.unshift(head);
head = head.parent;
}
ancestors.forEach((ancestor) => {
callback(ancestor);
});
}
// src/VRMNodeConstraintManager.ts
var VRMNodeConstraintManager = class {
constructor() {
this._constraints = /* @__PURE__ */ new Set();
this._objectConstraintsMap = /* @__PURE__ */ new Map();
}
get constraints() {
return this._constraints;
}
addConstraint(constraint) {
this._constraints.add(constraint);
let objectSet = this._objectConstraintsMap.get(constraint.destination);
if (objectSet == null) {
objectSet = /* @__PURE__ */ new Set();
this._objectConstraintsMap.set(constraint.destination, objectSet);
}
objectSet.add(constraint);
}
deleteConstraint(constraint) {
this._constraints.delete(constraint);
const objectSet = this._objectConstraintsMap.get(constraint.destination);
objectSet.delete(constraint);
}
setInitState() {
const constraintsTried = /* @__PURE__ */ new Set();
const constraintsDone = /* @__PURE__ */ new Set();
for (const constraint of this._constraints) {
this._processConstraint(constraint, constraintsTried, constraintsDone, (constraint2) => constraint2.setInitState());
}
}
update() {
const constraintsTried = /* @__PURE__ */ new Set();
const constraintsDone = /* @__PURE__ */ new Set();
for (const constraint of this._constraints) {
this._processConstraint(constraint, constraintsTried, constraintsDone, (constraint2) => constraint2.update());
}
}
/**
* Update a constraint.
* If there are other constraints that are dependant, it will try to update them recursively.
* It might throw an error if there are circular dependencies.
*
* Intended to be used in {@link update} and {@link _processConstraint} itself recursively.
*
* @param constraint A constraint you want to update
* @param constraintsTried Set of constraints that are already tried to be updated
* @param constraintsDone Set of constraints that are already up to date
*/
_processConstraint(constraint, constraintsTried, constraintsDone, callback) {
if (constraintsDone.has(constraint)) {
return;
}
if (constraintsTried.has(constraint)) {
throw new Error("VRMNodeConstraintManager: Circular dependency detected while updating constraints");
}
constraintsTried.add(constraint);
const depObjects = constraint.dependencies;
for (const depObject of depObjects) {
traverseAncestorsFromRoot(depObject, (depObjectAncestor) => {
const objectSet = this._objectConstraintsMap.get(depObjectAncestor);
if (objectSet) {
for (const depConstraint of objectSet) {
this._processConstraint(depConstraint, constraintsTried, constraintsDone, callback);
}
}
});
}
callback(constraint);
constraintsDone.add(constraint);
}
};
// src/VRMRotationConstraint.ts
import * as THREE4 from "three";
var _quatA2 = new THREE4.Quaternion();
var _quatB2 = new THREE4.Quaternion();
var VRMRotationConstraint = class extends VRMNodeConstraint {
get dependencies() {
return /* @__PURE__ */ new Set([this.source]);
}
constructor(destination, source) {
super(destination, source);
this._dstRestQuat = new THREE4.Quaternion();
this._invSrcRestQuat = new THREE4.Quaternion();
}
setInitState() {
this._dstRestQuat.copy(this.destination.quaternion);
quatInvertCompat(this._invSrcRestQuat.copy(this.source.quaternion));
}
update() {
const srcDeltaQuat = _quatA2.copy(this._invSrcRestQuat).multiply(this.source.quaternion);
const targetQuat = _quatB2.copy(this._dstRestQuat).multiply(srcDeltaQuat);
this.destination.quaternion.copy(this._dstRestQuat).slerp(targetQuat, this.weight);
}
};
// src/VRMRollConstraint.ts
import * as THREE5 from "three";
var _v3A4 = new THREE5.Vector3();
var _quatA3 = new THREE5.Quaternion();
var _quatB3 = new THREE5.Quaternion();
var VRMRollConstraint = class extends VRMNodeConstraint {
/**
* The roll axis of the constraint.
*/
get rollAxis() {
return this._rollAxis;
}
/**
* The roll axis of the constraint.
*/
set rollAxis(rollAxis) {
this._rollAxis = rollAxis;
this._v3RollAxis.set(rollAxis === "X" ? 1 : 0, rollAxis === "Y" ? 1 : 0, rollAxis === "Z" ? 1 : 0);
}
get dependencies() {
return /* @__PURE__ */ new Set([this.source]);
}
constructor(destination, source) {
super(destination, source);
this._rollAxis = "X";
this._v3RollAxis = new THREE5.Vector3(1, 0, 0);
this._dstRestQuat = new THREE5.Quaternion();
this._invDstRestQuat = new THREE5.Quaternion();
this._invSrcRestQuatMulDstRestQuat = new THREE5.Quaternion();
}
setInitState() {
this._dstRestQuat.copy(this.destination.quaternion);
quatInvertCompat(this._invDstRestQuat.copy(this._dstRestQuat));
quatInvertCompat(this._invSrcRestQuatMulDstRestQuat.copy(this.source.quaternion)).multiply(this._dstRestQuat);
}
update() {
const quatDelta = _quatA3.copy(this._invDstRestQuat).multiply(this.source.quaternion).multiply(this._invSrcRestQuatMulDstRestQuat);
const n1 = _v3A4.copy(this._v3RollAxis).applyQuaternion(quatDelta);
const quatFromTo = _quatB3.setFromUnitVectors(n1, this._v3RollAxis);
const targetQuat = quatFromTo.premultiply(this._dstRestQuat).multiply(quatDelta);
this.destination.quaternion.copy(this._dstRestQuat).slerp(targetQuat, this.weight);
}
};
// src/VRMNodeConstraintLoaderPlugin.ts
var POSSIBLE_SPEC_VERSIONS = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var _VRMNodeConstraintLoaderPlugin = class _VRMNodeConstraintLoaderPlugin {
get name() {
return _VRMNodeConstraintLoaderPlugin.EXTENSION_NAME;
}
constructor(parser, options) {
this.parser = parser;
this.helperRoot = options == null ? void 0 : options.helperRoot;
}
afterRoot(gltf) {
return __async(this, null, function* () {
gltf.userData.vrmNodeConstraintManager = yield this._import(gltf);
});
}
/**
* Import constraints from a GLTF and returns a {@link VRMNodeConstraintManager}.
* 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* () {
var _a;
const json = this.parser.json;
const isConstraintsUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf(_VRMNodeConstraintLoaderPlugin.EXTENSION_NAME)) !== -1;
if (!isConstraintsUsed) {
return null;
}
const manager = new VRMNodeConstraintManager();
const threeNodes = yield this.parser.getDependencies("node");
threeNodes.forEach((node, nodeIndex) => {
var _a2;
const schemaNode = json.nodes[nodeIndex];
const extension = (_a2 = schemaNode == null ? void 0 : schemaNode.extensions) == null ? void 0 : _a2[_VRMNodeConstraintLoaderPlugin.EXTENSION_NAME];
if (extension == null) {
return;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS.has(specVersion)) {
console.warn(
`VRMNodeConstraintLoaderPlugin: Unknown ${_VRMNodeConstraintLoaderPlugin.EXTENSION_NAME} specVersion "${specVersion}"`
);
return;
}
const constraintDef = extension.constraint;
if (constraintDef.roll != null) {
const constraint = this._importRollConstraint(node, threeNodes, constraintDef.roll);
manager.addConstraint(constraint);
} else if (constraintDef.aim != null) {
const constraint = this._importAimConstraint(node, threeNodes, constraintDef.aim);
manager.addConstraint(constraint);
} else if (constraintDef.rotation != null) {
const constraint = this._importRotationConstraint(node, threeNodes, constraintDef.rotation);
manager.addConstraint(constraint);
}
});
gltf.scene.updateMatrixWorld();
manager.setInitState();
return manager;
});
}
_importRollConstraint(destination, nodes, rollConstraintDef) {
const { source: sourceIndex, rollAxis, weight } = rollConstraintDef;
const source = nodes[sourceIndex];
const constraint = new VRMRollConstraint(destination, source);
if (rollAxis != null) {
constraint.rollAxis = rollAxis;
}
if (weight != null) {
constraint.weight = weight;
}
if (this.helperRoot) {
const helper = new VRMNodeConstraintHelper(constraint);
this.helperRoot.add(helper);
}
return constraint;
}
_importAimConstraint(destination, nodes, aimConstraintDef) {
const { source: sourceIndex, aimAxis, weight } = aimConstraintDef;
const source = nodes[sourceIndex];
const constraint = new VRMAimConstraint(destination, source);
if (aimAxis != null) {
constraint.aimAxis = aimAxis;
}
if (weight != null) {
constraint.weight = weight;
}
if (this.helperRoot) {
const helper = new VRMNodeConstraintHelper(constraint);
this.helperRoot.add(helper);
}
return constraint;
}
_importRotationConstraint(destination, nodes, rotationConstraintDef) {
const { source: sourceIndex, weight } = rotationConstraintDef;
const source = nodes[sourceIndex];
const constraint = new VRMRotationConstraint(destination, source);
if (weight != null) {
constraint.weight = weight;
}
if (this.helperRoot) {
const helper = new VRMNodeConstraintHelper(constraint);
this.helperRoot.add(helper);
}
return constraint;
}
};
_VRMNodeConstraintLoaderPlugin.EXTENSION_NAME = "VRMC_node_constraint";
var VRMNodeConstraintLoaderPlugin = _VRMNodeConstraintLoaderPlugin;
export {
VRMAimConstraint,
VRMNodeConstraint,
VRMNodeConstraintHelper,
VRMNodeConstraintLoaderPlugin,
VRMNodeConstraintManager,
VRMRollConstraint,
VRMRotationConstraint
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2hlbHBlcnMvVlJNTm9kZUNvbnN0cmFpbnRIZWxwZXIudHMiLCAiLi4vc3JjL1ZSTUFpbUNvbnN0cmFpbnQudHMiLCAiLi4vc3JjL3V0aWxzL2RlY29tcG9zZVBvc2l0aW9uLnRzIiwgIi4uL3NyYy91dGlscy9kZWNvbXBvc2VSb3RhdGlvbi50cyIsICIuLi9zcmMvdXRpbHMvcXVhdEludmVydENvbXBhdC50cyIsICIuLi9zcmMvVlJNTm9kZUNvbnN0cmFpbnQudHMiLCAiLi4vc3JjL3V0aWxzL3RyYXZlcnNlQW5jZXN0b3JzRnJvbVJvb3QudHMiLCAiLi4vc3JjL1ZSTU5vZGVDb25zdHJhaW50TWFuYWdlci50cyIsICIuLi9zcmMvVlJNUm90YXRpb25Db25zdHJhaW50LnRzIiwgIi4uL3NyYy9WUk1Sb2xsQ29uc3RyYWludC50cyIsICIuLi9zcmMvVlJNTm9kZUNvbnN0cmFpbnRMb2FkZXJQbHVnaW4udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB7IFZSTU5vZGVDb25zdHJhaW50IH0gZnJvbSAnLi4vVlJNTm9kZUNvbnN0cmFpbnQnO1xuXG5jb25zdCBfdjNBID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcblxuZXhwb3J0IGNsYXNzIFZSTU5vZGVDb25zdHJhaW50SGVscGVyIGV4dGVuZHMgVEhSRUUuR3JvdXAge1xuICBwdWJsaWMgcmVhZG9ubHkgY29uc3RyYWludDogVlJNTm9kZUNvbnN0cmFpbnQ7XG4gIHByaXZhdGUgX2xpbmU6IFRIUkVFLkxpbmU7XG4gIHByaXZhdGUgX2F0dHJQb3NpdGlvbjogVEhSRUUuQnVmZmVyQXR0cmlidXRlO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihjb25zdHJhaW50OiBWUk1Ob2RlQ29uc3RyYWludCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9hdHRyUG9zaXRpb24gPSBuZXcgVEhSRUUuQnVmZmVyQXR0cmlidXRlKG5ldyBGbG9hdDMyQXJyYXkoWzAsIDAsIDAsIDAsIDAsIDBdKSwgMyk7XG4gICAgdGhpcy5fYXR0clBvc2l0aW9uLnNldFVzYWdlKFRIUkVFLkR5bmFtaWNEcmF3VXNhZ2UpO1xuXG4gICAgY29uc3QgZ2VvbWV0cnkgPSBuZXcgVEhSRUUuQnVmZmVyR2VvbWV0cnkoKTtcbiAgICBnZW9tZXRyeS5zZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJywgdGhpcy5fYXR0clBvc2l0aW9uKTtcblxuICAgIGNvbnN0IG1hdGVyaWFsID0gbmV3IFRIUkVFLkxpbmVCYXNpY01hdGVyaWFsKHtcbiAgICAgIGNvbG9yOiAweGZmMDBmZixcbiAgICAgIGRlcHRoVGVzdDogZmFsc2UsXG4gICAgICBkZXB0aFdyaXRlOiBmYWxzZSxcbiAgICB9KTtcblxuICAgIHRoaXMuX2xpbmUgPSBuZXcgVEhSRUUuTGluZShnZW9tZXRyeSwgbWF0ZXJpYWwpO1xuICAgIHRoaXMuYWRkKHRoaXMuX2xpbmUpO1xuXG4gICAgdGhpcy5jb25zdHJhaW50ID0gY29uc3RyYWludDtcbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGVNYXRyaXhXb3JsZChmb3JjZT86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBfdjNBLnNldEZyb21NYXRyaXhQb3NpdGlvbih0aGlzLmNvbnN0cmFpbnQuZGVzdGluYXRpb24ubWF0cml4V29ybGQpO1xuICAgIHRoaXMuX2F0dHJQb3NpdGlvbi5zZXRYWVooMCwgX3YzQS54LCBfdjNBLnksIF92M0Eueik7XG5cbiAgICBpZiAodGhpcy5jb25zdHJhaW50LnNvdXJjZSkge1xuICAgICAgX3YzQS5zZXRGcm9tTWF0cml4UG9zaXRpb24odGhpcy5jb25zdHJhaW50LnNvdXJjZS5tYXRyaXhXb3JsZCk7XG4gICAgfVxuICAgIHRoaXMuX2F0dHJQb3NpdGlvbi5zZXRYWVooMSwgX3YzQS54LCBfdjNBLnksIF92M0Eueik7XG5cbiAgICB0aGlzLl9hdHRyUG9zaXRpb24ubmVlZHNVcGRhdGUgPSB0cnVlO1xuXG4gICAgc3VwZXIudXBkYXRlTWF0cml4V29ybGQoZm9yY2UpO1xuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuaW1wb3J0IHsgZGVjb21wb3NlUG9zaXRpb24gfSBmcm9tICcuL3V0aWxzL2RlY29tcG9zZVBvc2l0aW9uJztcbmltcG9ydCB7IGRlY29tcG9zZVJvdGF0aW9uIH0gZnJvbSAnLi91dGlscy9kZWNvbXBvc2VSb3RhdGlvbic7XG5pbXBvcnQgeyBxdWF0SW52ZXJ0Q29tcGF0IH0gZnJvbSAnLi91dGlscy9xdWF0SW52ZXJ0Q29tcGF0JztcbmltcG9ydCB7IFZSTU5vZGVDb25zdHJhaW50IH0gZnJvbSAnLi9WUk1Ob2RlQ29uc3RyYWludCc7XG5cbmNvbnN0IF92M0EgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuY29uc3QgX3YzQiA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG5jb25zdCBfdjNDID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcbmNvbnN0IF9xdWF0QSA9IG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCk7XG5jb25zdCBfcXVhdEIgPSBuZXcgVEhSRUUuUXVhdGVybmlvbigpO1xuY29uc3QgX3F1YXRDID0gbmV3IFRIUkVFLlF1YXRlcm5pb24oKTtcblxuLyoqXG4gKiBBIGNvbnN0cmFpbnQgdGhhdCBtYWtlcyBpdCBsb29rIGF0IGEgc291cmNlIG9iamVjdC5cbiAqXG4gKiBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92cm0tYy92cm0tc3BlY2lmaWNhdGlvbi90cmVlL21hc3Rlci9zcGVjaWZpY2F0aW9uL1ZSTUNfbm9kZV9jb25zdHJhaW50LTEuMF9iZXRhI3JvbGwtY29uc3RyYWludFxuICovXG5leHBvcnQgY2xhc3MgVlJNQWltQ29uc3RyYWludCBleHRlbmRzIFZSTU5vZGVDb25zdHJhaW50IHtcbiAgLyoqXG4gICAqIFRoZSBhaW0gYXhpcyBvZiB0aGUgY29uc3RyYWludC5cbiAgICovXG4gIHB1YmxpYyBnZXQgYWltQXhpcygpOiAnUG9zaXRpdmVYJyB8ICdOZWdhdGl2ZVgnIHwgJ1Bvc2l0aXZlWScgfCAnTmVnYXRpdmVZJyB8ICdQb3NpdGl2ZVonIHwgJ05lZ2F0aXZlWicge1xuICAgIHJldHVybiB0aGlzLl9haW1BeGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBhaW0gYXhpcyBvZiB0aGUgY29uc3RyYWludC5cbiAgICovXG4gIHB1YmxpYyBzZXQgYWltQXhpcyhhaW1BeGlzOiAnUG9zaXRpdmVYJyB8ICdOZWdhdGl2ZVgnIHwgJ1Bvc2l0aXZlWScgfCAnTmVnYXRpdmVZJyB8ICdQb3NpdGl2ZVonIHwgJ05lZ2F0aXZlWicpIHtcbiAgICB0aGlzLl9haW1BeGlzID0gYWltQXhpcztcbiAgICB0aGlzLl92M0FpbUF4aXMuc2V0KFxuICAgICAgYWltQ