@adatechnology/game-characters-three 0.7.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.
@@ -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 };
@@ -5439,8 +5523,8 @@ var GameCharactersThree = (() => {
5439
5523
  root.userData.rig = rig;
5440
5524
  return root;
5441
5525
  }
5442
- const marked = (...args) => markKitOrigin(build(...args), { owner: "game-characters-three", kind: "person" });
5443
- return { build: marked, TYPES, setLOD(k) {
5526
+ const marked2 = (...args) => markKitOrigin(build(...args), { owner: "game-characters-three", kind: "person" });
5527
+ return { build: marked2, TYPES, setLOD(k) {
5444
5528
  LK = k;
5445
5529
  SEG = Math.max(5, Math.round(16 * k));
5446
5530
  }, topM: () => topM_ref };
@@ -6908,7 +6992,10 @@ var GameCharactersThree = (() => {
6908
6992
  const quaternion = new three.Quaternion();
6909
6993
  const euler = new three.Euler();
6910
6994
  const trim = () => {
6911
- while (pieces.length > max) pieces.shift()?.object.removeFromParent();
6995
+ while (pieces.length > max) {
6996
+ const piece = pieces.shift();
6997
+ if (piece) discardObject3D(piece.object);
6998
+ }
6912
6999
  };
6913
7000
  const add = (object2, velocity, spin, tag) => {
6914
7001
  const piece = { object: object2, velocity, spin, rest: false, ...tag ? { tag } : {} };
@@ -6957,7 +7044,7 @@ var GameCharactersThree = (() => {
6957
7044
  }
6958
7045
  },
6959
7046
  clear() {
6960
- pieces.splice(0).forEach((piece) => piece.object.removeFromParent());
7047
+ discardObject3D(pieces.splice(0).map((piece) => piece.object));
6961
7048
  }
6962
7049
  };
6963
7050
  };
@@ -8568,6 +8655,8 @@ var GameCharactersThree = (() => {
8568
8655
  time += dt;
8569
8656
  for (const [id, entry] of entries) {
8570
8657
  if (!entry.root.parent) {
8658
+ if (entry.body) wounds?.untrack(entry.body);
8659
+ if (selected === entry) selected = null;
8571
8660
  entries.delete(id);
8572
8661
  continue;
8573
8662
  }
@@ -9809,6 +9898,233 @@ var GameCharactersThree = (() => {
9809
9898
  var FIRST_PERSON_CLIPS = first_person_clips_default.clips;
9810
9899
  var NAME_POOLS = { "pt-BR": names_default["pt-BR"] };
9811
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
+
9812
10128
  // src/presets/first-person-arms.json
9813
10129
  var first_person_arms_default = {
9814
10130
  source: {
@@ -10339,241 +10655,6 @@ var GameCharactersThree = (() => {
10339
10655
  }
10340
10656
  };
10341
10657
  }
10342
-
10343
- // src/player/room-avatar.ts
10344
- var impactOf = (clip) => clip.events?.find((event) => event.type === "impact")?.t ?? null;
10345
- var isPunch = (clip) => clip.events?.some((event) => event.type === "impact" && event.data?.kind === "punch") ?? false;
10346
- var GUARD_SPEED = 0.3;
10347
- var toRoomAvatar = (avatar, options = {}) => {
10348
- const arms = options.firstPerson === false || options.firstPerson === void 0 ? null : createFirstPersonArms(avatar.three, {
10349
- 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 },
10350
- clips: options.firstPersonClips ?? FIRST_PERSON_CLIPS,
10351
- hideWhenIdle: true,
10352
- ...options.firstPerson
10353
- });
10354
- const strikes = new Map((options.strikeClips ?? ATTACK_CLIPS).map((clip) => [clip.id, clip]));
10355
- const mirrored = /* @__PURE__ */ new Map();
10356
- const leftOf = (clip) => {
10357
- let found = mirrored.get(clip.id);
10358
- if (!found) mirrored.set(clip.id, found = mirrorPoseClip(clip, `${clip.id}_left`));
10359
- return found;
10360
- };
10361
- const guard = options.guardClip === false ? void 0 : strikes.get(options.guardClip ?? "fight_guard");
10362
- const guardHold = options.guardHold ?? 1.2;
10363
- const punchBlend = options.punchBlend ?? 0.05;
10364
- let strikeLeft = 0;
10365
- let guardLeft = 0;
10366
- let guarding = false;
10367
- const stepGuard = (dt, state) => {
10368
- if (!guard) return;
10369
- const free = state.speed < GUARD_SPEED && !state.down && !state.armed && !state.holding && !state.push && !state.door && !state.itemUse && !state.running;
10370
- if (strikeLeft > 0) {
10371
- strikeLeft -= dt;
10372
- if (strikeLeft <= 0 && guardLeft > 0 && free) {
10373
- avatar.play(guard);
10374
- guarding = true;
10375
- }
10376
- return;
10377
- }
10378
- guardLeft = Math.max(0, guardLeft - dt);
10379
- if (guarding && (guardLeft <= 0 || !free || avatar.playing !== guard.id)) {
10380
- if (avatar.playing === guard.id) avatar.stop();
10381
- guarding = false;
10382
- }
10383
- };
10384
- return {
10385
- root: avatar.root,
10386
- avatar,
10387
- arms,
10388
- eye: (out) => avatar.eye(out),
10389
- setView: (mode, camera) => avatar.setView(mode, camera),
10390
- update: (dt, state) => {
10391
- stepGuard(dt, state);
10392
- avatar.update(dt, {
10393
- speed: state.speed,
10394
- running: state.running,
10395
- crouch: state.crouch,
10396
- down: state.down,
10397
- armed: state.armed,
10398
- pitch: -state.pitch,
10399
- ...state.holding !== void 0 ? { holding: state.holding } : {},
10400
- ...state.itemUse !== void 0 ? { itemUse: state.itemUse } : {},
10401
- ...state.push !== void 0 ? { push: state.push } : {},
10402
- ...state.seat !== void 0 ? { seat: state.seat } : {},
10403
- ...state.door !== void 0 ? { door: state.door } : {}
10404
- });
10405
- },
10406
- hand: (side) => avatar.hand(side),
10407
- shoulder: (side) => avatar.shoulder(side),
10408
- reach: (targets, view) => avatar.reach(targets, view),
10409
- strike: (clipId, strikeOptions) => {
10410
- const clip = strikes.get(clipId);
10411
- if (!clip) return null;
10412
- const left = strikeOptions?.leg === "left" || strikeOptions?.hand === "left";
10413
- const punch = guard !== void 0 && isPunch(clip);
10414
- avatar.play(left ? leftOf(clip) : clip, punch ? { blend: punchBlend } : void 0);
10415
- strikeLeft = punch ? clip.duration : 0;
10416
- guardLeft = punch ? guardHold : 0;
10417
- guarding = false;
10418
- arms?.play(clipId, strikeOptions?.leg === "left" ? { leg: "left" } : strikeOptions?.hand === "left" ? { hand: "left" } : void 0);
10419
- return impactOf(clip);
10420
- }
10421
- };
10422
- };
10423
-
10424
- // src/player/test-text.ts
10425
- var AVATAR_TEXT = {
10426
- en: {
10427
- group: "Avatar",
10428
- name: "Player body",
10429
- actions: {
10430
- camera_first: "Camera: 1st person",
10431
- camera_third: "Camera: 3rd person",
10432
- crouch: "Crouch",
10433
- stand: "Stand up",
10434
- fall: "Fall down",
10435
- get_up: "Get up",
10436
- armed_on: "Armed: on",
10437
- armed_off: "Armed: off",
10438
- stop_clip: "Stop clip"
10439
- },
10440
- play: "Play",
10441
- metrics: { camera: "Camera", clip: "Clip playing", last_event: "Last clip event", state: "State", joints: "Joints" },
10442
- none: "none"
10443
- },
10444
- "pt-BR": {
10445
- group: "Avatar",
10446
- name: "Corpo do jogador",
10447
- actions: {
10448
- camera_first: "C\xE2mera: 1\xAA pessoa",
10449
- camera_third: "C\xE2mera: 3\xAA pessoa",
10450
- crouch: "Agachar",
10451
- stand: "Levantar",
10452
- fall: "Cair",
10453
- get_up: "Levantar do ch\xE3o",
10454
- armed_on: "Armado: ligado",
10455
- armed_off: "Armado: desligado",
10456
- stop_clip: "Parar clipe"
10457
- },
10458
- play: "Tocar",
10459
- metrics: { camera: "C\xE2mera", clip: "Clipe tocando", last_event: "\xDAltimo evento do clipe", state: "Estado", joints: "Juntas" },
10460
- none: "nenhum"
10461
- }
10462
- };
10463
-
10464
- // src/player/test-module.ts
10465
- var AVATAR_AREA_ID = "avatar_area";
10466
- var round = (value) => (Math.round(value * 100) / 100).toString();
10467
- function createAvatarTestModule(options) {
10468
- const clips = options.clips ?? POSE_CLIPS;
10469
- const textOf = (locale) => AVATAR_TEXT[locale ?? options.locale ?? "pt-BR"] ?? AVATAR_TEXT["pt-BR"];
10470
- const phaseLabel = (label, locale) => {
10471
- const id = locale ?? options.locale ?? "pt-BR";
10472
- const table = { ...POSE_CLIP_LOCALES[id] ?? POSE_CLIP_LOCALES["pt-BR"], ...options.clipLocales?.[id] ?? options.clipLocales?.["pt-BR"] };
10473
- return typeof label === "string" ? table[label] ?? label : "";
10474
- };
10475
- const state = { crouch: false, down: false, armed: null };
10476
- let host = null;
10477
- let lastEvent = "";
10478
- const log = (action, extra = {}) => {
10479
- const entry = { type: "avatar", action, ...extra };
10480
- host?.log(JSON.stringify(entry), entry);
10481
- };
10482
- const push = (action, patch, extra = {}) => {
10483
- Object.assign(state, patch);
10484
- options.state?.set(patch);
10485
- log(action, { crouch: state.crouch, down: state.down, armed: state.armed, ...extra });
10486
- };
10487
- const setCamera = (mode) => {
10488
- options.camera?.set(mode);
10489
- log(`camera_${mode}`, { mode: options.camera?.mode() ?? null });
10490
- };
10491
- const onChange = (change) => {
10492
- if (change.kind !== "action") return;
10493
- switch (change.id) {
10494
- case "camera_first":
10495
- return setCamera("first");
10496
- case "camera_third":
10497
- return setCamera("third");
10498
- case "crouch":
10499
- return push("crouch", { crouch: true });
10500
- case "stand":
10501
- return push("stand", { crouch: false });
10502
- case "fall":
10503
- return push("fall", { down: true });
10504
- case "get_up":
10505
- return push("get_up", { down: false });
10506
- case "armed_on":
10507
- return push("armed_on", { armed: true });
10508
- case "armed_off":
10509
- return push("armed_off", { armed: false });
10510
- case "stop_clip":
10511
- options.avatar.stop();
10512
- return log("stop_clip", { playing: options.avatar.playing });
10513
- default: {
10514
- const clip = clips.find((item) => `play_${item.id}` === change.id);
10515
- if (!clip) return;
10516
- options.avatar.play(clip);
10517
- log("play_clip", { clip: clip.id, duration: clip.duration, loop: clip.loop ?? false, channels: clip.channels ?? "full" });
10518
- }
10519
- }
10520
- };
10521
- const joints = () => {
10522
- const rig = options.avatar.rig;
10523
- const [armA, armB] = rig.arms;
10524
- const [legA, legB] = rig.legs;
10525
- 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)}`;
10526
- };
10527
- return {
10528
- id: AVATAR_AREA_ID,
10529
- name: textOf().name,
10530
- ground: { surface: "concrete_slab" },
10531
- group: textOf().group,
10532
- state,
10533
- items: () => [],
10534
- area: () => ({ placements: [], view: { eye: [0, 1.7, 6], target: [0, 1.2, 0] } }),
10535
- controls: (locale) => {
10536
- const text = textOf(locale);
10537
- const action = (id, name, hint) => ({ kind: "action", id, name, ...hint ? { hint } : {} });
10538
- return [
10539
- action("camera_first", text.actions.camera_first),
10540
- action("camera_third", text.actions.camera_third),
10541
- action("crouch", text.actions.crouch),
10542
- action("stand", text.actions.stand),
10543
- action("fall", text.actions.fall),
10544
- action("get_up", text.actions.get_up),
10545
- action("armed_on", text.actions.armed_on),
10546
- action("armed_off", text.actions.armed_off),
10547
- ...clips.map((clip) => action(`play_${clip.id}`, `${text.play}: ${clip.id}`)),
10548
- action("stop_clip", text.actions.stop_clip)
10549
- ];
10550
- },
10551
- metrics: (locale) => {
10552
- const text = textOf(locale);
10553
- return [
10554
- { id: "camera", name: text.metrics.camera, read: () => options.camera?.mode() ?? text.none },
10555
- { id: "clip", name: text.metrics.clip, read: () => options.avatar.playing ?? text.none },
10556
- { id: "last_event", name: text.metrics.last_event, read: () => lastEvent || text.none },
10557
- { id: "state", name: text.metrics.state, read: () => `${state.crouch ? "crouch " : ""}${state.down ? "down " : ""}${state.armed === null ? "" : state.armed ? "armed" : "unarmed"}`.trim() || text.none },
10558
- { id: "joints", name: text.metrics.joints, read: joints }
10559
- ];
10560
- },
10561
- attach(lent) {
10562
- host = lent;
10563
- const stopChange = lent.bench?.onChange(onChange);
10564
- const stopEvents = options.avatar.on("event", (event) => {
10565
- lastEvent = `${event.clip} ${event.type} ${round(event.t)}s${event.data && "label" in event.data ? ` ${phaseLabel(event.data.label)}` : ""}`;
10566
- log("clip_event", { clip: event.clip, event: event.type, t: event.t, data: event.data ?? null });
10567
- if (event.type === "impact") log("impact", { clip: event.clip, t: event.t, kind: event.data?.kind ?? null });
10568
- });
10569
- return () => {
10570
- stopChange?.();
10571
- stopEvents();
10572
- host = null;
10573
- };
10574
- }
10575
- };
10576
- }
10577
10658
  return __toCommonJS(index_exports);
10578
10659
  })();
10579
10660
  //# sourceMappingURL=index.global.js.map