@logomarks/logo3d 0.0.0-stage → 0.1.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 (54) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +21 -0
  3. package/README.md +55 -2
  4. package/assets/hdri/kloofendal_48d_partly_cloudy_puresky_1k.hdr +0 -0
  5. package/assets/hdri/studio_small_09_1k.hdr +0 -0
  6. package/package.json +82 -4
  7. package/src/export/glb.d.ts +5 -0
  8. package/src/export/glb.js +28 -0
  9. package/src/export/still.d.ts +23 -0
  10. package/src/export/still.js +144 -0
  11. package/src/geometry/buffer.js +102 -0
  12. package/src/geometry/caps.js +53 -0
  13. package/src/geometry/check.js +86 -0
  14. package/src/geometry/index.d.ts +114 -0
  15. package/src/geometry/index.js +112 -0
  16. package/src/geometry/inset.js +339 -0
  17. package/src/geometry/profiles.js +126 -0
  18. package/src/geometry/sides.js +86 -0
  19. package/src/index.d.ts +17 -0
  20. package/src/index.js +19 -0
  21. package/src/materials/factory.d.ts +11 -0
  22. package/src/materials/factory.js +112 -0
  23. package/src/materials/presets.d.ts +34 -0
  24. package/src/materials/presets.js +79 -0
  25. package/src/motion/index.d.ts +23 -0
  26. package/src/motion/index.js +56 -0
  27. package/src/scene/backdrop.d.ts +20 -0
  28. package/src/scene/backdrop.js +128 -0
  29. package/src/scene/camera.d.ts +10 -0
  30. package/src/scene/camera.js +51 -0
  31. package/src/scene/environments.d.ts +22 -0
  32. package/src/scene/environments.js +94 -0
  33. package/src/scene/studio.d.ts +12 -0
  34. package/src/scene/studio.js +81 -0
  35. package/src/scene/view.d.ts +69 -0
  36. package/src/scene/view.js +273 -0
  37. package/src/shape/index.d.ts +80 -0
  38. package/src/shape/index.js +32 -0
  39. package/src/shape/layers.js +142 -0
  40. package/src/shape/matrix.js +88 -0
  41. package/src/shape/normalise.js +92 -0
  42. package/src/shape/simplify.js +95 -0
  43. package/src/shape/svg.js +196 -0
  44. package/src/shape/thinnest.js +77 -0
  45. package/src/three/geometry.d.ts +5 -0
  46. package/src/three/geometry.js +25 -0
  47. package/src/three/index.d.ts +11 -0
  48. package/src/three/index.js +15 -0
  49. package/src/worker/build.d.ts +6 -0
  50. package/src/worker/build.js +37 -0
  51. package/src/worker/client.d.ts +29 -0
  52. package/src/worker/client.js +83 -0
  53. package/src/worker/worker.d.ts +2 -0
  54. package/src/worker/worker.js +23 -0
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @module @logomarks/logo3d/worker/client
3
+ *
4
+ * Builds geometry in the worker, latest request wins: while one build runs, a new request replaces any waiting one
5
+ * (the replaced one rejects with an `AbortError`), so dragging a slider never queues up stale builds. Without a
6
+ * worker it builds on the main thread, one request at a time, the same way.
7
+ */
8
+
9
+ import { makeBuild } from './build.js';
10
+
11
+ /**
12
+ * An `AbortError` for a request that a newer one replaced.
13
+ *
14
+ * @returns {Error} The error.
15
+ */
16
+ const superseded = () => Object.assign(new Error('logo3d: replaced by a newer request'), { name: 'AbortError' });
17
+
18
+ /**
19
+ * A builder.
20
+ *
21
+ * @param {(() => import('./client.js').WorkerLike) | null} [makeWorker] Makes the worker (null: build on the main
22
+ * thread).
23
+ * @returns {import('./client.js').Builder} The builder.
24
+ */
25
+ export function createBuilder(makeWorker = null) {
26
+ /** @type {import('./client.js').WorkerLike | null} */
27
+ const worker = makeWorker ? makeWorker() : null;
28
+ const local = worker ? null : makeBuild();
29
+ /** @typedef {{ req: import('./client.js').BuildRequest, resolve: (r: import('./client.js').BuildResult) => void, reject: (e: Error) => void }} Job */
30
+ /** @type {Job | null} */
31
+ let waiting = null;
32
+ /** @type {(Job & { id: number }) | null} */
33
+ let running = null;
34
+ let ids = 0;
35
+
36
+ function pump() {
37
+ if (running || !waiting) return;
38
+ const job = { ...waiting, id: ++ids };
39
+ waiting = null;
40
+ running = job;
41
+ if (worker) worker.postMessage({ id: job.id, svg: job.req.svg, options: job.req.options });
42
+ else
43
+ Promise.resolve().then(() => {
44
+ try {
45
+ finish(job.id, { result: /** @type {NonNullable<typeof local>} */ (local)(job.req) });
46
+ } catch (err) {
47
+ finish(job.id, { error: err instanceof Error ? err.message : String(err) });
48
+ }
49
+ });
50
+ }
51
+
52
+ /**
53
+ * A build is done.
54
+ *
55
+ * @param {number} id The build.
56
+ * @param {{ result?: import('./client.js').BuildResult, error?: string }} reply What came back.
57
+ */
58
+ function finish(id, reply) {
59
+ if (!running || running.id !== id) return;
60
+ const job = running;
61
+ running = null;
62
+ if (reply.error !== undefined) job.reject(new Error(reply.error));
63
+ else job.resolve(/** @type {import('./client.js').BuildResult} */ (reply.result));
64
+ pump();
65
+ }
66
+
67
+ if (worker) worker.onmessage = (e) => finish(e.data.id, e.data);
68
+
69
+ return {
70
+ build(req) {
71
+ return new Promise((resolve, reject) => {
72
+ waiting?.reject(superseded());
73
+ waiting = { req, resolve, reject };
74
+ pump();
75
+ });
76
+ },
77
+ dispose() {
78
+ waiting?.reject(superseded());
79
+ waiting = null;
80
+ worker?.terminate();
81
+ },
82
+ };
83
+ }
@@ -0,0 +1,2 @@
1
+ /** The geometry worker's entry: messages `{ id, svg, options }`, replies `{ id, result }` or `{ id, error }`. */
2
+ export {};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @module @logomarks/logo3d/worker
3
+ *
4
+ * The geometry worker: a module worker that reads SVGs and extrudes them off the main thread. Each message is
5
+ * `{ id, svg, options }`; each reply `{ id, result }` (its arrays transferred) or `{ id, error }`. Load it as a
6
+ * same-origin module worker (Vite: `import Worker from '@logomarks/logo3d/worker?worker'`); no blob: URL, no
7
+ * WebAssembly. Use it through `createBuilder`, which keeps only the latest request.
8
+ */
9
+
10
+ import { makeBuild, transferables } from './build.js';
11
+
12
+ const build = makeBuild();
13
+ const scope = /** @type {{ onmessage: ((e: MessageEvent) => void) | null, postMessage(m: unknown, t?: Transferable[]): void }} */ (/** @type {unknown} */ (globalThis));
14
+
15
+ scope.onmessage = (e) => {
16
+ const { id, svg, options } = e.data;
17
+ try {
18
+ const result = build({ svg, options });
19
+ scope.postMessage({ id, result }, transferables(result));
20
+ } catch (err) {
21
+ scope.postMessage({ id, error: err instanceof Error ? err.message : String(err) });
22
+ }
23
+ };