pixifact 0.2.2 → 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 (48) hide show
  1. package/README.md +14 -0
  2. package/dist/compiler/compileScenes.d.ts +1 -0
  3. package/dist/compiler/compileScenes.js +8 -9
  4. package/dist/compiler/index.d.ts +0 -4
  5. package/dist/compiler/index.js +0 -4
  6. package/dist/compiler/pixiNodeSchema.d.ts +2 -2
  7. package/dist/compiler/pixiNodeSchema.js +10 -0
  8. package/dist/compiler/sceneValidation.js +1 -1
  9. package/dist/compiler/scriptInterfaceExtractor.js +6 -0
  10. package/dist/compiler/spec.d.ts +2 -2
  11. package/dist/compiler/templateParser.js +1 -0
  12. package/dist/compiler/typescriptCompiler.js +54 -45
  13. package/dist/compiler-node/vite.d.ts +2 -1
  14. package/dist/compiler-node/vite.js +29 -2
  15. package/dist/platform/wechat/adapter.d.ts +316 -0
  16. package/dist/platform/wechat/adapter.js +26 -0
  17. package/dist/platform/wechat/application.d.ts +32 -0
  18. package/dist/platform/wechat/application.js +79 -0
  19. package/dist/platform/wechat/fetch.d.ts +1 -0
  20. package/dist/platform/wechat/fetch.js +145 -0
  21. package/dist/platform/wechat/index.d.ts +4 -0
  22. package/dist/platform/wechat/index.js +3 -0
  23. package/dist/platform/wechat/input.d.ts +12 -0
  24. package/dist/platform/wechat/input.js +93 -0
  25. package/dist/platform/wechat/lifecycle.d.ts +14 -0
  26. package/dist/platform/wechat/lifecycle.js +42 -0
  27. package/dist/platform/wechat/runtime.d.ts +49 -0
  28. package/dist/platform/wechat/runtime.js +189 -0
  29. package/dist/platform/wechat/subpackage.d.ts +1 -0
  30. package/dist/platform/wechat/subpackage.js +27 -0
  31. package/dist/platform/wechat/types.d.ts +105 -0
  32. package/dist/platform/wechat/types.js +3 -0
  33. package/dist/project/index.d.ts +23 -0
  34. package/dist/project/index.js +69 -0
  35. package/dist/{compiler → scene}/decorators.d.ts +1 -1
  36. package/dist/scene/index.d.ts +5 -0
  37. package/dist/scene/index.js +5 -0
  38. package/dist/scene/sceneAssetRuntime.d.ts +11 -0
  39. package/dist/scene/sceneAssetRuntime.js +43 -0
  40. package/dist/{compiler → scene}/sceneRuntime.d.ts +7 -0
  41. package/dist/scene/sceneRuntime.js +85 -0
  42. package/package.json +11 -1
  43. package/dist/compiler/sceneRuntime.js +0 -22
  44. /package/dist/{compiler → scene}/decorators.js +0 -0
  45. /package/dist/{compiler → scene}/eventRuntime.d.ts +0 -0
  46. /package/dist/{compiler → scene}/eventRuntime.js +0 -0
  47. /package/dist/{compiler → scene}/slotRuntime.d.ts +0 -0
  48. /package/dist/{compiler → scene}/slotRuntime.js +0 -0
