@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.
Files changed (113) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +26 -0
  3. package/api-surface.json +650 -2
  4. package/dist/assets/SvgParts.d.ts +31 -0
  5. package/dist/assets/SvgParts.d.ts.map +1 -0
  6. package/dist/assets/SvgParts.js +54 -0
  7. package/dist/assets/SvgParts.js.map +1 -0
  8. package/dist/assets/SvgSource.d.ts +3 -0
  9. package/dist/assets/SvgSource.d.ts.map +1 -0
  10. package/dist/assets/SvgSource.js +22 -0
  11. package/dist/assets/SvgSource.js.map +1 -0
  12. package/dist/assets/index.d.ts +2 -0
  13. package/dist/assets/index.d.ts.map +1 -1
  14. package/dist/assets/index.js +1 -0
  15. package/dist/assets/index.js.map +1 -1
  16. package/dist/assets/svg.d.ts.map +1 -1
  17. package/dist/assets/svg.js +9 -5
  18. package/dist/assets/svg.js.map +1 -1
  19. package/dist/mw_games.global.js +110 -110
  20. package/dist/mwl/presentation.d.ts +70 -0
  21. package/dist/mwl/presentation.d.ts.map +1 -0
  22. package/dist/mwl/presentation.js +419 -0
  23. package/dist/mwl/presentation.js.map +1 -0
  24. package/dist/physics/PhysicsWorld.d.ts +49 -17
  25. package/dist/physics/PhysicsWorld.d.ts.map +1 -1
  26. package/dist/physics/PhysicsWorld.js +297 -59
  27. package/dist/physics/PhysicsWorld.js.map +1 -1
  28. package/dist/physics/XpbdWorld.d.ts +1 -1
  29. package/dist/physics/XpbdWorld.js +1 -1
  30. package/dist/physics/cloth/index.d.ts +98 -0
  31. package/dist/physics/cloth/index.d.ts.map +1 -0
  32. package/dist/physics/cloth/index.js +207 -0
  33. package/dist/physics/cloth/index.js.map +1 -0
  34. package/dist/physics/index.d.ts +4 -0
  35. package/dist/physics/index.d.ts.map +1 -1
  36. package/dist/physics/index.js +2 -0
  37. package/dist/physics/index.js.map +1 -1
  38. package/dist/physics/spring/index.d.ts +90 -0
  39. package/dist/physics/spring/index.d.ts.map +1 -0
  40. package/dist/physics/spring/index.js +97 -0
  41. package/dist/physics/spring/index.js.map +1 -0
  42. package/dist/skeleton/index.d.ts +94 -13
  43. package/dist/skeleton/index.d.ts.map +1 -1
  44. package/dist/skeleton/index.js +192 -73
  45. package/dist/skeleton/index.js.map +1 -1
  46. package/dist/two-d/presentation/MwlPresentation.d.ts +110 -0
  47. package/dist/two-d/presentation/MwlPresentation.d.ts.map +1 -0
  48. package/dist/two-d/presentation/MwlPresentation.js +755 -0
  49. package/dist/two-d/presentation/MwlPresentation.js.map +1 -0
  50. package/dist/two-d/presentation/index.d.ts +3 -0
  51. package/dist/two-d/presentation/index.d.ts.map +1 -0
  52. package/dist/two-d/presentation/index.js +2 -0
  53. package/dist/two-d/presentation/index.js.map +1 -0
  54. package/dist/two-d/render/ClothSprite.d.ts +83 -0
  55. package/dist/two-d/render/ClothSprite.d.ts.map +1 -0
  56. package/dist/two-d/render/ClothSprite.js +105 -0
  57. package/dist/two-d/render/ClothSprite.js.map +1 -0
  58. package/dist/two-d/render/HazeLayer.d.ts +112 -0
  59. package/dist/two-d/render/HazeLayer.d.ts.map +1 -0
  60. package/dist/two-d/render/HazeLayer.js +185 -0
  61. package/dist/two-d/render/HazeLayer.js.map +1 -0
  62. package/dist/two-d/render/NeonGlow.d.ts +100 -0
  63. package/dist/two-d/render/NeonGlow.d.ts.map +1 -0
  64. package/dist/two-d/render/NeonGlow.js +183 -0
  65. package/dist/two-d/render/NeonGlow.js.map +1 -0
  66. package/dist/two-d/render/SkeletalSprite.d.ts +5 -2
  67. package/dist/two-d/render/SkeletalSprite.d.ts.map +1 -1
  68. package/dist/two-d/render/SkeletalSprite.js +27 -3
  69. package/dist/two-d/render/SkeletalSprite.js.map +1 -1
  70. package/dist/two-d/render/SpringSprite.d.ts +40 -0
  71. package/dist/two-d/render/SpringSprite.d.ts.map +1 -0
  72. package/dist/two-d/render/SpringSprite.js +39 -0
  73. package/dist/two-d/render/SpringSprite.js.map +1 -0
  74. package/dist/two-d/render/SpriteDeform.d.ts +156 -0
  75. package/dist/two-d/render/SpriteDeform.d.ts.map +1 -0
  76. package/dist/two-d/render/SpriteDeform.js +278 -0
  77. package/dist/two-d/render/SpriteDeform.js.map +1 -0
  78. package/dist/two-d/render/SvgSkeleton.d.ts +54 -0
  79. package/dist/two-d/render/SvgSkeleton.d.ts.map +1 -0
  80. package/dist/two-d/render/SvgSkeleton.js +112 -0
  81. package/dist/two-d/render/SvgSkeleton.js.map +1 -0
  82. package/dist/two-d/render/index.d.ts +12 -0
  83. package/dist/two-d/render/index.d.ts.map +1 -1
  84. package/dist/two-d/render/index.js +6 -0
  85. package/dist/two-d/render/index.js.map +1 -1
  86. package/dist/two-d/ui/Bar.d.ts +3 -1
  87. package/dist/two-d/ui/Bar.d.ts.map +1 -1
  88. package/dist/two-d/ui/Bar.js +5 -0
  89. package/dist/two-d/ui/Bar.js.map +1 -1
  90. package/dist/two-d/ui/Button.d.ts +12 -0
  91. package/dist/two-d/ui/Button.d.ts.map +1 -1
  92. package/dist/two-d/ui/Button.js +16 -4
  93. package/dist/two-d/ui/Button.js.map +1 -1
  94. package/dist/two-d/ui/Window.d.ts +10 -0
  95. package/dist/two-d/ui/Window.d.ts.map +1 -1
  96. package/dist/two-d/ui/Window.js +17 -6
  97. package/dist/two-d/ui/Window.js.map +1 -1
  98. package/dist/two-d/ui/index.d.ts +2 -0
  99. package/dist/two-d/ui/index.d.ts.map +1 -1
  100. package/dist/two-d/ui/index.js.map +1 -1
  101. package/dist/version.d.ts +1 -1
  102. package/dist/version.js +1 -1
  103. package/package.json +24 -7
  104. package/sbom.cdx.json +6 -58
  105. package/tools/asset-report.d.mts +37 -0
  106. package/tools/asset-report.mjs +157 -0
  107. package/tools/compile-resources.d.mts +2 -0
  108. package/tools/compile-resources.mjs +23 -2
  109. package/tools/emit-page.d.mts +2 -0
  110. package/tools/emit-page.mjs +11 -1
  111. package/tools/verify-scenarios.d.mts +15 -0
  112. package/tools/verify-scenarios.mjs +129 -0
  113. 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":"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"}
@@ -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":"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"}
@@ -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. { x: 0, y: 9.8 } (the default) matches matter-js's own default pull */
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; matter-js's default when omitted */
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
- export type PhysicsBody = Matter.Body;
52
- export type PhysicsConstraint = Matter.Constraint;
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 through matter-js, stepped on a fixed clock.
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
- * 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.
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
- readonly engine: Matter.Engine;
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 breakable;
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
  }