@datamoc/mw_games 0.37.0 → 0.39.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.
- package/CHANGELOG.md +79 -0
- package/README.md +26 -0
- package/api-surface.json +650 -2
- package/dist/assets/SvgParts.d.ts +31 -0
- package/dist/assets/SvgParts.d.ts.map +1 -0
- package/dist/assets/SvgParts.js +54 -0
- package/dist/assets/SvgParts.js.map +1 -0
- package/dist/assets/SvgSource.d.ts +3 -0
- package/dist/assets/SvgSource.d.ts.map +1 -0
- package/dist/assets/SvgSource.js +22 -0
- package/dist/assets/SvgSource.js.map +1 -0
- package/dist/assets/index.d.ts +2 -0
- package/dist/assets/index.d.ts.map +1 -1
- package/dist/assets/index.js +1 -0
- package/dist/assets/index.js.map +1 -1
- package/dist/assets/svg.d.ts.map +1 -1
- package/dist/assets/svg.js +9 -5
- package/dist/assets/svg.js.map +1 -1
- package/dist/mw_games.global.js +110 -110
- package/dist/mwl/presentation.d.ts +70 -0
- package/dist/mwl/presentation.d.ts.map +1 -0
- package/dist/mwl/presentation.js +419 -0
- package/dist/mwl/presentation.js.map +1 -0
- package/dist/physics/PhysicsWorld.d.ts +49 -17
- package/dist/physics/PhysicsWorld.d.ts.map +1 -1
- package/dist/physics/PhysicsWorld.js +297 -59
- package/dist/physics/PhysicsWorld.js.map +1 -1
- package/dist/physics/XpbdWorld.d.ts +1 -1
- package/dist/physics/XpbdWorld.js +1 -1
- package/dist/physics/cloth/index.d.ts +98 -0
- package/dist/physics/cloth/index.d.ts.map +1 -0
- package/dist/physics/cloth/index.js +207 -0
- package/dist/physics/cloth/index.js.map +1 -0
- package/dist/physics/index.d.ts +4 -0
- package/dist/physics/index.d.ts.map +1 -1
- package/dist/physics/index.js +2 -0
- package/dist/physics/index.js.map +1 -1
- package/dist/physics/spring/index.d.ts +90 -0
- package/dist/physics/spring/index.d.ts.map +1 -0
- package/dist/physics/spring/index.js +97 -0
- package/dist/physics/spring/index.js.map +1 -0
- package/dist/skeleton/index.d.ts +94 -13
- package/dist/skeleton/index.d.ts.map +1 -1
- package/dist/skeleton/index.js +192 -73
- package/dist/skeleton/index.js.map +1 -1
- package/dist/two-d/presentation/MwlPresentation.d.ts +110 -0
- package/dist/two-d/presentation/MwlPresentation.d.ts.map +1 -0
- package/dist/two-d/presentation/MwlPresentation.js +755 -0
- package/dist/two-d/presentation/MwlPresentation.js.map +1 -0
- package/dist/two-d/presentation/index.d.ts +3 -0
- package/dist/two-d/presentation/index.d.ts.map +1 -0
- package/dist/two-d/presentation/index.js +2 -0
- package/dist/two-d/presentation/index.js.map +1 -0
- package/dist/two-d/render/ClothSprite.d.ts +83 -0
- package/dist/two-d/render/ClothSprite.d.ts.map +1 -0
- package/dist/two-d/render/ClothSprite.js +105 -0
- package/dist/two-d/render/ClothSprite.js.map +1 -0
- package/dist/two-d/render/HazeLayer.d.ts +112 -0
- package/dist/two-d/render/HazeLayer.d.ts.map +1 -0
- package/dist/two-d/render/HazeLayer.js +185 -0
- package/dist/two-d/render/HazeLayer.js.map +1 -0
- package/dist/two-d/render/NeonGlow.d.ts +100 -0
- package/dist/two-d/render/NeonGlow.d.ts.map +1 -0
- package/dist/two-d/render/NeonGlow.js +183 -0
- package/dist/two-d/render/NeonGlow.js.map +1 -0
- package/dist/two-d/render/SkeletalSprite.d.ts +5 -2
- package/dist/two-d/render/SkeletalSprite.d.ts.map +1 -1
- package/dist/two-d/render/SkeletalSprite.js +27 -3
- package/dist/two-d/render/SkeletalSprite.js.map +1 -1
- package/dist/two-d/render/SpringSprite.d.ts +40 -0
- package/dist/two-d/render/SpringSprite.d.ts.map +1 -0
- package/dist/two-d/render/SpringSprite.js +39 -0
- package/dist/two-d/render/SpringSprite.js.map +1 -0
- package/dist/two-d/render/SpriteDeform.d.ts +156 -0
- package/dist/two-d/render/SpriteDeform.d.ts.map +1 -0
- package/dist/two-d/render/SpriteDeform.js +278 -0
- package/dist/two-d/render/SpriteDeform.js.map +1 -0
- package/dist/two-d/render/SvgSkeleton.d.ts +54 -0
- package/dist/two-d/render/SvgSkeleton.d.ts.map +1 -0
- package/dist/two-d/render/SvgSkeleton.js +112 -0
- package/dist/two-d/render/SvgSkeleton.js.map +1 -0
- package/dist/two-d/render/index.d.ts +12 -0
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +6 -0
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/two-d/ui/Bar.d.ts +3 -1
- package/dist/two-d/ui/Bar.d.ts.map +1 -1
- package/dist/two-d/ui/Bar.js +5 -0
- package/dist/two-d/ui/Bar.js.map +1 -1
- package/dist/two-d/ui/Button.d.ts +12 -0
- package/dist/two-d/ui/Button.d.ts.map +1 -1
- package/dist/two-d/ui/Button.js +16 -4
- package/dist/two-d/ui/Button.js.map +1 -1
- package/dist/two-d/ui/Window.d.ts +10 -0
- package/dist/two-d/ui/Window.d.ts.map +1 -1
- package/dist/two-d/ui/Window.js +17 -6
- package/dist/two-d/ui/Window.js.map +1 -1
- package/dist/two-d/ui/index.d.ts +2 -0
- package/dist/two-d/ui/index.d.ts.map +1 -1
- package/dist/two-d/ui/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +24 -7
- package/sbom.cdx.json +6 -58
- package/tools/asset-report.d.mts +37 -0
- package/tools/asset-report.mjs +157 -0
- package/tools/compile-resources.d.mts +2 -0
- package/tools/compile-resources.mjs +23 -2
- package/tools/emit-page.d.mts +2 -0
- package/tools/emit-page.mjs +11 -1
- package/tools/verify-scenarios.d.mts +15 -0
- package/tools/verify-scenarios.mjs +129 -0
- package/tools/vite.mjs +4 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type MwlSourceFile } from './compiler.ts';
|
|
2
|
+
export type PresentationScalarType = 'string' | 'number' | 'boolean';
|
|
3
|
+
export type PresentationValue = string | number | boolean;
|
|
4
|
+
export type PresentationItem = Readonly<Record<string, PresentationValue>>;
|
|
5
|
+
export interface PresentationCollection {
|
|
6
|
+
readonly type: 'items';
|
|
7
|
+
readonly fields: Readonly<Record<string, PresentationScalarType>>;
|
|
8
|
+
}
|
|
9
|
+
/** The game's TypeScript adapter declares these names and value types at build time. */
|
|
10
|
+
export interface PresentationManifest {
|
|
11
|
+
readonly values: Readonly<Record<string, PresentationScalarType | PresentationCollection>>;
|
|
12
|
+
readonly actions: readonly string[];
|
|
13
|
+
readonly adapters?: readonly string[];
|
|
14
|
+
readonly assets?: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
export type PresentationProperties = Readonly<Record<string, string>>;
|
|
17
|
+
export interface PresentationNode {
|
|
18
|
+
readonly kind: string;
|
|
19
|
+
readonly id: string;
|
|
20
|
+
/** Authored definition path, shared by every instance of a reusable component. */
|
|
21
|
+
readonly source: string;
|
|
22
|
+
readonly properties: PresentationProperties;
|
|
23
|
+
readonly states: Readonly<Record<string, PresentationProperties>>;
|
|
24
|
+
readonly children: readonly PresentationNode[];
|
|
25
|
+
}
|
|
26
|
+
export interface PresentationTheme {
|
|
27
|
+
readonly tokens: Readonly<Record<string, number>>;
|
|
28
|
+
readonly properties: PresentationProperties;
|
|
29
|
+
}
|
|
30
|
+
export interface PresentationContext {
|
|
31
|
+
readonly theme: string;
|
|
32
|
+
readonly tokens: Readonly<Record<string, number>>;
|
|
33
|
+
readonly overrides: Readonly<Record<string, PresentationProperties>>;
|
|
34
|
+
}
|
|
35
|
+
export interface PresentationScene {
|
|
36
|
+
readonly theme: string;
|
|
37
|
+
readonly children: readonly PresentationNode[];
|
|
38
|
+
}
|
|
39
|
+
export interface CompiledPresentation {
|
|
40
|
+
readonly scenes: Readonly<Record<string, PresentationScene>>;
|
|
41
|
+
readonly themes: Readonly<Record<string, PresentationTheme>>;
|
|
42
|
+
readonly contexts: Readonly<Record<string, PresentationContext>>;
|
|
43
|
+
readonly variants: Readonly<Record<string, PresentationProperties>>;
|
|
44
|
+
readonly manifest: PresentationManifest;
|
|
45
|
+
readonly ids: readonly string[];
|
|
46
|
+
readonly assets: readonly string[];
|
|
47
|
+
readonly messages: readonly string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compiles optional scene/UI definitions, validating every reference against the game's manifest.
|
|
51
|
+
* Reusable components are expanded at build time; emitted data contains no parser or executable content.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { compilePresentation, emitPresentationModule } from '@datamoc/mw_games/mwl/presentation';
|
|
56
|
+
* const data = compilePresentation([], { values: {}, actions: [] });
|
|
57
|
+
* console.log(emitPresentationModule(data).startsWith('export const presentationData')); // true
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function compilePresentation(files: readonly MwlSourceFile[], manifest: PresentationManifest): CompiledPresentation;
|
|
61
|
+
/**
|
|
62
|
+
* Emits data and literal ID types for a game's build script to write alongside its other MWL artifacts.
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import { compilePresentation, emitPresentationModule } from '@datamoc/mw_games/mwl/presentation';
|
|
66
|
+
* console.log(emitPresentationModule(compilePresentation([], { values: {}, actions: [] })));
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare function emitPresentationModule(data: CompiledPresentation): string;
|
|
70
|
+
//# sourceMappingURL=presentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../src/mwl/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAIzF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAC3E,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;CAClE;AACD,wFAAwF;AACxF,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,GAAG,sBAAsB,CAAC,CAAC,CAAC;IAC3F,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AACD,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AACtE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAClE,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AACD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC;CAC5C;AACD,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;CACrE;AACD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AACD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC7D,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC7D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACjE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACpE,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAoKD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,QAAQ,EAAE,oBAAoB,GAC5B,oBAAoB,CAqOtB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAEzE"}
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { compileSources } from './compiler.js';
|
|
2
|
+
import { schema10 } from './schema.js';
|
|
3
|
+
import { contrastRatio } from '../two-d/ui/contrast.js';
|
|
4
|
+
const styleAttributes = {
|
|
5
|
+
color_token: 'id',
|
|
6
|
+
background_token: 'id',
|
|
7
|
+
border_token: 'id',
|
|
8
|
+
width: 'number',
|
|
9
|
+
height: 'number',
|
|
10
|
+
gap: 'number',
|
|
11
|
+
padding: 'number',
|
|
12
|
+
alpha: 'number',
|
|
13
|
+
};
|
|
14
|
+
const commonAttributes = {
|
|
15
|
+
id: 'id',
|
|
16
|
+
...styleAttributes,
|
|
17
|
+
variant: 'id',
|
|
18
|
+
anchor: [
|
|
19
|
+
'top-left',
|
|
20
|
+
'top',
|
|
21
|
+
'top-right',
|
|
22
|
+
'left',
|
|
23
|
+
'center',
|
|
24
|
+
'right',
|
|
25
|
+
'bottom-left',
|
|
26
|
+
'bottom',
|
|
27
|
+
'bottom-right',
|
|
28
|
+
'fill',
|
|
29
|
+
],
|
|
30
|
+
x: 'number',
|
|
31
|
+
y: 'number',
|
|
32
|
+
visible: 'boolean',
|
|
33
|
+
visible_binding: 'string',
|
|
34
|
+
};
|
|
35
|
+
const uiTags = [
|
|
36
|
+
'ui_container',
|
|
37
|
+
'ui_row',
|
|
38
|
+
'ui_column',
|
|
39
|
+
'ui_grid',
|
|
40
|
+
'ui_label',
|
|
41
|
+
'ui_button',
|
|
42
|
+
'ui_bar',
|
|
43
|
+
'ui_window',
|
|
44
|
+
'ui_repeat',
|
|
45
|
+
'ui_mount',
|
|
46
|
+
'ui_adapter',
|
|
47
|
+
];
|
|
48
|
+
const children = [...uiTags, 'ui_state'];
|
|
49
|
+
const tree = { attributes: commonAttributes, required: ['id'], children };
|
|
50
|
+
const vocabulary = {
|
|
51
|
+
theme_definition: {
|
|
52
|
+
attributes: { id: 'id', font_family: 'string', font_size: 'number', padding: 'number', spacing: 'number' },
|
|
53
|
+
required: ['id'],
|
|
54
|
+
children: ['theme_token'],
|
|
55
|
+
},
|
|
56
|
+
theme_token: { attributes: { id: 'id', value: 'number' }, required: ['id', 'value'], children: [] },
|
|
57
|
+
presentation_context: {
|
|
58
|
+
attributes: { id: 'id', theme: 'id' },
|
|
59
|
+
required: ['id', 'theme'],
|
|
60
|
+
children: ['theme_token', 'ui_override'],
|
|
61
|
+
},
|
|
62
|
+
ui_override: {
|
|
63
|
+
attributes: { target: 'string', ...styleAttributes, image: 'string' },
|
|
64
|
+
required: ['target'],
|
|
65
|
+
children: [],
|
|
66
|
+
},
|
|
67
|
+
component_variant: { attributes: { id: 'id', ...styleAttributes }, required: ['id'], children: [] },
|
|
68
|
+
ui_component: { attributes: { id: 'id', items_binding: 'id' }, required: ['id'], children: uiTags },
|
|
69
|
+
scene_definition: {
|
|
70
|
+
attributes: { id: 'id', theme: 'id' },
|
|
71
|
+
required: ['id', 'theme'],
|
|
72
|
+
children: ['scene_layer', 'scene_camera', ...uiTags],
|
|
73
|
+
},
|
|
74
|
+
scene_layer: {
|
|
75
|
+
...tree,
|
|
76
|
+
attributes: { ...commonAttributes, space: ['world', 'screen'], adapter: 'id', image: 'string' },
|
|
77
|
+
},
|
|
78
|
+
scene_camera: {
|
|
79
|
+
attributes: { id: 'id', zoom: 'number', x: 'number', y: 'number', fit_width: 'number', fit_height: 'number' },
|
|
80
|
+
required: ['id'],
|
|
81
|
+
children: [],
|
|
82
|
+
},
|
|
83
|
+
ui_container: tree,
|
|
84
|
+
ui_row: { ...tree, attributes: { ...commonAttributes, wrap: 'boolean', align: ['start', 'center', 'end'] } },
|
|
85
|
+
ui_column: tree,
|
|
86
|
+
ui_grid: { ...tree, attributes: { ...commonAttributes, columns: 'integer' }, required: ['id', 'columns'] },
|
|
87
|
+
ui_label: {
|
|
88
|
+
...tree,
|
|
89
|
+
attributes: { ...commonAttributes, text: 'string', text_binding: 'string' },
|
|
90
|
+
children: ['ui_state'],
|
|
91
|
+
},
|
|
92
|
+
ui_button: {
|
|
93
|
+
...tree,
|
|
94
|
+
attributes: {
|
|
95
|
+
...commonAttributes,
|
|
96
|
+
text: 'string',
|
|
97
|
+
text_binding: 'string',
|
|
98
|
+
action: 'id',
|
|
99
|
+
selected_binding: 'string',
|
|
100
|
+
disabled_binding: 'string',
|
|
101
|
+
},
|
|
102
|
+
children: ['ui_state'],
|
|
103
|
+
},
|
|
104
|
+
ui_bar: {
|
|
105
|
+
...tree,
|
|
106
|
+
attributes: {
|
|
107
|
+
...commonAttributes,
|
|
108
|
+
value: 'number',
|
|
109
|
+
max: 'number',
|
|
110
|
+
value_binding: 'string',
|
|
111
|
+
max_binding: 'string',
|
|
112
|
+
color_binding: 'string',
|
|
113
|
+
},
|
|
114
|
+
children: ['ui_state'],
|
|
115
|
+
},
|
|
116
|
+
ui_window: {
|
|
117
|
+
...tree,
|
|
118
|
+
attributes: {
|
|
119
|
+
...commonAttributes,
|
|
120
|
+
anchor: ['center', 'top', 'bottom'],
|
|
121
|
+
title: 'string',
|
|
122
|
+
title_binding: 'string',
|
|
123
|
+
modal: 'boolean',
|
|
124
|
+
closable: 'boolean',
|
|
125
|
+
close_action: 'id',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
ui_repeat: {
|
|
129
|
+
...tree,
|
|
130
|
+
attributes: { ...commonAttributes, items_binding: 'id', key: 'id' },
|
|
131
|
+
required: ['id', 'items_binding', 'key'],
|
|
132
|
+
},
|
|
133
|
+
ui_mount: {
|
|
134
|
+
...tree,
|
|
135
|
+
attributes: { ...commonAttributes, component: 'id' },
|
|
136
|
+
required: ['id', 'component'],
|
|
137
|
+
children: [],
|
|
138
|
+
},
|
|
139
|
+
ui_adapter: {
|
|
140
|
+
...tree,
|
|
141
|
+
attributes: { ...commonAttributes, adapter: 'id', image: 'string' },
|
|
142
|
+
required: ['id', 'adapter'],
|
|
143
|
+
children: [],
|
|
144
|
+
},
|
|
145
|
+
ui_state: {
|
|
146
|
+
attributes: { state: ['idle', 'hover', 'pressed', 'disabled', 'selected', 'focused'], ...styleAttributes },
|
|
147
|
+
required: ['state'],
|
|
148
|
+
children: [],
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
const bindingTypes = {
|
|
152
|
+
text_binding: 'string',
|
|
153
|
+
title_binding: 'string',
|
|
154
|
+
value_binding: 'number',
|
|
155
|
+
max_binding: 'number',
|
|
156
|
+
color_binding: 'number',
|
|
157
|
+
visible_binding: 'boolean',
|
|
158
|
+
selected_binding: 'boolean',
|
|
159
|
+
disabled_binding: 'boolean',
|
|
160
|
+
};
|
|
161
|
+
const semanticTokens = ['panel', 'text', 'accent', 'success', 'warning', 'danger', 'selection'];
|
|
162
|
+
/** WCAG AA floor for body text, and for danger/selection indicators, against the panel. */
|
|
163
|
+
const MIN_TEXT_CONTRAST = 4.5;
|
|
164
|
+
const MIN_INDICATOR_CONTRAST = 3;
|
|
165
|
+
/**
|
|
166
|
+
* Compiles optional scene/UI definitions, validating every reference against the game's manifest.
|
|
167
|
+
* Reusable components are expanded at build time; emitted data contains no parser or executable content.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* import { compilePresentation, emitPresentationModule } from '@datamoc/mw_games/mwl/presentation';
|
|
172
|
+
* const data = compilePresentation([], { values: {}, actions: [] });
|
|
173
|
+
* console.log(emitPresentationModule(data).startsWith('export const presentationData')); // true
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export function compilePresentation(files, manifest) {
|
|
177
|
+
const game = compileSources(files, { schemas: { ...schema10, ...vocabulary } });
|
|
178
|
+
const roots = game.roots;
|
|
179
|
+
const definitions = new Map();
|
|
180
|
+
const sources = new Map();
|
|
181
|
+
const mountedComponents = new Set();
|
|
182
|
+
const tokenUses = [];
|
|
183
|
+
const fail = (node, message) => {
|
|
184
|
+
const location = node.location;
|
|
185
|
+
throw new Error(`${location?.file ?? '<presentation>'}:${location?.line ?? 1}:${location?.column ?? 1}: ${message}`);
|
|
186
|
+
};
|
|
187
|
+
const keyOf = (tag, id) => `${tag}:${id}`;
|
|
188
|
+
const checkReferences = (node, attributes, fields) => {
|
|
189
|
+
if (attributes.variant)
|
|
190
|
+
find(node, 'component_variant', attributes.variant);
|
|
191
|
+
for (const name of ['action', 'close_action'])
|
|
192
|
+
if (attributes[name] && !manifest.actions.includes(attributes[name]))
|
|
193
|
+
fail(node, `unknown action "${attributes[name]}"`);
|
|
194
|
+
if (attributes.adapter && !manifest.adapters?.includes(attributes.adapter))
|
|
195
|
+
fail(node, `unknown adapter "${attributes.adapter}"`);
|
|
196
|
+
for (const [name, expected] of Object.entries(bindingTypes)) {
|
|
197
|
+
const binding = attributes[name];
|
|
198
|
+
if (!binding)
|
|
199
|
+
continue;
|
|
200
|
+
const actual = binding.startsWith('item.') ? fields?.[binding.slice(5)] : manifest.values[binding];
|
|
201
|
+
if (actual !== expected)
|
|
202
|
+
fail(node, `binding "${binding}" for ${name} must be ${expected}`);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
for (const node of roots) {
|
|
206
|
+
if (node.attributes.id === '__proto__')
|
|
207
|
+
fail(node, 'reserved definition id "__proto__"');
|
|
208
|
+
if (![
|
|
209
|
+
'theme_definition',
|
|
210
|
+
'presentation_context',
|
|
211
|
+
'component_variant',
|
|
212
|
+
'ui_component',
|
|
213
|
+
'scene_definition',
|
|
214
|
+
].includes(node.tag))
|
|
215
|
+
continue;
|
|
216
|
+
const key = keyOf(node.tag, node.attributes.id);
|
|
217
|
+
if (definitions.has(key))
|
|
218
|
+
fail(node, `duplicate ${key}`);
|
|
219
|
+
definitions.set(key, node);
|
|
220
|
+
}
|
|
221
|
+
const find = (node, tag, id) => definitions.get(keyOf(tag, id)) ?? fail(node, `unknown ${tag} "${id}"`);
|
|
222
|
+
const props = (node, excluded = ['id']) => Object.fromEntries(Object.entries(node.attributes).filter(([key]) => !excluded.includes(key)));
|
|
223
|
+
const validateStyle = (node) => {
|
|
224
|
+
if (node.attributes.image && !manifest.assets?.includes(node.attributes.image))
|
|
225
|
+
fail(node, `unknown asset "${node.attributes.image}"`);
|
|
226
|
+
for (const [name, value] of Object.entries(node.attributes)) {
|
|
227
|
+
if (name.endsWith('_token'))
|
|
228
|
+
tokenUses.push({ node, token: value });
|
|
229
|
+
if (['width', 'height', 'gap', 'padding'].includes(name) && Number(value) < 0)
|
|
230
|
+
fail(node, `${name} must be nonnegative`);
|
|
231
|
+
if (name === 'alpha' && (Number(value) < 0 || Number(value) > 1))
|
|
232
|
+
fail(node, 'alpha must be between 0 and 1');
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
const readTokens = (node) => {
|
|
236
|
+
const tokens = Object.create(null);
|
|
237
|
+
for (const child of node.children.filter((child) => child.tag === 'theme_token')) {
|
|
238
|
+
const { id, value } = child.attributes;
|
|
239
|
+
if (id === '__proto__')
|
|
240
|
+
fail(child, 'reserved token id "__proto__"');
|
|
241
|
+
const color = Number(value);
|
|
242
|
+
if (Object.hasOwn(tokens, id))
|
|
243
|
+
fail(child, `duplicate theme token "${id}"`);
|
|
244
|
+
if (!Number.isInteger(color) || color < 0 || color > 0xffffff)
|
|
245
|
+
fail(child, `token "${id}" must be a 24-bit color`);
|
|
246
|
+
tokens[id] = color;
|
|
247
|
+
}
|
|
248
|
+
return tokens;
|
|
249
|
+
};
|
|
250
|
+
const themes = Object.create(null);
|
|
251
|
+
const contexts = Object.create(null);
|
|
252
|
+
const variants = Object.create(null);
|
|
253
|
+
const scenes = Object.create(null);
|
|
254
|
+
for (const node of roots) {
|
|
255
|
+
const id = node.attributes.id;
|
|
256
|
+
if (node.tag === 'theme_definition') {
|
|
257
|
+
validateStyle(node);
|
|
258
|
+
if (node.attributes.font_size !== undefined && Number(node.attributes.font_size) <= 0)
|
|
259
|
+
fail(node, 'font_size must be positive');
|
|
260
|
+
const tokens = readTokens(node);
|
|
261
|
+
for (const token of semanticTokens)
|
|
262
|
+
if (!Object.hasOwn(tokens, token))
|
|
263
|
+
fail(node, `missing semantic token "${token}"`);
|
|
264
|
+
themes[id] = { tokens, properties: props(node) };
|
|
265
|
+
}
|
|
266
|
+
else if (node.tag === 'component_variant') {
|
|
267
|
+
validateStyle(node);
|
|
268
|
+
variants[id] = props(node);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const buildTree = (nodes, prefix, fields, stack = []) => {
|
|
272
|
+
const siblings = new Set();
|
|
273
|
+
return nodes
|
|
274
|
+
.filter((node) => node.tag !== 'ui_state')
|
|
275
|
+
.map((node) => {
|
|
276
|
+
const id = node.attributes.id;
|
|
277
|
+
if (!id || siblings.has(id))
|
|
278
|
+
fail(node, `duplicate or missing component id "${id}" in ${prefix}`);
|
|
279
|
+
siblings.add(id);
|
|
280
|
+
const source = `${prefix}/${id}`;
|
|
281
|
+
sources.set(source, node);
|
|
282
|
+
validateStyle(node);
|
|
283
|
+
const attributes = node.attributes;
|
|
284
|
+
checkReferences(node, attributes, fields);
|
|
285
|
+
const states = Object.create(null);
|
|
286
|
+
for (const state of node.children.filter((child) => child.tag === 'ui_state')) {
|
|
287
|
+
if (Object.hasOwn(states, state.attributes.state))
|
|
288
|
+
fail(state, `duplicate component state "${state.attributes.state}"`);
|
|
289
|
+
validateStyle(state);
|
|
290
|
+
states[state.attributes.state] = props(state, ['state']);
|
|
291
|
+
}
|
|
292
|
+
let childNodes;
|
|
293
|
+
if (node.tag === 'ui_mount') {
|
|
294
|
+
const name = attributes.component;
|
|
295
|
+
if (stack.includes(name))
|
|
296
|
+
fail(node, `component cycle: ${[...stack, name].join(' -> ')}`);
|
|
297
|
+
mountedComponents.add(name);
|
|
298
|
+
const component = find(node, 'ui_component', name);
|
|
299
|
+
childNodes = buildTree(component.children, `component:${name}`, fields, [...stack, name]);
|
|
300
|
+
}
|
|
301
|
+
else if (node.tag === 'ui_repeat') {
|
|
302
|
+
const collection = manifest.values[attributes.items_binding];
|
|
303
|
+
if (!collection || typeof collection !== 'object' || collection.type !== 'items')
|
|
304
|
+
fail(node, `unknown collection "${attributes.items_binding}"`);
|
|
305
|
+
const itemFields = collection.fields;
|
|
306
|
+
if (!['string', 'number'].includes(itemFields[attributes.key]))
|
|
307
|
+
fail(node, `repeat key "${attributes.key}" must be a string or number field`);
|
|
308
|
+
if (node.children.filter((child) => child.tag !== 'ui_state').length !== 1)
|
|
309
|
+
fail(node, 'ui_repeat needs exactly one template child');
|
|
310
|
+
childNodes = buildTree(node.children, source, itemFields, stack);
|
|
311
|
+
}
|
|
312
|
+
else
|
|
313
|
+
childNodes = buildTree(node.children, source, fields, stack);
|
|
314
|
+
if (node.tag === 'ui_grid' && Number(attributes.columns) < 1)
|
|
315
|
+
fail(node, 'grid columns must be positive');
|
|
316
|
+
if (node.tag === 'scene_camera') {
|
|
317
|
+
if (attributes.zoom !== undefined && Number(attributes.zoom) <= 0)
|
|
318
|
+
fail(node, 'camera zoom must be positive');
|
|
319
|
+
if (Boolean(attributes.fit_width) !== Boolean(attributes.fit_height))
|
|
320
|
+
fail(node, 'camera fit needs width and height');
|
|
321
|
+
if (attributes.fit_width &&
|
|
322
|
+
(Number(attributes.fit_width) <= 0 || Number(attributes.fit_height) <= 0))
|
|
323
|
+
fail(node, 'camera fit dimensions must be positive');
|
|
324
|
+
}
|
|
325
|
+
return { kind: node.tag, id, source, properties: props(node), states, children: childNodes };
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
function componentFields(node) {
|
|
329
|
+
if (!node.attributes.items_binding)
|
|
330
|
+
return undefined;
|
|
331
|
+
const collection = manifest.values[node.attributes.items_binding];
|
|
332
|
+
if (typeof collection !== 'object' || collection.type !== 'items')
|
|
333
|
+
fail(node, `unknown collection "${node.attributes.items_binding}"`);
|
|
334
|
+
return collection.fields;
|
|
335
|
+
}
|
|
336
|
+
for (const node of roots.filter((node) => node.tag === 'scene_definition')) {
|
|
337
|
+
find(node, 'theme_definition', node.attributes.theme);
|
|
338
|
+
if (node.children.filter((child) => child.tag === 'scene_camera').length > 1)
|
|
339
|
+
fail(node, 'a scene can have only one camera');
|
|
340
|
+
scenes[node.attributes.id] = {
|
|
341
|
+
theme: node.attributes.theme,
|
|
342
|
+
children: buildTree(node.children, `scene:${node.attributes.id}`),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
// Validate unused reusable definitions too; an unmounted typo must not escape the build.
|
|
346
|
+
for (const node of roots.filter((node) => node.tag === 'ui_component')) {
|
|
347
|
+
if (!mountedComponents.has(node.attributes.id))
|
|
348
|
+
buildTree(node.children, `component:${node.attributes.id}`, componentFields(node), [node.attributes.id]);
|
|
349
|
+
}
|
|
350
|
+
for (const node of roots.filter((node) => node.tag === 'presentation_context')) {
|
|
351
|
+
find(node, 'theme_definition', node.attributes.theme);
|
|
352
|
+
const overrides = Object.create(null);
|
|
353
|
+
for (const override of node.children.filter((child) => child.tag === 'ui_override')) {
|
|
354
|
+
const target = override.attributes.target;
|
|
355
|
+
if (!sources.has(target))
|
|
356
|
+
fail(override, `unknown override target "${target}"`);
|
|
357
|
+
const targetNode = sources.get(target);
|
|
358
|
+
if (override.attributes.image && !['scene_layer', 'ui_adapter'].includes(targetNode.tag))
|
|
359
|
+
fail(override, 'image overrides require a scene layer or adapter');
|
|
360
|
+
if (Object.hasOwn(overrides, target))
|
|
361
|
+
fail(override, `duplicate override target "${target}"`);
|
|
362
|
+
validateStyle(override);
|
|
363
|
+
overrides[target] = props(override, ['target']);
|
|
364
|
+
}
|
|
365
|
+
const tokens = readTokens(node);
|
|
366
|
+
for (const token of Object.keys(tokens))
|
|
367
|
+
if (!Object.hasOwn(themes[node.attributes.theme].tokens, token))
|
|
368
|
+
fail(node, `unknown context token "${token}"`);
|
|
369
|
+
contexts[node.attributes.id] = { theme: node.attributes.theme, tokens, overrides };
|
|
370
|
+
}
|
|
371
|
+
const checkPalette = (node, tokens) => {
|
|
372
|
+
for (const use of tokenUses)
|
|
373
|
+
if (!Object.hasOwn(tokens, use.token))
|
|
374
|
+
fail(use.node, `unknown theme token "${use.token}" in ${node.attributes.id}`);
|
|
375
|
+
if (contrastRatio(tokens.text, tokens.panel) < MIN_TEXT_CONTRAST)
|
|
376
|
+
fail(node, 'text/panel contrast must reach 4.5');
|
|
377
|
+
for (const token of ['danger', 'selection'])
|
|
378
|
+
if (contrastRatio(tokens[token], tokens.panel) < MIN_INDICATOR_CONTRAST)
|
|
379
|
+
fail(node, `${token}/panel contrast must reach 3`);
|
|
380
|
+
};
|
|
381
|
+
for (const node of roots.filter((node) => node.tag === 'theme_definition'))
|
|
382
|
+
checkPalette(node, themes[node.attributes.id].tokens);
|
|
383
|
+
for (const node of roots.filter((node) => node.tag === 'presentation_context')) {
|
|
384
|
+
const context = contexts[node.attributes.id];
|
|
385
|
+
checkPalette(node, { ...themes[context.theme].tokens, ...context.tokens });
|
|
386
|
+
}
|
|
387
|
+
const ids = [];
|
|
388
|
+
const collect = (nodes, prefix) => {
|
|
389
|
+
for (const node of nodes) {
|
|
390
|
+
const path = `${prefix}/${node.id}`;
|
|
391
|
+
ids.push(path);
|
|
392
|
+
collect(node.children, node.kind === 'ui_repeat' ? `${path}/*` : path);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
for (const [id, scene] of Object.entries(scenes))
|
|
396
|
+
collect(scene.children, id);
|
|
397
|
+
return {
|
|
398
|
+
scenes,
|
|
399
|
+
themes,
|
|
400
|
+
contexts,
|
|
401
|
+
variants,
|
|
402
|
+
manifest,
|
|
403
|
+
ids: ids.sort(),
|
|
404
|
+
assets: game.assets,
|
|
405
|
+
messages: game.messages,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Emits data and literal ID types for a game's build script to write alongside its other MWL artifacts.
|
|
410
|
+
* @example
|
|
411
|
+
* ```ts
|
|
412
|
+
* import { compilePresentation, emitPresentationModule } from '@datamoc/mw_games/mwl/presentation';
|
|
413
|
+
* console.log(emitPresentationModule(compilePresentation([], { values: {}, actions: [] })));
|
|
414
|
+
* ```
|
|
415
|
+
*/
|
|
416
|
+
export function emitPresentationModule(data) {
|
|
417
|
+
return `export const presentationData = ${JSON.stringify(data, null, '\t')} as const;\ntype ExpandRepeat<S extends string> = S extends \`\${infer Prefix}/*/\${infer Rest}\` ? \`\${Prefix}/\${string}/\${ExpandRepeat<Rest>}\` : S;\nexport type PresentationId = ExpandRepeat<typeof presentationData.ids[number]>;\nexport type PresentationSceneId = keyof typeof presentationData.scenes;\n`;
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=presentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation.js","sourceRoot":"","sources":["../../src/mwl/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA4C,MAAM,eAAe,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAkDxD,MAAM,eAAe,GAAG;IACvB,WAAW,EAAE,IAAI;IACjB,gBAAgB,EAAE,IAAI;IACtB,YAAY,EAAE,IAAI;IAClB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,QAAQ;IACb,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,QAAQ;CACN,CAAC;AACX,MAAM,gBAAgB,GAAG;IACxB,EAAE,EAAE,IAAI;IACR,GAAG,eAAe;IAClB,OAAO,EAAE,IAAI;IACb,MAAM,EAAE;QACP,UAAU;QACV,KAAK;QACL,WAAW;QACX,MAAM;QACN,QAAQ;QACR,OAAO;QACP,aAAa;QACb,QAAQ;QACR,cAAc;QACd,MAAM;KACN;IACD,CAAC,EAAE,QAAQ;IACX,CAAC,EAAE,QAAQ;IACX,OAAO,EAAE,SAAS;IAClB,eAAe,EAAE,QAAQ;CAChB,CAAC;AACX,MAAM,MAAM,GAAG;IACd,cAAc;IACd,QAAQ;IACR,WAAW;IACX,SAAS;IACT,UAAU;IACV,WAAW;IACX,QAAQ;IACR,WAAW;IACX,WAAW;IACX,UAAU;IACV,YAAY;CACZ,CAAC;AACF,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,CAAC;AACzC,MAAM,IAAI,GAAG,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;AAC1E,MAAM,UAAU,GAA2C;IAC1D,gBAAgB,EAAE;QACjB,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC1G,QAAQ,EAAE,CAAC,IAAI,CAAC;QAChB,QAAQ,EAAE,CAAC,aAAa,CAAC;KACzB;IACD,WAAW,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IACnG,oBAAoB,EAAE;QACrB,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;QACrC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;QACzB,QAAQ,EAAE,CAAC,aAAa,EAAE,aAAa,CAAC;KACxC;IACD,WAAW,EAAE;QACZ,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE;QACrE,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,QAAQ,EAAE,EAAE;KACZ;IACD,iBAAiB,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,eAAe,EAAE,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IACnG,YAAY,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;IACnG,gBAAgB,EAAE;QACjB,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;QACrC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;QACzB,QAAQ,EAAE,CAAC,aAAa,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;KACpD;IACD,WAAW,EAAE;QACZ,GAAG,IAAI;QACP,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE;KAC/F;IACD,YAAY,EAAE;QACb,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC7G,QAAQ,EAAE,CAAC,IAAI,CAAC;QAChB,QAAQ,EAAE,EAAE;KACZ;IACD,YAAY,EAAE,IAAI;IAClB,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;IAC5G,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;IAC1G,QAAQ,EAAE;QACT,GAAG,IAAI;QACP,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE;QAC3E,QAAQ,EAAE,CAAC,UAAU,CAAC;KACtB;IACD,SAAS,EAAE;QACV,GAAG,IAAI;QACP,UAAU,EAAE;YACX,GAAG,gBAAgB;YACnB,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,IAAI;YACZ,gBAAgB,EAAE,QAAQ;YAC1B,gBAAgB,EAAE,QAAQ;SAC1B;QACD,QAAQ,EAAE,CAAC,UAAU,CAAC;KACtB;IACD,MAAM,EAAE;QACP,GAAG,IAAI;QACP,UAAU,EAAE;YACX,GAAG,gBAAgB;YACnB,KAAK,EAAE,QAAQ;YACf,GAAG,EAAE,QAAQ;YACb,aAAa,EAAE,QAAQ;YACvB,WAAW,EAAE,QAAQ;YACrB,aAAa,EAAE,QAAQ;SACvB;QACD,QAAQ,EAAE,CAAC,UAAU,CAAC;KACtB;IACD,SAAS,EAAE;QACV,GAAG,IAAI;QACP,UAAU,EAAE;YACX,GAAG,gBAAgB;YACnB,MAAM,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC;YACnC,KAAK,EAAE,QAAQ;YACf,aAAa,EAAE,QAAQ;YACvB,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,IAAI;SAClB;KACD;IACD,SAAS,EAAE;QACV,GAAG,IAAI;QACP,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE;QACnE,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,CAAC;KACxC;IACD,QAAQ,EAAE;QACT,GAAG,IAAI;QACP,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,SAAS,EAAE,IAAI,EAAE;QACpD,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC;QAC7B,QAAQ,EAAE,EAAE;KACZ;IACD,UAAU,EAAE;QACX,GAAG,IAAI;QACP,UAAU,EAAE,EAAE,GAAG,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE;QACnE,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC;QAC3B,QAAQ,EAAE,EAAE;KACZ;IACD,QAAQ,EAAE;QACT,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,eAAe,EAAE;QAC1G,QAAQ,EAAE,CAAC,OAAO,CAAC;QACnB,QAAQ,EAAE,EAAE;KACZ;CACD,CAAC;AACF,MAAM,YAAY,GAA2C;IAC5D,YAAY,EAAE,QAAQ;IACtB,aAAa,EAAE,QAAQ;IACvB,aAAa,EAAE,QAAQ;IACvB,WAAW,EAAE,QAAQ;IACrB,aAAa,EAAE,QAAQ;IACvB,eAAe,EAAE,SAAS;IAC1B,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;CAC3B,CAAC;AACF,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAChG,2FAA2F;AAC3F,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAClC,KAA+B,EAC/B,QAA8B;IAE9B,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,UAAU,EAAE,EAAE,CAAC,CAAC;IAChF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;IACnD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC5C,MAAM,SAAS,GAAoD,EAAE,CAAC;IACtE,MAAM,IAAI,GAAG,CAAC,IAAqB,EAAE,OAAe,EAAS,EAAE;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,IAAI,KAAK,CACd,GAAG,QAAQ,EAAE,IAAI,IAAI,gBAAgB,IAAI,QAAQ,EAAE,IAAI,IAAI,CAAC,IAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,KAAK,OAAO,EAAE,CACnG,CAAC;IACH,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,EAAU,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC;IAC1D,MAAM,eAAe,GAAG,CACvB,IAAqB,EACrB,UAAkC,EAClC,MAAyC,EAClC,EAAE;QACT,IAAI,UAAU,CAAC,OAAO;YAAE,IAAI,CAAC,IAAI,EAAE,mBAAmB,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;QAC5E,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC;YAC5C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBACnE,IAAI,CAAC,IAAI,EAAE,mBAAmB,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrD,IAAI,UAAU,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;YACzE,IAAI,CAAC,IAAI,EAAE,oBAAoB,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC;QACvD,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7D,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACnG,IAAI,MAAM,KAAK,QAAQ;gBAAE,IAAI,CAAC,IAAI,EAAE,YAAY,OAAO,SAAS,IAAI,YAAY,QAAQ,EAAE,CAAC,CAAC;QAC7F,CAAC;IACF,CAAC,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,WAAW;YAAE,IAAI,CAAC,IAAI,EAAE,oCAAoC,CAAC,CAAC;QACzF,IACC,CAAC;YACA,kBAAkB;YAClB,sBAAsB;YACtB,mBAAmB;YACnB,cAAc;YACd,kBAAkB;SAClB,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;YAEpB,SAAS;QACV,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,aAAa,GAAG,EAAE,CAAC,CAAC;QACzD,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,IAAqB,EAAE,GAAW,EAAE,EAAU,EAAmB,EAAE,CAChF,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,CAAC,IAAqB,EAAE,QAAQ,GAAG,CAAC,IAAI,CAAC,EAA0B,EAAE,CAClF,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,aAAa,GAAG,CAAC,IAAqB,EAAQ,EAAE;QACrD,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAC7E,IAAI,CAAC,IAAI,EAAE,kBAAkB,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC;QACxD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7D,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACpE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;gBAC5E,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,sBAAsB,CAAC,CAAC;YAC3C,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC/D,IAAI,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;QAC9C,CAAC;IACF,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,IAAqB,EAA0B,EAAE;QACpE,MAAM,MAAM,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3D,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,aAAa,CAAC,EAAE,CAAC;YAClF,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC;YACvC,IAAI,EAAE,KAAK,WAAW;gBAAE,IAAI,CAAC,KAAK,EAAE,+BAA+B,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;gBAAE,IAAI,CAAC,KAAK,EAAE,0BAA0B,EAAE,GAAG,CAAC,CAAC;YAC5E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,QAAQ;gBAC5D,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC;YACrD,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC;QACpB,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC,CAAC;IACF,MAAM,MAAM,GAAsC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAwC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAA2C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAsC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,GAAG,KAAK,kBAAkB,EAAE,CAAC;YACrC,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC;gBACpF,IAAI,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YAChC,KAAK,MAAM,KAAK,IAAI,cAAc;gBACjC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;oBAAE,IAAI,CAAC,IAAI,EAAE,2BAA2B,KAAK,GAAG,CAAC,CAAC;YACpF,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,CAAC;aAAM,IAAI,IAAI,CAAC,GAAG,KAAK,mBAAmB,EAAE,CAAC;YAC7C,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,QAAQ,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;IACF,CAAC;IACD,MAAM,SAAS,GAAG,CACjB,KAAiC,EACjC,MAAc,EACd,MAAyC,EACzC,KAAK,GAAsB,EAAE,EACR,EAAE;QACvB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,OAAO,KAAK;aACV,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,CAAC;aACzC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,EAAE,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,IAAI,CAAC,IAAI,EAAE,sCAAsC,EAAE,QAAQ,MAAM,EAAE,CAAC,CAAC;YAClG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjB,MAAM,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1B,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;YACnC,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;YAC1C,MAAM,MAAM,GAA2C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC3E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,UAAU,CAAC,EAAE,CAAC;gBAC/E,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;oBAChD,IAAI,CAAC,KAAK,EAAE,8BAA8B,KAAK,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC;gBACtE,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,UAA8B,CAAC;YACnC,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;gBAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC;gBAClC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC1F,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC;gBACnD,UAAU,GAAG,SAAS,CAAC,SAAS,CAAC,QAAQ,EAAE,aAAa,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3F,CAAC;iBAAM,IAAI,IAAI,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;gBACrC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;gBAC7D,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO;oBAC/E,IAAI,CAAC,IAAI,EAAE,uBAAuB,UAAU,CAAC,aAAa,GAAG,CAAC,CAAC;gBAChE,MAAM,UAAU,GAAI,UAAqC,CAAC,MAAM,CAAC;gBACjE,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;oBAC7D,IAAI,CAAC,IAAI,EAAE,eAAe,UAAU,CAAC,GAAG,oCAAoC,CAAC,CAAC;gBAC/E,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC;oBACzE,IAAI,CAAC,IAAI,EAAE,4CAA4C,CAAC,CAAC;gBAC1D,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;YAClE,CAAC;;gBAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACpE,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC;gBAC3D,IAAI,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YAC7C,IAAI,IAAI,CAAC,GAAG,KAAK,cAAc,EAAE,CAAC;gBACjC,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;oBAChE,IAAI,CAAC,IAAI,EAAE,8BAA8B,CAAC,CAAC;gBAC5C,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;oBACnE,IAAI,CAAC,IAAI,EAAE,mCAAmC,CAAC,CAAC;gBACjD,IACC,UAAU,CAAC,SAAS;oBACpB,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;oBAEzE,IAAI,CAAC,IAAI,EAAE,wCAAwC,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;QAC9F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IACF,SAAS,eAAe,CAAC,IAAqB;QAC7C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa;YAAE,OAAO,SAAS,CAAC;QACrD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAClE,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO;YAChE,IAAI,CAAC,IAAI,EAAE,uBAAuB,IAAI,CAAC,UAAU,CAAC,aAAa,GAAG,CAAC,CAAC;QACrE,OAAQ,UAAqC,CAAC,MAAM,CAAC;IACtD,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,kBAAkB,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC;YAC3E,IAAI,CAAC,IAAI,EAAE,kCAAkC,CAAC,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG;YAC5B,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;YAC5B,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;SACjE,CAAC;IACH,CAAC;IACD,yFAAyF;IACzF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,cAAc,CAAC,EAAE,CAAC;QACxE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7C,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3G,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,sBAAsB,CAAC,EAAE,CAAC;QAChF,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,SAAS,GAA2C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9E,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,aAAa,CAAC,EAAE,CAAC;YACrF,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;YAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,IAAI,CAAC,QAAQ,EAAE,4BAA4B,MAAM,GAAG,CAAC,CAAC;YAChF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAoB,CAAC;YAC1D,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;gBACvF,IAAI,CAAC,QAAQ,EAAE,kDAAkD,CAAC,CAAC;YACpE,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;gBAAE,IAAI,CAAC,QAAQ,EAAE,8BAA8B,MAAM,GAAG,CAAC,CAAC;YAC9F,aAAa,CAAC,QAAQ,CAAC,CAAC;YACxB,SAAS,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC;gBAC9D,IAAI,CAAC,IAAI,EAAE,0BAA0B,KAAK,GAAG,CAAC,CAAC;QACjD,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACpF,CAAC;IACD,MAAM,YAAY,GAAG,CAAC,IAAqB,EAAE,MAAwC,EAAQ,EAAE;QAC9F,KAAK,MAAM,GAAG,IAAI,SAAS;YAC1B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC;gBACpC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,wBAAwB,GAAG,CAAC,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;QAChF,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,iBAAiB;YAC/D,IAAI,CAAC,IAAI,EAAE,oCAAoC,CAAC,CAAC;QAClD,KAAK,MAAM,KAAK,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC;YAC1C,IAAI,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,sBAAsB;gBACtE,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,8BAA8B,CAAC,CAAC;IACtD,CAAC,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,kBAAkB,CAAC;QACzE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACvD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,sBAAsB,CAAC,EAAE,CAAC;QAChF,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC7C,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,CAAC,KAAkC,EAAE,MAAc,EAAQ,EAAE;QAC5E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACpC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACxE,CAAC;IACF,CAAC,CAAC;IACF,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC9E,OAAO;QACN,MAAM;QACN,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACvB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAA0B;IAChE,OAAO,mCAAmC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,uTAAuT,CAAC;AACnY,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import Matter from 'matter-js';
|
|
2
1
|
import { Signal } from '../core/Signal.ts';
|
|
3
2
|
export interface PhysicsOptions {
|
|
4
|
-
/** gravity strength per axis; y grows downward.
|
|
3
|
+
/** gravity strength per axis; y grows downward. The default matches matter-js's historical default pull */
|
|
5
4
|
gravity?: {
|
|
6
5
|
x: number;
|
|
7
6
|
y: number;
|
|
@@ -17,8 +16,9 @@ export interface BodyOptions {
|
|
|
17
16
|
/** 0 to 1, how much of its speed a bounce keeps; 0 when omitted */
|
|
18
17
|
restitution?: number;
|
|
19
18
|
friction?: number;
|
|
20
|
-
/** mass per unit area;
|
|
19
|
+
/** mass per unit area; 1 when omitted */
|
|
21
20
|
density?: number;
|
|
21
|
+
/** initial rotation in radians; bodies never spin, this is a display offset for sprites */
|
|
22
22
|
angle?: number;
|
|
23
23
|
/** a name for collision callbacks and lookups */
|
|
24
24
|
label?: string;
|
|
@@ -26,6 +26,7 @@ export interface BodyOptions {
|
|
|
26
26
|
export interface ConstraintOptions {
|
|
27
27
|
/** 0 to 1, how rigidly the ends are held: 1 is a rod, a small value a spring; 1 when omitted */
|
|
28
28
|
stiffness?: number;
|
|
29
|
+
/** 0 to 1, the share of radial oscillation removed per step; 0 when omitted */
|
|
29
30
|
damping?: number;
|
|
30
31
|
/** rest length; the distance between the attachment points when omitted */
|
|
31
32
|
length?: number;
|
|
@@ -48,19 +49,45 @@ export interface ConstraintOptions {
|
|
|
48
49
|
*/
|
|
49
50
|
maxStretch?: number;
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
export
|
|
52
|
+
/** a rigid body: a circle or an axis-aligned box with mutable position and velocity */
|
|
53
|
+
export interface PhysicsBody {
|
|
54
|
+
/** centre in world units; assign to teleport (velocity is left untouched) */
|
|
55
|
+
position: {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
};
|
|
59
|
+
/** world units per second; assign to shove */
|
|
60
|
+
velocity: {
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
};
|
|
64
|
+
/** rotation in radians; never integrated, a display offset for sprites */
|
|
65
|
+
angle: number;
|
|
66
|
+
/** collision name, '' when unnamed */
|
|
67
|
+
label: string;
|
|
68
|
+
/** true for ground and anchors: infinite mass, never moves */
|
|
69
|
+
readonly isStatic: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** a distance joint between two bodies, or a body and a fixed world point */
|
|
72
|
+
export interface PhysicsConstraint {
|
|
73
|
+
/** rest length both ends are held at */
|
|
74
|
+
readonly length: number;
|
|
75
|
+
}
|
|
53
76
|
/**
|
|
54
|
-
* Rigid bodies and constraints
|
|
77
|
+
* Rigid bodies and constraints in plain TypeScript, stepped on a fixed clock.
|
|
78
|
+
*
|
|
79
|
+
* The framework side of game physics in a mwg game: it owns the solver, steps it with a
|
|
80
|
+
* `FixedStepper` so the simulation is the same at any display refresh rate, and reports
|
|
81
|
+
* contacts through a `Signal`, while leaving the bodies themselves as plain objects a game
|
|
82
|
+
* reads `position` and `angle` from to place its sprites. It is renderer-free, so a game's
|
|
83
|
+
* headless tests can run the same world. No third-party engine: semi-implicit Euler,
|
|
84
|
+
* impulse contacts with restitution and Coulomb friction, and projected distance joints.
|
|
55
85
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* renderer-free, so a game's headless tests can run the same world.
|
|
86
|
+
* Bodies never spin: `angle` stays where a game puts it (a display offset), collisions use
|
|
87
|
+
* the unrotated shape, and joints rotate their attachment points by it. Circles and
|
|
88
|
+
* axis-aligned boxes collide with each other in every pairing; that is the whole shape
|
|
89
|
+
* catalogue, by design rather than by omission - a game needing polygons brings its own.
|
|
61
90
|
*
|
|
62
|
-
* `matter-js` is an optional peer dependency (`npm install matter-js`), imported only by this
|
|
63
|
-
* module (`@datamoc/mw_games/physics`), so a game that never simulates physics never bundles it.
|
|
64
91
|
* Constraints are springs and rods. Give one a `maxStretch` and it breaks when pulled that far
|
|
65
92
|
* past its rest length (`onBreak`); a game with a different stress rule reads `stretchOf` itself
|
|
66
93
|
* and calls `remove`.
|
|
@@ -77,8 +104,7 @@ export type PhysicsConstraint = Matter.Constraint;
|
|
|
77
104
|
* ```
|
|
78
105
|
*/
|
|
79
106
|
export declare class PhysicsWorld {
|
|
80
|
-
|
|
81
|
-
/** fires once per new contact between two bodies, with the matter-js bodies of the pair */
|
|
107
|
+
/** fires once per new contact between two bodies, with the bodies of the pair */
|
|
82
108
|
readonly onContact: Signal<{
|
|
83
109
|
a: PhysicsBody;
|
|
84
110
|
b: PhysicsBody;
|
|
@@ -89,7 +115,11 @@ export declare class PhysicsWorld {
|
|
|
89
115
|
stretch: number;
|
|
90
116
|
}>;
|
|
91
117
|
private readonly stepper;
|
|
92
|
-
private readonly
|
|
118
|
+
private readonly gravity;
|
|
119
|
+
private readonly bodies_;
|
|
120
|
+
private readonly constraints_;
|
|
121
|
+
private touching;
|
|
122
|
+
private nextId;
|
|
93
123
|
constructor(options?: PhysicsOptions);
|
|
94
124
|
get bodies(): readonly PhysicsBody[];
|
|
95
125
|
get constraints(): readonly PhysicsConstraint[];
|
|
@@ -103,7 +133,7 @@ export declare class PhysicsWorld {
|
|
|
103
133
|
x: number;
|
|
104
134
|
y: number;
|
|
105
135
|
}, options?: ConstraintOptions): PhysicsConstraint;
|
|
106
|
-
/** removes a body, or a constraint, from the simulation */
|
|
136
|
+
/** removes a body (with its joints), or a constraint, from the simulation */
|
|
107
137
|
remove(item: PhysicsBody | PhysicsConstraint): void;
|
|
108
138
|
/**
|
|
109
139
|
* How far a constraint is stretched past its rest length, as a fraction of it (0.1 is 10%
|
|
@@ -117,6 +147,8 @@ export declare class PhysicsWorld {
|
|
|
117
147
|
* @returns how many fixed steps ran
|
|
118
148
|
*/
|
|
119
149
|
update(dt: number): number;
|
|
150
|
+
private step;
|
|
151
|
+
private collide;
|
|
120
152
|
private breakOverstretched;
|
|
121
153
|
private add;
|
|
122
154
|
}
|