@datamoc/mw_games 0.36.1 → 0.38.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.
- package/CHANGELOG.md +58 -0
- package/README.md +32 -2
- package/api-surface.json +384 -0
- package/dist/assets/paths.d.ts.map +1 -1
- package/dist/assets/paths.js +3 -0
- package/dist/assets/paths.js.map +1 -1
- package/dist/audio/Playable.d.ts.map +1 -1
- package/dist/audio/Playable.js +14 -1
- package/dist/audio/Playable.js.map +1 -1
- package/dist/audio/Synth.d.ts +14 -0
- package/dist/audio/Synth.d.ts.map +1 -1
- package/dist/audio/Synth.js +16 -0
- package/dist/audio/Synth.js.map +1 -1
- package/dist/audio/index.d.ts +1 -1
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +1 -1
- package/dist/audio/index.js.map +1 -1
- package/dist/core/FixedStepper.d.ts +38 -0
- package/dist/core/FixedStepper.d.ts.map +1 -0
- package/dist/core/FixedStepper.js +56 -0
- package/dist/core/FixedStepper.js.map +1 -0
- package/dist/core/Input.d.ts +61 -0
- package/dist/core/Input.d.ts.map +1 -1
- package/dist/core/Input.js +101 -0
- package/dist/core/Input.js.map +1 -1
- package/dist/core/StoredValue.d.ts +11 -2
- package/dist/core/StoredValue.d.ts.map +1 -1
- package/dist/core/StoredValue.js +11 -2
- package/dist/core/StoredValue.js.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/mw_games.global.js +121 -121
- package/dist/mwl/presentation.d.ts +70 -0
- package/dist/mwl/presentation.d.ts.map +1 -0
- package/dist/mwl/presentation.js +412 -0
- package/dist/mwl/presentation.js.map +1 -0
- package/dist/physics/PhysicsWorld.d.ts +123 -0
- package/dist/physics/PhysicsWorld.d.ts.map +1 -0
- package/dist/physics/PhysicsWorld.js +137 -0
- package/dist/physics/PhysicsWorld.js.map +1 -0
- package/dist/physics/XpbdWorld.d.ts +139 -0
- package/dist/physics/XpbdWorld.d.ts.map +1 -0
- package/dist/physics/XpbdWorld.js +207 -0
- package/dist/physics/XpbdWorld.js.map +1 -0
- package/dist/physics/index.d.ts +3 -0
- package/dist/physics/index.d.ts.map +1 -0
- package/dist/physics/index.js +2 -0
- package/dist/physics/index.js.map +1 -0
- package/dist/physics/xpbd.d.ts +3 -0
- package/dist/physics/xpbd.d.ts.map +1 -0
- package/dist/physics/xpbd.js +2 -0
- package/dist/physics/xpbd.js.map +1 -0
- package/dist/two-d/presentation/MwlPresentation.d.ts +98 -0
- package/dist/two-d/presentation/MwlPresentation.d.ts.map +1 -0
- package/dist/two-d/presentation/MwlPresentation.js +704 -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/Camera.d.ts +6 -0
- package/dist/two-d/render/Camera.d.ts.map +1 -1
- package/dist/two-d/render/Camera.js +9 -0
- package/dist/two-d/render/Camera.js.map +1 -1
- package/dist/two-d/render/Particles.d.ts +10 -1
- package/dist/two-d/render/Particles.d.ts.map +1 -1
- package/dist/two-d/render/Particles.js +14 -7
- package/dist/two-d/render/Particles.js.map +1 -1
- package/dist/two-d/render/Shape2D.d.ts +7 -0
- package/dist/two-d/render/Shape2D.d.ts.map +1 -1
- package/dist/two-d/render/Shape2D.js +18 -0
- package/dist/two-d/render/Shape2D.js.map +1 -1
- package/dist/two-d/render/SpriteSheet.d.ts +5 -0
- package/dist/two-d/render/SpriteSheet.d.ts.map +1 -1
- package/dist/two-d/render/SpriteSheet.js +15 -0
- package/dist/two-d/render/SpriteSheet.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 +19 -0
- package/dist/two-d/ui/Button.d.ts.map +1 -1
- package/dist/two-d/ui/Button.js +30 -4
- package/dist/two-d/ui/Button.js.map +1 -1
- package/dist/two-d/ui/Dropdown.d.ts +3 -0
- package/dist/two-d/ui/Dropdown.d.ts.map +1 -1
- package/dist/two-d/ui/Dropdown.js +3 -0
- package/dist/two-d/ui/Dropdown.js.map +1 -1
- package/dist/two-d/ui/DropdownView.d.ts +40 -0
- package/dist/two-d/ui/DropdownView.d.ts.map +1 -0
- package/dist/two-d/ui/DropdownView.js +75 -0
- package/dist/two-d/ui/DropdownView.js.map +1 -0
- package/dist/two-d/ui/Label.d.ts +2 -0
- package/dist/two-d/ui/Label.d.ts.map +1 -1
- package/dist/two-d/ui/Label.js +7 -0
- package/dist/two-d/ui/Label.js.map +1 -1
- package/dist/two-d/ui/Layout.d.ts +34 -0
- package/dist/two-d/ui/Layout.d.ts.map +1 -1
- package/dist/two-d/ui/Layout.js +47 -0
- package/dist/two-d/ui/Layout.js.map +1 -1
- package/dist/two-d/ui/Window.d.ts +17 -0
- package/dist/two-d/ui/Window.d.ts.map +1 -1
- package/dist/two-d/ui/Window.js +28 -4
- package/dist/two-d/ui/Window.js.map +1 -1
- package/dist/two-d/ui/index.d.ts +6 -2
- package/dist/two-d/ui/index.d.ts.map +1 -1
- package/dist/two-d/ui/index.js +2 -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 +36 -2
- package/sbom.cdx.json +58 -6
- package/tools/browser-driver.d.mts +14 -0
- package/tools/browser-driver.mjs +62 -0
- package/tools/build-tablebases.mjs +6 -2
- package/tools/classic-html.mjs +9 -1
- package/tools/compile-openings.mjs +6 -2
- package/tools/compile-resources.d.mts +5 -0
- package/tools/compile-resources.mjs +45 -4
- package/tools/compress-dist.mjs +15 -3
- package/tools/emit-page.mjs +5 -1
- package/tools/init.d.mts +5 -0
- package/tools/init.mjs +145 -0
- package/tools/play-uci.mjs +6 -3
- package/tools/sbom.mjs +5 -1
- package/tools/single-file.mjs +9 -1
- package/tools/verify-scenarios.d.mts +15 -0
- package/tools/verify-scenarios.mjs +129 -0
- package/tools/vite.mjs +5 -0
- package/tools/webp-convert.mjs +9 -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":"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"}
|
|
@@ -0,0 +1,412 @@
|
|
|
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
|
+
/**
|
|
163
|
+
* Compiles optional scene/UI definitions, validating every reference against the game's manifest.
|
|
164
|
+
* Reusable components are expanded at build time; emitted data contains no parser or executable content.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* import { compilePresentation, emitPresentationModule } from '@datamoc/mw_games/mwl/presentation';
|
|
169
|
+
* const data = compilePresentation([], { values: {}, actions: [] });
|
|
170
|
+
* console.log(emitPresentationModule(data).startsWith('export const presentationData')); // true
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export function compilePresentation(files, manifest) {
|
|
174
|
+
const game = compileSources(files, { schemas: { ...schema10, ...vocabulary } });
|
|
175
|
+
const roots = game.roots;
|
|
176
|
+
const definitions = new Map();
|
|
177
|
+
const sources = new Map();
|
|
178
|
+
const mountedComponents = new Set();
|
|
179
|
+
const tokenUses = [];
|
|
180
|
+
const fail = (node, message) => {
|
|
181
|
+
const location = node.location;
|
|
182
|
+
throw new Error(`${location?.file ?? '<presentation>'}:${location?.line ?? 1}:${location?.column ?? 1}: ${message}`);
|
|
183
|
+
};
|
|
184
|
+
const keyOf = (tag, id) => `${tag}:${id}`;
|
|
185
|
+
for (const node of roots) {
|
|
186
|
+
if (node.attributes.id === '__proto__')
|
|
187
|
+
fail(node, 'reserved definition id "__proto__"');
|
|
188
|
+
if (![
|
|
189
|
+
'theme_definition',
|
|
190
|
+
'presentation_context',
|
|
191
|
+
'component_variant',
|
|
192
|
+
'ui_component',
|
|
193
|
+
'scene_definition',
|
|
194
|
+
].includes(node.tag))
|
|
195
|
+
continue;
|
|
196
|
+
const key = keyOf(node.tag, node.attributes.id);
|
|
197
|
+
if (definitions.has(key))
|
|
198
|
+
fail(node, `duplicate ${key}`);
|
|
199
|
+
definitions.set(key, node);
|
|
200
|
+
}
|
|
201
|
+
const find = (node, tag, id) => definitions.get(keyOf(tag, id)) ?? fail(node, `unknown ${tag} "${id}"`);
|
|
202
|
+
const props = (node, excluded = ['id']) => Object.fromEntries(Object.entries(node.attributes).filter(([key]) => !excluded.includes(key)));
|
|
203
|
+
const validateStyle = (node) => {
|
|
204
|
+
if (node.attributes.image && !manifest.assets?.includes(node.attributes.image))
|
|
205
|
+
fail(node, `unknown asset "${node.attributes.image}"`);
|
|
206
|
+
for (const [name, value] of Object.entries(node.attributes)) {
|
|
207
|
+
if (name.endsWith('_token'))
|
|
208
|
+
tokenUses.push({ node, token: value });
|
|
209
|
+
if (['width', 'height', 'gap', 'padding'].includes(name) && Number(value) < 0)
|
|
210
|
+
fail(node, `${name} must be nonnegative`);
|
|
211
|
+
if (name === 'alpha' && (Number(value) < 0 || Number(value) > 1))
|
|
212
|
+
fail(node, 'alpha must be between 0 and 1');
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const readTokens = (node) => {
|
|
216
|
+
const tokens = Object.create(null);
|
|
217
|
+
for (const child of node.children.filter((child) => child.tag === 'theme_token')) {
|
|
218
|
+
const { id, value } = child.attributes;
|
|
219
|
+
if (id === '__proto__')
|
|
220
|
+
fail(child, 'reserved token id "__proto__"');
|
|
221
|
+
const color = Number(value);
|
|
222
|
+
if (Object.hasOwn(tokens, id))
|
|
223
|
+
fail(child, `duplicate theme token "${id}"`);
|
|
224
|
+
if (!Number.isInteger(color) || color < 0 || color > 0xffffff)
|
|
225
|
+
fail(child, `token "${id}" must be a 24-bit color`);
|
|
226
|
+
tokens[id] = color;
|
|
227
|
+
}
|
|
228
|
+
return tokens;
|
|
229
|
+
};
|
|
230
|
+
const themes = Object.create(null);
|
|
231
|
+
const contexts = Object.create(null);
|
|
232
|
+
const variants = Object.create(null);
|
|
233
|
+
const scenes = Object.create(null);
|
|
234
|
+
for (const node of roots) {
|
|
235
|
+
const id = node.attributes.id;
|
|
236
|
+
if (node.tag === 'theme_definition') {
|
|
237
|
+
validateStyle(node);
|
|
238
|
+
if (node.attributes.font_size !== undefined && Number(node.attributes.font_size) <= 0)
|
|
239
|
+
fail(node, 'font_size must be positive');
|
|
240
|
+
const tokens = readTokens(node);
|
|
241
|
+
for (const token of semanticTokens)
|
|
242
|
+
if (!Object.hasOwn(tokens, token))
|
|
243
|
+
fail(node, `missing semantic token "${token}"`);
|
|
244
|
+
themes[id] = { tokens, properties: props(node) };
|
|
245
|
+
}
|
|
246
|
+
else if (node.tag === 'component_variant') {
|
|
247
|
+
validateStyle(node);
|
|
248
|
+
variants[id] = props(node);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const buildTree = (nodes, prefix, fields, stack = []) => {
|
|
252
|
+
const siblings = new Set();
|
|
253
|
+
return nodes
|
|
254
|
+
.filter((node) => node.tag !== 'ui_state')
|
|
255
|
+
.map((node) => {
|
|
256
|
+
const id = node.attributes.id;
|
|
257
|
+
if (!id || siblings.has(id))
|
|
258
|
+
fail(node, `duplicate or missing component id "${id}" in ${prefix}`);
|
|
259
|
+
siblings.add(id);
|
|
260
|
+
const source = `${prefix}/${id}`;
|
|
261
|
+
sources.set(source, node);
|
|
262
|
+
validateStyle(node);
|
|
263
|
+
const attributes = node.attributes;
|
|
264
|
+
if (attributes.variant)
|
|
265
|
+
find(node, 'component_variant', attributes.variant);
|
|
266
|
+
for (const name of ['action', 'close_action'])
|
|
267
|
+
if (attributes[name] && !manifest.actions.includes(attributes[name]))
|
|
268
|
+
fail(node, `unknown action "${attributes[name]}"`);
|
|
269
|
+
if (attributes.adapter && !manifest.adapters?.includes(attributes.adapter))
|
|
270
|
+
fail(node, `unknown adapter "${attributes.adapter}"`);
|
|
271
|
+
for (const [name, expected] of Object.entries(bindingTypes)) {
|
|
272
|
+
const binding = attributes[name];
|
|
273
|
+
if (!binding)
|
|
274
|
+
continue;
|
|
275
|
+
const actual = binding.startsWith('item.') ? fields?.[binding.slice(5)] : manifest.values[binding];
|
|
276
|
+
if (actual !== expected)
|
|
277
|
+
fail(node, `binding "${binding}" for ${name} must be ${expected}`);
|
|
278
|
+
}
|
|
279
|
+
const states = Object.create(null);
|
|
280
|
+
for (const state of node.children.filter((child) => child.tag === 'ui_state')) {
|
|
281
|
+
if (Object.hasOwn(states, state.attributes.state))
|
|
282
|
+
fail(state, `duplicate component state "${state.attributes.state}"`);
|
|
283
|
+
validateStyle(state);
|
|
284
|
+
states[state.attributes.state] = props(state, ['state']);
|
|
285
|
+
}
|
|
286
|
+
let childNodes;
|
|
287
|
+
if (node.tag === 'ui_mount') {
|
|
288
|
+
const name = attributes.component;
|
|
289
|
+
if (stack.includes(name))
|
|
290
|
+
fail(node, `component cycle: ${[...stack, name].join(' -> ')}`);
|
|
291
|
+
mountedComponents.add(name);
|
|
292
|
+
const component = find(node, 'ui_component', name);
|
|
293
|
+
childNodes = buildTree(component.children, `component:${name}`, fields, [...stack, name]);
|
|
294
|
+
}
|
|
295
|
+
else if (node.tag === 'ui_repeat') {
|
|
296
|
+
const collection = manifest.values[attributes.items_binding];
|
|
297
|
+
if (!collection || typeof collection !== 'object' || collection.type !== 'items')
|
|
298
|
+
fail(node, `unknown collection "${attributes.items_binding}"`);
|
|
299
|
+
const itemFields = collection.fields;
|
|
300
|
+
if (!['string', 'number'].includes(itemFields[attributes.key]))
|
|
301
|
+
fail(node, `repeat key "${attributes.key}" must be a string or number field`);
|
|
302
|
+
if (node.children.filter((child) => child.tag !== 'ui_state').length !== 1)
|
|
303
|
+
fail(node, 'ui_repeat needs exactly one template child');
|
|
304
|
+
childNodes = buildTree(node.children, source, itemFields, stack);
|
|
305
|
+
}
|
|
306
|
+
else
|
|
307
|
+
childNodes = buildTree(node.children, source, fields, stack);
|
|
308
|
+
if (node.tag === 'ui_grid' && Number(attributes.columns) < 1)
|
|
309
|
+
fail(node, 'grid columns must be positive');
|
|
310
|
+
if (node.tag === 'scene_camera') {
|
|
311
|
+
if (attributes.zoom !== undefined && Number(attributes.zoom) <= 0)
|
|
312
|
+
fail(node, 'camera zoom must be positive');
|
|
313
|
+
if (Boolean(attributes.fit_width) !== Boolean(attributes.fit_height))
|
|
314
|
+
fail(node, 'camera fit needs width and height');
|
|
315
|
+
if (attributes.fit_width &&
|
|
316
|
+
(Number(attributes.fit_width) <= 0 || Number(attributes.fit_height) <= 0))
|
|
317
|
+
fail(node, 'camera fit dimensions must be positive');
|
|
318
|
+
}
|
|
319
|
+
return { kind: node.tag, id, source, properties: props(node), states, children: childNodes };
|
|
320
|
+
});
|
|
321
|
+
};
|
|
322
|
+
function componentFields(node) {
|
|
323
|
+
if (!node.attributes.items_binding)
|
|
324
|
+
return undefined;
|
|
325
|
+
const collection = manifest.values[node.attributes.items_binding];
|
|
326
|
+
if (typeof collection !== 'object' || collection.type !== 'items')
|
|
327
|
+
fail(node, `unknown collection "${node.attributes.items_binding}"`);
|
|
328
|
+
return collection.fields;
|
|
329
|
+
}
|
|
330
|
+
for (const node of roots.filter((node) => node.tag === 'scene_definition')) {
|
|
331
|
+
find(node, 'theme_definition', node.attributes.theme);
|
|
332
|
+
if (node.children.filter((child) => child.tag === 'scene_camera').length > 1)
|
|
333
|
+
fail(node, 'a scene can have only one camera');
|
|
334
|
+
scenes[node.attributes.id] = {
|
|
335
|
+
theme: node.attributes.theme,
|
|
336
|
+
children: buildTree(node.children, `scene:${node.attributes.id}`),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
// Validate unused reusable definitions too; an unmounted typo must not escape the build.
|
|
340
|
+
for (const node of roots.filter((node) => node.tag === 'ui_component')) {
|
|
341
|
+
if (!mountedComponents.has(node.attributes.id))
|
|
342
|
+
buildTree(node.children, `component:${node.attributes.id}`, componentFields(node), [node.attributes.id]);
|
|
343
|
+
}
|
|
344
|
+
for (const node of roots.filter((node) => node.tag === 'presentation_context')) {
|
|
345
|
+
find(node, 'theme_definition', node.attributes.theme);
|
|
346
|
+
const overrides = Object.create(null);
|
|
347
|
+
for (const override of node.children.filter((child) => child.tag === 'ui_override')) {
|
|
348
|
+
const target = override.attributes.target;
|
|
349
|
+
if (!sources.has(target))
|
|
350
|
+
fail(override, `unknown override target "${target}"`);
|
|
351
|
+
if (override.attributes.image && !['scene_layer', 'ui_adapter'].includes(sources.get(target).tag))
|
|
352
|
+
fail(override, 'image overrides require a scene layer or adapter');
|
|
353
|
+
if (Object.hasOwn(overrides, target))
|
|
354
|
+
fail(override, `duplicate override target "${target}"`);
|
|
355
|
+
validateStyle(override);
|
|
356
|
+
overrides[target] = props(override, ['target']);
|
|
357
|
+
}
|
|
358
|
+
const tokens = readTokens(node);
|
|
359
|
+
for (const token of Object.keys(tokens))
|
|
360
|
+
if (!Object.hasOwn(themes[node.attributes.theme].tokens, token))
|
|
361
|
+
fail(node, `unknown context token "${token}"`);
|
|
362
|
+
contexts[node.attributes.id] = { theme: node.attributes.theme, tokens, overrides };
|
|
363
|
+
}
|
|
364
|
+
const checkPalette = (node, tokens) => {
|
|
365
|
+
for (const use of tokenUses)
|
|
366
|
+
if (!Object.hasOwn(tokens, use.token))
|
|
367
|
+
fail(use.node, `unknown theme token "${use.token}" in ${node.attributes.id}`);
|
|
368
|
+
if (contrastRatio(tokens.text, tokens.panel) < 4.5)
|
|
369
|
+
fail(node, 'text/panel contrast must reach 4.5');
|
|
370
|
+
for (const token of ['danger', 'selection'])
|
|
371
|
+
if (contrastRatio(tokens[token], tokens.panel) < 3)
|
|
372
|
+
fail(node, `${token}/panel contrast must reach 3`);
|
|
373
|
+
};
|
|
374
|
+
for (const node of roots.filter((node) => node.tag === 'theme_definition'))
|
|
375
|
+
checkPalette(node, themes[node.attributes.id].tokens);
|
|
376
|
+
for (const node of roots.filter((node) => node.tag === 'presentation_context')) {
|
|
377
|
+
const context = contexts[node.attributes.id];
|
|
378
|
+
checkPalette(node, { ...themes[context.theme].tokens, ...context.tokens });
|
|
379
|
+
}
|
|
380
|
+
const ids = [];
|
|
381
|
+
const collect = (nodes, prefix) => {
|
|
382
|
+
for (const node of nodes) {
|
|
383
|
+
const path = `${prefix}/${node.id}`;
|
|
384
|
+
ids.push(path);
|
|
385
|
+
collect(node.children, node.kind === 'ui_repeat' ? `${path}/*` : path);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
for (const [id, scene] of Object.entries(scenes))
|
|
389
|
+
collect(scene.children, id);
|
|
390
|
+
return {
|
|
391
|
+
scenes,
|
|
392
|
+
themes,
|
|
393
|
+
contexts,
|
|
394
|
+
variants,
|
|
395
|
+
manifest,
|
|
396
|
+
ids: ids.sort(),
|
|
397
|
+
assets: game.assets,
|
|
398
|
+
messages: game.messages,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Emits data and literal ID types for a game's build script to write alongside its other MWL artifacts.
|
|
403
|
+
* @example
|
|
404
|
+
* ```ts
|
|
405
|
+
* import { compilePresentation, emitPresentationModule } from '@datamoc/mw_games/mwl/presentation';
|
|
406
|
+
* console.log(emitPresentationModule(compilePresentation([], { values: {}, actions: [] })));
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
export function emitPresentationModule(data) {
|
|
410
|
+
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`;
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=presentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation.js","sourceRoot":"","sources":["../../src/mwl/presentation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import Matter from 'matter-js';
|
|
2
|
+
import { Signal } from '../core/Signal.ts';
|
|
3
|
+
export interface PhysicsOptions {
|
|
4
|
+
/** gravity strength per axis; y grows downward. { x: 0, y: 9.8 } (the default) matches matter-js's own default pull */
|
|
5
|
+
gravity?: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
/** the fixed simulation step in seconds; 1/60 when omitted */
|
|
10
|
+
step?: number;
|
|
11
|
+
/** steps one `update` may run before it drops the backlog; 5 when omitted */
|
|
12
|
+
maxSubsteps?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface BodyOptions {
|
|
15
|
+
/** an immovable body: ground, anchors */
|
|
16
|
+
isStatic?: boolean;
|
|
17
|
+
/** 0 to 1, how much of its speed a bounce keeps; 0 when omitted */
|
|
18
|
+
restitution?: number;
|
|
19
|
+
friction?: number;
|
|
20
|
+
/** mass per unit area; matter-js's default when omitted */
|
|
21
|
+
density?: number;
|
|
22
|
+
angle?: number;
|
|
23
|
+
/** a name for collision callbacks and lookups */
|
|
24
|
+
label?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ConstraintOptions {
|
|
27
|
+
/** 0 to 1, how rigidly the ends are held: 1 is a rod, a small value a spring; 1 when omitted */
|
|
28
|
+
stiffness?: number;
|
|
29
|
+
damping?: number;
|
|
30
|
+
/** rest length; the distance between the attachment points when omitted */
|
|
31
|
+
length?: number;
|
|
32
|
+
/** attachment points in each body's local space; the body centre when omitted */
|
|
33
|
+
pointA?: {
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
};
|
|
37
|
+
pointB?: {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Makes the joint breakable: once its two ends are further apart than the rest length times
|
|
43
|
+
* `1 + maxStretch`, the constraint is removed and `onBreak` fires. 0.2 lets a beam stretch 20%
|
|
44
|
+
* before it snaps. For a zero-length joint (a pin) it is the absolute distance instead.
|
|
45
|
+
* The strain is read after each step's solve, so a fully rigid joint (`stiffness` 1) is pulled
|
|
46
|
+
* back before it is measured under a light load: use a stiffness below 1, as a real beam has.
|
|
47
|
+
* Unbreakable when omitted.
|
|
48
|
+
*/
|
|
49
|
+
maxStretch?: number;
|
|
50
|
+
}
|
|
51
|
+
export type PhysicsBody = Matter.Body;
|
|
52
|
+
export type PhysicsConstraint = Matter.Constraint;
|
|
53
|
+
/**
|
|
54
|
+
* Rigid bodies and constraints through matter-js, stepped on a fixed clock.
|
|
55
|
+
*
|
|
56
|
+
* The adapter is the framework side of using matter-js in a mwg game: it owns the `Engine`,
|
|
57
|
+
* steps it with a `FixedStepper` so the simulation is the same at any display refresh rate,
|
|
58
|
+
* and reports contacts through a `Signal`, while leaving the bodies themselves as plain
|
|
59
|
+
* matter-js objects a game reads `position` and `angle` from to place its sprites. It is
|
|
60
|
+
* renderer-free, so a game's headless tests can run the same world.
|
|
61
|
+
*
|
|
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
|
+
* Constraints are springs and rods. Give one a `maxStretch` and it breaks when pulled that far
|
|
65
|
+
* past its rest length (`onBreak`); a game with a different stress rule reads `stretchOf` itself
|
|
66
|
+
* and calls `remove`.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { PhysicsWorld } from '@datamoc/mw_games/physics';
|
|
71
|
+
*
|
|
72
|
+
* const world = new PhysicsWorld();
|
|
73
|
+
* world.addBox(0, 300, 800, 20, { isStatic: true });
|
|
74
|
+
* const crate = world.addBox(100, 0, 40, 40, { restitution: 0.3 });
|
|
75
|
+
* world.update(1 / 30); // two fixed steps
|
|
76
|
+
* console.log(crate.position.y > 0); // true: it has started to fall
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare class PhysicsWorld {
|
|
80
|
+
readonly engine: Matter.Engine;
|
|
81
|
+
/** fires once per new contact between two bodies, with the matter-js bodies of the pair */
|
|
82
|
+
readonly onContact: Signal<{
|
|
83
|
+
a: PhysicsBody;
|
|
84
|
+
b: PhysicsBody;
|
|
85
|
+
}>;
|
|
86
|
+
/** fires when a breakable constraint passes its `maxStretch`; it is already removed from the world */
|
|
87
|
+
readonly onBreak: Signal<{
|
|
88
|
+
constraint: PhysicsConstraint;
|
|
89
|
+
stretch: number;
|
|
90
|
+
}>;
|
|
91
|
+
private readonly stepper;
|
|
92
|
+
private readonly breakable;
|
|
93
|
+
constructor(options?: PhysicsOptions);
|
|
94
|
+
get bodies(): readonly PhysicsBody[];
|
|
95
|
+
get constraints(): readonly PhysicsConstraint[];
|
|
96
|
+
/** how far into the next fixed step the clock is, 0 to 1, for interpolated drawing */
|
|
97
|
+
get alpha(): number;
|
|
98
|
+
/** a box centred on (x, y) */
|
|
99
|
+
addBox(x: number, y: number, width: number, height: number, options?: BodyOptions): PhysicsBody;
|
|
100
|
+
addCircle(x: number, y: number, radius: number, options?: BodyOptions): PhysicsBody;
|
|
101
|
+
/** joins two bodies, or a body to a fixed point in the world when `b` is a point */
|
|
102
|
+
addConstraint(a: PhysicsBody, b: PhysicsBody | {
|
|
103
|
+
x: number;
|
|
104
|
+
y: number;
|
|
105
|
+
}, options?: ConstraintOptions): PhysicsConstraint;
|
|
106
|
+
/** removes a body, or a constraint, from the simulation */
|
|
107
|
+
remove(item: PhysicsBody | PhysicsConstraint): void;
|
|
108
|
+
/**
|
|
109
|
+
* How far a constraint is stretched past its rest length, as a fraction of it (0.1 is 10%
|
|
110
|
+
* longer); for a zero-length joint, the distance between its ends. Negative when compressed.
|
|
111
|
+
*/
|
|
112
|
+
stretchOf(constraint: PhysicsConstraint): number;
|
|
113
|
+
/**
|
|
114
|
+
* Advances the simulation by `dt` seconds of real time, running as many fixed steps as that
|
|
115
|
+
* covers; call it from `Scene.update(dt)`.
|
|
116
|
+
*
|
|
117
|
+
* @returns how many fixed steps ran
|
|
118
|
+
*/
|
|
119
|
+
update(dt: number): number;
|
|
120
|
+
private breakOverstretched;
|
|
121
|
+
private add;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=PhysicsWorld.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhysicsWorld.d.ts","sourceRoot":"","sources":["../../src/physics/PhysicsWorld.ts"],"names":[],"mappings":"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"}
|