@adatechnology/game-interactables-three 0.1.14 → 0.2.0

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/dist/index.js CHANGED
@@ -1,3 +1,39 @@
1
+ // src/effects.ts
2
+ import { warnOnce } from "@adatechnology/game-contracts";
3
+
4
+ // src/routed-particles.ts
5
+ var channel = (value) => Math.round(Math.min(1, Math.max(0, value)) * 255);
6
+ var rgb = (red, green, blue) => channel(red) << 16 | channel(green) << 8 | channel(blue);
7
+ var EFFECT_OF = { smoke: "particle_puff", steam: "particle_puff", fire: "particle_glow", spark: "particle_streak" };
8
+ var isRoutedKind = (kind) => EFFECT_OF[kind] !== void 0;
9
+ function routedParticleRequest(particle) {
10
+ const { kind, flag, tint } = particle;
11
+ const look = lookOf(kind, flag, tint);
12
+ return {
13
+ effect: EFFECT_OF[kind],
14
+ point: particle.position,
15
+ values: {
16
+ vx: particle.velocity[0],
17
+ vy: particle.velocity[1],
18
+ vz: particle.velocity[2],
19
+ life: particle.life,
20
+ size: particle.startSize,
21
+ grow: particle.endSize / particle.startSize,
22
+ color: look.color,
23
+ alpha: look.alpha,
24
+ gravity: 0,
25
+ drag: 0
26
+ }
27
+ };
28
+ }
29
+ function lookOf(kind, flag, tint) {
30
+ if (kind === "smoke") return { color: rgb(tint, tint, tint), alpha: 0.55 };
31
+ if (kind === "steam") return { color: rgb(tint, tint, tint), alpha: 0.4 };
32
+ if (kind === "spark") return { color: rgb(1, 0.75, 0.3), alpha: 1 };
33
+ if (flag) return { color: rgb(0.25 + 0.15 * tint, 0.5 + 0.2 * tint, 1), alpha: 0.95 };
34
+ return { color: rgb(1, Math.max(0.15, 0.85 - tint * 0.1), 0.25), alpha: 0.8 };
35
+ }
36
+
1
37
  // src/effects.ts
2
38
  var POOLS = ["smoke", "steam", "fire", "water", "spark"];
3
39
  var WEIGHT = { smoke: 0.27, steam: 0.15, fire: 0.2, water: 0.28, spark: 0.1 };
