@linxin666/dsh-pet 0.2.2 → 0.2.3
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.i18n.yaml +2 -2
- package/README.md +66 -3
- package/README.zh.md +66 -3
- package/assets/whale/pet.json +169 -20
- package/assets/whale-refined/pet.json +17 -2
- package/lib/client.js +438 -21
- package/lib/client.js.map +1 -1
- package/lib/index.js +752 -36
- package/lib/live2d-vendor.js +995 -0
- package/lib/live2d-vendor.js.map +1 -0
- package/lib/types/client/PetDockEntry.d.ts.map +1 -1
- package/lib/types/client/PetDockEntry.js +2 -1
- package/lib/types/client/PetSettingsCard.d.ts +10 -0
- package/lib/types/client/PetSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PetSettingsCard.js +22 -1
- package/lib/types/client/PetSprite.d.ts +7 -1
- package/lib/types/client/PetSprite.d.ts.map +1 -1
- package/lib/types/client/PetSprite.js +17 -8
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +5 -0
- package/lib/types/client/locales.d.ts +10 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +10 -0
- package/lib/types/client/phase-stream.d.ts +22 -0
- package/lib/types/client/phase-stream.d.ts.map +1 -0
- package/lib/types/client/phase-stream.js +28 -0
- package/lib/types/client/renderers/PetRendererSwitch.d.ts +25 -0
- package/lib/types/client/renderers/PetRendererSwitch.d.ts.map +1 -0
- package/lib/types/client/renderers/PetRendererSwitch.js +24 -0
- package/lib/types/client/renderers/live2d/Live2dVisualMount.d.ts +22 -0
- package/lib/types/client/renderers/live2d/Live2dVisualMount.d.ts.map +1 -0
- package/lib/types/client/renderers/live2d/Live2dVisualMount.js +75 -0
- package/lib/types/client/renderers/live2d/runtime.d.ts +89 -0
- package/lib/types/client/renderers/live2d/runtime.d.ts.map +1 -0
- package/lib/types/client/renderers/live2d/runtime.js +63 -0
- package/lib/types/client/renderers/live2d/vendor-entry.d.ts +15 -0
- package/lib/types/client/renderers/live2d/vendor-entry.d.ts.map +1 -0
- package/lib/types/client/renderers/live2d/vendor-entry.js +14 -0
- package/lib/types/client/renderers/live2d.d.ts +52 -0
- package/lib/types/client/renderers/live2d.d.ts.map +1 -0
- package/lib/types/client/renderers/live2d.js +180 -0
- package/lib/types/client/renderers/registry.d.ts +32 -0
- package/lib/types/client/renderers/registry.d.ts.map +1 -0
- package/lib/types/client/renderers/registry.js +49 -0
- package/lib/types/contracts/renderer.d.ts +50 -0
- package/lib/types/contracts/renderer.d.ts.map +1 -0
- package/lib/types/contracts/renderer.js +15 -0
- package/lib/types/manifest-v2.d.ts +129 -0
- package/lib/types/manifest-v2.d.ts.map +1 -0
- package/lib/types/manifest-v2.js +387 -0
- package/lib/types/model3.d.ts +26 -0
- package/lib/types/model3.d.ts.map +1 -0
- package/lib/types/model3.js +96 -0
- package/lib/types/registry.d.ts +57 -3
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/registry.js +208 -33
- package/lib/types/routes.d.ts +39 -2
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +183 -12
- package/lib/types/service.d.ts +5 -1
- package/lib/types/service.d.ts.map +1 -1
- package/lib/types/service.js +4 -0
- package/package.json +3 -1
- package/src/client/PetDockEntry.tsx +19 -11
- package/src/client/PetSettingsCard.tsx +39 -0
- package/src/client/PetSprite.test.tsx +11 -0
- package/src/client/PetSprite.tsx +24 -9
- package/src/client/index.ts +6 -0
- package/src/client/locales.ts +10 -0
- package/src/client/phase-stream.test.ts +76 -0
- package/src/client/phase-stream.ts +39 -0
- package/src/client/renderers/PetRendererSwitch.test.tsx +66 -0
- package/src/client/renderers/PetRendererSwitch.tsx +48 -0
- package/src/client/renderers/live2d/Live2dVisualMount.tsx +98 -0
- package/src/client/renderers/live2d/runtime.test.ts +61 -0
- package/src/client/renderers/live2d/runtime.ts +119 -0
- package/src/client/renderers/live2d/vendor-entry.ts +14 -0
- package/src/client/renderers/live2d.test.ts +242 -0
- package/src/client/renderers/live2d.ts +218 -0
- package/src/client/renderers/registry.ts +58 -0
- package/src/client/settings-section.module.css +23 -0
- package/src/contracts/renderer.ts +54 -0
- package/src/manifest-v2.test.ts +251 -0
- package/src/manifest-v2.ts +414 -0
- package/src/model3.test.ts +79 -0
- package/src/model3.ts +91 -0
- package/src/registry.test.ts +215 -2
- package/src/registry.ts +246 -34
- package/src/routes.ts +202 -13
- package/src/service.ts +6 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live2D runtime loading (pet-center M3) — the two scripts a live2d mount
|
|
3
|
+
* needs, fetched lazily through the plugin's own runtime route: the
|
|
4
|
+
* user-supplied Cubism Core (proprietary; the plugin never bundles or
|
|
5
|
+
* downloads it — issue #623 M1 §0) and the plugin-shipped MIT vendor bundle
|
|
6
|
+
* (pixi.js + untitled-pixi-live2d-engine). Each loads at most once per page;
|
|
7
|
+
* concurrent mounts share the in-flight promise, and a failure is cached as
|
|
8
|
+
* 'absent' so a broken install stops retrying the network every mount.
|
|
9
|
+
*
|
|
10
|
+
* The vendor surface below is the structural slice the renderer consumes;
|
|
11
|
+
* the real objects come from 'window.__dshPetLive2d' (lib/live2d-vendor.js),
|
|
12
|
+
* so this module never imports pixi — the client bundle stays lean.
|
|
13
|
+
* @module @linxin666/dsh-pet/client/renderers/live2d/runtime
|
|
14
|
+
*/
|
|
15
|
+
/** The pixi Application slice the renderer uses. */
|
|
16
|
+
export interface Live2dVendorApp {
|
|
17
|
+
canvas: HTMLCanvasElement;
|
|
18
|
+
stage: {
|
|
19
|
+
addChild(child: unknown): unknown;
|
|
20
|
+
};
|
|
21
|
+
renderer: {
|
|
22
|
+
readonly width: number;
|
|
23
|
+
readonly height: number;
|
|
24
|
+
};
|
|
25
|
+
init(options: Record<string, unknown>): Promise<void>;
|
|
26
|
+
destroy(removeView?: boolean, options?: Record<string, unknown>): void;
|
|
27
|
+
}
|
|
28
|
+
/** The Live2DModel slice the renderer uses. */
|
|
29
|
+
export interface Live2dVendorModel {
|
|
30
|
+
anchor: {
|
|
31
|
+
set(x: number, y?: number): void;
|
|
32
|
+
};
|
|
33
|
+
position: {
|
|
34
|
+
set(x: number, y: number): void;
|
|
35
|
+
};
|
|
36
|
+
scale: {
|
|
37
|
+
set(x: number, y?: number): void;
|
|
38
|
+
};
|
|
39
|
+
readonly width: number;
|
|
40
|
+
readonly height: number;
|
|
41
|
+
internalModel: {
|
|
42
|
+
settings: {
|
|
43
|
+
motions?: Record<string, unknown[]>;
|
|
44
|
+
hitAreas?: readonly {
|
|
45
|
+
Name?: string;
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
motion(group: string, index?: number): Promise<unknown>;
|
|
50
|
+
expression(name?: string): unknown;
|
|
51
|
+
hitTest(x: number, y: number): string[];
|
|
52
|
+
on(event: string, fn: () => void): unknown;
|
|
53
|
+
}
|
|
54
|
+
/** The vendor bundle global (window.__dshPetLive2d). */
|
|
55
|
+
export interface Live2dVendor {
|
|
56
|
+
Application: new () => Live2dVendorApp;
|
|
57
|
+
extensions: {
|
|
58
|
+
add(...items: unknown[]): void;
|
|
59
|
+
};
|
|
60
|
+
Live2DPlugin: unknown;
|
|
61
|
+
configureCubismSDK(options: Record<string, unknown>): void;
|
|
62
|
+
Live2DModel: {
|
|
63
|
+
from(source: string, options?: Record<string, unknown>): Promise<Live2dVendorModel>;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
declare global {
|
|
67
|
+
interface Window {
|
|
68
|
+
Live2DCubismCore?: unknown;
|
|
69
|
+
__dshPetLive2d?: Live2dVendor;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Injects one classic script tag; resolves on load, rejects on error. */
|
|
73
|
+
type ScriptInjector = (src: string) => Promise<void>;
|
|
74
|
+
/** Test seam: swap the network for a stub injector. */
|
|
75
|
+
export interface Live2dRuntimeProbe {
|
|
76
|
+
inject?: ScriptInjector;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Ensure the Cubism Core global exists, injecting the runtime-route script
|
|
80
|
+
* once when absent. Resolves false when the user has not installed the core
|
|
81
|
+
* (a normal state — the renderer turns it into install guidance).
|
|
82
|
+
*/
|
|
83
|
+
export declare function ensureCubismCore(probe?: Live2dRuntimeProbe): Promise<boolean>;
|
|
84
|
+
/** Ensure the plugin vendor bundle global exists (same caching discipline). */
|
|
85
|
+
export declare function ensureLive2dVendor(probe?: Live2dRuntimeProbe): Promise<Live2dVendor | undefined>;
|
|
86
|
+
/** Reset the cached script promises (tests). */
|
|
87
|
+
export declare function resetLive2dRuntime(): void;
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../../src/client/renderers/live2d/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live2D runtime loading (pet-center M3) — the two scripts a live2d mount
|
|
3
|
+
* needs, fetched lazily through the plugin's own runtime route: the
|
|
4
|
+
* user-supplied Cubism Core (proprietary; the plugin never bundles or
|
|
5
|
+
* downloads it — issue #623 M1 §0) and the plugin-shipped MIT vendor bundle
|
|
6
|
+
* (pixi.js + untitled-pixi-live2d-engine). Each loads at most once per page;
|
|
7
|
+
* concurrent mounts share the in-flight promise, and a failure is cached as
|
|
8
|
+
* 'absent' so a broken install stops retrying the network every mount.
|
|
9
|
+
*
|
|
10
|
+
* The vendor surface below is the structural slice the renderer consumes;
|
|
11
|
+
* the real objects come from 'window.__dshPetLive2d' (lib/live2d-vendor.js),
|
|
12
|
+
* so this module never imports pixi — the client bundle stays lean.
|
|
13
|
+
* @module @linxin666/dsh-pet/client/renderers/live2d/runtime
|
|
14
|
+
*/
|
|
15
|
+
/** Runtime file URLs the host serves ('/api/pet/runtime/<name>', M3-2). */
|
|
16
|
+
const CORE_URL = '/api/pet/runtime/live2dcubismcore.min.js';
|
|
17
|
+
const VENDOR_URL = '/api/pet/runtime/live2d-vendor.js';
|
|
18
|
+
const defaultInjector = (src) => new Promise((resolve, reject) => {
|
|
19
|
+
const tag = document.createElement('script');
|
|
20
|
+
tag.src = src;
|
|
21
|
+
tag.onload = () => resolve();
|
|
22
|
+
tag.onerror = () => reject(new Error('script failed to load: ' + src));
|
|
23
|
+
document.head.appendChild(tag);
|
|
24
|
+
});
|
|
25
|
+
let corePromise;
|
|
26
|
+
let vendorPromise;
|
|
27
|
+
/**
|
|
28
|
+
* Ensure the Cubism Core global exists, injecting the runtime-route script
|
|
29
|
+
* once when absent. Resolves false when the user has not installed the core
|
|
30
|
+
* (a normal state — the renderer turns it into install guidance).
|
|
31
|
+
*/
|
|
32
|
+
export function ensureCubismCore(probe = {}) {
|
|
33
|
+
if (typeof window !== 'undefined' && window.Live2DCubismCore !== undefined)
|
|
34
|
+
return Promise.resolve(true);
|
|
35
|
+
if (probe.inject !== undefined) {
|
|
36
|
+
return probe.inject(CORE_URL)
|
|
37
|
+
.then(() => typeof window !== 'undefined' && window.Live2DCubismCore !== undefined)
|
|
38
|
+
.catch(() => false);
|
|
39
|
+
}
|
|
40
|
+
corePromise ??= defaultInjector(CORE_URL)
|
|
41
|
+
.then(() => typeof window !== 'undefined' && window.Live2DCubismCore !== undefined)
|
|
42
|
+
.catch(() => false);
|
|
43
|
+
return corePromise;
|
|
44
|
+
}
|
|
45
|
+
/** Ensure the plugin vendor bundle global exists (same caching discipline). */
|
|
46
|
+
export function ensureLive2dVendor(probe = {}) {
|
|
47
|
+
if (typeof window !== 'undefined' && window.__dshPetLive2d !== undefined)
|
|
48
|
+
return Promise.resolve(window.__dshPetLive2d);
|
|
49
|
+
if (probe.inject !== undefined) {
|
|
50
|
+
return probe.inject(VENDOR_URL)
|
|
51
|
+
.then(() => typeof window !== 'undefined' ? window.__dshPetLive2d : undefined)
|
|
52
|
+
.catch(() => undefined);
|
|
53
|
+
}
|
|
54
|
+
vendorPromise ??= defaultInjector(VENDOR_URL)
|
|
55
|
+
.then(() => typeof window !== 'undefined' ? window.__dshPetLive2d : undefined)
|
|
56
|
+
.catch(() => undefined);
|
|
57
|
+
return vendorPromise;
|
|
58
|
+
}
|
|
59
|
+
/** Reset the cached script promises (tests). */
|
|
60
|
+
export function resetLive2dRuntime() {
|
|
61
|
+
corePromise = undefined;
|
|
62
|
+
vendorPromise = undefined;
|
|
63
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live2D vendor bundle entry (pet-center M3) — builds pixi.js plus the
|
|
3
|
+
* untitled-pixi-live2d-engine Cubism stack into lib/live2d-vendor.js, an IIFE
|
|
4
|
+
* exposing 'window.__dshPetLive2d'. The sprite-only client bundle never pays
|
|
5
|
+
* for this stack: the live2d renderer lazy-loads the vendor file through the
|
|
6
|
+
* plugin's own runtime route, after the user-supplied Cubism Core script
|
|
7
|
+
* ('window.Live2DCubismCore') is already present.
|
|
8
|
+
*
|
|
9
|
+
* Redistribution: pixi.js and untitled-pixi-live2d-engine are MIT-licensed
|
|
10
|
+
* and may ship inside this plugin; the proprietary Cubism Core is NEVER
|
|
11
|
+
* bundled (issue #623, milestone M1 §0).
|
|
12
|
+
*/
|
|
13
|
+
export { Application, Point, extensions } from 'pixi.js';
|
|
14
|
+
export { configureCubismSDK, Live2DModel, Live2DPlugin } from 'untitled-pixi-live2d-engine/cubism';
|
|
15
|
+
//# sourceMappingURL=vendor-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vendor-entry.d.ts","sourceRoot":"","sources":["../../../../../src/client/renderers/live2d/vendor-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live2D vendor bundle entry (pet-center M3) — builds pixi.js plus the
|
|
3
|
+
* untitled-pixi-live2d-engine Cubism stack into lib/live2d-vendor.js, an IIFE
|
|
4
|
+
* exposing 'window.__dshPetLive2d'. The sprite-only client bundle never pays
|
|
5
|
+
* for this stack: the live2d renderer lazy-loads the vendor file through the
|
|
6
|
+
* plugin's own runtime route, after the user-supplied Cubism Core script
|
|
7
|
+
* ('window.Live2DCubismCore') is already present.
|
|
8
|
+
*
|
|
9
|
+
* Redistribution: pixi.js and untitled-pixi-live2d-engine are MIT-licensed
|
|
10
|
+
* and may ship inside this plugin; the proprietary Cubism Core is NEVER
|
|
11
|
+
* bundled (issue #623, milestone M1 §0).
|
|
12
|
+
*/
|
|
13
|
+
export { Application, Point, extensions } from 'pixi.js';
|
|
14
|
+
export { configureCubismSDK, Live2DModel, Live2DPlugin } from 'untitled-pixi-live2d-engine/cubism';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live2D renderer (pet-center M3, issue #623) — mounts a Cubism model into
|
|
3
|
+
* the center-owned container through the lazy vendor stack. The mount call
|
|
4
|
+
* itself is synchronous per the renderer contract: the boot (core script →
|
|
5
|
+
* vendor script → pixi → model) continues asynchronously and reports fatal
|
|
6
|
+
* failures through the handle's error sink, so the React bridge can render
|
|
7
|
+
* localized guidance. Disposing mid-boot is race-safe.
|
|
8
|
+
*
|
|
9
|
+
* Interaction model: the center chrome owns the affinity economy (its click
|
|
10
|
+
* handler fires the pet interaction exactly like sprite2d); this renderer's
|
|
11
|
+
* 'tap' affordance only drives the model's hit-area motion feedback. The
|
|
12
|
+
* contract's interact write-back stays available for future standalone
|
|
13
|
+
* mounts and is intentionally not invoked here.
|
|
14
|
+
*
|
|
15
|
+
* Motion mapping: manifests map ActivityPhases to motion GROUP names; every
|
|
16
|
+
* unmapped phase (and any mapped-but-absent group) falls back to the idle
|
|
17
|
+
* group — official sample models only ship Idle/TapBody, so the fallback is
|
|
18
|
+
* mandatory. Groups with multiple motions pick a random entry, and a tap
|
|
19
|
+
* that hits a declared hit area plays the conventional 'TapBody' group,
|
|
20
|
+
* returning to the phase's group when the tap motion finishes.
|
|
21
|
+
* @module @linxin666/dsh-pet/client/renderers/live2d
|
|
22
|
+
*/
|
|
23
|
+
import type { ActivityPhase } from '../../state.ts';
|
|
24
|
+
import { type PetRenderer, type PetRendererHandle } from '../../contracts/renderer.ts';
|
|
25
|
+
/** Renderer config: the client-visible live2d block (fail-closed validated). */
|
|
26
|
+
export interface PetLive2dConfig {
|
|
27
|
+
modelUrl: string;
|
|
28
|
+
scale?: number;
|
|
29
|
+
translate?: {
|
|
30
|
+
x?: number;
|
|
31
|
+
y?: number;
|
|
32
|
+
};
|
|
33
|
+
motions: Partial<Record<ActivityPhase, string>> & {
|
|
34
|
+
idle: string;
|
|
35
|
+
};
|
|
36
|
+
expressions?: Partial<Record<ActivityPhase, string>>;
|
|
37
|
+
hitAreas?: string[];
|
|
38
|
+
}
|
|
39
|
+
/** Fatal mount failure codes the bridge localizes. */
|
|
40
|
+
export type Live2dErrorCode = 'core-missing' | 'vendor-missing' | 'load-failed';
|
|
41
|
+
/** The live2d activation handle: contract dispose plus tap + error sink. */
|
|
42
|
+
export interface Live2dRendererHandle extends PetRendererHandle {
|
|
43
|
+
/** Forward a chrome tap in container coordinates; plays the hit motion. */
|
|
44
|
+
tap(x: number, y: number): void;
|
|
45
|
+
/** Subscribe to fatal mount errors (at most one fires per activation). */
|
|
46
|
+
onError(listener: (code: Live2dErrorCode) => void): void;
|
|
47
|
+
}
|
|
48
|
+
/** Reset module state (tests). */
|
|
49
|
+
export declare function resetLive2dRenderer(): void;
|
|
50
|
+
/** The live2d renderer implementation. */
|
|
51
|
+
export declare const live2dRenderer: PetRenderer<PetLive2dConfig>;
|
|
52
|
+
//# sourceMappingURL=live2d.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live2d.d.ts","sourceRoot":"","sources":["../../../../src/client/renderers/live2d.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,iBAAiB,EACvB,MAAM,6BAA6B,CAAA;AASpC,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAA;IACpD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,sDAAsD;AACtD,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,gBAAgB,GAAG,aAAa,CAAA;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,2EAA2E;IAC3E,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI,CAAA;CACzD;AAeD,kCAAkC;AAClC,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAcD,0CAA0C;AAC1C,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,eAAe,CA+HvD,CAAA"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live2D renderer (pet-center M3, issue #623) — mounts a Cubism model into
|
|
3
|
+
* the center-owned container through the lazy vendor stack. The mount call
|
|
4
|
+
* itself is synchronous per the renderer contract: the boot (core script →
|
|
5
|
+
* vendor script → pixi → model) continues asynchronously and reports fatal
|
|
6
|
+
* failures through the handle's error sink, so the React bridge can render
|
|
7
|
+
* localized guidance. Disposing mid-boot is race-safe.
|
|
8
|
+
*
|
|
9
|
+
* Interaction model: the center chrome owns the affinity economy (its click
|
|
10
|
+
* handler fires the pet interaction exactly like sprite2d); this renderer's
|
|
11
|
+
* 'tap' affordance only drives the model's hit-area motion feedback. The
|
|
12
|
+
* contract's interact write-back stays available for future standalone
|
|
13
|
+
* mounts and is intentionally not invoked here.
|
|
14
|
+
*
|
|
15
|
+
* Motion mapping: manifests map ActivityPhases to motion GROUP names; every
|
|
16
|
+
* unmapped phase (and any mapped-but-absent group) falls back to the idle
|
|
17
|
+
* group — official sample models only ship Idle/TapBody, so the fallback is
|
|
18
|
+
* mandatory. Groups with multiple motions pick a random entry, and a tap
|
|
19
|
+
* that hits a declared hit area plays the conventional 'TapBody' group,
|
|
20
|
+
* returning to the phase's group when the tap motion finishes.
|
|
21
|
+
* @module @linxin666/dsh-pet/client/renderers/live2d
|
|
22
|
+
*/
|
|
23
|
+
import { PET_RENDERER_API_VERSION, } from '../../contracts/renderer.js';
|
|
24
|
+
import { ensureCubismCore, ensureLive2dVendor, } from './live2d/runtime.js';
|
|
25
|
+
/** The de-facto tap-motion group of Cubism sample models. */
|
|
26
|
+
const TAP_GROUP = 'TapBody';
|
|
27
|
+
let vendorConfigured = false;
|
|
28
|
+
/** Configure pixi extensions + the Cubism SDK once per page. */
|
|
29
|
+
function configureOnce(vendor) {
|
|
30
|
+
if (vendorConfigured)
|
|
31
|
+
return;
|
|
32
|
+
vendorConfigured = true;
|
|
33
|
+
vendor.extensions.add(vendor.Live2DPlugin);
|
|
34
|
+
vendor.configureCubismSDK({ memorySizeMB: 32 });
|
|
35
|
+
}
|
|
36
|
+
/** Reset module state (tests). */
|
|
37
|
+
export function resetLive2dRenderer() {
|
|
38
|
+
vendorConfigured = false;
|
|
39
|
+
}
|
|
40
|
+
/** Fail-closed config validation (contract: unknown manifest block in). */
|
|
41
|
+
function validateLive2dConfig(config) {
|
|
42
|
+
if (typeof config !== 'object' || config === null)
|
|
43
|
+
throw new Error('live2d config is not an object');
|
|
44
|
+
const source = config;
|
|
45
|
+
if (typeof source.modelUrl !== 'string' || source.modelUrl === '')
|
|
46
|
+
throw new Error('live2d config modelUrl is required');
|
|
47
|
+
const motions = source.motions;
|
|
48
|
+
if (typeof motions !== 'object' || motions === null || typeof motions.idle !== 'string') {
|
|
49
|
+
throw new Error('live2d config motions.idle is required');
|
|
50
|
+
}
|
|
51
|
+
return config;
|
|
52
|
+
}
|
|
53
|
+
/** The live2d renderer implementation. */
|
|
54
|
+
export const live2dRenderer = {
|
|
55
|
+
id: 'live2d',
|
|
56
|
+
apiVersion: PET_RENDERER_API_VERSION,
|
|
57
|
+
validateConfig: validateLive2dConfig,
|
|
58
|
+
mount(ctx, config) {
|
|
59
|
+
let disposed = false;
|
|
60
|
+
let app;
|
|
61
|
+
let model;
|
|
62
|
+
let errorListener;
|
|
63
|
+
let unsubscribe;
|
|
64
|
+
/** The motion group the current phase maps to (resume target after taps). */
|
|
65
|
+
let phaseGroup = config.motions.idle;
|
|
66
|
+
let tapPlaying = false;
|
|
67
|
+
const playGroup = (group) => {
|
|
68
|
+
if (model === undefined)
|
|
69
|
+
return;
|
|
70
|
+
const groups = model.internalModel.settings.motions ?? {};
|
|
71
|
+
const count = Array.isArray(groups[group]) ? groups[group].length : 0;
|
|
72
|
+
if (count === 0) {
|
|
73
|
+
// A mapped-but-absent group falls back to idle (never blank motion).
|
|
74
|
+
if (group !== config.motions.idle)
|
|
75
|
+
playGroup(config.motions.idle);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const index = count > 1 ? Math.floor(Math.random() * count) : 0;
|
|
79
|
+
void model.motion(group, index);
|
|
80
|
+
};
|
|
81
|
+
const applyPhase = (phase) => {
|
|
82
|
+
phaseGroup = config.motions[phase] ?? config.motions.idle;
|
|
83
|
+
playGroup(phaseGroup);
|
|
84
|
+
const expression = config.expressions?.[phase];
|
|
85
|
+
if (expression !== undefined && model !== undefined)
|
|
86
|
+
void model.expression(expression);
|
|
87
|
+
};
|
|
88
|
+
const boot = async () => {
|
|
89
|
+
if (!await ensureCubismCore()) {
|
|
90
|
+
if (!disposed)
|
|
91
|
+
errorListener?.('core-missing');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const vendor = await ensureLive2dVendor();
|
|
95
|
+
if (vendor === undefined) {
|
|
96
|
+
if (!disposed)
|
|
97
|
+
errorListener?.('vendor-missing');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
configureOnce(vendor);
|
|
101
|
+
const pixiApp = new vendor.Application();
|
|
102
|
+
await pixiApp.init({
|
|
103
|
+
width: Math.max(1, ctx.container.clientWidth || 160),
|
|
104
|
+
height: Math.max(1, ctx.container.clientHeight || 174),
|
|
105
|
+
backgroundAlpha: 0,
|
|
106
|
+
antialias: true,
|
|
107
|
+
autoDensity: true,
|
|
108
|
+
preference: 'webgl',
|
|
109
|
+
});
|
|
110
|
+
if (disposed) {
|
|
111
|
+
pixiApp.destroy(true, { children: true });
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
pixiApp.canvas.style.display = 'block';
|
|
115
|
+
pixiApp.canvas.style.width = '100%';
|
|
116
|
+
pixiApp.canvas.style.height = '100%';
|
|
117
|
+
ctx.container.appendChild(pixiApp.canvas);
|
|
118
|
+
const loaded = await vendor.Live2DModel.from(config.modelUrl, { autoHitTest: false, autoFocus: false });
|
|
119
|
+
if (disposed) {
|
|
120
|
+
pixiApp.destroy(true, { children: true });
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
app = pixiApp;
|
|
124
|
+
model = loaded;
|
|
125
|
+
// Auto-fit the model into the container; the manifest scale multiplies
|
|
126
|
+
// the fit and translate offsets from the center anchor.
|
|
127
|
+
const fit = Math.min(pixiApp.renderer.width / Math.max(1, loaded.width), pixiApp.renderer.height / Math.max(1, loaded.height)) * 0.92;
|
|
128
|
+
loaded.scale.set(fit * (config.scale ?? 1));
|
|
129
|
+
loaded.anchor.set(0.5);
|
|
130
|
+
loaded.position.set(pixiApp.renderer.width / 2 + (config.translate?.x ?? 0), pixiApp.renderer.height / 2 + (config.translate?.y ?? 0));
|
|
131
|
+
pixiApp.stage.addChild(loaded);
|
|
132
|
+
// Resume the phase group once a tap motion finishes playing.
|
|
133
|
+
loaded.on('motionFinish', () => {
|
|
134
|
+
if (tapPlaying) {
|
|
135
|
+
tapPlaying = false;
|
|
136
|
+
playGroup(phaseGroup);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
applyPhase(ctx.phase.get());
|
|
140
|
+
unsubscribe = ctx.phase.subscribe(applyPhase);
|
|
141
|
+
};
|
|
142
|
+
void boot().catch(() => {
|
|
143
|
+
if (!disposed)
|
|
144
|
+
errorListener?.('load-failed');
|
|
145
|
+
});
|
|
146
|
+
return {
|
|
147
|
+
dispose() {
|
|
148
|
+
if (disposed)
|
|
149
|
+
return;
|
|
150
|
+
disposed = true;
|
|
151
|
+
unsubscribe?.();
|
|
152
|
+
model = undefined;
|
|
153
|
+
if (app !== undefined) {
|
|
154
|
+
app.destroy(true, { children: true });
|
|
155
|
+
app = undefined;
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
tap(x, y) {
|
|
159
|
+
const current = model;
|
|
160
|
+
if (disposed || current === undefined)
|
|
161
|
+
return;
|
|
162
|
+
const hits = current.hitTest(x, y);
|
|
163
|
+
const allowed = config.hitAreas;
|
|
164
|
+
const hit = allowed === undefined ? hits.length > 0 : hits.some(name => allowed.includes(name));
|
|
165
|
+
if (!hit)
|
|
166
|
+
return;
|
|
167
|
+
const groups = current.internalModel.settings.motions ?? {};
|
|
168
|
+
const group = groups[TAP_GROUP];
|
|
169
|
+
if (!Array.isArray(group) || group.length === 0)
|
|
170
|
+
return;
|
|
171
|
+
tapPlaying = true;
|
|
172
|
+
const index = group.length > 1 ? Math.floor(Math.random() * group.length) : 0;
|
|
173
|
+
void current.motion(TAP_GROUP, index);
|
|
174
|
+
},
|
|
175
|
+
onError(listener) {
|
|
176
|
+
errorListener = listener;
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer registry — dispatches a manifest's renderer kind to its
|
|
3
|
+
* implementation (pet-center M2 P4, issue #623). Unknown kinds never blank
|
|
4
|
+
* the pet: a fallback card names the problem and reports the kinds this
|
|
5
|
+
* build actually supports.
|
|
6
|
+
* @module @linxin666/dsh-pet/client/renderers/registry
|
|
7
|
+
*/
|
|
8
|
+
import type { PetRenderer, PetRendererContext, PetRendererHandle } from '../../contracts/renderer.ts';
|
|
9
|
+
/** Renderer dispatch table. */
|
|
10
|
+
export declare class RendererRegistry {
|
|
11
|
+
private readonly renderers;
|
|
12
|
+
/** Register one renderer implementation (id wins on re-register). */
|
|
13
|
+
register(renderer: PetRenderer): void;
|
|
14
|
+
/** Whether a renderer kind is available in this build. */
|
|
15
|
+
has(id: string): boolean;
|
|
16
|
+
/** The registered renderer kinds (for diagnostics). */
|
|
17
|
+
kinds(): string[];
|
|
18
|
+
/** Remove every registration (tests; the client index registers once). */
|
|
19
|
+
clear(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Mount a renderer for one activation. An unknown kind renders a clear
|
|
22
|
+
* diagnostic card into the container instead of failing silently.
|
|
23
|
+
*/
|
|
24
|
+
mount(kind: string, ctx: PetRendererContext, config: unknown): PetRendererHandle;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The plugin-wide renderer registry. The client entry registers the
|
|
28
|
+
* built-in renderers at apply time; the renderer switch and the live2d
|
|
29
|
+
* bridge dispatch through this instance.
|
|
30
|
+
*/
|
|
31
|
+
export declare const defaultPetRendererRegistry: RendererRegistry;
|
|
32
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../src/client/renderers/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAErG,+BAA+B;AAC/B,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAEpC;IAED,0DAA0D;IAC1D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvB;IAED,uDAAuD;IACvD,KAAK,IAAI,MAAM,EAAE,CAEhB;IAED,0EAA0E;IAC1E,KAAK,IAAI,IAAI,CAEZ;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,EAAE,OAAO,GAAG,iBAAiB,CAW/E;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,kBAAyB,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer registry — dispatches a manifest's renderer kind to its
|
|
3
|
+
* implementation (pet-center M2 P4, issue #623). Unknown kinds never blank
|
|
4
|
+
* the pet: a fallback card names the problem and reports the kinds this
|
|
5
|
+
* build actually supports.
|
|
6
|
+
* @module @linxin666/dsh-pet/client/renderers/registry
|
|
7
|
+
*/
|
|
8
|
+
/** Renderer dispatch table. */
|
|
9
|
+
export class RendererRegistry {
|
|
10
|
+
renderers = new Map();
|
|
11
|
+
/** Register one renderer implementation (id wins on re-register). */
|
|
12
|
+
register(renderer) {
|
|
13
|
+
this.renderers.set(renderer.id, renderer);
|
|
14
|
+
}
|
|
15
|
+
/** Whether a renderer kind is available in this build. */
|
|
16
|
+
has(id) {
|
|
17
|
+
return this.renderers.has(id);
|
|
18
|
+
}
|
|
19
|
+
/** The registered renderer kinds (for diagnostics). */
|
|
20
|
+
kinds() {
|
|
21
|
+
return [...this.renderers.keys()].sort();
|
|
22
|
+
}
|
|
23
|
+
/** Remove every registration (tests; the client index registers once). */
|
|
24
|
+
clear() {
|
|
25
|
+
this.renderers.clear();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Mount a renderer for one activation. An unknown kind renders a clear
|
|
29
|
+
* diagnostic card into the container instead of failing silently.
|
|
30
|
+
*/
|
|
31
|
+
mount(kind, ctx, config) {
|
|
32
|
+
const renderer = this.renderers.get(kind);
|
|
33
|
+
if (renderer === undefined) {
|
|
34
|
+
const note = document.createElement('div');
|
|
35
|
+
note.dataset.dshPetRendererFallback = kind;
|
|
36
|
+
note.textContent = 'Pet renderer "' + kind + '" is not available in this build (supported: ' + this.kinds().join(', ') + ').';
|
|
37
|
+
ctx.container.appendChild(note);
|
|
38
|
+
ctx.onCleanup(() => note.remove());
|
|
39
|
+
return { dispose: () => note.remove() };
|
|
40
|
+
}
|
|
41
|
+
return renderer.mount(ctx, renderer.validateConfig(config));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The plugin-wide renderer registry. The client entry registers the
|
|
46
|
+
* built-in renderers at apply time; the renderer switch and the live2d
|
|
47
|
+
* bridge dispatch through this instance.
|
|
48
|
+
*/
|
|
49
|
+
export const defaultPetRendererRegistry = new RendererRegistry();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer contract — the seam between the pet center and its renderers
|
|
3
|
+
* (issue #623, milestone M2 P4). Renderers never see the DSH session, the
|
|
4
|
+
* registry, or the network: they receive exactly three capabilities — an
|
|
5
|
+
* asset base URL, the ActivityPhase stream, and the interaction write-back —
|
|
6
|
+
* inside a center-owned container. Every mount is a fresh activation whose
|
|
7
|
+
* cleanups must be idempotent.
|
|
8
|
+
*
|
|
9
|
+
* This contract only serves real consumers: sprite2d (existing) and live2d
|
|
10
|
+
* (M3). Speculative capabilities join only when a renderer actually needs
|
|
11
|
+
* them.
|
|
12
|
+
* @module @linxin666/dsh-pet/contracts/renderer
|
|
13
|
+
*/
|
|
14
|
+
import type { ActivityPhase } from '../state.ts';
|
|
15
|
+
/** Contract version renderers declare against (independent of the manifest). */
|
|
16
|
+
export declare const PET_RENDERER_API_VERSION = "x-org.linxin666.pet-center/v1alpha1";
|
|
17
|
+
/** What the pet center hands a renderer on mount. */
|
|
18
|
+
export interface PetRendererContext {
|
|
19
|
+
/** The selected pet's id. */
|
|
20
|
+
readonly petId: string;
|
|
21
|
+
/** Same-origin URL prefix of this pet's assets ('/pet/<id>'). */
|
|
22
|
+
readonly assetBase: string;
|
|
23
|
+
/** Center-owned mount root; renderers must not attach to document.body. */
|
|
24
|
+
readonly container: HTMLElement;
|
|
25
|
+
/** The ActivityPhase stream (pet-center owned; renderers subscribe). */
|
|
26
|
+
readonly phase: {
|
|
27
|
+
get(): ActivityPhase;
|
|
28
|
+
subscribe(listener: (phase: ActivityPhase) => void): () => void;
|
|
29
|
+
};
|
|
30
|
+
/** The single interaction write-back into the affinity economy. */
|
|
31
|
+
readonly interact: (kind: 'tap') => void;
|
|
32
|
+
/** Register an activation-scoped cleanup; run on dispose, idempotently. */
|
|
33
|
+
onCleanup(fn: () => void): void;
|
|
34
|
+
}
|
|
35
|
+
/** A mounted renderer activation. */
|
|
36
|
+
export interface PetRendererHandle {
|
|
37
|
+
/** Tear the activation down; may be called 0/1/N times. */
|
|
38
|
+
dispose(): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One renderer implementation. validateConfig is fail-closed over the
|
|
42
|
+
* renderer-specific manifest block (schema v2 'sprite2d'/'live2d' blocks).
|
|
43
|
+
*/
|
|
44
|
+
export interface PetRenderer<Config = unknown> {
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly apiVersion: string;
|
|
47
|
+
validateConfig(config: unknown): Config;
|
|
48
|
+
mount(ctx: PetRendererContext, config: Config): PetRendererHandle;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/contracts/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,wCAAwC,CAAA;AAE7E,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAA;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE;QACd,GAAG,IAAI,aAAa,CAAA;QACpB,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;KAChE,CAAA;IACD,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAA;IACxC,2EAA2E;IAC3E,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;CAChC;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,OAAO,IAAI,IAAI,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW,CAAC,MAAM,GAAG,OAAO;IAC3C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAA;IACvC,KAAK,CAAC,GAAG,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAAA;CAClE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer contract — the seam between the pet center and its renderers
|
|
3
|
+
* (issue #623, milestone M2 P4). Renderers never see the DSH session, the
|
|
4
|
+
* registry, or the network: they receive exactly three capabilities — an
|
|
5
|
+
* asset base URL, the ActivityPhase stream, and the interaction write-back —
|
|
6
|
+
* inside a center-owned container. Every mount is a fresh activation whose
|
|
7
|
+
* cleanups must be idempotent.
|
|
8
|
+
*
|
|
9
|
+
* This contract only serves real consumers: sprite2d (existing) and live2d
|
|
10
|
+
* (M3). Speculative capabilities join only when a renderer actually needs
|
|
11
|
+
* them.
|
|
12
|
+
* @module @linxin666/dsh-pet/contracts/renderer
|
|
13
|
+
*/
|
|
14
|
+
/** Contract version renderers declare against (independent of the manifest). */
|
|
15
|
+
export const PET_RENDERER_API_VERSION = 'x-org.linxin666.pet-center/v1alpha1';
|