@playdrop/playdrop-cli 0.7.15 → 0.7.17

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.
Files changed (70) hide show
  1. package/config/client-meta.json +1 -1
  2. package/node_modules/@playdrop/ai-client/dist/index.js +461 -444
  3. package/node_modules/@playdrop/ai-client/package.json +1 -1
  4. package/node_modules/@playdrop/api-client/dist/client.js +903 -882
  5. package/node_modules/@playdrop/api-client/dist/core/errors.js +69 -45
  6. package/node_modules/@playdrop/api-client/dist/core/request.js +188 -159
  7. package/node_modules/@playdrop/api-client/dist/domains/admin.js +516 -491
  8. package/node_modules/@playdrop/api-client/dist/domains/ai.js +40 -14
  9. package/node_modules/@playdrop/api-client/dist/domains/apps.js +480 -462
  10. package/node_modules/@playdrop/api-client/dist/domains/asset-packs.js +439 -419
  11. package/node_modules/@playdrop/api-client/dist/domains/assets.js +696 -676
  12. package/node_modules/@playdrop/api-client/dist/domains/auth.js +346 -320
  13. package/node_modules/@playdrop/api-client/dist/domains/comments.js +124 -98
  14. package/node_modules/@playdrop/api-client/dist/domains/free-credits.js +91 -65
  15. package/node_modules/@playdrop/api-client/dist/domains/me.js +71 -45
  16. package/node_modules/@playdrop/api-client/dist/domains/payments.js +407 -386
  17. package/node_modules/@playdrop/api-client/dist/domains/player-meta.js +144 -118
  18. package/node_modules/@playdrop/api-client/dist/domains/search.js +117 -104
  19. package/node_modules/@playdrop/api-client/dist/domains/tags.js +188 -162
  20. package/node_modules/@playdrop/api-client/dist/index.js +993 -552
  21. package/node_modules/@playdrop/api-client/package.json +1 -1
  22. package/node_modules/@playdrop/boxel-three/dist/src/animations.js +84 -62
  23. package/node_modules/@playdrop/boxel-three/dist/src/builders.js +341 -308
  24. package/node_modules/@playdrop/boxel-three/dist/src/context.js +55 -29
  25. package/node_modules/@playdrop/boxel-three/dist/src/exporters/glb.js +856 -858
  26. package/node_modules/@playdrop/boxel-three/dist/src/exporters/image.js +267 -261
  27. package/node_modules/@playdrop/boxel-three/dist/src/index.js +64 -15
  28. package/node_modules/@playdrop/boxel-three/dist/src/instantiate.js +89 -63
  29. package/node_modules/@playdrop/boxel-three/dist/src/nodes.js +81 -56
  30. package/node_modules/@playdrop/boxel-three/dist/src/overlays.js +112 -86
  31. package/node_modules/@playdrop/boxel-three/dist/src/primitives.js +45 -17
  32. package/node_modules/@playdrop/boxel-three/dist/src/scene.js +160 -136
  33. package/node_modules/@playdrop/boxel-three/dist/src/skinned-mesh.js +582 -584
  34. package/node_modules/@playdrop/boxel-three/dist/src/texture-atlas.js +123 -97
  35. package/node_modules/@playdrop/boxel-three/dist/src/textures.js +207 -182
  36. package/node_modules/@playdrop/boxel-three/dist/src/types.js +15 -1
  37. package/node_modules/@playdrop/boxel-three/dist/src/voxels/faces.js +451 -425
  38. package/node_modules/@playdrop/boxel-three/dist/src/voxels/mesher.js +109 -84
  39. package/node_modules/@playdrop/boxel-three/dist/test/export-image.playwright.test.js +127 -106
  40. package/node_modules/@playdrop/boxel-three/dist/test/fixtures/render-worker.js +73 -51
  41. package/node_modules/@playdrop/boxel-three/dist/test/glb-skinned.test.js +97 -79
  42. package/node_modules/@playdrop/boxel-three/dist/test/index.test.js +29 -7
  43. package/node_modules/@playdrop/boxel-three/dist/test/instantiate.test.js +80 -60
  44. package/node_modules/@playdrop/boxel-three/dist/test/overlays.test.js +41 -19
  45. package/node_modules/@playdrop/boxel-three/dist/test/scene-filter.test.js +72 -50
  46. package/node_modules/@playdrop/boxel-three/dist/test/scene-smoke.test.js +84 -62
  47. package/node_modules/@playdrop/boxel-three/dist/test/skinned-mesh.test.js +69 -47
  48. package/node_modules/@playdrop/boxel-three/dist/test/textured-overlay.test.js +129 -109
  49. package/node_modules/@playdrop/boxel-three/dist/test/voxels.test.js +40 -18
  50. package/node_modules/@playdrop/boxel-three/package.json +1 -1
  51. package/node_modules/@playdrop/config/client-meta.json +1 -1
  52. package/node_modules/@playdrop/types/dist/api.js +289 -203
  53. package/node_modules/@playdrop/types/dist/app-capability-filters.js +112 -62
  54. package/node_modules/@playdrop/types/dist/app.js +91 -45
  55. package/node_modules/@playdrop/types/dist/asset-pack.js +37 -5
  56. package/node_modules/@playdrop/types/dist/asset-spec.js +170 -90
  57. package/node_modules/@playdrop/types/dist/asset.js +186 -108
  58. package/node_modules/@playdrop/types/dist/content-license.js +49 -15
  59. package/node_modules/@playdrop/types/dist/creator-public-image.js +60 -32
  60. package/node_modules/@playdrop/types/dist/ecs.js +102 -82
  61. package/node_modules/@playdrop/types/dist/engine-builtins.js +603 -573
  62. package/node_modules/@playdrop/types/dist/entity.js +63 -53
  63. package/node_modules/@playdrop/types/dist/graph.js +116 -80
  64. package/node_modules/@playdrop/types/dist/index.js +47 -20
  65. package/node_modules/@playdrop/types/dist/owned-assets.js +55 -33
  66. package/node_modules/@playdrop/types/dist/player-meta.js +151 -100
  67. package/node_modules/@playdrop/types/dist/realtime.js +27 -7
  68. package/node_modules/@playdrop/types/dist/version.js +182 -124
  69. package/node_modules/@playdrop/types/package.json +1 -1
  70. package/package.json +1 -1