@@ -172,6 +208,12 @@ function createEffects(THREE, a, b = {}) {
172
208
  let stamp = 0;
173
209
  let clock = 0;
174
210
  const spawn = (p, x, y, z, vx, vy, vz, life, s0, s1, tint, flag = 0, ground = -1e9) => {
211
+ const sink = isRoutedKind(p.kind) ? options.effects?.() : void 0;
212
+ if (sink) {
213
+ sink.play(routedParticleRequest({ kind: p.kind, flag, position: [x, y, z], velocity: [vx, vy, vz], life, startSize: s0, endSize: s1, tint }));
214
+ return;
215
+ }
216
+ if (isRoutedKind(p.kind)) warnOnce("game-interactables-three.own-particles", "game-interactables-three drew its smoke, steam, fire and sparks with pools of its own because the host lent no effects world (options.effects); pass the host effects so the particles share one budget");
175
217
  if (p.count >= p.cap) return;
176
218
  const i = p.count++;
177
219
  p.pos[i * 3] = x;
@@ -662,43 +704,12 @@ function createEffects(THREE, a, b = {}) {
662
704
  };
663
705
  }
664
706
 
665
- // src/cord.ts
666
- function catenary(a, b, sag, n = 12) {
667
- const count = Math.max(2, Math.floor(n));
668
- const span = Math.hypot(b[0] - a[0], b[2] - a[2]) || Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
669
- const depth = Math.max(0, sag);
670
- const out = [];
671
- let shape = () => 0;
672
- if (depth > 1e-6 && span > 1e-6) {
673
- let lo = 1e-4;
674
- let hi = span * 1e3;
675
- for (let i = 0; i < 80; i++) {
676
- const c2 = (lo + hi) / 2;
677
- const d = c2 * (Math.cosh(span / (2 * c2)) - 1);
678
- if (d > depth) lo = c2;
679
- else hi = c2;
680
- }
681
- const c = (lo + hi) / 2;
682
- shape = (s) => c * (Math.cosh((s - 0.5) * span / c) - Math.cosh(span / (2 * c)));
683
- }
684
- for (let i = 0; i < count; i++) {
685
- const s = i / (count - 1);
686
- out.push([a[0] + (b[0] - a[0]) * s, a[1] + (b[1] - a[1]) * s + shape(s), a[2] + (b[2] - a[2]) * s]);
687
- }
688
- return out;
689
- }
690
- function createCord(THREE, points, radius, material, radialSegments = 5) {
691
- if (points.length < 2) throw new Error("createCord needs at least two points");
692
- const curve = new THREE.CatmullRomCurve3(points.map((p) => new THREE.Vector3(p[0], p[1], p[2])), false, "centripetal");
693
- const segments = Math.max(4, (points.length - 1) * 4);
694
- const mesh = new THREE.Mesh(new THREE.TubeGeometry(curve, segments, radius, radialSegments, false), material);
695
- mesh.name = "cord";
696
- mesh.castShadow = true;
697
- return mesh;
698
- }
707
+ // src/adapter.ts
708
+ import { createCord, catenary } from "@adatechnology/game-shapes-three";
699
709
 
700
710
  // src/mesh.ts
701
711
  import { markKitOrigin } from "@adatechnology/game-contracts";
712
+ import { LIGHT_PRIORITY } from "@adatechnology/game-render-three";
702
713
  import { createShapeRecorder } from "@adatechnology/game-props3d";
703
714
  import { colorChannels, generate } from "@adatechnology/game-shapes";
704
715
 
@@ -1092,6 +1103,7 @@ function createMeshApi(THREE, options = {}) {
1092
1103
  if (first !== k) materialAlias[k] = first;
1093
1104
  }
1094
1105
  const lightsOut = [];
1106
+ const sourcesOut = [];
1095
1107
  const build = (batches, points, id, into, materialFor) => {
1096
1108
  for (const batch of batches) {
1097
1109
  const g = new THREE.BufferGeometry();
@@ -1113,6 +1125,14 @@ function createMeshApi(THREE, options = {}) {
1113
1125
  }
1114
1126
  for (const point of points) {
1115
1127
  const l = point.data;
1128
+ if (options.lights) {
1129
+ const bulb = new THREE.Object3D();
1130
+ bulb.name = "lamp";
1131
+ bulb.position.set(point.position[0], point.position[1], point.position[2]);
1132
+ into.add(bulb);
1133
+ sourcesOut.push(options.lights.addSource({ owner: "interactables.lamp", priority: LIGHT_PRIORITY.lamp, color: l.color, intensity: 1, distance: l.range, position: [0, 0, 0], follow: bulb }));
1134
+ continue;
1135
+ }
1116
1136
  const light = new THREE.PointLight(l.color, 1, l.range);
1117
1137
  light.position.set(point.position[0], point.position[1], point.position[2]);
1118
1138
  into.add(light);
@@ -1156,7 +1176,7 @@ function createMeshApi(THREE, options = {}) {
1156
1176
  }
1157
1177
  if (spec && (options.mergeParts ?? quality === "game")) mergeParts(THREE, group, parts, spec, { swayAmplitude: options.swayAmplitude });
1158
1178
  if (spec) tagDestruction(group, parts, spec);
1159
- return { group, parts, lights: lightsOut };
1179
+ return { group, parts, lights: lightsOut, sources: sourcesOut };
1160
1180
  }
1161
1181
  };
1162
1182
  }
@@ -1348,7 +1368,7 @@ function createScreen(THREE, options) {
1348
1368
  emissiveIntensity: 0
1349
1369
  });
1350
1370
  let on = false;
1351
- let channel = 0;
1371
+ let channel2 = 0;
1352
1372
  let clock = 0;
1353
1373
  let acc = 0;
