pixifact 0.1.5 → 0.2.1

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 (75) hide show
  1. package/README.md +13 -13
  2. package/dist/compiler/builtinScenes.d.ts +2 -2
  3. package/dist/compiler/builtinScenes.js +1 -9
  4. package/dist/compiler/compileScenes.js +16 -0
  5. package/dist/compiler/pixiNodeSchema.d.ts +17 -7
  6. package/dist/compiler/pixiNodeSchema.js +219 -0
  7. package/dist/compiler/sceneValidation.js +13 -2
  8. package/dist/compiler/spec.d.ts +5 -1
  9. package/dist/compiler/templateParser.js +18 -10
  10. package/dist/compiler/templateSerializer.js +1 -0
  11. package/dist/compiler/typescriptCompiler.js +53 -8
  12. package/dist/project/index.d.ts +5 -0
  13. package/dist/project/index.js +22 -0
  14. package/dist/runtime/Control.d.ts +18 -0
  15. package/dist/runtime/Control.js +49 -0
  16. package/dist/runtime/GridContainer.d.ts +25 -0
  17. package/dist/runtime/GridContainer.js +115 -0
  18. package/dist/runtime/Group.d.ts +2 -0
  19. package/dist/runtime/Group.js +30 -10
  20. package/dist/runtime/HBoxContainer.d.ts +21 -0
  21. package/dist/runtime/HBoxContainer.js +74 -0
  22. package/dist/runtime/Image.d.ts +47 -0
  23. package/dist/runtime/Image.js +220 -0
  24. package/dist/runtime/NineImage.d.ts +22 -0
  25. package/dist/runtime/NineImage.js +54 -0
  26. package/dist/runtime/Rect.d.ts +48 -0
  27. package/dist/runtime/Rect.js +162 -0
  28. package/dist/runtime/ScrollContainer.d.ts +28 -0
  29. package/dist/runtime/ScrollContainer.js +370 -0
  30. package/dist/runtime/TileImage.d.ts +27 -0
  31. package/dist/runtime/TileImage.js +57 -0
  32. package/dist/runtime/VBoxContainer.d.ts +21 -0
  33. package/dist/runtime/VBoxContainer.js +74 -0
  34. package/dist/runtime/frameLayout.d.ts +11 -0
  35. package/dist/runtime/frameLayout.js +116 -0
  36. package/dist/runtime/frameLayoutAccessors.d.ts +4 -0
  37. package/dist/runtime/frameLayoutAccessors.js +7 -0
  38. package/dist/runtime/index.d.ts +12 -0
  39. package/dist/runtime/index.js +12 -0
  40. package/dist/runtime/stackLayout.d.ts +16 -0
  41. package/dist/runtime/stackLayout.js +59 -0
  42. package/dist/viewport.d.ts +43 -0
  43. package/dist/viewport.js +93 -0
  44. package/package.json +2 -2
  45. package/dist/builtin-scenes/CenterContainer.d.ts +0 -13
  46. package/dist/builtin-scenes/CenterContainer.js +0 -71
  47. package/dist/builtin-scenes/CenterContainer.scene +0 -3
  48. package/dist/builtin-scenes/CenterContainer.ts +0 -77
  49. package/dist/builtin-scenes/Control.d.ts +0 -44
  50. package/dist/builtin-scenes/Control.js +0 -206
  51. package/dist/builtin-scenes/Control.scene +0 -3
  52. package/dist/builtin-scenes/Control.ts +0 -233
  53. package/dist/builtin-scenes/FlexItem.d.ts +0 -45
  54. package/dist/builtin-scenes/FlexItem.js +0 -164
  55. package/dist/builtin-scenes/FlexItem.scene +0 -3
  56. package/dist/builtin-scenes/FlexItem.ts +0 -180
  57. package/dist/builtin-scenes/FlexLayout.d.ts +0 -29
  58. package/dist/builtin-scenes/FlexLayout.js +0 -358
  59. package/dist/builtin-scenes/FlexLayout.scene +0 -3
  60. package/dist/builtin-scenes/FlexLayout.ts +0 -409
  61. package/dist/builtin-scenes/HBoxContainer.d.ts +0 -15
  62. package/dist/builtin-scenes/HBoxContainer.js +0 -70
  63. package/dist/builtin-scenes/HBoxContainer.scene +0 -3
  64. package/dist/builtin-scenes/HBoxContainer.ts +0 -75
  65. package/dist/builtin-scenes/MarginContainer.d.ts +0 -23
  66. package/dist/builtin-scenes/MarginContainer.js +0 -131
  67. package/dist/builtin-scenes/MarginContainer.scene +0 -3
  68. package/dist/builtin-scenes/MarginContainer.ts +0 -139
  69. package/dist/builtin-scenes/VBoxContainer.d.ts +0 -15
  70. package/dist/builtin-scenes/VBoxContainer.js +0 -70
  71. package/dist/builtin-scenes/VBoxContainer.scene +0 -3
  72. package/dist/builtin-scenes/VBoxContainer.ts +0 -75
  73. package/dist/builtin-scenes/controlLayout.d.ts +0 -57
  74. package/dist/builtin-scenes/controlLayout.js +0 -202
  75. package/dist/builtin-scenes/controlLayout.ts +0 -270