@@ -1,63 +1,85 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import * as THREE from 'three';
4
- import { createBoxelScene } from '../src/index.js';
5
- test('createBoxelScene exposes node metadata and animations for editor tooling', () => {
6
- const entity = {
7
- id: 'scene-smoke',
8
- geometry: {
9
- id: 'geom',
10
- root: {
11
- id: 'Root',
12
- position: [0, 0, 0],
13
- children: [
14
- {
15
- id: 'Child',
16
- position: [1, 0, 0],
17
- mesh: 'box',
18
- children: [],
19
- },
20
- ],
21
- },
22
- },
23
- primitives: [
24
- {
25
- id: 'box',
26
- kind: 'plain_box',
27
- size: [1, 1, 1],
28
- material: 'mat',
29
- },
30
- ],
31
- materials: [{ id: 'mat', baseColor: [200, 120, 60] }],
32
- textures: [],
33
- patterns: [],
34
- animations: [
35
- {
36
- id: 'wiggle',
37
- duration: 2,
38
- channels: [
39
- {
40
- node: 'Child',
41
- property: 'position',
42
- keyframes: [
43
- { time: 0, value: [1, 0, 0] },
44
- { time: 1, value: [1, 0.5, 0] },
45
- { time: 2, value: [1, 0, 0] },
46
- ],
47
- },
48
- ],
49
- },
50
- ],
51
- };
52
- const result = createBoxelScene({ THREE, entity });
53
- assert.ok(result.root.children.length >= 1, 'scene root should contain children');
54
- const childMeta = result.nodes.get('Child');
55
- assert.ok(childMeta, 'child node metadata should exist');
56
- assert.strictEqual(childMeta.object.userData?.nodeId, 'Child');
57
- assert.strictEqual(childMeta.object.parent?.userData?.nodeId, 'Root');
58
- assert.ok(result.animations.length >= 1, 'expected animation metadata');
59
- const clip = result.animations[0]?.clip;
60
- assert.ok(clip, 'animation clip missing');
61
- assert.ok(clip.duration >= 2, 'clip duration should cover keyframes');
62
- result.dispose();
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __copyProps = (to, from, except, desc) => {
8
+ if (from && typeof from === "object" || typeof from === "function") {
9
+ for (let key of __getOwnPropNames(from))
10
+ if (!__hasOwnProp.call(to, key) && key !== except)
11
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
12
+ }
13
+ return to;
14
+ };
15
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
16
+ // If the importer is in node compatibility mode or this is not an ESM
17
+ // file that has been converted to a CommonJS file using a Babel-
18
+ // compatible transform (i.e. "__esModule" has not been set), then set
19
+ // "default" to the CommonJS "module.exports" for node compatibility.
20
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
21
+ mod
22
+ ));
23
+ var import_node_test = __toESM(require("node:test"));
24
+ var import_strict = __toESM(require("node:assert/strict"));
25
+ var THREE = __toESM(require("three"));
26
+ var import_src = require("../src/index.js");
27
+ (0, import_node_test.default)("createBoxelScene exposes node metadata and animations for editor tooling", () => {
28
+ const entity = {
29
+ id: "scene-smoke",
30
+ geometry: {
31
+ id: "geom",
32
+ root: {
33
+ id: "Root",
34
+ position: [0, 0, 0],
35
+ children: [
36
+ {
37
+ id: "Child",
38
+ position: [1, 0, 0],
39
+ mesh: "box",
40
+ children: []
41
+ }
42
+ ]
43
+ }
44
+ },
45
+ primitives: [
46
+ {
47
+ id: "box",
48
+ kind: "plain_box",
49
+ size: [1, 1, 1],
50
+ material: "mat"
51
+ }
52
+ ],
53
+ materials: [{ id: "mat", baseColor: [200, 120, 60] }],
54
+ textures: [],
55
+ patterns: [],
56
+ animations: [
57
+ {
58
+ id: "wiggle",
59
+ duration: 2,
60
+ channels: [
61
+ {
62
+ node: "Child",
63
+ property: "position",
64
+ keyframes: [
65
+ { time: 0, value: [1, 0, 0] },
66
+ { time: 1, value: [1, 0.5, 0] },
67
+ { time: 2, value: [1, 0, 0] }
68
+ ]
69
+ }
70
+ ]
71
+ }
72
+ ]
73
+ };
74
+ const result = (0, import_src.createBoxelScene)({ THREE, entity });
75
+ import_strict.default.ok(result.root.children.length >= 1, "scene root should contain children");
76
+ const childMeta = result.nodes.get("Child");
77
+ import_strict.default.ok(childMeta, "child node metadata should exist");
78
+ import_strict.default.strictEqual(childMeta.object.userData?.nodeId, "Child");
79
+ import_strict.default.strictEqual(childMeta.object.parent?.userData?.nodeId, "Root");
80
+ import_strict.default.ok(result.animations.length >= 1, "expected animation metadata");
81
+ const clip = result.animations[0]?.clip;
82
+ import_strict.default.ok(clip, "animation clip missing");
83
+ import_strict.default.ok(clip.duration >= 2, "clip duration should cover keyframes");
84
+ result.dispose();
63
85
  });