1354
1374
  const fill = (style, x, y, rw, rh) => {
@@ -1358,7 +1378,7 @@ function createScreen(THREE, options) {
1358
1378
  };
1359
1379
  const drawBars = () => {
1360
1380
  const n = BARS.length;
1361
- for (let i = 0; i < n; i++) fill(BARS[(i + channel) % n], Math.floor(i * w / n), 0, Math.ceil(w / n), Math.floor(h * 0.75));
1381
+ for (let i = 0; i < n; i++) fill(BARS[(i + channel2) % n], Math.floor(i * w / n), 0, Math.ceil(w / n), Math.floor(h * 0.75));
1362
1382
  fill("#101010", 0, Math.floor(h * 0.75), w, h - Math.floor(h * 0.75));
1363
1383
  const x = clock * 20 % (w + 12) - 12;
1364
1384
  fill("#ffffff", x, Math.floor(h * 0.8), 12, Math.floor(h * 0.1));
@@ -1373,7 +1393,7 @@ function createScreen(THREE, options) {
1373
1393
  }
1374
1394
  };
1375
1395
  const drawScene = () => {
1376
- const hue = channel * 40 % 360;
1396
+ const hue = channel2 * 40 % 360;
1377
1397
  fill(`hsl(${(200 + hue) % 360},60%,${55 + 10 * Math.sin(clock * 0.3)}%)`, 0, 0, w, Math.floor(h * 0.65));
1378
1398
  fill(`hsl(${(110 + hue) % 360},40%,32%)`, 0, Math.floor(h * 0.65), w, h - Math.floor(h * 0.65));
1379
1399
  const sx = (0.5 + 0.4 * Math.sin(clock * 0.5)) * w;
@@ -1385,9 +1405,9 @@ function createScreen(THREE, options) {
1385
1405
  const draw = () => {
1386
1406
  if (!on) {
1387
1407
  fill("#000000", 0, 0, w, h);
1388
- } else if (channel % 3 === 0) {
1408
+ } else if (channel2 % 3 === 0) {
1389
1409
  drawBars();
1390
- } else if (channel % 3 === 1) {
1410
+ } else if (channel2 % 3 === 1) {
1391
1411
  drawNoise();
1392
1412
  } else {
1393
1413
  drawScene();
@@ -1408,7 +1428,7 @@ function createScreen(THREE, options) {
1408
1428
  return on;
1409
1429
  },
1410
1430
  get channel() {
1411
- return channel;
1431
+ return channel2;
1412
1432
  },
1413
1433
  setOn(value) {
1414
1434
  on = !!value;
@@ -1416,7 +1436,7 @@ function createScreen(THREE, options) {
1416
1436
  apply();
1417
1437
  },
1418
1438
  setChannel(n) {
1419
- channel = Math.max(0, Math.floor(n));
1439
+ channel2 = Math.max(0, Math.floor(n));
1420
1440
  if (on) draw();
1421
1441
  },
1422
1442
  update(dt) {
@@ -1515,7 +1535,7 @@ function attachSway(THREE, mesh, options = {}) {
1515
1535
  function createThreeAdapter(THREE, options = {}) {
1516
1536
  return {
1517
1537
  THREE,
1518
- createMeshApi: (o = {}) => createMeshApi(THREE, { quality: options.quality, materials: options.materials, ...o }),
1538
+ createMeshApi: (o = {}) => createMeshApi(THREE, { quality: options.quality, materials: options.materials, ...options.lights ? { lights: options.lights } : {}, ...o }),
1519
1539
  applyPose: (group, motion, t) => applyPose(THREE, group, motion, t),
1520
1540
  syncObject: (world, objectId, parts, o) => syncObject(THREE, world, objectId, parts, o),
1521
1541
  swayMaterial: (base, o) => swayMaterial(THREE, base, o),
@@ -1531,12 +1551,15 @@ function createThreeAdapter(THREE, options = {}) {
1531
1551
  catenary
1532
1552
  };
1533
1553
  }
1554
+
1555
+ // src/cord.ts
1556
+ import { catenary as catenary2, createCord as createCord2 } from "@adatechnology/game-shapes-three";
1534
1557
  export {
1535
1558
  MATERIAL_KEYS,
1536
1559
  applyPose,
1537
1560
  attachSway,
1538
- catenary,
1539
- createCord,
1561
+ catenary2 as catenary,
1562
+ createCord2 as createCord,
1540
1563
  createDefaultMaterials,
1541
1564
  createEffects,
1542
1565
  createMeshApi,