package/README.md CHANGED
@@ -1,44 +1,44 @@
1
1
  # Pixifact
2
2
 
3
- Pixifact is a Bun-first framework for AI-editable 2D game UI, HUDs, menus, and lightweight scenes on top of PixiJS v8.
3
+ Pixifact 是基于 PixiJS v8 的 Scene / UI / 轻场景语义层,面向 AI 可直接编辑的 `.scene` 工作流。
4
4
 
5
- Use `pixifact` for project config helpers, the `Group` runtime node, compiler APIs, and generated Scene runtime support.
5
+ `pixifact` 包提供项目配置解析、runtime 节点、compiler API 和生成 Scene 的运行时支持。CLI 和项目脚手架分别由 `pixifact-cli`、`create-pixifact` 提供。
6
6
 
7
- ## Install
7
+ ## 安装
8
8
 
9
9
  ```bash
10
10
  bun add pixifact pixi.js
11
11
  ```
12
12
 
13
- ## Usage
13
+ ## 使用
14
14
 
15
15
  ```ts
16
16
  import { parseSceneTemplate } from 'pixifact/compiler';
17
17
  import { Group } from 'pixifact/runtime';
18
18
  ```
19
19
 
20
- Compiler Scene projects usually also install the CLI:
20
+ Compiler Scene 项目通常还会安装 CLI:
21
21
 
22
22
  ```bash
23
23
  bun add -d pixifact-cli
24
24
  ```
25
25
 
26
- Then validate and compile `.scene` files:
26
+ 然后校验和编译 `.scene` 文件:
27
27
 
28
28
  ```bash
29
- pixifact scene validate --project-root . --all
30
- pixifact compile-scenes --project-root .
29
+ pixifact scene validate --all
30
+ pixifact compile-scenes
31
31
  ```
32
32
 
33
- ## Scene Workflow
33
+ ## Scene 工作流
34
34
 
35
- Pixifact treats project-relative `.scene` files as the source of truth. External agents edit `.scene` source directly, then run validation and compilation.
35
+ Pixifact 把项目相对 `.scene` 文件作为 source of truth。外部 Agent 直接编辑 `.scene` 源文件,然后运行校验和编译。
36
36
 
37
- Generated files such as `.pixifact/generated/**` are build artifacts and should not be edited by hand.
37
+ `.pixifact/generated/**` 等生成文件是构建产物,不要手写修改。
38
38
 
39
- ## Requirements
39
+ ## 环境要求
40
40
 
41
41
  - Bun
42
42
  - PixiJS v8
43
43
 
44
- The desktop editor is distributed separately from the npm runtime package.
44
+ 桌面编辑器不包含在 npm runtime 包中。
@@ -1,12 +1,12 @@
1
1
  import type { SceneTemplateInterface } from './spec.js';
2
2
  export declare const builtinScenePrefix = "pixifact:";
3
- export declare const builtinSceneNames: readonly ["CenterContainer", "Control", "FlexItem", "FlexLayout", "HBoxContainer", "MarginContainer", "VBoxContainer"];
3
+ export declare const builtinSceneNames: readonly [];
4
4
  export type BuiltinSceneName = typeof builtinSceneNames[number];
5
5
  export type BuiltinSceneScriptSources = Record<BuiltinSceneName, string>;
6
6
  export declare function isBuiltinSceneName(value: string): value is BuiltinSceneName;
7
7
  export declare function builtinSceneAssetId(name: string): string;
8
8
  export declare function isBuiltinSceneAssetId(value: string): boolean;
9
- export declare function builtinSceneNameFromAssetId(assetId: string): "CenterContainer" | "Control" | "FlexItem" | "FlexLayout" | "HBoxContainer" | "MarginContainer" | "VBoxContainer";
9
+ export declare function builtinSceneNameFromAssetId(assetId: string): never;
10
10
  export declare function builtinSceneAssetIds(): string[];
11
11
  export declare function builtinSceneInterface(assetId: string, scriptSources: BuiltinSceneScriptSources): SceneTemplateInterface;