@@ -0,0 +1,93 @@
1
+ import { WechatPointerEvent } from './runtime.js';
2
+ import { wechatApi } from './types.js';
3
+ function pointerState(touch) {
4
+ return {
5
+ force: touch.force ?? 0.5,
6
+ pointerId: (touch.identifier ?? 0) + 1,
7
+ x: touch.clientX ?? touch.x ?? touch.pageX ?? 0,
8
+ y: touch.clientY ?? touch.y ?? touch.pageY ?? 0,
9
+ };
10
+ }
11
+ function changedTouches(event) {
12
+ return event.changedTouches?.length ? event.changedTouches : event.touches ?? [];
13
+ }
14
+ export function bindWechatPointerEvents(canvas, sink) {
15
+ const wx = wechatApi();
16
+ const activePointers = new Map();
17
+ let disposed = false;
18
+ let primaryPointerId = null;
19
+ const dispatch = (type, state, eventTarget, buttons) => {
20
+ const event = new WechatPointerEvent(type, {
21
+ button: 0,
22
+ buttons,
23
+ clientX: state.x,
24
+ clientY: state.y,
25
+ height: 1,
26
+ isPrimary: state.pointerId === primaryPointerId,
27
+ pointerId: state.pointerId,
28
+ pointerType: 'touch',
29
+ pressure: buttons ? state.force : 0,
30
+ width: 1,
31
+ });
32
+ event.target = eventTarget;
33
+ event.srcElement = canvas;
34
+ event.isTrusted = true;
35
+ sink[type](event);
36
+ };
37
+ const handleStart = (event) => {
38
+ for (const touch of changedTouches(event)) {
39
+ const state = pointerState(touch);
40
+ primaryPointerId ??= state.pointerId;
41
+ activePointers.set(state.pointerId, state);
42
+ dispatch('pointerdown', state, canvas, 1);
43
+ }
44
+ };
45
+ const handleMove = (event) => {
46
+ for (const touch of changedTouches(event)) {
47
+ const state = pointerState(touch);
48
+ activePointers.set(state.pointerId, state);
49
+ dispatch('pointermove', state, canvas, 1);
50
+ }
51
+ };
52
+ const release = (event, cancelled) => {
53
+ const touches = event.changedTouches?.length
54
+ ? event.changedTouches.map(pointerState)
55
+ : [...activePointers.values()];
56
+ for (const state of touches) {
57
+ dispatch('pointerup', state, cancelled ? globalThis : canvas, 0);
58
+ activePointers.delete(state.pointerId);
59
+ }
60
+ if (primaryPointerId !== null && !activePointers.has(primaryPointerId)) {
61
+ primaryPointerId = activePointers.keys().next().value ?? null;
62
+ }
63
+ };
64
+ const handleEnd = (event) => release(event, false);
65
+ const handleCancel = (event) => release(event, true);
66
+ wx.onTouchStart(handleStart);
67
+ wx.onTouchMove(handleMove);
68
+ wx.onTouchEnd(handleEnd);
69
+ wx.onTouchCancel(handleCancel);
70
+ return {
71
+ get activePointerCount() {
72
+ return activePointers.size;
73
+ },
74
+ cancelAll() {
75
+ for (const state of activePointers.values()) {
76
+ dispatch('pointerup', state, globalThis, 0);
77
+ }
78
+ activePointers.clear();
79
+ primaryPointerId = null;
80
+ },
81
+ dispose() {
82
+ if (disposed) {
83
+ return;
84
+ }
85
+ disposed = true;
86
+ this.cancelAll();
87
+ wx.offTouchStart?.(handleStart);
88
+ wx.offTouchMove?.(handleMove);
89
+ wx.offTouchEnd?.(handleEnd);
90
+ wx.offTouchCancel?.(handleCancel);
91
+ },
92
+ };
93
+ }
@@ -0,0 +1,14 @@
1
+ interface LifecycleTarget {
2
+ readonly started?: boolean;
3
+ start(): void;
4
+ stop(): void;
5
+ }
6
+ export interface WechatLifecycleBinding {
7
+ dispose(): void;
8
+ readonly hidden: boolean;
9
+ }
10
+ export declare function bindWechatLifecycle(target: LifecycleTarget, options?: {
11
+ onHide?(): void;
12
+ onShow?(): void;
13
+ }): WechatLifecycleBinding;
14
+ export {};
@@ -0,0 +1,42 @@
1
+ import { wechatApi } from './types.js';
2
+ export function bindWechatLifecycle(target, options = {}) {
3
+ const wx = wechatApi();
4
+ let disposed = false;
5
+ let hidden = false;
6
+ let resumeOnShow = false;
7
+ const handleHide = () => {
8
+ if (disposed || hidden) {
9
+ return;
10
+ }
11
+ hidden = true;
12
+ resumeOnShow = target.started ?? true;
13
+ options.onHide?.();
14
+ target.stop();
15
+ };
16
+ const handleShow = () => {
17
+ if (disposed || !hidden) {
18
+ return;
19
+ }
20
+ hidden = false;
21
+ if (resumeOnShow) {
22
+ target.start();
23
+ }
24
+ options.onShow?.();
25
+ };
26
+ wx.onHide(handleHide);
27
+ wx.onShow(handleShow);
28
+ return {
29
+ dispose() {
30
+ if (disposed) {
31
+ return;
32
+ }
33
+ disposed = true;
34
+ target.stop();
35
+ wx.offHide?.(handleHide);
36
+ wx.offShow?.(handleShow);
37
+ },
38
+ get hidden() {
39
+ return hidden;
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,49 @@
1
+ import { type WechatCanvas } from './types.js';
2
+ export interface WechatRuntime {
3
+ canvas: WechatCanvas;
4
+ context: WebGLRenderingContext | WebGL2RenderingContext;
5
+ height: number;
6
+ resolution: number;
7
+ userAgent: string;
8
+ webGLVersion: 1 | 2;
9
+ width: number;
10
+ }
11
+ export declare class WechatPointerEvent {
12
+ altKey: boolean;
13
+ bubbles: boolean;
14
+ button: number;
15
+ buttons: number;
16
+ cancelBubble: boolean;
17
+ cancelable: boolean;
18
+ clientX: number;
19
+ clientY: number;
20
+ ctrlKey: boolean;
21
+ defaultPrevented: boolean;
22
+ height: number;
23
+ isPrimary: boolean;
24
+ isTrusted: boolean;
25
+ metaKey: boolean;
26
+ movementX: number;
27
+ movementY: number;
28
+ pageX: number;
29
+ pageY: number;
30
+ pointerId: number;
31
+ pointerType: string;
32
+ pressure: number;
33
+ relatedTarget: EventTarget | null;
34
+ shiftKey: boolean;
35
+ srcElement: EventTarget | null;
36
+ tangentialPressure: number;
37
+ target: EventTarget | null;
38
+ tiltX: number;
39
+ tiltY: number;
40
+ twist: number;
41
+ type: string;
42
+ width: number;
43
+ constructor(type: string, init?: PointerEventInit);
44
+ composedPath(): EventTarget[];
45
+ preventDefault(): void;
46
+ stopImmediatePropagation(): void;
47
+ stopPropagation(): void;
48
+ }
49
+ export declare function createWechatRuntime(): WechatRuntime;
@@ -0,0 +1,189 @@
1
+ import { wechatApi } from './types.js';
2
+ export class WechatPointerEvent {
3
+ altKey = false;
4
+ bubbles = true;
5
+ button = 0;
6
+ buttons = 0;
7
+ cancelBubble = false;
8
+ cancelable = true;
9
+ clientX = 0;
10
+ clientY = 0;
11
+ ctrlKey = false;
12
+ defaultPrevented = false;
13
+ height = 1;
14
+ isPrimary = false;
15
+ isTrusted = false;
16
+ metaKey = false;
17
+ movementX = 0;
18
+ movementY = 0;
19
+ pageX = 0;
20
+ pageY = 0;
21
+ pointerId = 0;
22
+ pointerType = '';
23
+ pressure = 0;
24
+ relatedTarget = null;
25
+ shiftKey = false;
26
+ srcElement = null;
27
+ tangentialPressure = 0;
28
+ target = null;
29
+ tiltX = 0;
30
+ tiltY = 0;
31
+ twist = 0;
32
+ type;
33
+ width = 1;
34
+ constructor(type, init = {}) {
35
+ this.type = type;
36
+ Object.assign(this, init);
37
+ this.pageX = this.clientX;
38
+ this.pageY = this.clientY;
39
+ }
40
+ composedPath() {
41
+ return this.target ? [this.target] : [];
42
+ }
43
+ preventDefault() {
44
+ this.defaultPrevented = true;
45
+ }
46
+ stopImmediatePropagation() {
47
+ this.cancelBubble = true;
48
+ }
49
+ stopPropagation() {
50
+ this.cancelBubble = true;
51
+ }
52
+ }
53
+ function installEventTarget(target, nativeTypes = new Set()) {
54
+ const listeners = new Map();
55
+ const nativeAdd = target.addEventListener?.bind(target);
56
+ const nativeRemove = target.removeEventListener?.bind(target);
57
+ target.addEventListener = (type, listener, options) => {
58
+ const typeListeners = listeners.get(type) ?? new Set();
59
+ typeListeners.add(listener);
60
+ listeners.set(type, typeListeners);
61
+ if (nativeTypes.has(type)) {
62
+ nativeAdd?.(type, listener, options);
63
+ }
64
+ };
65
+ target.removeEventListener = (type, listener, options) => {
66
+ listeners.get(type)?.delete(listener);
67
+ if (nativeTypes.has(type)) {
68
+ nativeRemove?.(type, listener, options);
69
+ }
70
+ };
71
+ target.dispatchEvent = (event) => {
72
+ const mutableEvent = event;
73
+ mutableEvent.target ??= target;
74
+ mutableEvent.srcElement ??= mutableEvent.target;
75
+ for (const listener of listeners.get(event.type) ?? []) {
76
+ if (typeof listener === 'function') {
77
+ listener.call(target, event);
78
+ }
79
+ else {
80
+ listener.handleEvent(event);
81
+ }
82
+ if (mutableEvent.cancelBubble) {
83
+ break;
84
+ }
85
+ }
86
+ return !event.defaultPrevented;
87
+ };
88
+ }
89
+ function installCanvasSurface(canvas, width, height) {
90
+ installEventTarget(canvas, new Set(['webglcontextlost', 'webglcontextrestored']));
91
+ canvas.style ??= {};
92
+ Object.defineProperty(canvas, 'isConnected', { configurable: true, value: true });
93
+ Object.defineProperty(canvas, 'getBoundingClientRect', {
94
+ configurable: true,
95
+ value: () => ({
96
+ bottom: height,
97
+ height,
98
+ left: 0,
99
+ right: width,
100
+ top: 0,
101
+ width,
102
+ x: 0,
103
+ y: 0,
104
+ }),
105
+ });
106
+ }
107
+ function createDocumentElement(tagName) {
108
+ const wx = wechatApi();
109
+ if (tagName.toLowerCase() === 'canvas') {
110
+ const canvas = wx.createOffscreenCanvas?.({ type: '2d', width: 1, height: 1 }) ?? wx.createCanvas();
111
+ canvas.width = 1;
112
+ canvas.height = 1;
113
+ return canvas;
114
+ }
115
+ if (tagName.toLowerCase() === 'video') {
116
+ return { canPlayType: () => '' };
117
+ }
118
+ return {};
119
+ }
120
+ function installGlobals(canvas, userAgent) {
121
+ const globals = globalThis;
122
+ const mutableGlobals = globals;
123
+ installEventTarget(mutableGlobals);
124
+ const documentTarget = (globals.document ?? {});
125
+ installEventTarget(documentTarget);
126
+ documentTarget.createElement ??= createDocumentElement;
127
+ if (!globals.document) {
128
+ Object.defineProperty(globals, 'document', { configurable: true, value: documentTarget });
129
+ }
130
+ if (!globals.PointerEvent) {
131
+ Object.defineProperty(globals, 'PointerEvent', { configurable: true, value: WechatPointerEvent });
132
+ }
133
+ if (!globals.navigator) {
134
+ Object.defineProperty(globals, 'navigator', {
135
+ configurable: true,
136
+ value: { gpu: null, userAgent },
137
+ });
138
+ }
139
+ if (!globals.performance) {
140
+ Object.defineProperty(globals, 'performance', {
141
+ configurable: true,
142
+ value: { now: () => Date.now() },
143
+ });
144
+ }
145
+ globals.requestAnimationFrame ??= canvas.requestAnimationFrame
146
+ ? canvas.requestAnimationFrame.bind(canvas)
147
+ : (callback) => setTimeout(() => callback(performance.now()), 16);
148
+ globals.cancelAnimationFrame ??= canvas.cancelAnimationFrame
149
+ ? canvas.cancelAnimationFrame.bind(canvas)
150
+ : (requestId) => clearTimeout(requestId);
151
+ }
152
+ function createContext(canvas) {
153
+ const attributes = {
154
+ alpha: false,
155
+ antialias: true,
156
+ powerPreference: 'high-performance',
157
+ premultipliedAlpha: true,
158
+ preserveDrawingBuffer: false,
159
+ stencil: true,
160
+ };
161
+ const webGL2 = canvas.getContext('webgl2', attributes);
162
+ if (webGL2) {
163
+ return { context: webGL2, webGLVersion: 2 };
164
+ }
165
+ const webGL1 = canvas.getContext('webgl', attributes);
166
+ if (webGL1) {
167
+ return { context: webGL1, webGLVersion: 1 };
168
+ }
169
+ throw new Error('The current WeChat Mini Game runtime does not provide WebGL.');
170
+ }
171
+ export function createWechatRuntime() {
172
+ const wx = wechatApi();
173
+ const canvas = wx.createCanvas();
174
+ const info = {
175
+ ...(wx.getSystemInfoSync?.() ?? {}),
176
+ ...(wx.getDeviceInfo?.() ?? {}),
177
+ ...(wx.getWindowInfo?.() ?? {}),
178
+ };
179
+ const width = Math.max(1, Math.round(Number(info.windowWidth ?? info.screenWidth)));
180
+ const height = Math.max(1, Math.round(Number(info.windowHeight ?? info.screenHeight)));
181
+ const resolution = Math.min(2, Math.max(1, Number(info.pixelRatio)));
182
+ const userAgent = ['WeChatMiniGame', info.platform, info.system, info.model]
183
+ .filter(Boolean)
184
+ .join('/');
185
+ installCanvasSurface(canvas, width, height);
186
+ installGlobals(canvas, userAgent);
187
+ const { context, webGLVersion } = createContext(canvas);
188
+ return { canvas, context, height, resolution, userAgent, webGLVersion, width };
189
+ }
@@ -0,0 +1 @@
1
+ export declare function loadWechatSubpackage(name: string): Promise<void>;
@@ -0,0 +1,27 @@
1
+ import { wechatApi } from './types.js';
2
+ const loaded = new Set();
3
+ const loading = new Map();
4
+ export function loadWechatSubpackage(name) {
5
+ if (loaded.has(name)) {
6
+ return Promise.resolve();
7
+ }
8
+ const existing = loading.get(name);
9
+ if (existing) {
10
+ return existing;
11
+ }
12
+ const pending = new Promise((resolve, reject) => {
13
+ wechatApi().loadSubpackage({
14
+ name,
15
+ fail: (error) => reject(new Error(`Failed to load WeChat subpackage ${name}: ${error.errMsg}`)),
16
+ success: resolve,
17
+ });
18
+ }).then(() => {
19
+ loaded.add(name);
20
+ loading.delete(name);
21
+ }, (error) => {
22
+ loading.delete(name);
23
+ throw error;
24
+ });
25
+ loading.set(name, pending);
26
+ return pending;
27
+ }
@@ -0,0 +1,105 @@
1
+ export interface WechatCanvas {
2
+ width: number;
3
+ height: number;
4
+ isConnected?: boolean;
5
+ style?: Record<string, string>;
6
+ getContext(contextId: string, options?: Record<string, unknown>): unknown;
7
+ getBoundingClientRect?(): {
8
+ bottom: number;
9
+ height: number;
10
+ left: number;
11
+ right: number;
12
+ top: number;
13
+ width: number;
14
+ x: number;
15
+ y: number;
16
+ };
17
+ requestAnimationFrame?(callback: FrameRequestCallback): number;
18
+ cancelAnimationFrame?(requestId: number): void;
19
+ addEventListener?(type: string, listener: EventListenerOrEventListenerObject, options?: unknown): void;
20
+ removeEventListener?(type: string, listener: EventListenerOrEventListenerObject, options?: unknown): void;
21
+ dispatchEvent?(event: Event): boolean;
22
+ }
23
+ export interface WechatImage {
24
+ width: number;
25
+ height: number;
26
+ complete?: boolean;
27
+ crossOrigin?: string | null;
28
+ src: string;
29
+ onload: (() => void) | null;
30
+ onerror: ((error: unknown) => void) | null;
31
+ }
32
+ export interface WechatTouch {
33
+ clientX?: number;
34
+ clientY?: number;
35
+ force?: number;
36
+ identifier?: number;
37
+ pageX?: number;
38
+ pageY?: number;
39
+ x?: number;
40
+ y?: number;
41
+ }
42
+ export interface WechatTouchEvent {
43
+ changedTouches?: WechatTouch[];
44
+ touches?: WechatTouch[];
45
+ }
46
+ export interface WechatMiniGameApi {
47
+ createCanvas(): WechatCanvas;
48
+ createImage(): WechatImage;
49
+ createOffscreenCanvas?(options: {
50
+ type: '2d' | 'webgl';
51
+ width: number;
52
+ height: number;
53
+ }): WechatCanvas;
54
+ getDeviceInfo?(): Record<string, unknown>;
55
+ getFileSystemManager(): {
56
+ readFile(options: {
57
+ filePath: string;
58
+ fail(error: {
59
+ errMsg: string;
60
+ }): void;
61
+ success(result: {
62
+ data: ArrayBuffer | string;
63
+ }): void;
64
+ }): void;
65
+ };
66
+ getSystemInfoSync?(): Record<string, unknown>;
67
+ getWindowInfo?(): Record<string, unknown>;
68
+ loadSubpackage(options: {
69
+ name: string;
70
+ fail(error: {
71
+ errMsg: string;
72
+ }): void;
73
+ success(): void;
74
+ }): {
75
+ onProgressUpdate(callback: (progress: {
76
+ progress: number;
77
+ }) => void): void;
78
+ };
79
+ request(options: {
80
+ url: string;
81
+ method: 'GET';
82
+ responseType: 'arraybuffer';
83
+ fail(error: {
84
+ errMsg: string;
85
+ }): void;
86
+ success(result: {
87
+ data: ArrayBuffer | string | Record<string, unknown>;
88
+ header: Record<string, string>;
89
+ statusCode: number;
90
+ }): void;
91
+ }): void;
92
+ onHide(callback: () => void): void;
93
+ offHide?(callback: () => void): void;
94
+ onShow(callback: () => void): void;
95
+ offShow?(callback: () => void): void;
96
+ onTouchStart(callback: (event: WechatTouchEvent) => void): void;
97
+ offTouchStart?(callback: (event: WechatTouchEvent) => void): void;
98
+ onTouchMove(callback: (event: WechatTouchEvent) => void): void;
99
+ offTouchMove?(callback: (event: WechatTouchEvent) => void): void;
100
+ onTouchEnd(callback: (event: WechatTouchEvent) => void): void;
101
+ offTouchEnd?(callback: (event: WechatTouchEvent) => void): void;
102
+ onTouchCancel(callback: (event: WechatTouchEvent) => void): void;
103
+ offTouchCancel?(callback: (event: WechatTouchEvent) => void): void;
104
+ }
105
+ export declare function wechatApi(): WechatMiniGameApi;
@@ -0,0 +1,3 @@
1
+ export function wechatApi() {
2
+ return globalThis.wx;
3
+ }
@@ -10,12 +10,33 @@ export interface PixifactProjectResolution {
10
10
  width: number;
11
11
  height: number;
12
12
  }
13
+ export interface PixifactProjectResourcePack {
14
+ root: string;
15
+ }
16
+ export type PixifactWechatResourcePack = {
17
+ delivery: 'subpackage';
18
+ root: string;
19
+ } | {
20
+ delivery: 'remote';
21
+ baseUrl: string;
22
+ };
23
+ export interface PixifactWechatTargetConfig {
24
+ entry: string;
25
+ configDir: string;
26
+ outDir: string;
27
+ resourcePacks: Record<string, PixifactWechatResourcePack>;
28
+ }
29
+ export interface PixifactProjectTargets {
30
+ wechat?: PixifactWechatTargetConfig;
31
+ }
13
32
  export interface PixifactProjectConfig {
14
33
  version: 1;
15
34
  name: string;
16
35
  resolution: PixifactProjectResolution;
17
36
  viewport: PixifactProjectViewport;
18
37
  scenes: Record<string, string>;
38
+ resourcePacks?: Record<string, PixifactProjectResourcePack>;
39
+ targets?: PixifactProjectTargets;
19
40
  run?: PixifactProjectRunConfig;
20
41
  }
21
42
  export type PixifactProjectViewport = PixifactViewportConfig;
@@ -24,6 +45,8 @@ export interface PixifactProjectSummary {
24
45
  resolution: PixifactProjectResolution;
25
46
  viewport: PixifactProjectViewport;
26
47
  scenes: Record<string, string>;
48
+ resourcePacks?: Record<string, PixifactProjectResourcePack>;
49
+ targets?: PixifactProjectTargets;
27
50
  run?: PixifactProjectRunConfig;
28
51
  }
29
52
  export declare const defaultPixifactProjectResolution: PixifactProjectResolution;
@@ -49,6 +49,13 @@ function normalizeRunCwd(value) {
49
49
  }
50
50
  return normalizeProjectPath(input, 'run.cwd');
51
51
  }
52
+ function normalizeProjectChildPath(value, name) {
53
+ const input = normalizeProjectPath(value, name);
54
+ if (input === '.') {
55
+ throw new Error(`${name} must not be projectRoot.`);
56
+ }
57
+ return input;
58
+ }
52
59
  function parseScenes(value) {
53
60
  const scenes = assertRecord(value, 'scenes');
54
61
  return Object.fromEntries(Object.entries(scenes).map(([key, scenePath]) => [
@@ -97,17 +104,77 @@ function parseRun(value) {
97
104
  ...(run.url === undefined ? {} : { url: assertString(run.url, 'run.url') }),
98
105
  };
99
106
  }
107
+ function parseResourcePacks(value) {
108
+ if (value === undefined) {
109
+ return undefined;
110
+ }
111
+ const packs = assertRecord(value, 'resourcePacks');
112
+ return Object.fromEntries(Object.entries(packs).map(([name, packValue]) => {
113
+ const pack = assertRecord(packValue, `resourcePacks.${name}`);
114
+ return [assertString(name, 'resource pack name'), {
115
+ root: normalizeProjectChildPath(pack.root, `resourcePacks.${name}.root`),
116
+ }];
117
+ }));
118
+ }
119
+ function parseWechatResourcePacks(value) {
120
+ const packs = assertRecord(value, 'targets.wechat.resourcePacks');
121
+ return Object.fromEntries(Object.entries(packs).map(([name, packValue]) => {
122
+ const pack = assertRecord(packValue, `targets.wechat.resourcePacks.${name}`);
123
+ const delivery = assertString(pack.delivery, `targets.wechat.resourcePacks.${name}.delivery`);
124
+ if (delivery === 'subpackage') {
125
+ return [name, {
126
+ delivery,
127
+ root: normalizeProjectChildPath(pack.root, `targets.wechat.resourcePacks.${name}.root`),
128
+ }];
129
+ }
130
+ if (delivery === 'remote') {
131
+ return [name, {
132
+ delivery,
133
+ baseUrl: assertString(pack.baseUrl, `targets.wechat.resourcePacks.${name}.baseUrl`).replace(/\/+$/, ''),
134
+ }];
135
+ }
136
+ throw new Error(`targets.wechat.resourcePacks.${name}.delivery must be subpackage or remote.`);
137
+ }));
138
+ }
139
+ function parseTargets(value) {
140
+ if (value === undefined) {
141
+ return undefined;
142
+ }
143
+ const targets = assertRecord(value, 'targets');
144
+ if (targets.wechat === undefined) {
145
+ return {};
146
+ }
147
+ const wechat = assertRecord(targets.wechat, 'targets.wechat');
148
+ const outDir = normalizeProjectChildPath(wechat.outDir, 'targets.wechat.outDir');
149
+ return {
150
+ wechat: {
151
+ entry: normalizeProjectPath(wechat.entry, 'targets.wechat.entry'),
152
+ configDir: normalizeProjectPath(wechat.configDir, 'targets.wechat.configDir'),
153
+ outDir,
154
+ resourcePacks: parseWechatResourcePacks(wechat.resourcePacks),
155
+ },
156
+ };
157
+ }
100
158
  export function parsePixifactProjectConfig(value) {
101
159
  const config = assertRecord(value, 'pixifact.project.json');
102
160
  if (config.version !== 1) {
103
161
  throw new Error('pixifact.project.json version must be 1.');
104
162
  }
163
+ const resourcePacks = parseResourcePacks(config.resourcePacks);
164
+ const targets = parseTargets(config.targets);
165
+ for (const name of Object.keys(targets?.wechat?.resourcePacks ?? {})) {
166
+ if (!resourcePacks?.[name]) {
167
+ throw new Error(`targets.wechat.resourcePacks.${name} must reference resourcePacks.${name}.`);
168
+ }
169
+ }
105
170
  return {
106
171
  version: 1,
107
172
  name: assertString(config.name, 'name'),
108
173
  resolution: parseResolution(config.resolution),
109
174
  viewport: parseViewport(config.viewport),
110
175
  scenes: parseScenes(config.scenes),
176
+ ...(resourcePacks === undefined ? {} : { resourcePacks }),
177
+ ...(targets === undefined ? {} : { targets }),
111
178
  run: parseRun(config.run),
112
179
  };
113
180
  }
@@ -117,6 +184,8 @@ export function summarizePixifactProjectConfig(config) {
117
184
  resolution: config.resolution,
118
185
  viewport: config.viewport,
119
186
  scenes: config.scenes,
187
+ ...(config.resourcePacks === undefined ? {} : { resourcePacks: config.resourcePacks }),
188
+ ...(config.targets === undefined ? {} : { targets: config.targets }),
120
189
  ...(config.run === undefined ? {} : { run: config.run }),
121
190
  };
122
191
  }
@@ -1,4 +1,4 @@
1
- import type { SceneClassDecorator, SceneEventDecoratorOptions, SceneMemberDecorator, ScenePartDecoratorOptions, ScenePropDecoratorOptions, SceneSlotDecoratorOptions } from './spec.js';
1
+ import type { SceneClassDecorator, SceneEventDecoratorOptions, SceneMemberDecorator, ScenePartDecoratorOptions, ScenePropDecoratorOptions, SceneSlotDecoratorOptions } from '../compiler/spec.js';
2
2
  export declare function scene(): SceneClassDecorator;
3
3
  export declare function prop(options: ScenePropDecoratorOptions): SceneMemberDecorator;
4
4
  export declare function event(_options?: SceneEventDecoratorOptions): SceneMemberDecorator;
@@ -0,0 +1,5 @@
1
+ export * from './decorators.js';
2
+ export * from './eventRuntime.js';
3
+ export * from './sceneAssetRuntime.js';
4
+ export * from './sceneRuntime.js';
5
+ export * from './slotRuntime.js';
@@ -0,0 +1,5 @@
1
+ export * from './decorators.js';
2
+ export * from './eventRuntime.js';
3
+ export * from './sceneAssetRuntime.js';
4
+ export * from './sceneRuntime.js';
5
+ export * from './slotRuntime.js';