@doki-land/live2d 0.0.16 → 0.0.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.
package/README.md CHANGED
@@ -25,19 +25,28 @@ pnpm add @doki-land/live2d
25
25
 
26
26
  The implementation packages are installed transitively. Most applications should not depend on them directly.
27
27
 
28
+ ## 🧭 Source Layout
29
+
30
+ ```text
31
+ src/facade/ createLive2D() — default stage + single actor
32
+ src/motion/ motion3 parse, curves, MotionPlayer
33
+ src/stage/ Live2dStage, actors, asset registry, transforms
34
+ src/reexports/ optional subpath exports for core / loader / renderer
35
+ ```
36
+
28
37
  ## 🚀 Quick Start
29
38
 
30
39
  ```ts
31
- import { createLive2D } from "@doki-land/live2d";
40
+ import {createLive2D} from "@doki-land/live2d";
32
41
 
33
42
  const canvas = document.querySelector<HTMLCanvasElement>("#live2d");
34
43
 
35
44
  if (!canvas) {
36
- throw new Error("Missing Live2D canvas");
45
+ throw new Error("Missing Live2D canvas");
37
46
  }
38
47
 
39
48
  const runtime = createLive2D({
40
- prefer: ["webgpu", "webgl2", "canvas2d"],
49
+ prefer: ["webgpu", "webgl2", "canvas2d"],
41
50
  });
42
51
 
43
52
  runtime.mount(canvas);
@@ -46,9 +55,9 @@ await runtime.loadModel("/models/character.model3.json");
46
55
  let previous = performance.now();
47
56
 
48
57
  function frame(now: number) {
49
- runtime.update((now - previous) / 1000);
50
- previous = now;
51
- requestAnimationFrame(frame);
58
+ runtime.update((now - previous) / 1000);
59
+ previous = now;
60
+ requestAnimationFrame(frame);
52
61
  }
53
62
 
54
63
  requestAnimationFrame(frame);
@@ -60,7 +69,7 @@ The runtime does not require ownership of `requestAnimationFrame`. Drive it from
60
69
 
61
70
  ```ts
62
71
  engine.onUpdate((deltaTime) => {
63
- runtime.update(deltaTime);
72
+ runtime.update(deltaTime);
64
73
  });
65
74
  ```
66
75
 
@@ -73,11 +82,11 @@ animation and physics once those systems are enabled.
73
82
  await runtime.loadModel("/models/actor.model3.json");
74
83
 
75
84
  await runtime.loadModel(
76
- "https://cdn.example.com/models/actor.model3.json",
85
+ "https://cdn.example.com/models/actor.model3.json",
77
86
  );
78
87
 
79
88
  await runtime.loadModel(
80
- "npm:live2d-widget-model-hijiki@1.0.5/assets/hijiki.model.json",
89
+ "npm:live2d-widget-model-hijiki@1.0.5/assets/hijiki.model.json",
81
90
  );
82
91
  ```
83
92
 
@@ -97,8 +106,8 @@ Remote servers must allow cross-origin access to settings, model binaries, and t
97
106
  runtime.setParameter("PARAM_ANGLE_X", 15);
98
107
 
99
108
  const angleX = runtime
100
- .listParameters()
101
- .find((parameter) => parameter.id === "PARAM_ANGLE_X");
109
+ .listParameters()
110
+ .find((parameter) => parameter.id === "PARAM_ANGLE_X");
102
111
 
103
112
  console.log(angleX);
104
113
  ```
@@ -113,7 +122,7 @@ Parameter availability and ranges belong to the loaded model. Do not assume ever
113
122
  const area = runtime.hitTest(modelX, modelY);
114
123
 
115
124
  if (area) {
116
- console.log("Hit", area);
125
+ console.log("Hit", area);
117
126
  }
118
127
  ```
119
128
 
@@ -143,8 +152,8 @@ Advanced applications can provide a renderer or model backends:
143
152
 