@@ -1,51 +1,73 @@
1
1
  "use strict";
2
- import test from 'node:test';
3
- import assert from 'node:assert/strict';
4
- import * as THREE from 'three';
5
- import { readFile } from 'node:fs/promises';
6
- import path from 'node:path';
7
- import { fileURLToPath } from 'node:url';
8
- import { parseBoxel } from '@playdrop/boxel-core';
9
- import { buildEntitySkinnedMesh } from '../src/skinned-mesh.js';
10
- const HERE = path.dirname(fileURLToPath(import.meta.url));
11
- const fixture = (...segments) => path.resolve(HERE, './fixtures', ...segments);
12
- test('buildEntitySkinnedMesh exposes atlas and connect stats', async () => {
13
- const entityRaw = await readFile(fixture('entity-connect.json'), 'utf-8');
14
- const entity = parseBoxel(JSON.parse(entityRaw));
15
- const result = buildEntitySkinnedMesh({ THREE, entity });
16
- try {
17
- const { mesh, stats } = result;
18
- assert.ok(mesh instanceof THREE.SkinnedMesh, 'skinned mesh returned');
19
- assert.ok(!Array.isArray(mesh.material), 'single material used');
20
- const material = mesh.material;
21
- assert.strictEqual(material.skinning, true);
22
- assert.ok(stats.atlas === null || typeof stats.atlas === 'object', 'atlas info present (or null)');
23
- const breakdown = stats.connectBreakdown;
24
- assert.deepEqual(Object.keys(breakdown).sort(), ['Chest'], 'connect breakdown captured child node');
25
- assert.ok(breakdown.Chest.childVertices > 0, 'child vertices blended');
26
- assert.ok(breakdown.Chest.parentVertices > 0, 'parent vertices blended');
27
- const geometry = mesh.geometry;
28
- const connectStrength = geometry.getAttribute('connectStrength');
29
- assert.ok(connectStrength, 'connect strength attribute exists');
30
- let sawHalf = false;
31
- let sawFull = false;
32
- for (let i = 0; i < connectStrength.count; i += 1) {
33
- const value = connectStrength.getX(i);
34
- if (Math.abs(value - 0.5) < 1e-3)
35
- sawHalf = true;
36
- if (Math.abs(value - 1) < 1e-3)
37
- sawFull = true;
38
- }
39
- assert.ok(sawHalf, 'detected vertices blending 50/50');
40
- assert.ok(sawFull || !breakdown.Chest.childVertices || sawHalf, 'detected vertices fully or partially reassigned when expected');
41
- const skinWeights = geometry.getAttribute('skinWeight');
42
- assert.ok(skinWeights, 'skin weights present');
43
- for (let i = 0; i < skinWeights.count; i += 1) {
44
- const sum = skinWeights.getX(i) + skinWeights.getY(i) + skinWeights.getZ(i) + skinWeights.getW(i);
45
- assert.ok(Math.abs(sum - 1) < 1e-3, 'weights normalised per vertex');
46
- }
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+ var import_node_test = __toESM(require("node:test"));
25
+ var import_strict = __toESM(require("node:assert/strict"));
26
+ var THREE = __toESM(require("three"));
27
+ var import_promises = require("node:fs/promises");
28
+ var import_node_path = __toESM(require("node:path"));
29
+ var import_node_url = require("node:url");
30
+ var import_boxel_core = require("@playdrop/boxel-core");
31
+ var import_skinned_mesh = require("../src/skinned-mesh.js");
32
+ const import_meta = {};
33
+ const HERE = import_node_path.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
34
+ const fixture = (...segments) => import_node_path.default.resolve(HERE, "./fixtures", ...segments);
35
+ (0, import_node_test.default)("buildEntitySkinnedMesh exposes atlas and connect stats", async () => {
36
+ const entityRaw = await (0, import_promises.readFile)(fixture("entity-connect.json"), "utf-8");
37
+ const entity = (0, import_boxel_core.parseBoxel)(JSON.parse(entityRaw));
38
+ const result = (0, import_skinned_mesh.buildEntitySkinnedMesh)({ THREE, entity });
39
+ try {
40
+ const { mesh, stats } = result;
41
+ import_strict.default.ok(mesh instanceof THREE.SkinnedMesh, "skinned mesh returned");
42
+ import_strict.default.ok(!Array.isArray(mesh.material), "single material used");
43
+ const material = mesh.material;
44
+ import_strict.default.strictEqual(material.skinning, true);
45
+ import_strict.default.ok(stats.atlas === null || typeof stats.atlas === "object", "atlas info present (or null)");
46
+ const breakdown = stats.connectBreakdown;
47
+ import_strict.default.deepEqual(Object.keys(breakdown).sort(), ["Chest"], "connect breakdown captured child node");
48
+ import_strict.default.ok(breakdown.Chest.childVertices > 0, "child vertices blended");
49
+ import_strict.default.ok(breakdown.Chest.parentVertices > 0, "parent vertices blended");
50
+ const geometry = mesh.geometry;
51
+ const connectStrength = geometry.getAttribute("connectStrength");
52
+ import_strict.default.ok(connectStrength, "connect strength attribute exists");
53
+ let sawHalf = false;
54
+ let sawFull = false;
55
+ for (let i = 0; i < connectStrength.count; i += 1) {
56
+ const value = connectStrength.getX(i);
57
+ if (Math.abs(value - 0.5) < 1e-3)
58
+ sawHalf = true;
59
+ if (Math.abs(value - 1) < 1e-3)
60
+ sawFull = true;
47
61
  }
48
- finally {
49
- result.dispose();
62
+ import_strict.default.ok(sawHalf, "detected vertices blending 50/50");
63
+ import_strict.default.ok(sawFull || !breakdown.Chest.childVertices || sawHalf, "detected vertices fully or partially reassigned when expected");
64
+ const skinWeights = geometry.getAttribute("skinWeight");
65
+ import_strict.default.ok(skinWeights, "skin weights present");
66
+ for (let i = 0; i < skinWeights.count; i += 1) {
67
+ const sum = skinWeights.getX(i) + skinWeights.getY(i) + skinWeights.getZ(i) + skinWeights.getW(i);
68
+ import_strict.default.ok(Math.abs(sum - 1) < 1e-3, "weights normalised per vertex");
50
69
  }
70
+ } finally {
71
+ result.dispose();
72
+ }
51
73
  });
@@ -1,116 +1,136 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import * as THREE from 'three';
4
- import { createBoxelScene, createBoxelSceneGraph } from '../src/index.js';
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __copyProps = (to, from, except, desc) => {
8
+ if (from && typeof from === "object" || typeof from === "function") {
9
+ for (let key of __getOwnPropNames(from))
10
+ if (!__hasOwnProp.call(to, key) && key !== except)
11
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
12
+ }
13
+ return to;
14
+ };
15
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
16
+ // If the importer is in node compatibility mode or this is not an ESM
17
+ // file that has been converted to a CommonJS file using a Babel-
18
+ // compatible transform (i.e. "__esModule" has not been set), then set
19
+ // "default" to the CommonJS "module.exports" for node compatibility.
20
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
21
+ mod
22
+ ));
23
+ var import_node_test = __toESM(require("node:test"));
24
+ var import_strict = __toESM(require("node:assert/strict"));
25
+ var THREE = __toESM(require("three"));
26
+ var import_src = require("../src/index.js");
5
27
  const OVERLAY_THICKNESS = 0.25;
6
28
  const overlayEntity = {
7
- id: 'overlay-sample',
8
- geometry: {
9
- id: 'geom',
10
- root: {
11
- id: 'Root',
12
- position: [0, 0, 0],
13
- children: [
14
- {
15
- id: 'BoxNode',
16
- position: [0, 0, 0],
17
- mesh: 'overlay_box',
18
- children: [],
19
- },
20
- ],
21
- },
22
- },
23
- primitives: [
24
- {
25
- id: 'overlay_box',
26
- kind: 'textured_box',
27
- size: [2, 2, 2],
28
- all: 'base_texture',
29
- northOverlay: 'overlay_texture',
30
- },
31
- ],
32
- textures: [
33
- {
34
- id: 'base_texture',
35
- pattern: 'base_pattern',
36
- materials: ['base_material'],
37
- },
38
- {
39
- id: 'overlay_texture',
40
- pattern: 'overlay_pattern',
41
- materials: ['overlay_material'],
42
- },
43
- ],
44
- patterns: [
29
+ id: "overlay-sample",
30
+ geometry: {
31
+ id: "geom",
32
+ root: {
33
+ id: "Root",
34
+ position: [0, 0, 0],
35
+ children: [
45
36
  {
46
- id: 'base_pattern',
47
- size: [2, 2],
48
- data: [0, 0, 0, 0],
49
- },
50
- {
51
- id: 'overlay_pattern',
52
- size: [2, 2],
53
- data: [0, 0, 0, 0],
54
- },
55
- ],
56
- materials: [
57
- { id: 'base_material', baseColor: [255, 0, 0] },
58
- { id: 'overlay_material', baseColor: [0, 255, 0] },
59
- ],
60
- animations: [],
61
- };
62
- test('textured box overlay attaches inflated mesh with transparent materials', () => {
63
- const scene = createBoxelScene({ THREE, entity: overlayEntity });
64
- let baseMesh = null;
65
- let overlayMesh = null;
66
- scene.root.traverse(object => {
67
- if (object instanceof THREE.Mesh && object.userData?.primitiveId === 'overlay_box' && !object.userData.overlay) {
68
- baseMesh = object;
69
- const overlayChild = object.children.find(child => child instanceof THREE.Mesh && child.userData?.overlay);
70
- if (overlayChild instanceof THREE.Mesh) {
71
- overlayMesh = overlayChild;
72
- }
37
+ id: "BoxNode",
38
+ position: [0, 0, 0],
39
+ mesh: "overlay_box",
40
+ children: []
73
41
  }
74
- });
75
- assert.ok(baseMesh, 'base textured mesh missing');
76
- assert.ok(overlayMesh, 'overlay mesh missing');
77
- const baseMeshRef = baseMesh;
78
- const overlayMeshRef = overlayMesh;
79
- const baseGeometry = baseMeshRef.geometry;
80
- const overlayGeometry = overlayMeshRef.geometry;
81
- assert.ok(baseGeometry && overlayGeometry, 'expected box geometries on both meshes');
82
- const overlayWidth = overlayGeometry.parameters?.width ?? 0;
83
- const baseWidth = baseGeometry.parameters?.width ?? 0;
84
- assert.equal(overlayWidth, baseWidth + OVERLAY_THICKNESS * 2, 'overlay geometry should be inflated along X axis');
85
- const overlayMaterials = (Array.isArray(overlayMeshRef.material)
86
- ? overlayMeshRef.material
87
- : [overlayMeshRef.material]);
88
- const visibleMaterials = overlayMaterials.filter(material => material.visible !== false && material.opacity !== 0);
89
- const hiddenMaterials = overlayMaterials.filter(material => material.visible === false || material.opacity === 0);
90
- assert.ok(visibleMaterials.length >= 1, 'expected at least one visible overlay material');
91
- assert.ok(hiddenMaterials.length >= 1, 'expected non-overlay faces to be hidden');
92
- visibleMaterials.forEach((material) => {
93
- assert.equal(material.transparent, true, 'overlay materials must be rendered with transparency');
94
- assert.equal(material.depthWrite, false, 'overlay materials should disable depth writing');
95
- });
96
- scene.dispose();
42
+ ]
43
+ }
44
+ },
45
+ primitives: [
46
+ {
47
+ id: "overlay_box",
48
+ kind: "textured_box",
49
+ size: [2, 2, 2],
50
+ all: "base_texture",
51
+ northOverlay: "overlay_texture"
52
+ }
53
+ ],
54
+ textures: [
55
+ {
56
+ id: "base_texture",
57
+ pattern: "base_pattern",
58
+ materials: ["base_material"]
59
+ },
60
+ {
61
+ id: "overlay_texture",
62
+ pattern: "overlay_pattern",
63
+ materials: ["overlay_material"]
64
+ }
65
+ ],
66
+ patterns: [
67
+ {
68
+ id: "base_pattern",
69
+ size: [2, 2],
70
+ data: [0, 0, 0, 0]
71
+ },
72
+ {
73
+ id: "overlay_pattern",
74
+ size: [2, 2],
75
+ data: [0, 0, 0, 0]
76
+ }
77
+ ],
78
+ materials: [
79
+ { id: "base_material", baseColor: [255, 0, 0] },
80
+ { id: "overlay_material", baseColor: [0, 255, 0] }
81
+ ],
82
+ animations: []
83
+ };
84
+ (0, import_node_test.default)("textured box overlay attaches inflated mesh with transparent materials", () => {
85
+ const scene = (0, import_src.createBoxelScene)({ THREE, entity: overlayEntity });
86
+ let baseMesh = null;
87
+ let overlayMesh = null;
88
+ scene.root.traverse((object) => {
89
+ if (object instanceof THREE.Mesh && object.userData?.primitiveId === "overlay_box" && !object.userData.overlay) {
90
+ baseMesh = object;
91
+ const overlayChild = object.children.find((child) => child instanceof THREE.Mesh && child.userData?.overlay);
92
+ if (overlayChild instanceof THREE.Mesh) {
93
+ overlayMesh = overlayChild;
94
+ }
95
+ }
96
+ });
97
+ import_strict.default.ok(baseMesh, "base textured mesh missing");
98
+ import_strict.default.ok(overlayMesh, "overlay mesh missing");
99
+ const baseMeshRef = baseMesh;
100
+ const overlayMeshRef = overlayMesh;
101
+ const baseGeometry = baseMeshRef.geometry;
102
+ const overlayGeometry = overlayMeshRef.geometry;
103
+ import_strict.default.ok(baseGeometry && overlayGeometry, "expected box geometries on both meshes");
104
+ const overlayWidth = overlayGeometry.parameters?.width ?? 0;
105
+ const baseWidth = baseGeometry.parameters?.width ?? 0;
106
+ import_strict.default.equal(overlayWidth, baseWidth + OVERLAY_THICKNESS * 2, "overlay geometry should be inflated along X axis");
107
+ const overlayMaterials = Array.isArray(overlayMeshRef.material) ? overlayMeshRef.material : [overlayMeshRef.material];
108
+ const visibleMaterials = overlayMaterials.filter((material) => material.visible !== false && material.opacity !== 0);
109
+ const hiddenMaterials = overlayMaterials.filter((material) => material.visible === false || material.opacity === 0);
110
+ import_strict.default.ok(visibleMaterials.length >= 1, "expected at least one visible overlay material");
111
+ import_strict.default.ok(hiddenMaterials.length >= 1, "expected non-overlay faces to be hidden");
112
+ visibleMaterials.forEach((material) => {
113
+ import_strict.default.equal(material.transparent, true, "overlay materials must be rendered with transparency");
114
+ import_strict.default.equal(material.depthWrite, false, "overlay materials should disable depth writing");
115
+ });
116
+ scene.dispose();
97
117
  });
98
- test('merged scene graph export includes overlay atlas data', () => {
99
- const graph = createBoxelSceneGraph({ THREE, model: overlayEntity, mode: 'merged' });
100
- let meshCount = 0;
101
- let transparentMaterialDetected = false;
102
- graph.root.traverse(object => {
103
- if (object instanceof THREE.Mesh) {
104
- meshCount += 1;
105
- const materials = Array.isArray(object.material) ? object.material : [object.material];
106
- materials.forEach(material => {
107
- if (material.transparent) {
108
- transparentMaterialDetected = true;
109
- }
110
- });
118
+ (0, import_node_test.default)("merged scene graph export includes overlay atlas data", () => {
119
+ const graph = (0, import_src.createBoxelSceneGraph)({ THREE, model: overlayEntity, mode: "merged" });
120
+ let meshCount = 0;
121
+ let transparentMaterialDetected = false;
122
+ graph.root.traverse((object) => {
123
+ if (object instanceof THREE.Mesh) {
124
+ meshCount += 1;
125
+ const materials = Array.isArray(object.material) ? object.material : [object.material];
126
+ materials.forEach((material) => {
127
+ if (material.transparent) {
128
+ transparentMaterialDetected = true;
111
129
  }
112
- });
113
- assert.ok(meshCount >= 1, 'merged graph should contain at least one mesh');
114
- assert.equal(transparentMaterialDetected, true, 'merged atlas material should be marked transparent when overlays are present');
115
- graph.dispose();
130
+ });
131
+ }
132
+ });
133
+ import_strict.default.ok(meshCount >= 1, "merged graph should contain at least one mesh");
134
+ import_strict.default.equal(transparentMaterialDetected, true, "merged atlas material should be marked transparent when overlays are present");
135
+ graph.dispose();
116
136
  });
@@ -1,20 +1,42 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { buildVoxelMesh } from '../src/voxels/mesher.js';
4
- const makeMesh = () => buildVoxelMesh({
5
- voxels: [1, 2],
6
- dimensions: [2, 1, 1],
7
- size: [2, 1, 1],
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __copyProps = (to, from, except, desc) => {
8
+ if (from && typeof from === "object" || typeof from === "function") {
9
+ for (let key of __getOwnPropNames(from))
10
+ if (!__hasOwnProp.call(to, key) && key !== except)
11
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
12
+ }
13
+ return to;
14
+ };
15
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
16
+ // If the importer is in node compatibility mode or this is not an ESM
17
+ // file that has been converted to a CommonJS file using a Babel-
18
+ // compatible transform (i.e. "__esModule" has not been set), then set
19
+ // "default" to the CommonJS "module.exports" for node compatibility.
20
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
21
+ mod
22
+ ));
23
+ var import_node_test = __toESM(require("node:test"));
24
+ var import_strict = __toESM(require("node:assert/strict"));
25
+ var import_mesher = require("../src/voxels/mesher.js");
26
+ const makeMesh = () => (0, import_mesher.buildVoxelMesh)({
27
+ voxels: [1, 2],
28
+ dimensions: [2, 1, 1],
29
+ size: [2, 1, 1]
8
30
  });
9
- test('buildVoxelMesh assigns material groups without mixing palette indices', () => {
10
- const result = makeMesh();
11
- assert.ok(result.groups.length > 1, 'expected multiple material groups');
12
- assert.equal(new Set(result.groups.map(group => group.material)).size, 2, 'should contain both palette indices');
13
- let covered = 0;
14
- result.groups.forEach(group => {
15
- assert.equal(group.start % 6, 0, 'group should align with triangle pairs');
16
- assert.equal(group.count % 6, 0, 'group count should be a multiple of a quad');
17
- covered += group.count;
18
- });
19
- assert.equal(covered, result.indices.length, 'groups should cover entire index buffer');
31
+ (0, import_node_test.default)("buildVoxelMesh assigns material groups without mixing palette indices", () => {
32
+ const result = makeMesh();
33
+ import_strict.default.ok(result.groups.length > 1, "expected multiple material groups");
34
+ import_strict.default.equal(new Set(result.groups.map((group) => group.material)).size, 2, "should contain both palette indices");
35
+ let covered = 0;
36
+ result.groups.forEach((group) => {
37
+ import_strict.default.equal(group.start % 6, 0, "group should align with triangle pairs");
38
+ import_strict.default.equal(group.count % 6, 0, "group count should be a multiple of a quad");
39
+ covered += group.count;
40
+ });
41
+ import_strict.default.equal(covered, result.indices.length, "groups should cover entire index buffer");
20
42
  });
@@ -2,7 +2,7 @@
2
2
  "name": "@playdrop/boxel-three",
3
3
  "version": "0.7.2",
4
4
  "description": "Three.js utilities for rendering and exporting Playdrop boxels",
5
- "type": "module",
5
+ "type": "commonjs",
6
6
  "main": "dist/src/index.js",
7
7
  "types": "dist/src/index.d.ts",
8
8
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.7.15",
2
+ "version": "0.7.17",
3
3
  "build": 1,
4
4
  "clients": {
5
5
  "all": {