12
12
  export declare function builtinSceneInterfaces(scriptSources: BuiltinSceneScriptSources): {
@@ -1,14 +1,6 @@
1
1
  import { extractSceneScriptInterfaces } from './scriptInterfaceExtractor.js';
2
2
  export const builtinScenePrefix = 'pixifact:';
3
- export const builtinSceneNames = [
4
- 'CenterContainer',
5
- 'Control',
6
- 'FlexItem',
7
- 'FlexLayout',
8
- 'HBoxContainer',
9
- 'MarginContainer',
10
- 'VBoxContainer',
11
- ];
3
+ export const builtinSceneNames = [];
12
4
  const builtinSceneNameSet = new Set(builtinSceneNames);
13
5
  export function isBuiltinSceneName(value) {
14
6
  return builtinSceneNameSet.has(value);
@@ -8,6 +8,7 @@ import { extractSceneScriptInterfaces } from './scriptInterfaceExtractor.js';
8
8
  import { findMissingScenePartReferences } from './scenePartValidation.js';
9
9
  import { parseSceneTemplate } from './templateParser.js';
10
10
  import { compileSceneTemplateToTs } from './typescriptCompiler.js';
11
+ import { parsePixifactProjectConfig, pixifactProjectConfigFileName, } from '../project/index.js';
11
12
  export class CompileSceneError extends Error {
12
13
  scene;
13
14
  source;
@@ -23,6 +24,7 @@ export async function compileScenes(options) {
23
24
  ? options.projectRoot
24
25
  : fileURLToPath(options.projectRoot);
25
26
  const generatedDir = path.resolve(projectRoot, options.generatedDir ?? '.pixifact/generated');
27
+ const projectConfig = await readProjectConfig(projectRoot);
26
28
  const projectScenePaths = await collectSceneAssetIds(projectRoot, options.sourceRoots);
27
29
  const sceneRecords = [
28
30
  ...projectScenePaths.map((scenePath) => ({ scenePath, kind: 'project' })),
@@ -74,6 +76,7 @@ export async function compileScenes(options) {
74
76
  const generatedFileDir = path.dirname(generatedFile);
75
77
  const code = compileSceneTemplateToTs(template, {
76
78
  registrationPath: scenePath,
79
+ defaultRootSize: rootDefaultSizeForScene(projectConfig, scenePath),
77
80
  scriptImport: {
78
81
  exportName: template.name,
79
82
  localName: sceneClassAlias(scenePath),
@@ -98,6 +101,19 @@ export async function compileScenes(options) {
98
101
  ...projectRegistryImports,
99
102
  ].join('\n')}\n`);
100
103
  }
104
+ async function readProjectConfig(projectRoot) {
105
+ const configPath = path.join(projectRoot, pixifactProjectConfigFileName);
106
+ if (!await exists(configPath)) {
107
+ return undefined;
108
+ }
109
+ return parsePixifactProjectConfig(JSON.parse(await readFile(configPath, 'utf8')));
110
+ }
111
+ function rootDefaultSizeForScene(config, scenePath) {
112
+ if (!config || !Object.values(config.scenes).includes(scenePath)) {
113
+ return undefined;
114
+ }
115
+ return config.resolution;
116
+ }
101
117
  function sceneIsReferencedByProjectScenes(scenePath, projectScenePaths, templates) {
102
118
  if (!isBuiltinSceneAssetId(scenePath)) {
103
119
  return false;
@@ -1,7 +1,7 @@
1
1
  import type { SceneTemplatePrimitiveType, SceneTemplateValue } from './spec.js';
2
- export type PixiSceneNodeType = Extract<SceneTemplatePrimitiveType, 'Container' | 'Sprite' | 'NineSliceSprite' | 'TilingSprite' | 'Text' | 'BitmapText' | 'HTMLText' | 'Graphics'>;
2
+ export type PixiSceneNodeType = Extract<SceneTemplatePrimitiveType, 'Container' | 'Sprite' | 'NineSliceSprite' | 'TilingSprite' | 'Text' | 'BitmapText' | 'HTMLText' | 'Graphics' | 'Rect' | 'Image' | 'NineImage' | 'TileImage' | 'GridContainer' | 'HBoxContainer' | 'ScrollContainer' | 'VBoxContainer'>;
3
3
  export type PixiSceneFieldType = 'string' | 'number' | 'boolean' | 'color' | 'enum';
4
- export type PixiScenePropGroup = 'transform' | 'display' | 'sprite' | 'nineSlice' | 'tiling' | 'text' | 'graphics';
4
+ export type PixiScenePropGroup = 'transform' | 'display' | 'sprite' | 'nineSlice' | 'tiling' | 'text' | 'graphics' | 'stack' | 'props';
5
5
  export interface PixiSceneFieldSchema {
6
6
  key: string;
7
7
  type: PixiSceneFieldType;
@@ -14,17 +14,27 @@ export interface PixiSceneNodeSchema {
14
14
  groups: Partial<Record<PixiScenePropGroup, readonly string[]>>;
15
15
  }
16
16
  export declare const pixiSceneTransformProps: readonly ["x", "y", "width", "height", "scaleX", "scaleY", "rotation", "pivotX", "pivotY", "skewX", "skewY"];
17
+ export declare const pixiSceneLayoutProps: readonly ["left", "right", "top", "bottom", "horizontal", "vertical"];
17
18
  export declare const pixiSceneDisplayProps: readonly ["alpha", "visible", "zIndex", "eventMode", "cursor", "label"];
18
19
  export declare const pixiSceneSpriteProps: readonly ["texture", "anchorX", "anchorY", "tint"];
20
+ export declare const pixiSceneImageProps: readonly ["texture", "fit", "anchorX", "anchorY", "tint"];
21
+ export declare const pixiSceneNineImageProps: readonly ["texture", "leftWidth", "rightWidth", "topHeight", "bottomHeight", "anchorX", "anchorY", "tint"];
22
+ export declare const pixiSceneTileImageProps: readonly ["texture", "tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation", "anchorX", "anchorY", "tint"];
19
23
  export declare const pixiSceneNineSliceProps: readonly ["leftWidth", "rightWidth", "topHeight", "bottomHeight"];
20
24
  export declare const pixiSceneTilingProps: readonly ["tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation"];
21
25
  export declare const pixiSceneTextProps: readonly ["text", "fontSize", "fontFamily", "fontWeight", "fill"];
22
26
  export declare const pixiSceneGraphicsProps: readonly ["shape", "radius", "fill", "fillAlpha", "strokeColor", "strokeWidth", "strokeAlpha"];
27
+ export declare const pixiSceneRectProps: readonly ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth", "radius"];
28
+ export declare const pixiSceneStackHBoxProps: readonly ["gap", "alignY", "justify"];
29
+ export declare const pixiSceneGridProps: readonly ["columns", "gapX", "gapY", "alignX", "alignY"];
30
+ export declare const pixiSceneStackVBoxProps: readonly ["gap", "alignX", "justify"];
31
+ export declare const pixiSceneStackProps: readonly ["columns", "gap", "gapX", "gapY", "alignX", "alignY", "justify"];
32
+ export declare const pixiSceneScrollProps: readonly ["direction", "scrollX", "scrollY"];
23
33
  export declare const pixiSceneTextStyleProps: readonly ["fontSize", "fontFamily", "fontWeight", "fill"];
24
- export declare const pixiSceneSpriteLikeProps: readonly ["texture", "anchorX", "anchorY", "tint", "leftWidth", "rightWidth", "topHeight", "bottomHeight", "tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation"];
25
- export declare const pixiSceneKnownProps: readonly ["x", "y", "width", "height", "scaleX", "scaleY", "rotation", "pivotX", "pivotY", "skewX", "skewY", "alpha", "visible", "zIndex", "eventMode", "cursor", "label", "texture", "anchorX", "anchorY", "tint", "leftWidth", "rightWidth", "topHeight", "bottomHeight", "tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation", "text", "fontSize", "fontFamily", "fontWeight", "fill", "shape", "radius", "fill", "fillAlpha", "strokeColor", "strokeWidth", "strokeAlpha"];
26
- export declare const pixiSceneAddableNodeTypes: readonly ["Container", "Sprite", "NineSliceSprite", "TilingSprite", "Text", "BitmapText", "HTMLText", "Graphics"];
27
- export declare const pixiSceneNodePropGroupOrder: readonly ["sprite", "nineSlice", "tiling", "text", "graphics"];
34
+ export declare const pixiSceneSpriteLikeProps: readonly ["texture", "anchorX", "anchorY", "tint", "texture", "fit", "anchorX", "anchorY", "tint", "texture", "leftWidth", "rightWidth", "topHeight", "bottomHeight", "anchorX", "anchorY", "tint", "texture", "tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation", "anchorX", "anchorY", "tint", "leftWidth", "rightWidth", "topHeight", "bottomHeight", "tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation"];
35
+ export declare const pixiSceneKnownProps: readonly ["x", "y", "width", "height", "scaleX", "scaleY", "rotation", "pivotX", "pivotY", "skewX", "skewY", "left", "right", "top", "bottom", "horizontal", "vertical", "alpha", "visible", "zIndex", "eventMode", "cursor", "label", "texture", "anchorX", "anchorY", "tint", "texture", "fit", "anchorX", "anchorY", "tint", "texture", "leftWidth", "rightWidth", "topHeight", "bottomHeight", "anchorX", "anchorY", "tint", "texture", "tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation", "anchorX", "anchorY", "tint", "leftWidth", "rightWidth", "topHeight", "bottomHeight", "tilePositionX", "tilePositionY", "tileScaleX", "tileScaleY", "tileRotation", "text", "fontSize", "fontFamily", "fontWeight", "fill", "shape", "radius", "fill", "fillAlpha", "strokeColor", "strokeWidth", "strokeAlpha", "fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth", "radius", "columns", "gap", "gapX", "gapY", "alignX", "alignY", "justify", "direction", "scrollX", "scrollY"];
36
+ export declare const pixiSceneAddableNodeTypes: readonly ["GridContainer", "HBoxContainer", "ScrollContainer", "VBoxContainer", "Container", "Sprite", "NineSliceSprite", "TilingSprite", "Text", "BitmapText", "HTMLText", "Graphics", "Rect", "Image", "NineImage", "TileImage"];
37
+ export declare const pixiSceneNodePropGroupOrder: readonly ["stack", "sprite", "nineSlice", "tiling", "text", "graphics", "props"];
28
38
  export declare function pixiSceneNodeSchema(type: PixiSceneNodeType): PixiSceneNodeSchema;
29
39
  export declare function isPixiSceneNodeType(type: SceneTemplatePrimitiveType): type is PixiSceneNodeType;
30
40
  export declare function pixiSceneNodeDefaults(type: PixiSceneNodeType): {
@@ -33,7 +43,7 @@ export declare function pixiSceneNodeDefaults(type: PixiSceneNodeType): {
33
43
  export declare function pixiSceneNodeAcceptsChildren(type: SceneTemplatePrimitiveType): boolean;
34
44
  export declare function pixiSceneNodePropKeys(type: PixiSceneNodeType): string[];
35
45
  export declare function pixiSceneNodePropGroups(type: PixiSceneNodeType): {
36
- group: "text" | "sprite" | "nineSlice" | "tiling" | "graphics";
46
+ group: "text" | "sprite" | "nineSlice" | "tiling" | "graphics" | "stack" | "props";
37
47
  fields: readonly string[];
38
48
  }[];
39
49
  export declare function pixiSceneFieldSchema(key: string): PixiSceneFieldSchema | undefined;
@@ -11,6 +11,14 @@ export const pixiSceneTransformProps = [
11
11
  'skewX',
12
12
  'skewY',
13
13
  ];
14
+ export const pixiSceneLayoutProps = [
15
+ 'left',
16
+ 'right',
17
+ 'top',
18
+ 'bottom',
19
+ 'horizontal',
20
+ 'vertical',
21
+ ];
14
22
  export const pixiSceneDisplayProps = [
15
23
  'alpha',
16
24
  'visible',
@@ -25,6 +33,34 @@ export const pixiSceneSpriteProps = [
25
33
  'anchorY',
26
34
  'tint',
27
35
  ];
36
+ export const pixiSceneImageProps = [
37
+ 'texture',
38
+ 'fit',
39
+ 'anchorX',
40
+ 'anchorY',
41
+ 'tint',
42
+ ];
43
+ export const pixiSceneNineImageProps = [
44
+ 'texture',
45
+ 'leftWidth',
46
+ 'rightWidth',
47
+ 'topHeight',
48
+ 'bottomHeight',
49
+ 'anchorX',
50
+ 'anchorY',
51
+ 'tint',
52
+ ];
53
+ export const pixiSceneTileImageProps = [
54
+ 'texture',
55
+ 'tilePositionX',
56
+ 'tilePositionY',
57
+ 'tileScaleX',
58
+ 'tileScaleY',
59
+ 'tileRotation',
60
+ 'anchorX',
61
+ 'anchorY',
62
+ 'tint',
63
+ ];
28
64
  export const pixiSceneNineSliceProps = [
29
65
  'leftWidth',
30
66
  'rightWidth',
@@ -54,6 +90,45 @@ export const pixiSceneGraphicsProps = [
54
90
  'strokeWidth',
55
91
  'strokeAlpha',
56
92
  ];
93
+ export const pixiSceneRectProps = [
94
+ 'fillColor',
95
+ 'fillAlpha',
96
+ 'strokeColor',
97
+ 'strokeAlpha',
98
+ 'strokeWidth',
99
+ 'radius',
100
+ ];
101
+ export const pixiSceneStackHBoxProps = [
102
+ 'gap',
103
+ 'alignY',
104
+ 'justify',
105
+ ];
106
+ export const pixiSceneGridProps = [
107
+ 'columns',
108
+ 'gapX',
109
+ 'gapY',
110
+ 'alignX',
111
+ 'alignY',
112
+ ];
113
+ export const pixiSceneStackVBoxProps = [
114
+ 'gap',
115
+ 'alignX',
116
+ 'justify',
117
+ ];
118
+ export const pixiSceneStackProps = [
119
+ 'columns',
120
+ 'gap',
121
+ 'gapX',
122
+ 'gapY',
123
+ 'alignX',
124
+ 'alignY',
125
+ 'justify',
126
+ ];
127
+ export const pixiSceneScrollProps = [
128
+ 'direction',
129
+ 'scrollX',
130
+ 'scrollY',
131
+ ];
57
132
  export const pixiSceneTextStyleProps = [
58
133
  'fontSize',
59
134
  'fontFamily',
@@ -62,17 +137,28 @@ export const pixiSceneTextStyleProps = [
62
137
  ];
63
138
  export const pixiSceneSpriteLikeProps = [
64
139
  ...pixiSceneSpriteProps,
140
+ ...pixiSceneImageProps,
141
+ ...pixiSceneNineImageProps,
142
+ ...pixiSceneTileImageProps,
65
143
  ...pixiSceneNineSliceProps,
66
144
  ...pixiSceneTilingProps,
67
145
  ];
68
146
  export const pixiSceneKnownProps = [
69
147
  ...pixiSceneTransformProps,
148
+ ...pixiSceneLayoutProps,
70
149
  ...pixiSceneDisplayProps,
71
150
  ...pixiSceneSpriteLikeProps,
72
151
  ...pixiSceneTextProps,
73
152
  ...pixiSceneGraphicsProps,
153
+ ...pixiSceneRectProps,
154
+ ...pixiSceneStackProps,
155
+ ...pixiSceneScrollProps,
74
156
  ];
75
157
  export const pixiSceneAddableNodeTypes = [
158
+ 'GridContainer',
159
+ 'HBoxContainer',
160
+ 'ScrollContainer',
161
+ 'VBoxContainer',
76
162
  'Container',
77
163
  'Sprite',
78
164
  'NineSliceSprite',
@@ -81,13 +167,19 @@ export const pixiSceneAddableNodeTypes = [
81
167
  'BitmapText',
82
168
  'HTMLText',
83
169
  'Graphics',
170
+ 'Rect',
171
+ 'Image',
172
+ 'NineImage',
173
+ 'TileImage',
84
174
  ];
85
175
  export const pixiSceneNodePropGroupOrder = [
176
+ 'stack',
86
177
  'sprite',
87
178
  'nineSlice',
88
179
  'tiling',
89
180
  'text',
90
181
  'graphics',
182
+ 'props',
91
183
  ];
92
184
  const pixiSceneFieldSchemas = {
93
185
  x: { key: 'x', type: 'number' },
@@ -101,6 +193,12 @@ const pixiSceneFieldSchemas = {
101
193
  pivotY: { key: 'pivotY', type: 'number' },
102
194
  skewX: { key: 'skewX', type: 'number' },
103
195
  skewY: { key: 'skewY', type: 'number' },
196
+ left: { key: 'left', type: 'number' },
197
+ right: { key: 'right', type: 'number' },
198
+ top: { key: 'top', type: 'number' },
199
+ bottom: { key: 'bottom', type: 'number' },
200
+ horizontal: { key: 'horizontal', type: 'number' },
201
+ vertical: { key: 'vertical', type: 'number' },
104
202
  alpha: { key: 'alpha', type: 'number' },
105
203
  visible: { key: 'visible', type: 'boolean' },
106
204
  zIndex: { key: 'zIndex', type: 'number' },
@@ -108,6 +206,7 @@ const pixiSceneFieldSchemas = {
108
206
  cursor: { key: 'cursor', type: 'enum', options: ['default', 'pointer', 'text', 'grab', 'grabbing'] },
109
207
  label: { key: 'label', type: 'string' },
110
208
  texture: { key: 'texture', type: 'string' },
209
+ fit: { key: 'fit', type: 'enum', options: ['stretch', 'contain', 'cover', 'none'] },
111
210
  anchorX: { key: 'anchorX', type: 'number' },
112
211
  anchorY: { key: 'anchorY', type: 'number' },
113
212
  tint: { key: 'tint', type: 'color' },
@@ -125,12 +224,23 @@ const pixiSceneFieldSchemas = {
125
224
  fontFamily: { key: 'fontFamily', type: 'string' },
126
225
  fontWeight: { key: 'fontWeight', type: 'enum', options: [400, 500, 600, 700, '400', '500', '600', '700', 'bold'] },
127
226
  fill: { key: 'fill', type: 'color' },
227
+ fillColor: { key: 'fillColor', type: 'color' },
128
228
  shape: { key: 'shape', type: 'enum', options: ['roundRect', 'rect'] },
129
229
  radius: { key: 'radius', type: 'number' },
130
230
  fillAlpha: { key: 'fillAlpha', type: 'number' },
131
231
  strokeColor: { key: 'strokeColor', type: 'color' },
132
232
  strokeWidth: { key: 'strokeWidth', type: 'number' },
133
233
  strokeAlpha: { key: 'strokeAlpha', type: 'number' },
234
+ columns: { key: 'columns', type: 'number' },
235
+ gap: { key: 'gap', type: 'number' },
236
+ gapX: { key: 'gapX', type: 'number' },
237
+ gapY: { key: 'gapY', type: 'number' },
238
+ alignX: { key: 'alignX', type: 'enum', options: ['start', 'center', 'end'] },
239
+ alignY: { key: 'alignY', type: 'enum', options: ['start', 'center', 'end'] },
240
+ justify: { key: 'justify', type: 'enum', options: ['start', 'center', 'end', 'space-between'] },
241
+ direction: { key: 'direction', type: 'enum', options: ['vertical', 'horizontal', 'both'] },
242
+ scrollX: { key: 'scrollX', type: 'number' },
243
+ scrollY: { key: 'scrollY', type: 'number' },
134
244
  };
135
245
  const pixiSceneNodeSchemas = {
136
246
  Container: {
@@ -239,6 +349,115 @@ const pixiSceneNodeSchemas = {
239
349
  graphics: pixiSceneGraphicsProps,
240
350
  },
241
351
  },
352
+ Rect: {
353
+ type: 'Rect',
354
+ acceptsChildren: false,
355
+ defaults: {
356
+ width: 100,
357
+ height: 60,
358
+ fillColor: 0xffffff,
359
+ fillAlpha: 1,
360
+ strokeColor: 0x000000,
361
+ strokeAlpha: 1,
362
+ strokeWidth: 0,
363
+ radius: 0,
364
+ },
365
+ groups: {
366
+ props: pixiSceneRectProps,
367
+ },
368
+ },
369
+ Image: {
370
+ type: 'Image',
371
+ acceptsChildren: false,
372
+ defaults: {
373
+ width: 96,
374
+ height: 96,
375
+ fit: 'stretch',
376
+ },
377
+ groups: {
378
+ props: pixiSceneImageProps,
379
+ },
380
+ },
381
+ NineImage: {
382
+ type: 'NineImage',
383
+ acceptsChildren: false,
384
+ defaults: {
385
+ width: 160,
386
+ height: 80,
387
+ leftWidth: 10,
388
+ rightWidth: 10,
389
+ topHeight: 10,
390
+ bottomHeight: 10,
391
+ },
392
+ groups: {
393
+ props: pixiSceneNineImageProps,
394
+ },
395
+ },
396
+ TileImage: {
397
+ type: 'TileImage',
398
+ acceptsChildren: false,
399
+ defaults: {
400
+ width: 160,
401
+ height: 96,
402
+ tileScaleX: 1,
403
+ tileScaleY: 1,
404
+ },
405
+ groups: {
406
+ props: pixiSceneTileImageProps,
407
+ },
408
+ },
409
+ GridContainer: {
410
+ type: 'GridContainer',
411
+ acceptsChildren: true,
412
+ defaults: {
413
+ width: 240,
414
+ height: 160,
415
+ columns: 2,
416
+ gapX: 8,
417
+ gapY: 8,
418
+ },
419
+ groups: {
420
+ stack: pixiSceneGridProps,
421
+ },
422
+ },
423
+ HBoxContainer: {
424
+ type: 'HBoxContainer',
425
+ acceptsChildren: true,
426
+ defaults: {
427
+ width: 240,
428
+ height: 64,
429
+ gap: 8,
430
+ },
431
+ groups: {
432
+ stack: pixiSceneStackHBoxProps,
433
+ },
434
+ },
435
+ ScrollContainer: {
436
+ type: 'ScrollContainer',
437
+ acceptsChildren: true,
438
+ defaults: {
439
+ width: 240,
440
+ height: 160,
441
+ direction: 'vertical',
442
+ scrollX: 0,
443
+ scrollY: 0,
444
+ },
445
+ groups: {
446
+ props: pixiSceneScrollProps,
447
+ },
448
+ },
449
+ VBoxContainer: {
450
+ type: 'VBoxContainer',
451
+ acceptsChildren: true,
452
+ defaults: {
453
+ width: 160,
454
+ height: 240,
455
+ gap: 8,
456
+ },
457
+ groups: {
458
+ stack: pixiSceneStackVBoxProps,
459
+ },
460
+ },
242
461
  };
243
462
  export function pixiSceneNodeSchema(type) {
244
463
  return pixiSceneNodeSchemas[type];
@@ -1,4 +1,4 @@
1
- import { isPixiSceneNodeType, pixiSceneFieldSchema, pixiSceneNodePropKeys, pixiSceneTransformProps, pixiSceneDisplayProps, } from './pixiNodeSchema.js';
1
+ import { isPixiSceneNodeType, pixiSceneFieldSchema, pixiSceneLayoutProps, pixiSceneNodeAcceptsChildren, pixiSceneNodePropKeys, pixiSceneTransformProps, pixiSceneDisplayProps, } from './pixiNodeSchema.js';
2
2
  import { parseSceneTemplate } from './templateParser.js';
3
3
  import { serializeSceneTemplate } from './templateSerializer.js';
4
4
  export function createSceneRevision(source) {
@@ -139,12 +139,22 @@ function validatePixiNode(node, path, existingAssets) {
139
139
  prop: 'type',
140
140
  expected: 'supported compiler Pixi node type',
141
141
  actual: node.type,
142
- hint: 'Use Container, Sprite, NineSliceSprite, TilingSprite, Text, BitmapText, HTMLText, or Graphics.',
142
+ hint: 'Use GridContainer, HBoxContainer, ScrollContainer, VBoxContainer, Container, Sprite, NineSliceSprite, TilingSprite, Text, BitmapText, HTMLText, Graphics, Rect, Image, NineImage, or TileImage.',
143
143
  }];
144
144
  }
145
145
  const diagnostics = [];
146
+ if (!pixiSceneNodeAcceptsChildren(node.type) && node.children.length > 0) {
147
+ diagnostics.push({
148
+ path,
149
+ prop: 'children',
150
+ expected: 'no child nodes',
151
+ actual: `${node.children.length} ${node.children.length === 1 ? 'child node' : 'child nodes'}`,
152
+ hint: `${node.type} is a leaf drawing node. Wrap it and sibling content in a Container or Group Scene.`,
153
+ });
154
+ }
146
155
  const knownProps = new Set([
147
156
  ...pixiSceneTransformProps,
157
+ ...pixiSceneLayoutProps,
148
158
  ...pixiSceneDisplayProps,
149
159
  ...pixiSceneNodePropKeys(node.type),
150
160
  ]);
@@ -209,6 +219,7 @@ function validateSceneInstanceNode(node, path, context) {
209
219
  const diagnostics = [];
210
220
  const allowedProps = new Set([
211
221
  ...pixiSceneTransformProps,
222
+ ...pixiSceneLayoutProps,
212
223
  ...pixiSceneDisplayProps,
213
224
  ...Object.keys(sceneInterface.props),
214
225
  ]);
@@ -1,4 +1,4 @@
1
- export type SceneTemplatePrimitiveType = 'Container' | 'Sprite' | 'Text' | 'Graphics' | 'BitmapText' | 'HTMLText' | 'Mesh' | 'NineSliceSprite' | 'TilingSprite' | 'DOMContainer';
1
+ export type SceneTemplatePrimitiveType = 'Container' | 'Sprite' | 'Text' | 'Graphics' | 'Rect' | 'Image' | 'NineImage' | 'TileImage' | 'BitmapText' | 'HTMLText' | 'Mesh' | 'NineSliceSprite' | 'TilingSprite' | 'DOMContainer' | 'GridContainer' | 'HBoxContainer' | 'ScrollContainer' | 'VBoxContainer';
2
2
  export type SceneTemplateScalarValue = string | number | boolean;
3
3
  export type SceneTemplateStructValue = Record<string, SceneTemplateScalarValue>;
4
4
  export type SceneTemplateValue = SceneTemplateScalarValue | SceneTemplateStructValue;
@@ -66,6 +66,10 @@ export interface CompileSceneTemplateOptions {
66
66
  functionName?: string;
67
67
  actionsParameter?: string;
68
68
  registrationPath?: string;
69
+ defaultRootSize?: {
70
+ width: number;
71
+ height: number;
72
+ };
69
73
  scriptImport?: SceneTemplateScriptImport;
70
74
  sceneImports?: SceneTemplateScriptImport[];
71
75
  sceneClassAliases?: Record<string, string>;
@@ -5,12 +5,20 @@ const pixiTypes = new Set([
5
5
  'Sprite',
6
6
  'Text',
7
7
  'Graphics',
8
+ 'Rect',
9
+ 'Image',
10
+ 'NineImage',
11
+ 'TileImage',
8
12
  'BitmapText',
9
13
  'HTMLText',
10
14
  'Mesh',
11
15
  'NineSliceSprite',
12
16
  'TilingSprite',
13
17
  'DOMContainer',
18
+ 'GridContainer',
19
+ 'HBoxContainer',
20
+ 'ScrollContainer',
21
+ 'VBoxContainer',
14
22
  ]);
15
23
  export function parseSceneTemplate(source) {
16
24
  const root = new TemplateXmlParser(source).parse();
@@ -52,16 +60,6 @@ function parseTemplateNode(element) {
52
60
  };
53
61
  return node;
54
62
  }
55
- if (pixiTypes.has(element.name)) {
56
- const node = {
57
- kind: 'pixi',
58
- type: element.name,
59
- props: parseProps(element, ['id', 'slot']),
60
- children: element.children.map(parseTemplateNode),
61
- ...(element.attributes.id ? { id: element.attributes.id } : {}),
62
- };
63
- return node;
64
- }
65
63
  if (element.attributes.scene !== undefined || isBuiltinSceneName(element.name)) {
66
64
  const slots = {};
67
65
  for (const child of element.children) {
@@ -80,6 +78,16 @@ function parseTemplateNode(element) {
80
78
  };
81
79
  return node;
82
80
  }
81
+ if (pixiTypes.has(element.name)) {
82
+ const node = {
83
+ kind: 'pixi',
84
+ type: element.name,
85
+ props: parseProps(element, ['id', 'slot']),
86
+ children: element.children.map(parseTemplateNode),
87
+ ...(element.attributes.id ? { id: element.attributes.id } : {}),
88
+ };
89
+ return node;
90
+ }
83
91
  throw new Error(`Unsupported template tag <${element.name}>. Add scene="..." or use a built-in Scene name.`);
84
92
  }
85
93
  function parseProps(element, omitted, shouldOmit = () => false) {
@@ -4,6 +4,7 @@ const colorPropNames = new Set([
4
4
  'borderColor',
5
5
  'disabledColor',
6
6
  'fill',
7
+ 'fillColor',
7
8
  'highlightedColor',
8
9
  'normalColor',
9
10
  'pressedColor',