144
153
  ```ts
145
154
  const runtime = createLive2D({
146
- renderer: customRenderer,
147
- backends: [customBackend],
155
+ renderer: customRenderer,
156
+ backends: [customBackend],
148
157
  });
149
158
  ```
150
159
 
@@ -183,9 +192,33 @@ applicable.
183
192
 
184
193
  ## 🤝 Contributing
185
194
 
186
- Keep the facade small. Model-format behavior belongs in `@doki-land/live2d-renderer`, source resolution belongs in
187
- `@doki-land/live2d-loader`, and webpage chrome belongs in `@doki-land/live2d-widget`.
195
+ ### Package ownership
196
+
197
+ - Keep the facade small and host-independent.
198
+ - Put model-format behavior in `@doki-land/live2d-renderer`.
199
+ - Put source resolution in `@doki-land/live2d-loader`.
200
+ - Put webpage chrome in `@doki-land/live2d-widget`.
201
+ - Include tests for state transitions, cancellation, events, and resource cleanup where applicable.
188
202
 
189
203
  ## 📄 License
190
204
 
191
- See the repository license. Model and artwork licenses are separate from the runtime license.
205
+ ### Implementation independence
206
+
207
+ - This package composes an independently developed clean-room runtime.
208
+ - It does not load, link against, wrap, translate, port, or derive its implementation from an official Cubism SDK or
209
+ Core binary.
210
+ - Compatible model support is an interoperability goal, not evidence of a shared implementation, endorsement,
211
+ affiliation, sponsorship, or employment relationship.
212
+ - The project and its contributors are independent and do not act on behalf of the official Cubism SDK vendor.
213
+
214
+ ### Contribution boundary
215
+
216
+ - Do not submit official SDK or shader source, disassembly-derived code, mechanically translated implementation code, or
217
+ changes that require an official runtime.
218
+ - Support compatibility-sensitive work with public format facts, neutral fixtures, reproducible independent
219
+ observations, or independently authored technical rationale.
220
+
221
+ ### Terms
222
+
223
+ - See the repository license for source-code terms.
224
+ - Model and artwork licenses are separate from the runtime license.
package/dist/index.d.ts CHANGED
@@ -367,11 +367,11 @@ interface Live2DRuntime extends Live2DSession {
367
367
  declare function createLive2D(options?: CreateLive2DOptions): Live2DRuntime;
368
368
 
369
369
  /**
370
- * Map canvas focus (-1..1, Y-up) onto standard Cubism drag parameters.
370
+ * Map canvas focus (-1..1, Y-up) onto commonly used model parameter IDs.
371
371
  *
372
- * Matches the Cubism sample / community widget weights:
373
- * ANGLE_X/Y full range, ANGLE_Z = -dragX*dragY, BODY_ANGLE_X, EYE_BALL_*.
374
- * Missing ids on a given model are skipped.
372
+ * ANGLE_X/Y use the full declared range, ANGLE_Z combines both axes, and body
373
+ * and eye parameters receive the corresponding normalized axis. Parameters not
374
+ * declared by a model are skipped.
375
375
  */
376
376
  declare function focusParameterUpdates(parameters: readonly ParameterBinding[], dragX: number, dragY: number): Array<{
377
377
  id: string;
@@ -381,6 +381,12 @@ declare function focusParameterUpdates(parameters: readonly ParameterBinding[],
381
381
  /**
382
382
  * `@doki-land/live2d` — public facade.
383
383
  *
384
+ * Layout:
385
+ * - `facade/` — `createLive2D()` default stage + actor entry
386
+ * - `motion/` — motion3 parse + playback
387
+ * - `stage/` — multi-actor stage, assets, transforms
388
+ * - `reexports/` — optional subpath `@doki-land/live2d/{core,loader,renderer}`
389
+ *
384
390
  * ```ts
385
391
  * import { createLive2D } from "@doki-land/live2d";
386
392
  * ```
package/dist/index.js CHANGED
@@ -20,14 +20,14 @@ import {
20
20
  serializeCpuProgram
21
21
  } from "@doki-land/live2d-renderer";
22
22
 
23
- // src/create-live2d.ts
23
+ // src/facade/create-live2d.ts
24
24
  import {
25
25
  createMoc2Backend as createMoc2Backend2,
26
26
  createMoc3Backend as createMoc3Backend2,
27
27
  createRenderer as createRenderer2
28
28
  } from "@doki-land/live2d-renderer";
29
29
 
30
- // src/focus.ts
30
+ // src/stage/assets/focus.ts
31
31
  function focusParameterUpdates(parameters, dragX, dragY) {
32
32
  const byId = new Map(parameters.map((p) => [p.id, p]));
33
33
  const x = clampUnit(dragX);
@@ -1195,7 +1195,7 @@ import {
1195
1195
  selectModelBackend
1196
1196
  } from "@doki-land/live2d-renderer";
1197
1197
 
1198
- // src/load-textures.ts
1198
+ // src/stage/assets/load-textures.ts
1199
1199
  function guessMime(path) {
1200
1200
  const lower = path.toLowerCase();
1201
1201
  if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
@@ -1816,7 +1816,7 @@ function createLive2dStage(options) {
1816
1816
  return new Live2dStageImpl(options);
1817
1817
  }
1818
1818
 
1819
- // src/create-live2d.ts
1819
+ // src/facade/create-live2d.ts
1820
1820
  function createLive2D(options = {}) {
1821
1821
  const backends = options.backends ?? [
1822
1822
  createMoc2Backend2(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doki-land/live2d",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "Live2D in the browser — load moc2/moc3 models, Stage + multi-actor, motion; WebGPU/WebGL2/Canvas2D. Main entry for live2d.ts.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -59,9 +59,9 @@
59
59
  "test": "vitest run --passWithNoTests"
60
60
  },
61
61
  "dependencies": {
62
- "@doki-land/live2d-core": "0.0.16",
63
- "@doki-land/live2d-loader": "0.0.16",
64
- "@doki-land/live2d-renderer": "0.0.16"
62
+ "@doki-land/live2d-core": "0.0.17",
63
+ "@doki-land/live2d-loader": "0.0.17",
64
+ "@doki-land/live2d-renderer": "0.0.17"
65
65
  },
66
66
  "sideEffects": false
67
67
  }
@@ -3,22 +3,22 @@ import {
3
3
  createMoc3Backend,
4
4
  createRenderer,
5
5
  } from "@doki-land/live2d-renderer";
6
- import { allocateActorId } from "./stage/actor.js";
6
+ import { allocateActorId } from "../stage/actor.js";
7
7
  import {
8
8
  type CreateLive2DOptions,
9
9
  createSingleActorFacade,
10
10
  type Live2DRuntime,
11
- } from "./stage/single-facade.js";
12
- import { createLive2dStage } from "./stage/stage.js";
11
+ } from "../stage/single-facade.js";
12
+ import { createLive2dStage } from "../stage/stage.js";
13
13
 
14
14
  export type {
15
15
  CreateLive2DOptions,
16
16
  Live2DRuntime,
17
- } from "./stage/single-facade.js";
17
+ } from "../stage/single-facade.js";
18
18
  export {
19
19
  MotionPriority,
20
20
  type PlayMotionOptions,
21
- } from "./stage/single-facade.js";
21
+ } from "../stage/single-facade.js";
22
22
 
23
23
  /** Wire moc backends and a renderer into one single-actor session. */
24
24
  export function createLive2D(options: CreateLive2DOptions = {}): Live2DRuntime {
@@ -31,9 +31,9 @@ export function createLive2D(options: CreateLive2DOptions = {}): Live2DRuntime {
31
31
  renderer:
32
32
  options.renderer ?? createRenderer({ prefer: options.prefer }),
33
33
  updateMode: options.updateMode ?? "manual",
34
- }) as import("./stage/stage.js").Live2dStageImpl;
34
+ }) as import("../stage/stage.js").Live2dStageImpl;
35
35
  const actor = stage.createActor({
36
36
  id: allocateActorId("default"),
37
- }) as import("./stage/actor.js").Live2dActorImpl;
37
+ }) as import("../stage/actor.js").Live2dActorImpl;
38
38
  return createSingleActorFacade(stage, actor, backends);
