@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.
- package/CHANGELOG.md +78 -0
- package/LICENSE +2 -0
- package/README.md +50 -2
- package/dist/bake.d.ts +80 -0
- package/dist/bake.js +214 -0
- package/dist/browser.d.ts +89 -0
- package/dist/browser.js +534 -0
- package/dist/compat.d.ts +17 -0
- package/dist/compat.js +153 -0
- package/dist/compiler.d.ts +18 -0
- package/dist/compiler.js +1264 -0
- package/dist/diagnostics.d.ts +5 -0
- package/dist/diagnostics.js +8 -0
- package/dist/export.d.ts +54 -0
- package/dist/export.js +272 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/legacy.d.ts +36 -0
- package/dist/legacy.js +180 -0
- package/dist/math.d.ts +16 -0
- package/dist/math.js +62 -0
- package/dist/mesh.d.ts +11 -0
- package/dist/mesh.js +153 -0
- package/dist/motion.d.ts +63 -0
- package/dist/motion.js +1476 -0
- package/dist/pixel.d.ts +268 -0
- package/dist/pixel.js +942 -0
- package/dist/required.d.ts +2 -0
- package/dist/required.js +6 -0
- package/dist/shapes.d.ts +71 -0
- package/dist/shapes.js +396 -0
- package/dist/sprite-brief.d.ts +5 -0
- package/dist/sprite-brief.js +47 -0
- package/dist/sprite-compiler.d.ts +62 -0
- package/dist/sprite-compiler.js +1745 -0
- package/dist/sprite-decompile.d.ts +68 -0
- package/dist/sprite-decompile.js +786 -0
- package/dist/sprite-format.d.ts +4 -0
- package/dist/sprite-format.js +155 -0
- package/dist/sprite-guide.d.ts +40 -0
- package/dist/sprite-guide.js +330 -0
- package/dist/sprite-scene.d.ts +277 -0
- package/dist/sprite-scene.js +664 -0
- package/dist/sprite-types.d.ts +110 -0
- package/dist/sprite-types.js +1 -0
- package/dist/sprite.d.ts +8 -0
- package/dist/sprite.js +8 -0
- package/dist/svg/schema.d.ts +71 -0
- package/dist/svg/schema.js +217 -0
- package/dist/svg/types.d.ts +148 -0
- package/dist/svg/types.js +1 -0
- package/dist/svg.d.ts +26 -0
- package/dist/svg.js +539 -0
- package/dist/text.d.ts +12 -0
- package/dist/text.js +75 -0
- package/dist/types.d.ts +478 -0
- package/dist/types.js +1 -0
- package/docs/svg/README.md +150 -0
- package/docs/svg/specification.md +108 -0
- package/examples/svg/arcane-shield.json +261 -0
- package/examples/svg/aurora-ribbon.json +158 -0
- package/examples/svg/bouncing-ember.json +76 -0
- package/examples/svg/ember-fountain.json +224 -0
- package/examples/svg/lantern-keeper.json +1159 -0
- package/examples/svg/night-workshop.json +1120 -0
- package/examples/svg/waygate-platform.json +64 -0
- package/examples/svg/waygate-spark.json +92 -0
- package/examples/svg/waygate-wisp.json +105 -0
- package/examples/svg/waygate.json +485 -0
- package/package.json +132 -4
- package/schemas/asset-assembly-0.1.schema.json +354 -0
- package/schemas/asset-assembly-0.2.schema.json +429 -0
- package/schemas/asset-assembly-0.3.schema.json +572 -0
- package/schemas/motion-set-0.1.schema.json +178 -0
- package/schemas/pixel-sprite-0.1.schema.json +892 -0
- package/schemas/pixel-sprite-scene-0.1.schema.json +149 -0
- package/schemas/svg-asset-0.1.schema.json +1157 -0
- package/tools/svg-asset.mjs +106 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
compileSvgAsset,
|
|
6
|
+
renderSvgFrame,
|
|
7
|
+
exportSvgAnimation,
|
|
8
|
+
SvgAssetError,
|
|
9
|
+
SVG_ASSET_LIMITS,
|
|
10
|
+
} from "../dist/svg.js";
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const [source, target, ...args] = process.argv.slice(2);
|
|
14
|
+
if (!source || !target)
|
|
15
|
+
throw new Error(
|
|
16
|
+
"Usage: node tools/svg-asset.mjs source.json output.svg [--clip name] [--time seconds] [--animated | --frames] [--fps 24] [--params overrides.json]. --frames uses output as a directory.",
|
|
17
|
+
);
|
|
18
|
+
const options = {},
|
|
19
|
+
flags = new Set();
|
|
20
|
+
for (let i = 0; i < args.length; i++) {
|
|
21
|
+
const key = args[i];
|
|
22
|
+
if (key === "--animated" || key === "--frames") {
|
|
23
|
+
flags.add(key);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (!["--clip", "--time", "--fps", "--params"].includes(key) || args[i + 1] === undefined)
|
|
27
|
+
throw new Error(`Unknown or incomplete option ${key}`);
|
|
28
|
+
const value = args[++i];
|
|
29
|
+
if (key === "--clip") options.animation = value;
|
|
30
|
+
if (key === "--time") options.time = Number(value);
|
|
31
|
+
if (key === "--fps") options.fps = Number(value);
|
|
32
|
+
if (key === "--params") options.params = JSON.parse(await readFile(value, "utf8"));
|
|
33
|
+
}
|
|
34
|
+
if (flags.size > 1 || (flags.size && options.time !== undefined))
|
|
35
|
+
throw new Error("Choose a static time, --animated, or --frames.");
|
|
36
|
+
if (options.params && (typeof options.params !== "object" || Array.isArray(options.params)))
|
|
37
|
+
throw new Error("Parameter overrides must be a JSON object.");
|
|
38
|
+
const compiled = compileSvgAsset(JSON.parse(await readFile(source, "utf8")));
|
|
39
|
+
if (!compiled.ok) {
|
|
40
|
+
console.error(JSON.stringify({ ok: false, diagnostics: compiled.diagnostics }, null, 2));
|
|
41
|
+
process.exitCode = 1;
|
|
42
|
+
} else {
|
|
43
|
+
const asset = compiled.asset;
|
|
44
|
+
if (flags.has("--frames")) {
|
|
45
|
+
const name = options.animation ?? asset.spec.defaultAnimation;
|
|
46
|
+
if (!name || !Object.hasOwn(asset.spec.animations ?? {}, name))
|
|
47
|
+
throw new Error("Select an existing clip for frame export.");
|
|
48
|
+
const clip = asset.spec.animations[name],
|
|
49
|
+
fps = options.fps ?? 24;
|
|
50
|
+
if (!Number.isFinite(fps) || fps < 1 || fps > 60) throw new Error("fps must be in [1, 60].");
|
|
51
|
+
const steps = Math.ceil(clip.duration * fps),
|
|
52
|
+
count = steps + (clip.loop ? 0 : 1);
|
|
53
|
+
if (count > SVG_ASSET_LIMITS.frames) throw new Error(`Frame count exceeds ${SVG_ASSET_LIMITS.frames}.`);
|
|
54
|
+
// Evaluate the entire bounded sequence before writing any outputs.
|
|
55
|
+
let size = 0;
|
|
56
|
+
const frames = Array.from({ length: count }, (_, index) => {
|
|
57
|
+
const time = (index * clip.duration) / steps;
|
|
58
|
+
const svg = renderSvgFrame(asset, { ...options, animation: name, time });
|
|
59
|
+
size += svg.length;
|
|
60
|
+
if (size > SVG_ASSET_LIMITS.outputCharacters)
|
|
61
|
+
throw new Error("Frame sequence exceeds output budget.");
|
|
62
|
+
return { file: `${String(index).padStart(4, "0")}.svg`, time, svg };
|
|
63
|
+
});
|
|
64
|
+
await mkdir(target, { recursive: true });
|
|
65
|
+
for (const { file, svg } of frames) await writeFile(join(target, file), svg);
|
|
66
|
+
await writeFile(
|
|
67
|
+
join(target, "manifest.json"),
|
|
68
|
+
JSON.stringify(
|
|
69
|
+
{
|
|
70
|
+
schema: "svg-frames/0.1",
|
|
71
|
+
source,
|
|
72
|
+
animation: name,
|
|
73
|
+
duration: clip.duration,
|
|
74
|
+
loop: clip.loop,
|
|
75
|
+
requestedFps: fps,
|
|
76
|
+
sampleFps: steps / clip.duration,
|
|
77
|
+
viewBox: asset.spec.viewBox,
|
|
78
|
+
frames: frames.map(({ file, time }) => ({ file, time })),
|
|
79
|
+
},
|
|
80
|
+
null,
|
|
81
|
+
2,
|
|
82
|
+
) + "\n",
|
|
83
|
+
);
|
|
84
|
+
} else
|
|
85
|
+
await writeFile(
|
|
86
|
+
target,
|
|
87
|
+
flags.has("--animated") ? exportSvgAnimation(asset, options) : renderSvgFrame(asset, options),
|
|
88
|
+
);
|
|
89
|
+
console.log(JSON.stringify({ ok: true, output: target }));
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error(
|
|
93
|
+
JSON.stringify(
|
|
94
|
+
{
|
|
95
|
+
ok: false,
|
|
96
|
+
diagnostics:
|
|
97
|
+
error instanceof SvgAssetError
|
|
98
|
+
? error.diagnostics
|
|
99
|
+
: [{ code: "SVG_CLI", path: "$", message: error.message }],
|
|
100
|
+
},
|
|
101
|
+
null,
|
|
102
|
+
2,
|
|
103
|
+
),
|
|
104
|
+
);
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
}
|