@ludic-labs/assembly 0.0.0-stage → 0.4.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/LICENSE +2 -0
  3. package/README.md +50 -2
  4. package/dist/bake.d.ts +80 -0
  5. package/dist/bake.js +214 -0
  6. package/dist/browser.d.ts +89 -0
  7. package/dist/browser.js +534 -0
  8. package/dist/compat.d.ts +17 -0
  9. package/dist/compat.js +153 -0
  10. package/dist/compiler.d.ts +18 -0
  11. package/dist/compiler.js +1264 -0
  12. package/dist/diagnostics.d.ts +5 -0
  13. package/dist/diagnostics.js +8 -0
  14. package/dist/export.d.ts +54 -0
  15. package/dist/export.js +272 -0
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.js +3 -0
  18. package/dist/legacy.d.ts +36 -0
  19. package/dist/legacy.js +180 -0
  20. package/dist/math.d.ts +16 -0
  21. package/dist/math.js +62 -0
  22. package/dist/mesh.d.ts +11 -0
  23. package/dist/mesh.js +153 -0
  24. package/dist/motion.d.ts +63 -0
  25. package/dist/motion.js +1476 -0
  26. package/dist/pixel.d.ts +268 -0
  27. package/dist/pixel.js +942 -0
  28. package/dist/required.d.ts +2 -0
  29. package/dist/required.js +6 -0
  30. package/dist/shapes.d.ts +71 -0
  31. package/dist/shapes.js +396 -0
  32. package/dist/sprite-brief.d.ts +5 -0
  33. package/dist/sprite-brief.js +47 -0
  34. package/dist/sprite-compiler.d.ts +62 -0
  35. package/dist/sprite-compiler.js +1745 -0
  36. package/dist/sprite-decompile.d.ts +68 -0
  37. package/dist/sprite-decompile.js +786 -0
  38. package/dist/sprite-format.d.ts +4 -0
  39. package/dist/sprite-format.js +155 -0
  40. package/dist/sprite-guide.d.ts +40 -0
  41. package/dist/sprite-guide.js +330 -0
  42. package/dist/sprite-scene.d.ts +277 -0
  43. package/dist/sprite-scene.js +664 -0
  44. package/dist/sprite-types.d.ts +110 -0
  45. package/dist/sprite-types.js +1 -0
  46. package/dist/sprite.d.ts +8 -0
  47. package/dist/sprite.js +8 -0
  48. package/dist/svg/schema.d.ts +71 -0
  49. package/dist/svg/schema.js +217 -0
  50. package/dist/svg/types.d.ts +148 -0
  51. package/dist/svg/types.js +1 -0
  52. package/dist/svg.d.ts +26 -0
  53. package/dist/svg.js +539 -0
  54. package/dist/text.d.ts +12 -0
  55. package/dist/text.js +75 -0
  56. package/dist/types.d.ts +478 -0
  57. package/dist/types.js +1 -0
  58. package/docs/svg/README.md +150 -0
  59. package/docs/svg/specification.md +108 -0
  60. package/examples/svg/arcane-shield.json +261 -0
  61. package/examples/svg/aurora-ribbon.json +158 -0
  62. package/examples/svg/bouncing-ember.json +76 -0
  63. package/examples/svg/ember-fountain.json +224 -0
  64. package/examples/svg/lantern-keeper.json +1159 -0
  65. package/examples/svg/night-workshop.json +1120 -0
  66. package/examples/svg/waygate-platform.json +64 -0
  67. package/examples/svg/waygate-spark.json +92 -0
  68. package/examples/svg/waygate-wisp.json +105 -0
  69. package/examples/svg/waygate.json +485 -0
  70. package/package.json +132 -4
  71. package/schemas/asset-assembly-0.1.schema.json +354 -0
  72. package/schemas/asset-assembly-0.2.schema.json +429 -0
  73. package/schemas/asset-assembly-0.3.schema.json +572 -0
  74. package/schemas/motion-set-0.1.schema.json +178 -0
  75. package/schemas/pixel-sprite-0.1.schema.json +892 -0
  76. package/schemas/pixel-sprite-scene-0.1.schema.json +149 -0
  77. package/schemas/svg-asset-0.1.schema.json +1157 -0
  78. package/tools/svg-asset.mjs +106 -0