39
39
  }
package/src/index.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  /**
2
2
  * `@doki-land/live2d` — public facade.
3
3
  *
4
+ * Layout:
5
+ * - `facade/` — `createLive2D()` default stage + actor entry
6
+ * - `motion/` — motion3 parse + playback
7
+ * - `stage/` — multi-actor stage, assets, transforms
8
+ * - `reexports/` — optional subpath `@doki-land/live2d/{core,loader,renderer}`
9
+ *
4
10
  * ```ts
5
11
  * import { createLive2D } from "@doki-land/live2d";
6
12
  * ```
@@ -66,8 +72,8 @@ export {
66
72
  type Live2DRuntime,
67
73
  MotionPriority,
68
74
  type PlayMotionOptions,
69
- } from "./create-live2d.js";
70
- export { focusParameterUpdates } from "./focus.js";
75
+ } from "./facade/create-live2d.js";
76
+ export { focusParameterUpdates } from "./stage/assets/focus.js";
71
77
  export {
72
78
  blendMotionLayers,
73
79
  evaluateCurve,
@@ -8,7 +8,7 @@ import type {
8
8
  PlayMotionActorOptions,
9
9
  } from "@doki-land/live2d-core";
10
10
  import type { DrawableMesh, Renderer } from "@doki-land/live2d-renderer";
11
- import { focusParameterUpdates } from "../focus.js";
11
+ import { focusParameterUpdates } from "./assets/focus.js";
12
12
  import type { PlayMotionOptions } from "../motion/index.js";
13
13
  import { ActorModelSlot } from "./actor-model-slot.js";
14
14
  import type { ModelAssetRegistry } from "./model-asset-registry.js";
@@ -1,11 +1,11 @@
1
1
  import type { ParameterBinding } from "@doki-land/live2d-renderer";
2
2
 
3
3
  /**
4
- * Map canvas focus (-1..1, Y-up) onto standard Cubism drag parameters.
4
+ * Map canvas focus (-1..1, Y-up) onto commonly used model parameter IDs.
5
5
  *
6
- * Matches the Cubism sample / community widget weights:
7
- * ANGLE_X/Y full range, ANGLE_Z = -dragX*dragY, BODY_ANGLE_X, EYE_BALL_*.
8
- * Missing ids on a given model are skipped.
6
+ * ANGLE_X/Y use the full declared range, ANGLE_Z combines both axes, and body
7
+ * and eye parameters receive the corresponding normalized axis. Parameters not
8
+ * declared by a model are skipped.
9
9
  */
