@adatechnology/game-characters-three 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +164 -105
- package/dist/index.global.js +604 -331
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +522 -333
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.global.js
CHANGED
|
@@ -1687,6 +1687,90 @@ var GameCharactersThree = (() => {
|
|
|
1687
1687
|
shims.add(result);
|
|
1688
1688
|
return result;
|
|
1689
1689
|
}
|
|
1690
|
+
var isTexture = (v) => !!v && typeof v === "object" && v.isTexture === true;
|
|
1691
|
+
function texturesOf(material, out) {
|
|
1692
|
+
for (const value of Object.values(material)) if (isTexture(value)) out.add(value);
|
|
1693
|
+
const uniforms = material.uniforms;
|
|
1694
|
+
if (uniforms) {
|
|
1695
|
+
for (const u of Object.values(uniforms)) if (isTexture(u?.value)) out.add(u.value);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
function collect(roots) {
|
|
1699
|
+
const geometries = /* @__PURE__ */ new Set();
|
|
1700
|
+
const materials = /* @__PURE__ */ new Set();
|
|
1701
|
+
const textures = /* @__PURE__ */ new Set();
|
|
1702
|
+
const skeletons = /* @__PURE__ */ new Set();
|
|
1703
|
+
for (const root of roots) {
|
|
1704
|
+
root.traverse((object2) => {
|
|
1705
|
+
const o = object2;
|
|
1706
|
+
if (o.geometry && typeof o.geometry.dispose === "function") geometries.add(o.geometry);
|
|
1707
|
+
if (o.skeleton && typeof o.skeleton.dispose === "function") skeletons.add(o.skeleton);
|
|
1708
|
+
const list2 = Array.isArray(o.material) ? o.material : o.material ? [o.material] : [];
|
|
1709
|
+
for (const m of list2) {
|
|
1710
|
+
if (!m || typeof m.dispose !== "function") continue;
|
|
1711
|
+
materials.add(m);
|
|
1712
|
+
texturesOf(m, textures);
|
|
1713
|
+
}
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
return { geometries, materials, textures, skeletons };
|
|
1717
|
+
}
|
|
1718
|
+
var marked = /* @__PURE__ */ new WeakSet();
|
|
1719
|
+
var shared = (r) => r.userData?.shared === true || marked.has(r);
|
|
1720
|
+
function releaseObject3D(roots, options = {}) {
|
|
1721
|
+
const list2 = Array.isArray(roots) ? roots : [roots];
|
|
1722
|
+
const report2 = { geometries: 0, materials: 0, textures: 0 };
|
|
1723
|
+
if (list2.length === 0) return report2;
|
|
1724
|
+
const found = collect(list2);
|
|
1725
|
+
const keepRoots = options.keep === void 0 ? [] : Array.isArray(options.keep) ? options.keep : [options.keep];
|
|
1726
|
+
const releasing = new Set(list2);
|
|
1727
|
+
for (const keep of keepRoots) {
|
|
1728
|
+
const walk = (o) => {
|
|
1729
|
+
if (releasing.has(o)) return;
|
|
1730
|
+
const owner = o;
|
|
1731
|
+
if (owner.geometry) found.geometries.delete(owner.geometry);
|
|
1732
|
+
if (owner.skeleton) found.skeletons.delete(owner.skeleton);
|
|
1733
|
+
const mats = Array.isArray(owner.material) ? owner.material : owner.material ? [owner.material] : [];
|
|
1734
|
+
for (const m of mats) {
|
|
1735
|
+
if (!m) continue;
|
|
1736
|
+
found.materials.delete(m);
|
|
1737
|
+
const t = /* @__PURE__ */ new Set();
|
|
1738
|
+
texturesOf(m, t);
|
|
1739
|
+
for (const x of t) found.textures.delete(x);
|
|
1740
|
+
}
|
|
1741
|
+
for (const c of o.children) walk(c);
|
|
1742
|
+
};
|
|
1743
|
+
walk(keep);
|
|
1744
|
+
}
|
|
1745
|
+
for (const g of found.geometries) {
|
|
1746
|
+
if (shared(g)) continue;
|
|
1747
|
+
g.dispose();
|
|
1748
|
+
report2.geometries++;
|
|
1749
|
+
}
|
|
1750
|
+
for (const m of found.materials) {
|
|
1751
|
+
if (shared(m)) continue;
|
|
1752
|
+
m.dispose();
|
|
1753
|
+
report2.materials++;
|
|
1754
|
+
}
|
|
1755
|
+
for (const t of found.textures) {
|
|
1756
|
+
if (shared(t)) continue;
|
|
1757
|
+
t.dispose();
|
|
1758
|
+
report2.textures++;
|
|
1759
|
+
}
|
|
1760
|
+
for (const s of found.skeletons) s.dispose();
|
|
1761
|
+
return report2;
|
|
1762
|
+
}
|
|
1763
|
+
function discardObject3D(objects, options = {}) {
|
|
1764
|
+
const list2 = Array.isArray(objects) ? objects : [objects];
|
|
1765
|
+
const keep = options.keep === void 0 ? [] : Array.isArray(options.keep) ? [...options.keep] : [options.keep];
|
|
1766
|
+
for (const object2 of list2) {
|
|
1767
|
+
let top = object2;
|
|
1768
|
+
while (top.parent) top = top.parent;
|
|
1769
|
+
object2.removeFromParent();
|
|
1770
|
+
if (top !== object2 && !keep.includes(top)) keep.push(top);
|
|
1771
|
+
}
|
|
1772
|
+
return releaseObject3D(list2, { keep });
|
|
1773
|
+
}
|
|
1690
1774
|
|
|
1691
1775
|
// ../game-contracts/dist/index.js
|
|
1692
1776
|
var DEFAULT_BLAST_SHOVE = { coupling: 0.02, maxSpeed: 20, lift: 0.3, minSpeed: 0.3, falloffPower: 2 };
|
|
@@ -5221,7 +5305,7 @@ var GameCharactersThree = (() => {
|
|
|
5221
5305
|
});
|
|
5222
5306
|
}
|
|
5223
5307
|
const neckLen = 0.14 + Math.max(0, P.neck);
|
|
5224
|
-
|
|
5308
|
+
const neck = cut.head ? void 0 : add(U, CYL(0.058, 0.068, neckLen, SEG), skinM, 0, 1.63 + Math.max(0, P.neck) / 2, 0);
|
|
5225
5309
|
const headG = new THREE.Group();
|
|
5226
5310
|
headG.position.set(0, 1.64 + P.neck, P.headFwd || 0);
|
|
5227
5311
|
headG.rotation.x = P.headX;
|
|
@@ -5428,6 +5512,7 @@ var GameCharactersThree = (() => {
|
|
|
5428
5512
|
if (o.userData.flap) flaps.push(o);
|
|
5429
5513
|
});
|
|
5430
5514
|
const rig = { flaps, dangles: arms.filter((a) => a.el.userData.dangle), type: spec.type || "Lento", fig, upper, headG, arms, legs, P, ph: spec.phase ?? options.random() * 6, dropBase: fig.position.y, leanBase: P.lean, hxBase: P.headX };
|
|
5515
|
+
if (neck) Object.defineProperty(rig, "neck", { value: neck });
|
|
5431
5516
|
if (spec.lying) {
|
|
5432
5517
|
root.rotation.x = -PI / 2;
|
|
5433
5518
|
root.position.set(0, 0.16 * P.s, 0.9 * P.s);
|
|
@@ -5438,8 +5523,8 @@ var GameCharactersThree = (() => {
|
|
|
5438
5523
|
root.userData.rig = rig;
|
|
5439
5524
|
return root;
|
|
5440
5525
|
}
|
|
5441
|
-
const
|
|
5442
|
-
return { build:
|
|
5526
|
+
const marked2 = (...args) => markKitOrigin(build(...args), { owner: "game-characters-three", kind: "person" });
|
|
5527
|
+
return { build: marked2, TYPES, setLOD(k) {
|
|
5443
5528
|
LK = k;
|
|
5444
5529
|
SEG = Math.max(5, Math.round(16 * k));
|
|
5445
5530
|
}, topM: () => topM_ref };
|
|
@@ -6907,7 +6992,10 @@ var GameCharactersThree = (() => {
|
|
|
6907
6992
|
const quaternion = new three.Quaternion();
|
|
6908
6993
|
const euler = new three.Euler();
|
|
6909
6994
|
const trim = () => {
|
|
6910
|
-
while (pieces.length > max)
|
|
6995
|
+
while (pieces.length > max) {
|
|
6996
|
+
const piece = pieces.shift();
|
|
6997
|
+
if (piece) discardObject3D(piece.object);
|
|
6998
|
+
}
|
|
6911
6999
|
};
|
|
6912
7000
|
const add = (object2, velocity, spin, tag) => {
|
|
6913
7001
|
const piece = { object: object2, velocity, spin, rest: false, ...tag ? { tag } : {} };
|
|
@@ -6956,7 +7044,7 @@ var GameCharactersThree = (() => {
|
|
|
6956
7044
|
}
|
|
6957
7045
|
},
|
|
6958
7046
|
clear() {
|
|
6959
|
-
pieces.splice(0).
|
|
7047
|
+
discardObject3D(pieces.splice(0).map((piece) => piece.object));
|
|
6960
7048
|
}
|
|
6961
7049
|
};
|
|
6962
7050
|
};
|
|
@@ -8165,7 +8253,8 @@ var GameCharactersThree = (() => {
|
|
|
8165
8253
|
const makeKit = () => options.createKit ? options.createKit({ penetration: settings.penetration, deathRule: settings.deathRule }) : createCharacters({ ...options.packs ? { packs: options.packs } : {}, penetration: settings.penetration, damage: { deathRule: settings.deathRule } });
|
|
8166
8254
|
let kit = makeKit();
|
|
8167
8255
|
let undead = options.createUndead ? options.createUndead(kit) : null;
|
|
8168
|
-
|
|
8256
|
+
let stream = createRng(options.seed ?? 1);
|
|
8257
|
+
const random = () => stream();
|
|
8169
8258
|
let seedCounter = 100;
|
|
8170
8259
|
let host = null;
|
|
8171
8260
|
let three = null;
|
|
@@ -8545,6 +8634,14 @@ var GameCharactersThree = (() => {
|
|
|
8545
8634
|
wounds = createWounds(lent.THREE, { random, scene: scene2, groundAt: (x, z) => lent.groundAt(x, z), ...bridge ? { bridge } : {}, ...sound ? { sound } : {} });
|
|
8546
8635
|
for (const entry of entries.values()) trackEntry(entry);
|
|
8547
8636
|
const stopChange = lent.bench?.onChange(onChange);
|
|
8637
|
+
const stopReset = lent.onReset?.(() => {
|
|
8638
|
+
stream = createRng(options.seed ?? 1);
|
|
8639
|
+
seedCounter = 100;
|
|
8640
|
+
time = 0;
|
|
8641
|
+
selected = null;
|
|
8642
|
+
lastCrossed = 0;
|
|
8643
|
+
lastEnergy = 1;
|
|
8644
|
+
});
|
|
8548
8645
|
const stopEvents = lent.on((event) => {
|
|
8549
8646
|
if (event.type !== "explosion") return;
|
|
8550
8647
|
for (const entry of entries.values()) {
|
|
@@ -8558,6 +8655,8 @@ var GameCharactersThree = (() => {
|
|
|
8558
8655
|
time += dt;
|
|
8559
8656
|
for (const [id, entry] of entries) {
|
|
8560
8657
|
if (!entry.root.parent) {
|
|
8658
|
+
if (entry.body) wounds?.untrack(entry.body);
|
|
8659
|
+
if (selected === entry) selected = null;
|
|
8561
8660
|
entries.delete(id);
|
|
8562
8661
|
continue;
|
|
8563
8662
|
}
|
|
@@ -8569,6 +8668,7 @@ var GameCharactersThree = (() => {
|
|
|
8569
8668
|
});
|
|
8570
8669
|
return () => {
|
|
8571
8670
|
stopChange?.();
|
|
8671
|
+
stopReset?.();
|
|
8572
8672
|
stopEvents();
|
|
8573
8673
|
stopFrame();
|
|
8574
8674
|
clearOverlays();
|
|
@@ -8678,8 +8778,22 @@ var GameCharactersThree = (() => {
|
|
|
8678
8778
|
slack: 0.96,
|
|
8679
8779
|
/** Where the elbow points: down and out from the body, a little back (body space, x outward). */
|
|
8680
8780
|
elbowPole: [0.55, -1, -0.25],
|
|
8781
|
+
/** The support arm's elbow: under the gun, hardly out of the body (the first-person arms' `elbowPoleLeft`), so the forearm meets the handguard nearer the aim's line. */
|
|
8782
|
+
elbowPoleSupport: [0.1, -1, -0.2],
|
|
8681
8783
|
/** From the wrist joint to the middle of the palm, metres of the body. */
|
|
8682
|
-
palm: 0.042
|
|
8784
|
+
palm: 0.042,
|
|
8785
|
+
/** In a view the elbow keeps at least this interior bend where a hand is out of reach, right then left (the first-person arms' numbers). */
|
|
8786
|
+
viewBend: [1.35, 0.95],
|
|
8787
|
+
/** In a view a hand stays this far before a surface, metres. */
|
|
8788
|
+
contactMargin: 5e-3,
|
|
8789
|
+
/** In a view a hand is never nearer than this to the eye, metres. */
|
|
8790
|
+
contactNearest: 0.12,
|
|
8791
|
+
/** How far in front of the eye a surface is looked for, metres. */
|
|
8792
|
+
contactProbe: 1.4,
|
|
8793
|
+
/** How far a hand reaches forward of its middle at least (the thickness of the palm), and per metre of fingers pointing ahead. */
|
|
8794
|
+
contactPalm: 0.03,
|
|
8795
|
+
/** From the middle of the palm to the fingertips. */
|
|
8796
|
+
contactFingers: 0.085
|
|
8683
8797
|
};
|
|
8684
8798
|
var createArmReach = (THREE, rig, hands) => {
|
|
8685
8799
|
const arms = {
|
|
@@ -8700,11 +8814,17 @@ var GameCharactersThree = (() => {
|
|
|
8700
8814
|
const v = { shoulder: new THREE.Vector3(), elbow: new THREE.Vector3(), wrist: new THREE.Vector3(), palm: new THREE.Vector3(), target: new THREE.Vector3(), pole: new THREE.Vector3(), a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
|
|
8701
8815
|
const q = { hand: new THREE.Quaternion(), parent: new THREE.Quaternion(), body: new THREE.Quaternion(), local: new THREE.Quaternion(), swing: new THREE.Quaternion(), twist: new THREE.Quaternion(), rest: new THREE.Quaternion() };
|
|
8702
8816
|
const basis = new THREE.Matrix4();
|
|
8817
|
+
const camera = { position: new THREE.Vector3(), quaternion: new THREE.Quaternion(), inverse: new THREE.Quaternion(), probe: new THREE.Vector3(), forward: new THREE.Vector3(), fingers: new THREE.Vector3(), hand: new THREE.Quaternion() };
|
|
8818
|
+
let bendLimit = null;
|
|
8703
8819
|
const yAxis = new THREE.Vector3(0, 1, 0);
|
|
8704
8820
|
const lengthsOf = (arm) => {
|
|
8705
8821
|
const scale = arm.g.getWorldScale(v.a).y;
|
|
8706
8822
|
return { upper: arm.el.position.length() * scale, fore: arm.hand.position.length() * scale, palm: ARM_REACH.palm * scale };
|
|
8707
8823
|
};
|
|
8824
|
+
const limitOf = (side, upperLength, fore) => {
|
|
8825
|
+
if (!bendLimit) return (upperLength + fore) * ARM_REACH.slack;
|
|
8826
|
+
return Math.sqrt(upperLength * upperLength + fore * fore + 2 * upperLength * fore * Math.cos(bendLimit[side === "R" ? 0 : 1]));
|
|
8827
|
+
};
|
|
8708
8828
|
const wristOf = (side, pose, palm) => {
|
|
8709
8829
|
q.hand.set(...pose.quaternion).multiply(handBasis[side]);
|
|
8710
8830
|
v.palm.set(...pose.position);
|
|
@@ -8713,14 +8833,14 @@ var GameCharactersThree = (() => {
|
|
|
8713
8833
|
const turnChest = (pose) => {
|
|
8714
8834
|
const { upper: up, fore, palm } = lengthsOf(arms.L);
|
|
8715
8835
|
wristOf("L", pose, palm);
|
|
8716
|
-
const excess = arms.L.g.getWorldPosition(v.shoulder).distanceTo(v.wrist) - (up
|
|
8836
|
+
const excess = arms.L.g.getWorldPosition(v.shoulder).distanceTo(v.wrist) - limitOf("L", up, fore);
|
|
8717
8837
|
if (excess <= 0) return;
|
|
8718
8838
|
const chestRadius = Math.hypot(arms.L.g.position.x, arms.L.g.position.z) * arms.L.g.getWorldScale(v.a).y;
|
|
8719
8839
|
upper.rotation.y -= Math.min(ARM_REACH.chestTurn, excess / Math.max(0.05, chestRadius));
|
|
8720
8840
|
upper.updateMatrixWorld(true);
|
|
8721
8841
|
};
|
|
8722
|
-
const protract = (arm,
|
|
8723
|
-
const excess = arm.g.getWorldPosition(v.shoulder).distanceTo(v.wrist) -
|
|
8842
|
+
const protract = (arm, limit) => {
|
|
8843
|
+
const excess = arm.g.getWorldPosition(v.shoulder).distanceTo(v.wrist) - limit;
|
|
8724
8844
|
if (excess <= 0) return;
|
|
8725
8845
|
const parent = arm.g.parent;
|
|
8726
8846
|
v.b.copy(v.wrist).sub(v.shoulder).normalize().multiplyScalar(Math.min(excess, ARM_REACH.protraction)).add(v.shoulder);
|
|
@@ -8741,11 +8861,13 @@ var GameCharactersThree = (() => {
|
|
|
8741
8861
|
const arm = arms[side];
|
|
8742
8862
|
const { upper: up, fore, palm } = lengthsOf(arm);
|
|
8743
8863
|
wristOf(side, pose, palm);
|
|
8744
|
-
protract(arm, up
|
|
8864
|
+
protract(arm, limitOf(side, up, fore));
|
|
8745
8865
|
arm.g.getWorldPosition(v.shoulder);
|
|
8746
8866
|
upper.getWorldQuaternion(q.body);
|
|
8747
|
-
|
|
8748
|
-
|
|
8867
|
+
const pole = side === "L" ? ARM_REACH.elbowPoleSupport : ARM_REACH.elbowPole;
|
|
8868
|
+
v.pole.set(pole[0] * arm.outward, pole[1], pole[2]).applyQuaternion(q.body);
|
|
8869
|
+
const lockLimit = Math.sqrt(up * up + fore * fore + 2 * up * fore * Math.cos(ARM_REACH.elbowMin));
|
|
8870
|
+
const most = bendLimit ? Math.min(lockLimit, limitOf(side, up, fore)) : lockLimit;
|
|
8749
8871
|
const least = Math.sqrt(up * up + fore * fore + 2 * up * fore * Math.cos(ARM_REACH.elbowMax));
|
|
8750
8872
|
const line = v.c.copy(v.wrist).sub(v.shoulder);
|
|
8751
8873
|
const distance3 = Math.min(most, Math.max(least, line.length()));
|
|
@@ -8770,6 +8892,20 @@ var GameCharactersThree = (() => {
|
|
|
8770
8892
|
arm.el.getWorldQuaternion(q.parent);
|
|
8771
8893
|
arm.hand.quaternion.copy(limitWrist(q.local.copy(q.parent.invert()).multiply(q.hand)));
|
|
8772
8894
|
};
|
|
8895
|
+
const keepOutside = (pose, outside) => {
|
|
8896
|
+
const place = v.a.set(...pose.position).sub(camera.position).applyQuaternion(camera.inverse);
|
|
8897
|
+
camera.probe.set(place.x, place.y, 0).applyQuaternion(camera.quaternion).add(camera.position);
|
|
8898
|
+
camera.forward.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
8899
|
+
const distance3 = outside.contact([camera.probe.x, camera.probe.y, camera.probe.z], [camera.forward.x, camera.forward.y, camera.forward.z], ARM_REACH.contactProbe);
|
|
8900
|
+
if (distance3 === null) return pose;
|
|
8901
|
+
camera.hand.set(...pose.quaternion).premultiply(camera.inverse);
|
|
8902
|
+
const ahead = Math.max(ARM_REACH.contactPalm, -camera.fingers.set(1, 0, 0).applyQuaternion(camera.hand).z * ARM_REACH.contactFingers);
|
|
8903
|
+
const limit = Math.max(outside.nearest ?? ARM_REACH.contactNearest, distance3 - ahead - (outside.margin ?? ARM_REACH.contactMargin));
|
|
8904
|
+
if (-place.z <= limit) return pose;
|
|
8905
|
+
place.z = -limit;
|
|
8906
|
+
place.applyQuaternion(camera.quaternion).add(camera.position);
|
|
8907
|
+
return { ...pose, position: [place.x, place.y, place.z] };
|
|
8908
|
+
};
|
|
8773
8909
|
const save = () => {
|
|
8774
8910
|
saved.twist = upper.rotation.y;
|
|
8775
8911
|
for (const side of ["R", "L"]) {
|
|
@@ -8782,14 +8918,24 @@ var GameCharactersThree = (() => {
|
|
|
8782
8918
|
}
|
|
8783
8919
|
};
|
|
8784
8920
|
return {
|
|
8785
|
-
apply(targets) {
|
|
8921
|
+
apply(targets, view) {
|
|
8786
8922
|
if (!targets || !targets.R && !targets.L) return;
|
|
8787
8923
|
save();
|
|
8788
8924
|
applied = true;
|
|
8789
8925
|
upper.updateWorldMatrix(true, true);
|
|
8790
|
-
|
|
8791
|
-
|
|
8792
|
-
if (
|
|
8926
|
+
let { R, L } = targets;
|
|
8927
|
+
bendLimit = view ? view.reachBend ?? ARM_REACH.viewBend : null;
|
|
8928
|
+
if (view?.keepOutside) {
|
|
8929
|
+
view.camera.updateWorldMatrix(true, false);
|
|
8930
|
+
view.camera.matrixWorld.decompose(camera.position, camera.quaternion, v.a);
|
|
8931
|
+
camera.inverse.copy(camera.quaternion).invert();
|
|
8932
|
+
if (R) R = keepOutside(R, view.keepOutside);
|
|
8933
|
+
if (L) L = keepOutside(L, view.keepOutside);
|
|
8934
|
+
}
|
|
8935
|
+
if (L && R) turnChest(L);
|
|
8936
|
+
if (R) reach("R", R);
|
|
8937
|
+
if (L) reach("L", L);
|
|
8938
|
+
bendLimit = null;
|
|
8793
8939
|
},
|
|
8794
8940
|
restore() {
|
|
8795
8941
|
if (!applied) return;
|
|
@@ -8807,12 +8953,56 @@ var GameCharactersThree = (() => {
|
|
|
8807
8953
|
};
|
|
8808
8954
|
};
|
|
8809
8955
|
|
|
8956
|
+
// src/player/head-hiding.ts
|
|
8957
|
+
var isDrawable = (object2) => {
|
|
8958
|
+
const flagged = object2;
|
|
8959
|
+
return Boolean(flagged.isMesh || flagged.isSprite || flagged.isPoints);
|
|
8960
|
+
};
|
|
8961
|
+
var createHeadHider = (roots) => {
|
|
8962
|
+
let isHiding = false;
|
|
8963
|
+
let viewCamera = null;
|
|
8964
|
+
const drawables = [];
|
|
8965
|
+
for (const root of roots) root.traverse((object2) => isDrawable(object2) && drawables.push(object2));
|
|
8966
|
+
for (const drawable of drawables) {
|
|
8967
|
+
const previousBefore = drawable.onBeforeRender;
|
|
8968
|
+
const previousAfter = drawable.onAfterRender;
|
|
8969
|
+
let saved = [];
|
|
8970
|
+
drawable.onBeforeRender = (renderer, scene2, camera, geometry, material, group) => {
|
|
8971
|
+
previousBefore.call(drawable, renderer, scene2, camera, geometry, material, group);
|
|
8972
|
+
if (!isHiding || camera !== viewCamera) return;
|
|
8973
|
+
const drawn = Array.isArray(drawable.material) ? drawable.material : [material];
|
|
8974
|
+
saved = drawn.map((entry) => ({ material: entry, colorWrite: entry.colorWrite, depthWrite: entry.depthWrite }));
|
|
8975
|
+
for (const entry of drawn) {
|
|
8976
|
+
entry.colorWrite = false;
|
|
8977
|
+
entry.depthWrite = false;
|
|
8978
|
+
}
|
|
8979
|
+
};
|
|
8980
|
+
drawable.onAfterRender = (renderer, scene2, camera, geometry, material, group) => {
|
|
8981
|
+
previousAfter.call(drawable, renderer, scene2, camera, geometry, material, group);
|
|
8982
|
+
for (const flags of saved) {
|
|
8983
|
+
flags.material.colorWrite = flags.colorWrite;
|
|
8984
|
+
flags.material.depthWrite = flags.depthWrite;
|
|
8985
|
+
}
|
|
8986
|
+
saved = [];
|
|
8987
|
+
};
|
|
8988
|
+
}
|
|
8989
|
+
return {
|
|
8990
|
+
setView(mode, camera) {
|
|
8991
|
+
isHiding = mode === "first" && camera !== null;
|
|
8992
|
+
viewCamera = camera;
|
|
8993
|
+
}
|
|
8994
|
+
};
|
|
8995
|
+
};
|
|
8996
|
+
|
|
8810
8997
|
// src/player/avatar.ts
|
|
8811
8998
|
var TWO_PI2 = Math.PI * 2;
|
|
8812
8999
|
var MAX_GAIT = 1.4;
|
|
8813
9000
|
var CLIP_BLEND = 0.12;
|
|
8814
9001
|
var CLIP_CASCADE = 5;
|
|
8815
9002
|
var FALL_SECONDS2 = 0.3;
|
|
9003
|
+
var BUILDER_EYE = [0, 1.815, 0.16];
|
|
9004
|
+
var EYE_OFFSET = [0, -0.068, 0];
|
|
9005
|
+
var EYE_BOB = 0.5;
|
|
8816
9006
|
var HIP_HEIGHT = 0.95;
|
|
8817
9007
|
var WALK_ARM = 0.28;
|
|
8818
9008
|
var WALK_BOB = 0.035;
|
|
@@ -8822,7 +9012,11 @@ var GameCharactersThree = (() => {
|
|
|
8822
9012
|
var REST_ARM_Z = 0.18;
|
|
8823
9013
|
var CROUCH = { thigh: -0.95, thighWalk: 0.3, shin: 1.9, lean: 0.25, drop: -0.35 };
|
|
8824
9014
|
var AIMED = { shoulder: -1.42, perAim: 0.85, swing: 0.02, zRight: -0.54, zLeft: 0.36, elbowRight: -0.04, elbowLeft: -0.12 };
|
|
9015
|
+
var SIT = { thigh: -1.5, lean: -0.08, arm: -0.45, armZ: 0.12, elbow: -0.75 };
|
|
9016
|
+
var LIE = { knee: 0.08, armZ: 0.12, elbow: -0.1 };
|
|
8825
9017
|
var DOWN = { thighWalk: 0.5, shinSwing: 0.85, shinBend: 1.3, armHigh: -2.8, armLow: -0.35, armWave: 0.3, armZ: 0.5, armZWave: 0.3, tilt: 1.5, roll: 0.3, hipY: 0.16, hipZ: 0.6, hipZFlip: 1.2 };
|
|
9018
|
+
var DOOR_SHOULDER = 1.42;
|
|
9019
|
+
var DOOR_ARM = 0.62;
|
|
8826
9020
|
var HAND_OFFSET = { x: 0, y: -0.33, z: 0.04 };
|
|
8827
9021
|
var hexOf = (value) => typeof value === "string" ? Number.parseInt(value, 16) : value;
|
|
8828
9022
|
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
@@ -8852,6 +9046,8 @@ var GameCharactersThree = (() => {
|
|
|
8852
9046
|
const fallSeconds = options.fallSeconds ?? FALL_SECONDS2;
|
|
8853
9047
|
const smooth = options.cascade ?? true;
|
|
8854
9048
|
const clipCascade = options.clipCascade ?? CLIP_CASCADE;
|
|
9049
|
+
const eyeBob = options.eyeBob ?? EYE_BOB;
|
|
9050
|
+
const eyeOffset = options.eyeOffset ?? EYE_OFFSET;
|
|
8855
9051
|
const root = new THREE.Group();
|
|
8856
9052
|
const tilt = new THREE.Group();
|
|
8857
9053
|
tilt.add(body);
|
|
@@ -8911,7 +9107,23 @@ var GameCharactersThree = (() => {
|
|
|
8911
9107
|
if (hand.th) hand.th.rotation.z = -hand.side * (0.32 + grip * 0.25);
|
|
8912
9108
|
hand.hg.rotation.x = wristX;
|
|
8913
9109
|
};
|
|
9110
|
+
const eyeSocket = new THREE.Object3D();
|
|
9111
|
+
eyeSocket.name = "eye";
|
|
9112
|
+
eyeSocket.position.set(BUILDER_EYE[0] + eyeOffset[0], BUILDER_EYE[1] + eyeOffset[1], BUILDER_EYE[2] + eyeOffset[2]);
|
|
9113
|
+
rig.headG.children[0].add(eyeSocket);
|
|
9114
|
+
const headHider = createHeadHider([rig.headG, ...rig.neck ? [rig.neck] : []]);
|
|
9115
|
+
const eyeLocal = new THREE.Vector3();
|
|
9116
|
+
let bob = 0;
|
|
9117
|
+
let hipWithoutBob = null;
|
|
8914
9118
|
const legRestX = rig.legs.map((leg) => leg.g.position.x);
|
|
9119
|
+
const legLengths = (() => {
|
|
9120
|
+
const thigh = rig.legs[0].g;
|
|
9121
|
+
const shin = rig.legs[0].kn;
|
|
9122
|
+
root.updateMatrixWorld(true);
|
|
9123
|
+
const hipY = thigh.getWorldPosition(new THREE.Vector3()).y;
|
|
9124
|
+
const kneeY = shin.getWorldPosition(new THREE.Vector3()).y;
|
|
9125
|
+
return { hipBelowTrunk: HIP_HEIGHT - hipY, thigh: hipY - kneeY, shin: kneeY - new THREE.Box3().setFromObject(shin).min.y };
|
|
9126
|
+
})();
|
|
8915
9127
|
const legSide = (index) => index === 0 ? 1 : -1;
|
|
8916
9128
|
let cycles = 0;
|
|
8917
9129
|
let time = 0;
|
|
@@ -8970,10 +9182,29 @@ var GameCharactersThree = (() => {
|
|
|
8970
9182
|
...strain ? { legL: -0.5, legR: 0.4, kneeL: 0.55, kneeR: 0.08, drop: -0.05 } : {}
|
|
8971
9183
|
};
|
|
8972
9184
|
};
|
|
9185
|
+
const doorPose = (door) => {
|
|
9186
|
+
const { phase, progress } = door;
|
|
9187
|
+
const on = phase === "reach" ? progress : phase === "release" ? 1 - progress : 1;
|
|
9188
|
+
const swing = phase === "swing" ? progress : phase === "release" ? 1 : 0;
|
|
9189
|
+
const shake = phase === "rattle" ? Math.sin(time * 55) * 0.06 * (1 - progress) : 0;
|
|
9190
|
+
const drop = clamp((DOOR_SHOULDER - door.height) / DOOR_ARM, -0.9, 1);
|
|
9191
|
+
const low = clamp((0.75 - door.height) / 0.5, 0, 1);
|
|
9192
|
+
const raise = -Math.acos(clamp(drop, -1, 1)) * on - 0.35 * low * on;
|
|
9193
|
+
const elbow = door.pull ? -0.35 - 0.75 * swing : -0.95 + 0.75 * swing;
|
|
9194
|
+
return {
|
|
9195
|
+
armR: raise + shake,
|
|
9196
|
+
armRz: REST_ARM_Z * (1 - on) + 0.05 * on,
|
|
9197
|
+
elbR: -0.12 + (elbow + 0.12) * on,
|
|
9198
|
+
armLz: -REST_ARM_Z,
|
|
9199
|
+
elbL: -0.12,
|
|
9200
|
+
lean: ((door.pull ? -0.06 : 0.1) * swing + 0.35 * low) * on,
|
|
9201
|
+
headX: 0.06 * on + 0.2 * low * on
|
|
9202
|
+
};
|
|
9203
|
+
};
|
|
8973
9204
|
const holdingPose = (gait, itemUse) => {
|
|
8974
|
-
const
|
|
9205
|
+
const bob2 = Math.sin(cycles * TWO_PI2) * 0.05 * gait;
|
|
8975
9206
|
if (!itemUse) {
|
|
8976
|
-
return { armL: -0.45 +
|
|
9207
|
+
return { armL: -0.45 + bob2, armLz: 0.22, elbL: -1.05 };
|
|
8977
9208
|
}
|
|
8978
9209
|
const { id, position, rotation } = itemUse;
|
|
8979
9210
|
if (id === "drink" || id === "sip" || id === "chug") {
|
|
@@ -8986,7 +9217,7 @@ var GameCharactersThree = (() => {
|
|
|
8986
9217
|
headX: -0.26 * tilt3
|
|
8987
9218
|
};
|
|
8988
9219
|
}
|
|
8989
|
-
if (id === "open" || id === "close") {
|
|
9220
|
+
if (id === "open" || id === "close" || itemUse.gripL !== void 0) {
|
|
8990
9221
|
const reach = clamp((0.22 - position[0]) / 0.12, 0, 1);
|
|
8991
9222
|
return {
|
|
8992
9223
|
armL: -0.45 - 0.35 * reach,
|
|
@@ -9085,6 +9316,31 @@ var GameCharactersThree = (() => {
|
|
|
9085
9316
|
drop: Math.abs(Math.sin(ph)) * WALK_BOB * gait
|
|
9086
9317
|
};
|
|
9087
9318
|
};
|
|
9319
|
+
const sitPose = (hip) => {
|
|
9320
|
+
const knee = hip - legLengths.hipBelowTrunk - legLengths.thigh * Math.cos(SIT.thigh);
|
|
9321
|
+
const shinFromVertical = Math.acos(clamp(knee / legLengths.shin, 0, 1));
|
|
9322
|
+
const bend = -SIT.thigh - shinFromVertical;
|
|
9323
|
+
return {
|
|
9324
|
+
legL: SIT.thigh,
|
|
9325
|
+
legR: SIT.thigh,
|
|
9326
|
+
kneeL: bend,
|
|
9327
|
+
kneeR: bend,
|
|
9328
|
+
lean: SIT.lean,
|
|
9329
|
+
drop: hip - HIP_HEIGHT,
|
|
9330
|
+
armR: SIT.arm,
|
|
9331
|
+
armL: SIT.arm,
|
|
9332
|
+
armRz: SIT.armZ,
|
|
9333
|
+
armLz: -SIT.armZ,
|
|
9334
|
+
elbR: SIT.elbow,
|
|
9335
|
+
elbL: SIT.elbow
|
|
9336
|
+
};
|
|
9337
|
+
};
|
|
9338
|
+
const liePose = () => ({ legL: 0, legR: 0, kneeL: LIE.knee, kneeR: LIE.knee, lean: 0, drop: 0, armR: 0, armL: 0, armRz: LIE.armZ, armLz: -LIE.armZ, elbR: LIE.elbow, elbL: LIE.elbow });
|
|
9339
|
+
const layBody = (hip) => {
|
|
9340
|
+
tilt.rotation.set(-Math.PI / 2, 0, 0, "XYZ");
|
|
9341
|
+
const pivot = new THREE.Vector3(0, HIP_HEIGHT, 0).applyEuler(tilt.rotation);
|
|
9342
|
+
tilt.position.set(0, hip, 0).sub(pivot);
|
|
9343
|
+
};
|
|
9088
9344
|
const placeBody = (progress) => {
|
|
9089
9345
|
const fk = progress * progress * (3 - 2 * progress);
|
|
9090
9346
|
const flip = fract(cycles * 1.7) >= 0.5 ? 1 : 0;
|
|
@@ -9145,13 +9401,27 @@ var GameCharactersThree = (() => {
|
|
|
9145
9401
|
profile.bob = (running ? RUN_BOB : WALK_BOB) * gait;
|
|
9146
9402
|
time = cycles / (walkCadence(Math.max(speed, 0)) * (running ? 1.3 : 1));
|
|
9147
9403
|
animator.animate(body, time, { speed });
|
|
9404
|
+
bob = rig.fig.position.y - rig.dropBase;
|
|
9148
9405
|
fall = fallSeconds <= 0 ? down ? 1 : 0 : clamp(fall + (down ? dt : -dt) / fallSeconds, 0, 1);
|
|
9149
9406
|
resetLegYaw();
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9407
|
+
const seat = down ? null : state.seat ?? null;
|
|
9408
|
+
if (down) {
|
|
9409
|
+
animator.setPose(rig, downPose());
|
|
9410
|
+
bob = rig.fig.position.y - rig.dropBase;
|
|
9411
|
+
} else if (seat) {
|
|
9412
|
+
animator.setPose(rig, seat.pose === "lie" ? liePose() : sitPose(seat.hip));
|
|
9413
|
+
bob = 0;
|
|
9414
|
+
} else {
|
|
9415
|
+
if (running) {
|
|
9416
|
+
animator.setPose(rig, runningPose(gait, Boolean(state.armed || state.holding || state.itemUse)));
|
|
9417
|
+
bob = rig.fig.position.y - rig.dropBase;
|
|
9418
|
+
}
|
|
9419
|
+
if (state.crouch) {
|
|
9420
|
+
animator.setPose(rig, crouchPose(gait));
|
|
9421
|
+
bob = rig.fig.position.y - rig.dropBase - CROUCH.drop;
|
|
9422
|
+
}
|
|
9154
9423
|
if (state.push) animator.setPose(rig, pushingPose(state.push));
|
|
9424
|
+
else if (state.door) animator.setPose(rig, doorPose(state.door));
|
|
9155
9425
|
else if (state.armed) animator.setPose(rig, armed(state.pitch ?? 0, gait, state.hip ?? 0));
|
|
9156
9426
|
else if (state.holding || state.itemUse) animator.setPose(rig, holdingPose(gait, state.itemUse));
|
|
9157
9427
|
else if (!running) {
|
|
@@ -9163,20 +9433,33 @@ var GameCharactersThree = (() => {
|
|
|
9163
9433
|
});
|
|
9164
9434
|
}
|
|
9165
9435
|
}
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9436
|
+
if (seat?.pose === "lie") layBody(seat.hip);
|
|
9437
|
+
else placeBody(fall);
|
|
9438
|
+
stepClip(dt, down, Boolean(state.crouch || seat));
|
|
9439
|
+
const cascadeDt = run && !run.clip.loop ? dt * clipCascade : dt;
|
|
9440
|
+
const targetWithoutBob = rig.fig.position.y - bob;
|
|
9441
|
+
if (smooth) animator.cascade(rig, cascadeDt);
|
|
9442
|
+
hipWithoutBob = smooth && hipWithoutBob !== null ? stepCascade(hipWithoutBob, targetWithoutBob, cascadeDt, "hip") : targetWithoutBob;
|
|
9443
|
+
bob = rig.fig.position.y - hipWithoutBob;
|
|
9169
9444
|
const blow = run?.clip.events?.find((event) => (event.type === "impact" || event.type === "grip") && event.data?.kind)?.data?.kind;
|
|
9170
9445
|
const ph = cycles * TWO_PI2;
|
|
9171
9446
|
hands.forEach((hand) => {
|
|
9172
9447
|
const isRight = hand.side < 0;
|
|
9173
9448
|
const holdRight = isRight && (!!state.holding || !!state.itemUse);
|
|
9174
|
-
const holdLeft = !isRight && (state.itemUse?.id === "open" || state.itemUse?.id === "close");
|
|
9175
|
-
const grip = blow === "punch" ? 1.4 : blow === "shove" ? 0.15 : state.armed || holdRight || holdLeft ? 1.22 : running ? 0.85 : 0.12;
|
|
9449
|
+
const holdLeft = !isRight && (state.itemUse?.id === "open" || state.itemUse?.id === "close" || state.itemUse?.gripL !== void 0);
|
|
9450
|
+
const grip = !isRight && state.itemUse?.gripL !== void 0 ? 1.22 * state.itemUse.gripL : blow === "punch" ? 1.4 : blow === "shove" ? 0.15 : state.armed || holdRight || holdLeft ? 1.22 : running ? 0.85 : 0.12;
|
|
9176
9451
|
const wristSwing = holdRight || state.armed || running ? 0 : -Math.min(1, gait) * Math.sin(ph - 0.6) * 0.12 * hand.side;
|
|
9177
9452
|
setHandGrip(hand, grip, wristSwing);
|
|
9178
9453
|
});
|
|
9454
|
+
root.updateMatrixWorld(true);
|
|
9455
|
+
root.worldToLocal(eyeSocket.getWorldPosition(eyeLocal));
|
|
9456
|
+
eyeLocal.y -= (1 - eyeBob) * bob;
|
|
9457
|
+
},
|
|
9458
|
+
eye(out = new THREE.Vector3()) {
|
|
9459
|
+
root.updateWorldMatrix(true, false);
|
|
9460
|
+
return root.localToWorld(out.copy(eyeLocal));
|
|
9179
9461
|
},
|
|
9462
|
+
setView: (mode, camera) => headHider.setView(mode, camera),
|
|
9180
9463
|
play(clip, playOptions = {}) {
|
|
9181
9464
|
const found = typeof clip === "string" ? clips.get(clip) : clip;
|
|
9182
9465
|
if (!found) throw new Error(`Unknown pose clip: ${String(clip)}`);
|
|
@@ -9188,10 +9471,11 @@ var GameCharactersThree = (() => {
|
|
|
9188
9471
|
if (run) run.target = 0;
|
|
9189
9472
|
},
|
|
9190
9473
|
hand: (side) => sockets[side],
|
|
9191
|
-
|
|
9474
|
+
shoulder: (side) => armOf[side].g,
|
|
9475
|
+
reach(targets, view) {
|
|
9192
9476
|
if (run || fall > 0) return;
|
|
9193
9477
|
root.updateMatrixWorld(true);
|
|
9194
|
-
armReach.apply(targets);
|
|
9478
|
+
armReach.apply(targets, view);
|
|
9195
9479
|
},
|
|
9196
9480
|
on(_type, listener) {
|
|
9197
9481
|
listeners.add(listener);
|
|
@@ -9614,6 +9898,233 @@ var GameCharactersThree = (() => {
|
|
|
9614
9898
|
var FIRST_PERSON_CLIPS = first_person_clips_default.clips;
|
|
9615
9899
|
var NAME_POOLS = { "pt-BR": names_default["pt-BR"] };
|
|
9616
9900
|
|
|
9901
|
+
// src/player/room-avatar.ts
|
|
9902
|
+
var impactOf = (clip) => clip.events?.find((event) => event.type === "impact")?.t ?? null;
|
|
9903
|
+
var isPunch = (clip) => clip.events?.some((event) => event.type === "impact" && event.data?.kind === "punch") ?? false;
|
|
9904
|
+
var GUARD_SPEED = 0.3;
|
|
9905
|
+
var toRoomAvatar = (avatar, options = {}) => {
|
|
9906
|
+
const strikes = new Map((options.strikeClips ?? ATTACK_CLIPS).map((clip) => [clip.id, clip]));
|
|
9907
|
+
const mirrored = /* @__PURE__ */ new Map();
|
|
9908
|
+
const leftOf = (clip) => {
|
|
9909
|
+
let found = mirrored.get(clip.id);
|
|
9910
|
+
if (!found) mirrored.set(clip.id, found = mirrorPoseClip(clip, `${clip.id}_left`));
|
|
9911
|
+
return found;
|
|
9912
|
+
};
|
|
9913
|
+
const guard = options.guardClip === false ? void 0 : strikes.get(options.guardClip ?? "fight_guard");
|
|
9914
|
+
const guardHold = options.guardHold ?? 1.2;
|
|
9915
|
+
const punchBlend = options.punchBlend ?? 0.05;
|
|
9916
|
+
let strikeLeft = 0;
|
|
9917
|
+
let guardLeft = 0;
|
|
9918
|
+
let guarding = false;
|
|
9919
|
+
const stepGuard = (dt, state) => {
|
|
9920
|
+
if (!guard) return;
|
|
9921
|
+
const free = state.speed < GUARD_SPEED && !state.down && !state.armed && !state.holding && !state.push && !state.door && !state.itemUse && !state.running;
|
|
9922
|
+
if (strikeLeft > 0) {
|
|
9923
|
+
strikeLeft -= dt;
|
|
9924
|
+
if (strikeLeft <= 0 && guardLeft > 0 && free) {
|
|
9925
|
+
avatar.play(guard);
|
|
9926
|
+
guarding = true;
|
|
9927
|
+
}
|
|
9928
|
+
return;
|
|
9929
|
+
}
|
|
9930
|
+
guardLeft = Math.max(0, guardLeft - dt);
|
|
9931
|
+
if (guarding && (guardLeft <= 0 || !free || avatar.playing !== guard.id)) {
|
|
9932
|
+
if (avatar.playing === guard.id) avatar.stop();
|
|
9933
|
+
guarding = false;
|
|
9934
|
+
}
|
|
9935
|
+
};
|
|
9936
|
+
return {
|
|
9937
|
+
root: avatar.root,
|
|
9938
|
+
avatar,
|
|
9939
|
+
eye: (out) => avatar.eye(out),
|
|
9940
|
+
setView: (mode, camera) => avatar.setView(mode, camera),
|
|
9941
|
+
update: (dt, state) => {
|
|
9942
|
+
stepGuard(dt, state);
|
|
9943
|
+
avatar.update(dt, {
|
|
9944
|
+
speed: state.speed,
|
|
9945
|
+
running: state.running,
|
|
9946
|
+
crouch: state.crouch,
|
|
9947
|
+
down: state.down,
|
|
9948
|
+
armed: state.armed,
|
|
9949
|
+
pitch: -state.pitch,
|
|
9950
|
+
...state.holding !== void 0 ? { holding: state.holding } : {},
|
|
9951
|
+
...state.itemUse !== void 0 ? { itemUse: state.itemUse } : {},
|
|
9952
|
+
...state.push !== void 0 ? { push: state.push } : {},
|
|
9953
|
+
...state.seat !== void 0 ? { seat: state.seat } : {},
|
|
9954
|
+
...state.door !== void 0 ? { door: state.door } : {}
|
|
9955
|
+
});
|
|
9956
|
+
},
|
|
9957
|
+
hand: (side) => avatar.hand(side),
|
|
9958
|
+
shoulder: (side) => avatar.shoulder(side),
|
|
9959
|
+
reach: (targets, view) => avatar.reach(targets, view),
|
|
9960
|
+
strike: (clipId, strikeOptions) => {
|
|
9961
|
+
const clip = strikes.get(clipId);
|
|
9962
|
+
if (!clip) return null;
|
|
9963
|
+
const left = strikeOptions?.leg === "left" || strikeOptions?.hand === "left";
|
|
9964
|
+
const punch = guard !== void 0 && isPunch(clip);
|
|
9965
|
+
avatar.play(left ? leftOf(clip) : clip, punch ? { blend: punchBlend } : void 0);
|
|
9966
|
+
strikeLeft = punch ? clip.duration : 0;
|
|
9967
|
+
guardLeft = punch ? guardHold : 0;
|
|
9968
|
+
guarding = false;
|
|
9969
|
+
return impactOf(clip);
|
|
9970
|
+
}
|
|
9971
|
+
};
|
|
9972
|
+
};
|
|
9973
|
+
|
|
9974
|
+
// src/player/test-text.ts
|
|
9975
|
+
var AVATAR_TEXT = {
|
|
9976
|
+
en: {
|
|
9977
|
+
group: "Avatar",
|
|
9978
|
+
name: "Player body",
|
|
9979
|
+
actions: {
|
|
9980
|
+
camera_first: "Camera: 1st person",
|
|
9981
|
+
camera_third: "Camera: 3rd person",
|
|
9982
|
+
crouch: "Crouch",
|
|
9983
|
+
stand: "Stand up",
|
|
9984
|
+
fall: "Fall down",
|
|
9985
|
+
get_up: "Get up",
|
|
9986
|
+
armed_on: "Armed: on",
|
|
9987
|
+
armed_off: "Armed: off",
|
|
9988
|
+
stop_clip: "Stop clip"
|
|
9989
|
+
},
|
|
9990
|
+
play: "Play",
|
|
9991
|
+
metrics: { camera: "Camera", clip: "Clip playing", last_event: "Last clip event", state: "State", joints: "Joints" },
|
|
9992
|
+
none: "none"
|
|
9993
|
+
},
|
|
9994
|
+
"pt-BR": {
|
|
9995
|
+
group: "Avatar",
|
|
9996
|
+
name: "Corpo do jogador",
|
|
9997
|
+
actions: {
|
|
9998
|
+
camera_first: "C\xE2mera: 1\xAA pessoa",
|
|
9999
|
+
camera_third: "C\xE2mera: 3\xAA pessoa",
|
|
10000
|
+
crouch: "Agachar",
|
|
10001
|
+
stand: "Levantar",
|
|
10002
|
+
fall: "Cair",
|
|
10003
|
+
get_up: "Levantar do ch\xE3o",
|
|
10004
|
+
armed_on: "Armado: ligado",
|
|
10005
|
+
armed_off: "Armado: desligado",
|
|
10006
|
+
stop_clip: "Parar clipe"
|
|
10007
|
+
},
|
|
10008
|
+
play: "Tocar",
|
|
10009
|
+
metrics: { camera: "C\xE2mera", clip: "Clipe tocando", last_event: "\xDAltimo evento do clipe", state: "Estado", joints: "Juntas" },
|
|
10010
|
+
none: "nenhum"
|
|
10011
|
+
}
|
|
10012
|
+
};
|
|
10013
|
+
|
|
10014
|
+
// src/player/test-module.ts
|
|
10015
|
+
var AVATAR_AREA_ID = "avatar_area";
|
|
10016
|
+
var round = (value) => (Math.round(value * 100) / 100).toString();
|
|
10017
|
+
function createAvatarTestModule(options) {
|
|
10018
|
+
const clips = options.clips ?? POSE_CLIPS;
|
|
10019
|
+
const textOf = (locale) => AVATAR_TEXT[locale ?? options.locale ?? "pt-BR"] ?? AVATAR_TEXT["pt-BR"];
|
|
10020
|
+
const phaseLabel = (label, locale) => {
|
|
10021
|
+
const id = locale ?? options.locale ?? "pt-BR";
|
|
10022
|
+
const table = { ...POSE_CLIP_LOCALES[id] ?? POSE_CLIP_LOCALES["pt-BR"], ...options.clipLocales?.[id] ?? options.clipLocales?.["pt-BR"] };
|
|
10023
|
+
return typeof label === "string" ? table[label] ?? label : "";
|
|
10024
|
+
};
|
|
10025
|
+
const state = { crouch: false, down: false, armed: null };
|
|
10026
|
+
let host = null;
|
|
10027
|
+
let lastEvent = "";
|
|
10028
|
+
const log = (action, extra = {}) => {
|
|
10029
|
+
const entry = { type: "avatar", action, ...extra };
|
|
10030
|
+
host?.log(JSON.stringify(entry), entry);
|
|
10031
|
+
};
|
|
10032
|
+
const push = (action, patch, extra = {}) => {
|
|
10033
|
+
Object.assign(state, patch);
|
|
10034
|
+
options.state?.set(patch);
|
|
10035
|
+
log(action, { crouch: state.crouch, down: state.down, armed: state.armed, ...extra });
|
|
10036
|
+
};
|
|
10037
|
+
const setCamera = (mode) => {
|
|
10038
|
+
options.camera?.set(mode);
|
|
10039
|
+
log(`camera_${mode}`, { mode: options.camera?.mode() ?? null });
|
|
10040
|
+
};
|
|
10041
|
+
const onChange = (change) => {
|
|
10042
|
+
if (change.kind !== "action") return;
|
|
10043
|
+
switch (change.id) {
|
|
10044
|
+
case "camera_first":
|
|
10045
|
+
return setCamera("first");
|
|
10046
|
+
case "camera_third":
|
|
10047
|
+
return setCamera("third");
|
|
10048
|
+
case "crouch":
|
|
10049
|
+
return push("crouch", { crouch: true });
|
|
10050
|
+
case "stand":
|
|
10051
|
+
return push("stand", { crouch: false });
|
|
10052
|
+
case "fall":
|
|
10053
|
+
return push("fall", { down: true });
|
|
10054
|
+
case "get_up":
|
|
10055
|
+
return push("get_up", { down: false });
|
|
10056
|
+
case "armed_on":
|
|
10057
|
+
return push("armed_on", { armed: true });
|
|
10058
|
+
case "armed_off":
|
|
10059
|
+
return push("armed_off", { armed: false });
|
|
10060
|
+
case "stop_clip":
|
|
10061
|
+
options.avatar.stop();
|
|
10062
|
+
return log("stop_clip", { playing: options.avatar.playing });
|
|
10063
|
+
default: {
|
|
10064
|
+
const clip = clips.find((item) => `play_${item.id}` === change.id);
|
|
10065
|
+
if (!clip) return;
|
|
10066
|
+
options.avatar.play(clip);
|
|
10067
|
+
log("play_clip", { clip: clip.id, duration: clip.duration, loop: clip.loop ?? false, channels: clip.channels ?? "full" });
|
|
10068
|
+
}
|
|
10069
|
+
}
|
|
10070
|
+
};
|
|
10071
|
+
const joints = () => {
|
|
10072
|
+
const rig = options.avatar.rig;
|
|
10073
|
+
const [armA, armB] = rig.arms;
|
|
10074
|
+
const [legA, legB] = rig.legs;
|
|
10075
|
+
return `arms ${round(armA.g.rotation.x)}/${round(armB.g.rotation.x)} elbows ${round(armA.el.rotation.x)}/${round(armB.el.rotation.x)} legs ${round(legA.g.rotation.x)}/${round(legB.g.rotation.x)} knees ${round(legA.kn.rotation.x)}/${round(legB.kn.rotation.x)} lean ${round(rig.upper.rotation.x)}`;
|
|
10076
|
+
};
|
|
10077
|
+
return {
|
|
10078
|
+
id: AVATAR_AREA_ID,
|
|
10079
|
+
name: textOf().name,
|
|
10080
|
+
ground: { surface: "concrete_slab" },
|
|
10081
|
+
group: textOf().group,
|
|
10082
|
+
state,
|
|
10083
|
+
items: () => [],
|
|
10084
|
+
area: () => ({ placements: [], view: { eye: [0, 1.7, 6], target: [0, 1.2, 0] } }),
|
|
10085
|
+
controls: (locale) => {
|
|
10086
|
+
const text = textOf(locale);
|
|
10087
|
+
const action = (id, name, hint) => ({ kind: "action", id, name, ...hint ? { hint } : {} });
|
|
10088
|
+
return [
|
|
10089
|
+
action("camera_first", text.actions.camera_first),
|
|
10090
|
+
action("camera_third", text.actions.camera_third),
|
|
10091
|
+
action("crouch", text.actions.crouch),
|
|
10092
|
+
action("stand", text.actions.stand),
|
|
10093
|
+
action("fall", text.actions.fall),
|
|
10094
|
+
action("get_up", text.actions.get_up),
|
|
10095
|
+
action("armed_on", text.actions.armed_on),
|
|
10096
|
+
action("armed_off", text.actions.armed_off),
|
|
10097
|
+
...clips.map((clip) => action(`play_${clip.id}`, `${text.play}: ${clip.id}`)),
|
|
10098
|
+
action("stop_clip", text.actions.stop_clip)
|
|
10099
|
+
];
|
|
10100
|
+
},
|
|
10101
|
+
metrics: (locale) => {
|
|
10102
|
+
const text = textOf(locale);
|
|
10103
|
+
return [
|
|
10104
|
+
{ id: "camera", name: text.metrics.camera, read: () => options.camera?.mode() ?? text.none },
|
|
10105
|
+
{ id: "clip", name: text.metrics.clip, read: () => options.avatar.playing ?? text.none },
|
|
10106
|
+
{ id: "last_event", name: text.metrics.last_event, read: () => lastEvent || text.none },
|
|
10107
|
+
{ id: "state", name: text.metrics.state, read: () => `${state.crouch ? "crouch " : ""}${state.down ? "down " : ""}${state.armed === null ? "" : state.armed ? "armed" : "unarmed"}`.trim() || text.none },
|
|
10108
|
+
{ id: "joints", name: text.metrics.joints, read: joints }
|
|
10109
|
+
];
|
|
10110
|
+
},
|
|
10111
|
+
attach(lent) {
|
|
10112
|
+
host = lent;
|
|
10113
|
+
const stopChange = lent.bench?.onChange(onChange);
|
|
10114
|
+
const stopEvents = options.avatar.on("event", (event) => {
|
|
10115
|
+
lastEvent = `${event.clip} ${event.type} ${round(event.t)}s${event.data && "label" in event.data ? ` ${phaseLabel(event.data.label)}` : ""}`;
|
|
10116
|
+
log("clip_event", { clip: event.clip, event: event.type, t: event.t, data: event.data ?? null });
|
|
10117
|
+
if (event.type === "impact") log("impact", { clip: event.clip, t: event.t, kind: event.data?.kind ?? null });
|
|
10118
|
+
});
|
|
10119
|
+
return () => {
|
|
10120
|
+
stopChange?.();
|
|
10121
|
+
stopEvents();
|
|
10122
|
+
host = null;
|
|
10123
|
+
};
|
|
10124
|
+
}
|
|
10125
|
+
};
|
|
10126
|
+
}
|
|
10127
|
+
|
|
9617
10128
|
// src/presets/first-person-arms.json
|
|
9618
10129
|
var first_person_arms_default = {
|
|
9619
10130
|
source: {
|
|
@@ -9623,7 +10134,9 @@ var GameCharactersThree = (() => {
|
|
|
9623
10134
|
shoulder: [0.16, -0.36, 0.18],
|
|
9624
10135
|
upper: 0.32,
|
|
9625
10136
|
fore: 0.3,
|
|
9626
|
-
reachShift: 0.
|
|
10137
|
+
reachShift: 0.42,
|
|
10138
|
+
reachBend: [1.35, 0.95],
|
|
10139
|
+
elbowView: [[0.96, -0.26, -0.06], null],
|
|
9627
10140
|
wrist: 0.07,
|
|
9628
10141
|
elbowPole: [0.45, -1, 0.2],
|
|
9629
10142
|
shoulderLeft: [-0.07, -0.46, 0.18],
|
|
@@ -9650,22 +10163,14 @@ var GameCharactersThree = (() => {
|
|
|
9650
10163
|
};
|
|
9651
10164
|
|
|
9652
10165
|
// src/first-person/hand.ts
|
|
9653
|
-
var
|
|
9654
|
-
|
|
9655
|
-
|
|
9656
|
-
{ z: 9e-3, lengths: [0.035, 0.025, 0.02], width: 0.0155 },
|
|
9657
|
-
{ z: 0.027, lengths: [0.029, 0.02, 0.018], width: 0.0135 }
|
|
9658
|
-
];
|
|
9659
|
-
var PALM = { length: 0.09, thick: 0.026, width: 0.09, wristWidth: 0.066 };
|
|
9660
|
-
var FINGER_THICK = 0.0135;
|
|
9661
|
-
var CURL = { near: 1.05, mid: 1.25, far: 0.85, spread: 0.06 };
|
|
9662
|
-
var THUMB = { base: [5e-3, -6e-3, -0.044], near: 0.034, far: 0.028, width: 0.019 };
|
|
10166
|
+
var PALM = { radius: 0.048, scale: [0.6, 1.05, 1], down: 0.035 };
|
|
10167
|
+
var CURL = { closed: 1.25, near: 0.9, far: 1.1 };
|
|
10168
|
+
var THUMB = { open: 0.32, closed: 0.25 };
|
|
9663
10169
|
var createHandMesh = (THREE, skin, wristSkin = skin) => {
|
|
9664
10170
|
const root = new THREE.Group();
|
|
9665
10171
|
root.name = "first-person-hand";
|
|
9666
10172
|
const geometries = [];
|
|
9667
|
-
const
|
|
9668
|
-
const geometry = new THREE.BoxGeometry(sx, sy, sz);
|
|
10173
|
+
const add = (parent, geometry, material, x = 0, y = 0, z = 0) => {
|
|
9669
10174
|
geometries.push(geometry);
|
|
9670
10175
|
const mesh2 = new THREE.Mesh(geometry, material);
|
|
9671
10176
|
mesh2.position.set(x, y, z);
|
|
@@ -9673,64 +10178,26 @@ var GameCharactersThree = (() => {
|
|
|
9673
10178
|
parent.add(mesh2);
|
|
9674
10179
|
return mesh2;
|
|
9675
10180
|
};
|
|
9676
|
-
const
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
const palm = new THREE.Mesh(palmGeometry, skin);
|
|
9684
|
-
palm.frustumCulled = false;
|
|
9685
|
-
root.add(palm);
|
|
9686
|
-
const wristGeometry = new THREE.CylinderGeometry(0.03, 0.033, 0.05, 8);
|
|
10181
|
+
const group = new THREE.Group();
|
|
10182
|
+
group.quaternion.setFromRotationMatrix(new THREE.Matrix4().makeBasis(new THREE.Vector3(0, -1, 0), new THREE.Vector3(-1, 0, 0), new THREE.Vector3(0, 0, -1)));
|
|
10183
|
+
group.position.set(-PALM.down, 0, 0);
|
|
10184
|
+
root.add(group);
|
|
10185
|
+
add(group, new THREE.SphereGeometry(PALM.radius, 14, 10), skin, 0, -PALM.down, 0).scale.set(...PALM.scale);
|
|
10186
|
+
const built = buildHand({ THREE, add, hg: group, handM: skin, s: -1, detailed: true });
|
|
10187
|
+
const wristGeometry = new THREE.CylinderGeometry(0.03, 0.033, 0.05, 10);
|
|
9687
10188
|
wristGeometry.rotateZ(Math.PI / 2);
|
|
9688
|
-
|
|
9689
|
-
const wrist = new THREE.Mesh(wristGeometry, wristSkin);
|
|
9690
|
-
wrist.position.set(-PALM.length / 2 - 0.018, 0, 0);
|
|
9691
|
-
wrist.frustumCulled = false;
|
|
9692
|
-
root.add(wrist);
|
|
9693
|
-
const joints = [];
|
|
9694
|
-
FINGERS.forEach((finger, index) => {
|
|
9695
|
-
const segments = [];
|
|
9696
|
-
let parent = root;
|
|
9697
|
-
let at = PALM.length / 2;
|
|
9698
|
-
finger.lengths.forEach((length, k) => {
|
|
9699
|
-
const group = new THREE.Group();
|
|
9700
|
-
group.position.set(at, k === 0 ? 2e-3 : 0, k === 0 ? finger.z : 0);
|
|
9701
|
-
const taper = 1 - k * 0.07;
|
|
9702
|
-
box2(group, length, FINGER_THICK * taper, finger.width * taper, length / 2, 0, 0);
|
|
9703
|
-
parent.add(group);
|
|
9704
|
-
segments.push(group);
|
|
9705
|
-
parent = group;
|
|
9706
|
-
at = length;
|
|
9707
|
-
});
|
|
9708
|
-
joints.push({ segments, weight: 1 + index * (CURL.spread / CURL.near) });
|
|
9709
|
-
});
|
|
9710
|
-
const thumbNear = new THREE.Group();
|
|
9711
|
-
thumbNear.rotation.order = "YZX";
|
|
9712
|
-
thumbNear.position.set(...THUMB.base);
|
|
9713
|
-
box2(thumbNear, THUMB.near, FINGER_THICK * 1.1, THUMB.width, THUMB.near / 2, 0, 0);
|
|
9714
|
-
const thumbFar = new THREE.Group();
|
|
9715
|
-
thumbFar.position.set(THUMB.near, 0, 0);
|
|
9716
|
-
box2(thumbFar, THUMB.far, FINGER_THICK, THUMB.width * 0.9, THUMB.far / 2, 0, 0);
|
|
9717
|
-
thumbNear.add(thumbFar);
|
|
9718
|
-
root.add(thumbNear);
|
|
10189
|
+
add(root, wristGeometry, wristSkin, -PALM.down - 0.03, 0, 0);
|
|
9719
10190
|
let lastGrip = 0;
|
|
9720
10191
|
let indexCurl;
|
|
9721
|
-
const
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
if (!finger) return;
|
|
9725
|
-
const k = indexCurl === void 0 ? lastGrip : Math.min(1, Math.max(0, indexCurl));
|
|
9726
|
-
finger.segments.forEach((segment, i) => segment.rotation.z = -curl[i] * k * finger.weight);
|
|
10192
|
+
const curlFinger = (finger, k) => {
|
|
10193
|
+
built.fingers[finger * 2].rotation.z = k * CURL.closed * CURL.near;
|
|
10194
|
+
built.fingers[finger * 2 + 1].rotation.z = k * CURL.closed * CURL.far;
|
|
9727
10195
|
};
|
|
10196
|
+
const applyIndex = () => curlFinger(0, indexCurl === void 0 ? lastGrip : Math.min(1, Math.max(0, indexCurl)));
|
|
9728
10197
|
const setGrip = (grip) => {
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
|
|
9732
|
-
thumbNear.rotation.set(0, 0.55 - 1.45 * k, -0.1 - 0.75 * k);
|
|
9733
|
-
thumbFar.rotation.z = -0.1 - 0.7 * k;
|
|
10198
|
+
lastGrip = Math.min(1, Math.max(0, grip));
|
|
10199
|
+
for (let finger = 1; finger < 4; finger++) curlFinger(finger, lastGrip);
|
|
10200
|
+
if (built.th) built.th.rotation.z = THUMB.open + lastGrip * THUMB.closed;
|
|
9734
10201
|
applyIndex();
|
|
9735
10202
|
};
|
|
9736
10203
|
const setIndex = (value) => {
|
|
@@ -9752,6 +10219,8 @@ var GameCharactersThree = (() => {
|
|
|
9752
10219
|
var DEFAULT_BLEND = 0.18;
|
|
9753
10220
|
var ELBOW_SEGMENTS = 8;
|
|
9754
10221
|
var REACH_SLACK = 0.97;
|
|
10222
|
+
var ELBOW_VIEW_MARGIN = 0.86;
|
|
10223
|
+
var ELBOW_VIEW_PASSES = 4;
|
|
9755
10224
|
var CONTACT_PROBE = 1.4;
|
|
9756
10225
|
var CONTACT_MIN = 0.12;
|
|
9757
10226
|
var CONTACT_MARGIN = 5e-3;
|
|
@@ -9900,6 +10369,11 @@ var GameCharactersThree = (() => {
|
|
|
9900
10369
|
const shoulderOf = (sign2, out) => sign2 === -1 && rig.shoulderLeft ? out.set(...rig.shoulderLeft) : out.set(rig.shoulder[0] * sign2, rig.shoulder[1], rig.shoulder[2]);
|
|
9901
10370
|
const poleOf = (sign2) => sign2 === -1 && rig.elbowPoleLeft ? new THREE.Vector3(...rig.elbowPoleLeft) : new THREE.Vector3(rig.elbowPole[0] * sign2, rig.elbowPole[1], rig.elbowPole[2]);
|
|
9902
10371
|
const kneePole = new THREE.Vector3(...rig.kneePole);
|
|
10372
|
+
const reachOf = (sign2) => {
|
|
10373
|
+
const bend = rig.reachBend?.[sign2 === 1 ? 0 : 1];
|
|
10374
|
+
if (bend === void 0) return (rig.upper + rig.fore) * REACH_SLACK;
|
|
10375
|
+
return Math.sqrt(rig.upper * rig.upper + rig.fore * rig.fore + 2 * rig.upper * rig.fore * Math.cos(bend));
|
|
10376
|
+
};
|
|
9903
10377
|
const hip = new THREE.Vector3(...rig.hip);
|
|
9904
10378
|
const euler = new THREE.Euler(0, 0, 0, "YZX");
|
|
9905
10379
|
const quaternionOf = (r) => new THREE.Quaternion().setFromEuler(euler.set(r[0], r[1], r[2], "YZX"));
|
|
@@ -9989,15 +10463,45 @@ var GameCharactersThree = (() => {
|
|
|
9989
10463
|
out.scale = base.scale;
|
|
9990
10464
|
return out;
|
|
9991
10465
|
};
|
|
9992
|
-
const
|
|
10466
|
+
const elbowAt = new THREE.Vector3();
|
|
10467
|
+
const viewOf = (camera) => {
|
|
10468
|
+
const lens = camera;
|
|
10469
|
+
if (!lens.isPerspectiveCamera) return null;
|
|
10470
|
+
const tanV = Math.tan(lens.fov * Math.PI / 360);
|
|
10471
|
+
return { tanV, tanH: tanV * lens.aspect };
|
|
10472
|
+
};
|
|
10473
|
+
const placeElbowInView = (sign2, view) => {
|
|
10474
|
+
const way = rig.elbowView?.[sign2 === 1 ? 0 : 1];
|
|
10475
|
+
if (!way) return false;
|
|
10476
|
+
elbowAt.set(way[0], way[1], way[2]).setLength(rig.fore).add(wristAt);
|
|
10477
|
+
for (let pass = 0; pass < ELBOW_VIEW_PASSES; pass++) {
|
|
10478
|
+
const depth = Math.max(0.05, -elbowAt.z);
|
|
10479
|
+
const high = view.tanV * ELBOW_VIEW_MARGIN * depth;
|
|
10480
|
+
const wide = view.tanH * ELBOW_VIEW_MARGIN * depth;
|
|
10481
|
+
elbowAt.y = Math.max(elbowAt.y, -high);
|
|
10482
|
+
elbowAt.x = Math.min(wide, Math.max(-wide, elbowAt.x));
|
|
10483
|
+
elbowAt.sub(wristAt).setLength(rig.fore).add(wristAt);
|
|
10484
|
+
}
|
|
10485
|
+
shoulder.sub(elbowAt).setLength(rig.upper).add(elbowAt);
|
|
10486
|
+
return true;
|
|
10487
|
+
};
|
|
10488
|
+
const drawArm = (arm, pose, view) => {
|
|
9993
10489
|
copyPose(arm.drawn, pose);
|
|
9994
10490
|
const scale = pose.scale;
|
|
9995
10491
|
fingers.set(1, 0, 0).applyQuaternion(pose.q);
|
|
9996
10492
|
wristAt.copy(pose.p).addScaledVector(fingers, -rig.wrist * scale);
|
|
9997
10493
|
shoulderOf(arm.sign, shoulder).add(bobOffset);
|
|
9998
|
-
|
|
10494
|
+
if (view && placeElbowInView(arm.sign, view)) {
|
|
10495
|
+
solveTwoBone(shoulder, wristAt, rig.upper, rig.fore, towards.copy(elbowAt).sub(shoulder).add(elbowAt).sub(wristAt), bone);
|
|
10496
|
+
finishArm(arm, pose, scale);
|
|
10497
|
+
return;
|
|
10498
|
+
}
|
|
10499
|
+
const excess = shoulder.distanceTo(wristAt) - reachOf(arm.sign);
|
|
9999
10500
|
if (excess > 0 && rig.reachShift > 0) shoulder.addScaledVector(towards.subVectors(wristAt, shoulder).normalize(), Math.min(excess, rig.reachShift));
|
|
10000
10501
|
solveTwoBone(shoulder, wristAt, rig.upper, rig.fore, poleOf(arm.sign), bone);
|
|
10502
|
+
finishArm(arm, pose, scale);
|
|
10503
|
+
};
|
|
10504
|
+
const finishArm = (arm, pose, scale) => {
|
|
10001
10505
|
palmAt.copy(bone.end).addScaledVector(fingers, rig.wrist * scale);
|
|
10002
10506
|
arm.drawn.p.copy(palmAt);
|
|
10003
10507
|
arm.anchor.position.copy(palmAt);
|
|
@@ -10109,7 +10613,7 @@ var GameCharactersThree = (() => {
|
|
|
10109
10613
|
dropped.p.y -= AWAY_DROP * ease2(arm.away);
|
|
10110
10614
|
pose = dropped;
|
|
10111
10615
|
}
|
|
10112
|
-
drawArm(arm, pose);
|
|
10616
|
+
drawArm(arm, pose, mode === "target" && targets?.elbows !== "body" ? viewOf(state.camera) : null);
|
|
10113
10617
|
const shown = arm.away < AWAY_HIDDEN;
|
|
10114
10618
|
for (const part of [arm.anchor, arm.upper, arm.fore, arm.cuff, arm.elbow]) part.visible = shown;
|
|
10115
10619
|
}
|
|
@@ -10151,237 +10655,6 @@ var GameCharactersThree = (() => {
|
|
|
10151
10655
|
}
|
|
10152
10656
|
};
|
|
10153
10657
|
}
|
|
10154
|
-
|
|
10155
|
-
// src/player/room-avatar.ts
|
|
10156
|
-
var impactOf = (clip) => clip.events?.find((event) => event.type === "impact")?.t ?? null;
|
|
10157
|
-
var isPunch = (clip) => clip.events?.some((event) => event.type === "impact" && event.data?.kind === "punch") ?? false;
|
|
10158
|
-
var GUARD_SPEED = 0.3;
|
|
10159
|
-
var toRoomAvatar = (avatar, options = {}) => {
|
|
10160
|
-
const arms = options.firstPerson === false ? null : createFirstPersonArms(avatar.three, {
|
|
10161
|
-
colors: { skin: avatar.colors.skin, sleeve: avatar.colors.longSleeves ? avatar.colors.shirt : avatar.colors.skin, trouser: avatar.colors.trousers, shoe: avatar.colors.shoes, ...options.firstPerson?.colors },
|
|
10162
|
-
clips: options.firstPersonClips ?? FIRST_PERSON_CLIPS,
|
|
10163
|
-
hideWhenIdle: true,
|
|
10164
|
-
...options.firstPerson
|
|
10165
|
-
});
|
|
10166
|
-
const strikes = new Map((options.strikeClips ?? ATTACK_CLIPS).map((clip) => [clip.id, clip]));
|
|
10167
|
-
const mirrored = /* @__PURE__ */ new Map();
|
|
10168
|
-
const leftOf = (clip) => {
|
|
10169
|
-
let found = mirrored.get(clip.id);
|
|
10170
|
-
if (!found) mirrored.set(clip.id, found = mirrorPoseClip(clip, `${clip.id}_left`));
|
|
10171
|
-
return found;
|
|
10172
|
-
};
|
|
10173
|
-
const guard = options.guardClip === false ? void 0 : strikes.get(options.guardClip ?? "fight_guard");
|
|
10174
|
-
const guardHold = options.guardHold ?? 1.2;
|
|
10175
|
-
const punchBlend = options.punchBlend ?? 0.05;
|
|
10176
|
-
let strikeLeft = 0;
|
|
10177
|
-
let guardLeft = 0;
|
|
10178
|
-
let guarding = false;
|
|
10179
|
-
const stepGuard = (dt, state) => {
|
|
10180
|
-
if (!guard) return;
|
|
10181
|
-
const free = state.speed < GUARD_SPEED && !state.down && !state.armed && !state.holding && !state.push && !state.itemUse && !state.running;
|
|
10182
|
-
if (strikeLeft > 0) {
|
|
10183
|
-
strikeLeft -= dt;
|
|
10184
|
-
if (strikeLeft <= 0 && guardLeft > 0 && free) {
|
|
10185
|
-
avatar.play(guard);
|
|
10186
|
-
guarding = true;
|
|
10187
|
-
}
|
|
10188
|
-
return;
|
|
10189
|
-
}
|
|
10190
|
-
guardLeft = Math.max(0, guardLeft - dt);
|
|
10191
|
-
if (guarding && (guardLeft <= 0 || !free || avatar.playing !== guard.id)) {
|
|
10192
|
-
if (avatar.playing === guard.id) avatar.stop();
|
|
10193
|
-
guarding = false;
|
|
10194
|
-
}
|
|
10195
|
-
};
|
|
10196
|
-
return {
|
|
10197
|
-
root: avatar.root,
|
|
10198
|
-
avatar,
|
|
10199
|
-
arms,
|
|
10200
|
-
...arms ? { firstPerson: { root: arms.root, update: (dt, state) => arms.update(dt, state) } } : {},
|
|
10201
|
-
update: (dt, state) => {
|
|
10202
|
-
stepGuard(dt, state);
|
|
10203
|
-
avatar.update(dt, {
|
|
10204
|
-
speed: state.speed,
|
|
10205
|
-
running: state.running,
|
|
10206
|
-
crouch: state.crouch,
|
|
10207
|
-
down: state.down,
|
|
10208
|
-
armed: state.armed,
|
|
10209
|
-
pitch: -state.pitch,
|
|
10210
|
-
...state.holding !== void 0 ? { holding: state.holding } : {},
|
|
10211
|
-
...state.itemUse !== void 0 ? { itemUse: state.itemUse } : {},
|
|
10212
|
-
...state.push !== void 0 ? { push: state.push } : {}
|
|
10213
|
-
});
|
|
10214
|
-
},
|
|
10215
|
-
hand: (side) => avatar.hand(side),
|
|
10216
|
-
reach: (targets) => avatar.reach(targets),
|
|
10217
|
-
strike: (clipId, strikeOptions) => {
|
|
10218
|
-
const clip = strikes.get(clipId);
|
|
10219
|
-
if (!clip) return null;
|
|
10220
|
-
const left = strikeOptions?.leg === "left" || strikeOptions?.hand === "left";
|
|
10221
|
-
const punch = guard !== void 0 && isPunch(clip);
|
|
10222
|
-
avatar.play(left ? leftOf(clip) : clip, punch ? { blend: punchBlend } : void 0);
|
|
10223
|
-
strikeLeft = punch ? clip.duration : 0;
|
|
10224
|
-
guardLeft = punch ? guardHold : 0;
|
|
10225
|
-
guarding = false;
|
|
10226
|
-
arms?.play(clipId, strikeOptions?.leg === "left" ? { leg: "left" } : strikeOptions?.hand === "left" ? { hand: "left" } : void 0);
|
|
10227
|
-
return impactOf(clip);
|
|
10228
|
-
}
|
|
10229
|
-
};
|
|
10230
|
-
};
|
|
10231
|
-
|
|
10232
|
-
// src/player/test-text.ts
|
|
10233
|
-
var AVATAR_TEXT = {
|
|
10234
|
-
en: {
|
|
10235
|
-
group: "Avatar",
|
|
10236
|
-
name: "Player body",
|
|
10237
|
-
actions: {
|
|
10238
|
-
camera_first: "Camera: 1st person",
|
|
10239
|
-
camera_third: "Camera: 3rd person",
|
|
10240
|
-
crouch: "Crouch",
|
|
10241
|
-
stand: "Stand up",
|
|
10242
|
-
fall: "Fall down",
|
|
10243
|
-
get_up: "Get up",
|
|
10244
|
-
armed_on: "Armed: on",
|
|
10245
|
-
armed_off: "Armed: off",
|
|
10246
|
-
stop_clip: "Stop clip"
|
|
10247
|
-
},
|
|
10248
|
-
play: "Play",
|
|
10249
|
-
metrics: { camera: "Camera", clip: "Clip playing", last_event: "Last clip event", state: "State", joints: "Joints" },
|
|
10250
|
-
none: "none"
|
|
10251
|
-
},
|
|
10252
|
-
"pt-BR": {
|
|
10253
|
-
group: "Avatar",
|
|
10254
|
-
name: "Corpo do jogador",
|
|
10255
|
-
actions: {
|
|
10256
|
-
camera_first: "C\xE2mera: 1\xAA pessoa",
|
|
10257
|
-
camera_third: "C\xE2mera: 3\xAA pessoa",
|
|
10258
|
-
crouch: "Agachar",
|
|
10259
|
-
stand: "Levantar",
|
|
10260
|
-
fall: "Cair",
|
|
10261
|
-
get_up: "Levantar do ch\xE3o",
|
|
10262
|
-
armed_on: "Armado: ligado",
|
|
10263
|
-
armed_off: "Armado: desligado",
|
|
10264
|
-
stop_clip: "Parar clipe"
|
|
10265
|
-
},
|
|
10266
|
-
play: "Tocar",
|
|
10267
|
-
metrics: { camera: "C\xE2mera", clip: "Clipe tocando", last_event: "\xDAltimo evento do clipe", state: "Estado", joints: "Juntas" },
|
|
10268
|
-
none: "nenhum"
|
|
10269
|
-
}
|
|
10270
|
-
};
|
|
10271
|
-
|
|
10272
|
-
// src/player/test-module.ts
|
|
10273
|
-
var AVATAR_AREA_ID = "avatar_area";
|
|
10274
|
-
var round = (value) => (Math.round(value * 100) / 100).toString();
|
|
10275
|
-
function createAvatarTestModule(options) {
|
|
10276
|
-
const clips = options.clips ?? POSE_CLIPS;
|
|
10277
|
-
const textOf = (locale) => AVATAR_TEXT[locale ?? options.locale ?? "pt-BR"] ?? AVATAR_TEXT["pt-BR"];
|
|
10278
|
-
const phaseLabel = (label, locale) => {
|
|
10279
|
-
const id = locale ?? options.locale ?? "pt-BR";
|
|
10280
|
-
const table = { ...POSE_CLIP_LOCALES[id] ?? POSE_CLIP_LOCALES["pt-BR"], ...options.clipLocales?.[id] ?? options.clipLocales?.["pt-BR"] };
|
|
10281
|
-
return typeof label === "string" ? table[label] ?? label : "";
|
|
10282
|
-
};
|
|
10283
|
-
const state = { crouch: false, down: false, armed: null };
|
|
10284
|
-
let host = null;
|
|
10285
|
-
let lastEvent = "";
|
|
10286
|
-
const log = (action, extra = {}) => {
|
|
10287
|
-
const entry = { type: "avatar", action, ...extra };
|
|
10288
|
-
host?.log(JSON.stringify(entry), entry);
|
|
10289
|
-
};
|
|
10290
|
-
const push = (action, patch, extra = {}) => {
|
|
10291
|
-
Object.assign(state, patch);
|
|
10292
|
-
options.state?.set(patch);
|
|
10293
|
-
log(action, { crouch: state.crouch, down: state.down, armed: state.armed, ...extra });
|
|
10294
|
-
};
|
|
10295
|
-
const setCamera = (mode) => {
|
|
10296
|
-
options.camera?.set(mode);
|
|
10297
|
-
log(`camera_${mode}`, { mode: options.camera?.mode() ?? null });
|
|
10298
|
-
};
|
|
10299
|
-
const onChange = (change) => {
|
|
10300
|
-
if (change.kind !== "action") return;
|
|
10301
|
-
switch (change.id) {
|
|
10302
|
-
case "camera_first":
|
|
10303
|
-
return setCamera("first");
|
|
10304
|
-
case "camera_third":
|
|
10305
|
-
return setCamera("third");
|
|
10306
|
-
case "crouch":
|
|
10307
|
-
return push("crouch", { crouch: true });
|
|
10308
|
-
case "stand":
|
|
10309
|
-
return push("stand", { crouch: false });
|
|
10310
|
-
case "fall":
|
|
10311
|
-
return push("fall", { down: true });
|
|
10312
|
-
case "get_up":
|
|
10313
|
-
return push("get_up", { down: false });
|
|
10314
|
-
case "armed_on":
|
|
10315
|
-
return push("armed_on", { armed: true });
|
|
10316
|
-
case "armed_off":
|
|
10317
|
-
return push("armed_off", { armed: false });
|
|
10318
|
-
case "stop_clip":
|
|
10319
|
-
options.avatar.stop();
|
|
10320
|
-
return log("stop_clip", { playing: options.avatar.playing });
|
|
10321
|
-
default: {
|
|
10322
|
-
const clip = clips.find((item) => `play_${item.id}` === change.id);
|
|
10323
|
-
if (!clip) return;
|
|
10324
|
-
options.avatar.play(clip);
|
|
10325
|
-
log("play_clip", { clip: clip.id, duration: clip.duration, loop: clip.loop ?? false, channels: clip.channels ?? "full" });
|
|
10326
|
-
}
|
|
10327
|
-
}
|
|
10328
|
-
};
|
|
10329
|
-
const joints = () => {
|
|
10330
|
-
const rig = options.avatar.rig;
|
|
10331
|
-
const [armA, armB] = rig.arms;
|
|
10332
|
-
const [legA, legB] = rig.legs;
|
|
10333
|
-
return `arms ${round(armA.g.rotation.x)}/${round(armB.g.rotation.x)} elbows ${round(armA.el.rotation.x)}/${round(armB.el.rotation.x)} legs ${round(legA.g.rotation.x)}/${round(legB.g.rotation.x)} knees ${round(legA.kn.rotation.x)}/${round(legB.kn.rotation.x)} lean ${round(rig.upper.rotation.x)}`;
|
|
10334
|
-
};
|
|
10335
|
-
return {
|
|
10336
|
-
id: AVATAR_AREA_ID,
|
|
10337
|
-
name: textOf().name,
|
|
10338
|
-
ground: { surface: "concrete_slab" },
|
|
10339
|
-
group: textOf().group,
|
|
10340
|
-
state,
|
|
10341
|
-
items: () => [],
|
|
10342
|
-
area: () => ({ placements: [], view: { eye: [0, 1.7, 6], target: [0, 1.2, 0] } }),
|
|
10343
|
-
controls: (locale) => {
|
|
10344
|
-
const text = textOf(locale);
|
|
10345
|
-
const action = (id, name, hint) => ({ kind: "action", id, name, ...hint ? { hint } : {} });
|
|
10346
|
-
return [
|
|
10347
|
-
action("camera_first", text.actions.camera_first),
|
|
10348
|
-
action("camera_third", text.actions.camera_third),
|
|
10349
|
-
action("crouch", text.actions.crouch),
|
|
10350
|
-
action("stand", text.actions.stand),
|
|
10351
|
-
action("fall", text.actions.fall),
|
|
10352
|
-
action("get_up", text.actions.get_up),
|
|
10353
|
-
action("armed_on", text.actions.armed_on),
|
|
10354
|
-
action("armed_off", text.actions.armed_off),
|
|
10355
|
-
...clips.map((clip) => action(`play_${clip.id}`, `${text.play}: ${clip.id}`)),
|
|
10356
|
-
action("stop_clip", text.actions.stop_clip)
|
|
10357
|
-
];
|
|
10358
|
-
},
|
|
10359
|
-
metrics: (locale) => {
|
|
10360
|
-
const text = textOf(locale);
|
|
10361
|
-
return [
|
|
10362
|
-
{ id: "camera", name: text.metrics.camera, read: () => options.camera?.mode() ?? text.none },
|
|
10363
|
-
{ id: "clip", name: text.metrics.clip, read: () => options.avatar.playing ?? text.none },
|
|
10364
|
-
{ id: "last_event", name: text.metrics.last_event, read: () => lastEvent || text.none },
|
|
10365
|
-
{ id: "state", name: text.metrics.state, read: () => `${state.crouch ? "crouch " : ""}${state.down ? "down " : ""}${state.armed === null ? "" : state.armed ? "armed" : "unarmed"}`.trim() || text.none },
|
|
10366
|
-
{ id: "joints", name: text.metrics.joints, read: joints }
|
|
10367
|
-
];
|
|
10368
|
-
},
|
|
10369
|
-
attach(lent) {
|
|
10370
|
-
host = lent;
|
|
10371
|
-
const stopChange = lent.bench?.onChange(onChange);
|
|
10372
|
-
const stopEvents = options.avatar.on("event", (event) => {
|
|
10373
|
-
lastEvent = `${event.clip} ${event.type} ${round(event.t)}s${event.data && "label" in event.data ? ` ${phaseLabel(event.data.label)}` : ""}`;
|
|
10374
|
-
log("clip_event", { clip: event.clip, event: event.type, t: event.t, data: event.data ?? null });
|
|
10375
|
-
if (event.type === "impact") log("impact", { clip: event.clip, t: event.t, kind: event.data?.kind ?? null });
|
|
10376
|
-
});
|
|
10377
|
-
return () => {
|
|
10378
|
-
stopChange?.();
|
|
10379
|
-
stopEvents();
|
|
10380
|
-
host = null;
|
|
10381
|
-
};
|
|
10382
|
-
}
|
|
10383
|
-
};
|
|
10384
|
-
}
|
|
10385
10658
|
return __toCommonJS(index_exports);
|
|
10386
10659
|
})();
|
|
10387
10660
|
//# sourceMappingURL=index.global.js.map
|