package/dist/compat.js ADDED
@@ -0,0 +1,153 @@
1
+ import { requireValue } from "./required.js";
2
+ import { sub, cross, dot, normalize } from "./math.js";
3
+ export { fromLegacyRig } from "./legacy.js";
4
+ export const linear = (v) => ((v /= 255) <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
5
+ export class MeshBuilder {
6
+ mesh = { positions: [], normals: [], colors: [], indices: [] };
7
+ joint = 0;
8
+ constructor(jointPivots) {
9
+ if (jointPivots) {
10
+ this.mesh.joints = [];
11
+ this.mesh.rigPivots = jointPivots;
12
+ }
13
+ }
14
+ face(points, color, center) {
15
+ let normal = normalize(cross(sub(requireValue(points[1]), requireValue(points[0])), sub(requireValue(points[2]), requireValue(points[0]))));
16
+ if (dot(normal, sub(requireValue(points[0]), center)) < 0) {
17
+ points = [...points].reverse();
18
+ normal = normalize(cross(sub(requireValue(points[1]), requireValue(points[0])), sub(requireValue(points[2]), requireValue(points[0]))));
19
+ }
20
+ const first = this.mesh.positions.length / 3;
21
+ for (const p of points) {
22
+ this.mesh.positions.push(...p);
23
+ this.mesh.joints?.push(this.joint);
24
+ this.mesh.normals.push(...normal);
25
+ this.mesh.colors.push(linear((color >> 16) & 255), linear((color >> 8) & 255), linear(color & 255));
26
+ }
27
+ for (let n = 1; n < points.length - 1; n++)
28
+ this.mesh.indices.push(first, first + n, first + n + 1);
29
+ }
30
+ box(x, y, z, w, h, d, color, bevel = 0.018) {
31
+ const r = Math.min(bevel, w / 4, h / 4, d / 4), c = [x, y + h / 2, z];
32
+ const outline = [
33
+ [-w / 2 + r, -d / 2],
34
+ [w / 2 - r, -d / 2],
35
+ [w / 2, -d / 2 + r],
36
+ [w / 2, d / 2 - r],
37
+ [w / 2 - r, d / 2],
38
+ [-w / 2 + r, d / 2],
39
+ [-w / 2, d / 2 - r],
40
+ [-w / 2, -d / 2 + r],
41
+ ];
42
+ const ring = (at, inset) => outline.map(([a, b]) => [
43
+ x + requireValue(a) * (1 - (inset * 2) / w),
44
+ y + at,
45
+ z + requireValue(b) * (1 - (inset * 2) / d),
46
+ ]);
47
+ const rings = [ring(0, r), ring(r, 0), ring(h - r, 0), ring(h, r)];
48
+ this.face(requireValue(rings[0]), color, c);
49
+ this.face(requireValue(rings[3]), color, c);
50
+ for (let n = 0; n < 3; n++)
51
+ for (let j = 0; j < 8; j++)
52
+ this.face([
53
+ requireValue(requireValue(rings[n])[j]),
54
+ requireValue(requireValue(rings[n])[(j + 1) % 8]),
55
+ requireValue(requireValue(rings[n + 1])[(j + 1) % 8]),
56
+ requireValue(requireValue(rings[n + 1])[j]),
57
+ ], color, c);
58
+ return this;
59
+ }
60
+ beam(a, b, width, color) {
61
+ const up = normalize(sub(b, a)), right = normalize(cross(Math.abs(up[2]) < 0.9 ? [0, 0, 1] : [1, 0, 0], up)), forward = cross(right, up);
62
+ const part = new MeshBuilder().box(0, 0, 0, width, Math.hypot(...sub(b, a)), width, color, width / 5).mesh;
63
+ const first = this.mesh.positions.length / 3;
64
+ for (let n = 0; n < part.positions.length; n += 3) {
65
+ for (const [input, output, translate] of [
66
+ [part.positions, this.mesh.positions, true],
67
+ [part.normals, this.mesh.normals, false],
68
+ ])
69
+ for (let c = 0; c < 3; c++)
70
+ output.push((translate ? requireValue(a[c]) : 0) +
71
+ requireValue(right[c]) * requireValue(input[n]) +
72
+ requireValue(up[c]) * requireValue(input[n + 1]) +
73
+ requireValue(forward[c]) * requireValue(input[n + 2]));
74
+ }
75
+ this.mesh.colors.push(...part.colors);
76
+ this.mesh.joints?.push(...Array(part.positions.length / 3).fill(this.joint));
77
+ this.mesh.indices.push(...part.indices.map((i) => i + first));
78
+ return this;
79
+ }
80
+ /** A round shaft in any direction; the asset supplies its physical endpoints. */
81
+ tube(a, b, radius, color) {
82
+ const up = normalize(sub(b, a)), right = normalize(cross(Math.abs(up[2]) < 0.9 ? [0, 0, 1] : [1, 0, 0], up)), forward = cross(right, up), part = new MeshBuilder().cylinder(0, 0, 0, radius, Math.hypot(...sub(b, a)), color).mesh, first = this.mesh.positions.length / 3;
83
+ for (let n = 0; n < part.positions.length; n += 3)
84
+ for (const [input, output, translate] of [
85
+ [part.positions, this.mesh.positions, true],
86
+ [part.normals, this.mesh.normals, false],
87
+ ])
88
+ for (let c = 0; c < 3; c++)
89
+ output.push((translate ? requireValue(a[c]) : 0) +
90
+ requireValue(right[c]) * requireValue(input[n]) +
91
+ requireValue(up[c]) * requireValue(input[n + 1]) +
92
+ requireValue(forward[c]) * requireValue(input[n + 2]));
93
+ this.mesh.colors.push(...part.colors);
94
+ this.mesh.joints?.push(...Array(part.positions.length / 3).fill(this.joint));
95
+ this.mesh.indices.push(...part.indices.map((i) => i + first));
96
+ return this;
97
+ }
98
+ funnel(x, y, z, bottomRadius, topRadius, height, color) {
99
+ const bottom = [], top = [], center = [x, y + height / 2, z];
100
+ for (let n = 0; n < 16; n++) {
101
+ const a = (n * Math.PI) / 8;
102
+ bottom.push([x + Math.cos(a) * bottomRadius, y, z + Math.sin(a) * bottomRadius]);
103
+ top.push([x + Math.cos(a) * topRadius, y + height, z + Math.sin(a) * topRadius]);
104
+ }
105
+ this.face(bottom, color, center);
106
+ this.face(top, color, center);
107
+ for (let n = 0; n < 16; n++)
108
+ this.face([
109
+ requireValue(bottom[n]),
110
+ requireValue(bottom[(n + 1) % 16]),
111
+ requireValue(top[(n + 1) % 16]),
112
+ requireValue(top[n]),
113
+ ], color, center);
114
+ return this;
115
+ }
116
+ /** Coil in the YZ plane. Small cross-section segments keep distant details economical. */
117
+ coil(x, y, z, radius, thickness, color) {
118
+ const point = (a, b) => [
119
+ x + Math.sin(b) * thickness,
120
+ y + Math.cos(a) * (radius + Math.cos(b) * thickness),
121
+ z + Math.sin(a) * (radius + Math.cos(b) * thickness),
122
+ ];
123
+ for (let n = 0; n < 16; n++)
124
+ for (let k = 0; k < 6; k++) {
125
+ const a = (n * Math.PI) / 8, b = (k * Math.PI) / 3, nextA = a + Math.PI / 8, nextB = b + Math.PI / 3, mid = (a + nextA) / 2;
126
+ this.face([point(a, b), point(nextA, b), point(nextA, nextB), point(a, nextB)], color, [
127
+ x,
128
+ y + Math.cos(mid) * radius,
129
+ z + Math.sin(mid) * radius,
130
+ ]);
131
+ }
132
+ return this;
133
+ }
134
+ cylinder(x, y, z, r, h, color) {
135
+ const c = [x, y + h / 2, z];
136
+ const bottom = [], top = [];
137
+ for (let n = 0; n < 16; n++) {
138
+ const a = (n * Math.PI) / 8;
139
+ bottom.push([x + Math.cos(a) * r, y, z + Math.sin(a) * r]);
140
+ top.push([x + Math.cos(a) * r, y + h, z + Math.sin(a) * r]);
141
+ }
142
+ this.face(bottom, color, c);
143
+ this.face(top, color, c);
144
+ for (let n = 0; n < 16; n++)
145
+ this.face([
146
+ requireValue(bottom[n]),
147
+ requireValue(bottom[(n + 1) % 16]),
148
+ requireValue(top[(n + 1) % 16]),
149
+ requireValue(top[n]),
150
+ ], color, c);
151
+ return this;
152
+ }
153
+ }
@@ -0,0 +1,18 @@
1
+ import type { Axis, CompileOptions, CompiledAsset, Diagnostic, Vec3 } from "./types.js";
2
+ import { AssetCompileError } from "./diagnostics.js";
3
+ export { AssetCompileError };
4
+ export declare const SCHEMA: "asset-assembly/0.1";
5
+ /** Characters: joints, mirrored sides, slots, identities, states and limbs. */
6
+ export declare const SCHEMA_V2: "asset-assembly/0.2";
7
+ /** Schema 0.2 plus rotations, arrays, sided round shapes, spheres, cones, wedges, lathes and extrusions. */
8
+ export declare const SCHEMA_V3: "asset-assembly/0.3";
9
+ export declare const AXES: Record<Axis, Vec3>;
10
+ export declare const ANCHORS: readonly ["center", "top-center", "bottom-center", "left-center", "right-center", "front-center", "back-center"];
11
+ /** Largest number of instances one array may create. */
12
+ export declare const MAX_ARRAY_COUNT = 256;
13
+ export declare function compileAsset(input: unknown, options?: CompileOptions): CompiledAsset;
14
+ /**
15
+ * Returns [] when the description compiles. For schema 0.2 without an explicit identity, the base
16
+ * description and every declared identity are compiled; diagnostics carry the identity they came from.
17
+ */
18
+ export declare function validateAsset(input: unknown, options?: CompileOptions): Diagnostic[];