10
10
  export function focusParameterUpdates(
11
11
  parameters: readonly ParameterBinding[],
@@ -26,8 +26,7 @@ export function focusParameterUpdates(
26
26
  set("PARAM_ANGLE_X", x);
27
27
  set("PARAM_ANGLE_Y", y);
28
28
  set("PARAM_ANGLE_Z", clampUnit(x * y * -1));
29
- // Official sample uses dragX*10 vs ANGLE's *30; BODY range is typically ±10,
30
- // so full-range normalized drag still matches that relative weight.
29
+ // Each binding maps normalized input through its own declared range.
31
30
  set("PARAM_BODY_ANGLE_X", x);
32
31
  set("PARAM_BODY_ANGLE_Y", y);
33
32
  set("PARAM_EYE_BALL_X", x);
@@ -23,7 +23,7 @@ import {
23
23
  compileSharedModelCompile,
24
24
  selectModelBackend,
25
25
  } from "@doki-land/live2d-renderer";
26
- import { loadTextureData, releaseTextureData } from "../load-textures.js";
26
+ import { loadTextureData, releaseTextureData } from "./assets/load-textures.js";
27
27
  import type { Motion3Clip } from "../motion/index.js";
28
28
  import { resolveModelAssetKey } from "./model-asset-key.js";
29
29