@datamoc/mw_games 0.42.0 → 0.44.2

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 (333) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +84 -1
  3. package/REFERENCE.md +134 -6
  4. package/api-surface.json +1814 -116
  5. package/data/microgm-essential.PROVENANCE.md +13 -0
  6. package/data/microgm-essential.sf2 +0 -0
  7. package/data/soundfont-catalog.json +8 -0
  8. package/dist/actors/Resource.d.ts.map +1 -1
  9. package/dist/actors/Resource.js +2 -3
  10. package/dist/actors/Resource.js.map +1 -1
  11. package/dist/audio/AdaptiveMusic.d.ts +85 -0
  12. package/dist/audio/AdaptiveMusic.d.ts.map +1 -0
  13. package/dist/audio/AdaptiveMusic.js +230 -0
  14. package/dist/audio/AdaptiveMusic.js.map +1 -0
  15. package/dist/audio/AudioLoader.d.ts +33 -0
  16. package/dist/audio/AudioLoader.d.ts.map +1 -0
  17. package/dist/audio/AudioLoader.js +58 -0
  18. package/dist/audio/AudioLoader.js.map +1 -0
  19. package/dist/audio/AudioViews.d.ts +70 -0
  20. package/dist/audio/AudioViews.d.ts.map +1 -0
  21. package/dist/audio/AudioViews.js +119 -0
  22. package/dist/audio/AudioViews.js.map +1 -0
  23. package/dist/audio/BusBudget.d.ts +89 -0
  24. package/dist/audio/BusBudget.d.ts.map +1 -0
  25. package/dist/audio/BusBudget.js +120 -0
  26. package/dist/audio/BusBudget.js.map +1 -0
  27. package/dist/audio/Channels.d.ts +66 -1
  28. package/dist/audio/Channels.d.ts.map +1 -1
  29. package/dist/audio/Channels.js +119 -31
  30. package/dist/audio/Channels.js.map +1 -1
  31. package/dist/audio/CoreHost.d.ts +114 -0
  32. package/dist/audio/CoreHost.d.ts.map +1 -0
  33. package/dist/audio/CoreHost.js +335 -0
  34. package/dist/audio/CoreHost.js.map +1 -0
  35. package/dist/audio/DecoderGuard.d.ts +139 -0
  36. package/dist/audio/DecoderGuard.d.ts.map +1 -0
  37. package/dist/audio/DecoderGuard.js +208 -0
  38. package/dist/audio/DecoderGuard.js.map +1 -0
  39. package/dist/audio/Fft.d.ts +3 -0
  40. package/dist/audio/Fft.d.ts.map +1 -0
  41. package/dist/audio/Fft.js +45 -0
  42. package/dist/audio/Fft.js.map +1 -0
  43. package/dist/audio/LoopTags.d.ts +18 -0
  44. package/dist/audio/LoopTags.d.ts.map +1 -1
  45. package/dist/audio/LoopTags.js +20 -0
  46. package/dist/audio/LoopTags.js.map +1 -1
  47. package/dist/audio/Midi.d.ts +35 -0
  48. package/dist/audio/Midi.d.ts.map +1 -1
  49. package/dist/audio/Midi.js +71 -1
  50. package/dist/audio/Midi.js.map +1 -1
  51. package/dist/audio/MidiRender.d.ts +47 -0
  52. package/dist/audio/MidiRender.d.ts.map +1 -1
  53. package/dist/audio/MidiRender.js +100 -2
  54. package/dist/audio/MidiRender.js.map +1 -1
  55. package/dist/audio/MidiSynth.d.ts +147 -0
  56. package/dist/audio/MidiSynth.d.ts.map +1 -0
  57. package/dist/audio/MidiSynth.js +205 -0
  58. package/dist/audio/MidiSynth.js.map +1 -0
  59. package/dist/audio/MusicPlayer.d.ts +80 -0
  60. package/dist/audio/MusicPlayer.d.ts.map +1 -0
  61. package/dist/audio/MusicPlayer.js +147 -0
  62. package/dist/audio/MusicPlayer.js.map +1 -0
  63. package/dist/audio/Playable.d.ts +7 -0
  64. package/dist/audio/Playable.d.ts.map +1 -1
  65. package/dist/audio/Playable.js.map +1 -1
  66. package/dist/audio/Positional.d.ts +12 -4
  67. package/dist/audio/Positional.d.ts.map +1 -1
  68. package/dist/audio/Positional.js +5 -2
  69. package/dist/audio/Positional.js.map +1 -1
  70. package/dist/audio/Resample.d.ts +61 -0
  71. package/dist/audio/Resample.d.ts.map +1 -0
  72. package/dist/audio/Resample.js +97 -0
  73. package/dist/audio/Resample.js.map +1 -0
  74. package/dist/audio/SampleDecoder.d.ts +16 -2
  75. package/dist/audio/SampleDecoder.d.ts.map +1 -1
  76. package/dist/audio/SampleDecoder.js +10 -6
  77. package/dist/audio/SampleDecoder.js.map +1 -1
  78. package/dist/audio/Settings.d.ts +99 -0
  79. package/dist/audio/Settings.d.ts.map +1 -0
  80. package/dist/audio/Settings.js +134 -0
  81. package/dist/audio/Settings.js.map +1 -0
  82. package/dist/audio/Sfx.d.ts +148 -0
  83. package/dist/audio/Sfx.d.ts.map +1 -0
  84. package/dist/audio/Sfx.js +213 -0
  85. package/dist/audio/Sfx.js.map +1 -0
  86. package/dist/audio/Sound.d.ts +2 -0
  87. package/dist/audio/Sound.d.ts.map +1 -1
  88. package/dist/audio/Sound.js +3 -0
  89. package/dist/audio/Sound.js.map +1 -1
  90. package/dist/audio/SoundFont.d.ts +5 -3
  91. package/dist/audio/SoundFont.d.ts.map +1 -1
  92. package/dist/audio/SoundFont.js +10 -8
  93. package/dist/audio/SoundFont.js.map +1 -1
  94. package/dist/audio/SpectralDistance.d.ts +34 -0
  95. package/dist/audio/SpectralDistance.d.ts.map +1 -0
  96. package/dist/audio/SpectralDistance.js +64 -0
  97. package/dist/audio/SpectralDistance.js.map +1 -0
  98. package/dist/audio/StreamChannel.d.ts +150 -0
  99. package/dist/audio/StreamChannel.d.ts.map +1 -0
  100. package/dist/audio/StreamChannel.js +390 -0
  101. package/dist/audio/StreamChannel.js.map +1 -0
  102. package/dist/audio/StreamPlayable.d.ts +73 -0
  103. package/dist/audio/StreamPlayable.d.ts.map +1 -0
  104. package/dist/audio/StreamPlayable.js +130 -0
  105. package/dist/audio/StreamPlayable.js.map +1 -0
  106. package/dist/audio/Synth.d.ts +1 -1
  107. package/dist/audio/Synth.d.ts.map +1 -1
  108. package/dist/audio/Synth.js +4 -0
  109. package/dist/audio/Synth.js.map +1 -1
  110. package/dist/audio/SyxBank.d.ts +73 -0
  111. package/dist/audio/SyxBank.d.ts.map +1 -0
  112. package/dist/audio/SyxBank.js +130 -0
  113. package/dist/audio/SyxBank.js.map +1 -0
  114. package/dist/audio/Underrun.d.ts +25 -0
  115. package/dist/audio/Underrun.d.ts.map +1 -0
  116. package/dist/audio/Underrun.js +18 -0
  117. package/dist/audio/Underrun.js.map +1 -0
  118. package/dist/audio/Wav.d.ts +56 -0
  119. package/dist/audio/Wav.d.ts.map +1 -0
  120. package/dist/audio/Wav.js +164 -0
  121. package/dist/audio/Wav.js.map +1 -0
  122. package/dist/audio/WebMidi.d.ts +58 -0
  123. package/dist/audio/WebMidi.d.ts.map +1 -0
  124. package/dist/audio/WebMidi.js +79 -0
  125. package/dist/audio/WebMidi.js.map +1 -0
  126. package/dist/audio/humanize/Onsets.d.ts.map +1 -1
  127. package/dist/audio/humanize/Onsets.js +1 -44
  128. package/dist/audio/humanize/Onsets.js.map +1 -1
  129. package/dist/audio/index.d.ts +43 -7
  130. package/dist/audio/index.d.ts.map +1 -1
  131. package/dist/audio/index.js +21 -3
  132. package/dist/audio/index.js.map +1 -1
  133. package/dist/battle/AttackPreview.d.ts.map +1 -1
  134. package/dist/battle/AttackPreview.js +8 -8
  135. package/dist/battle/AttackPreview.js.map +1 -1
  136. package/dist/battle/StatStages.d.ts.map +1 -1
  137. package/dist/battle/StatStages.js +2 -1
  138. package/dist/battle/StatStages.js.map +1 -1
  139. package/dist/board/Engine.d.ts +2 -0
  140. package/dist/board/Engine.d.ts.map +1 -1
  141. package/dist/board/Engine.js +1 -1
  142. package/dist/board/Engine.js.map +1 -1
  143. package/dist/board/HexSkirmish.d.ts.map +1 -1
  144. package/dist/board/HexSkirmish.js +11 -72
  145. package/dist/board/HexSkirmish.js.map +1 -1
  146. package/dist/board/Tactics.d.ts.map +1 -1
  147. package/dist/board/Tactics.js +3 -5
  148. package/dist/board/Tactics.js.map +1 -1
  149. package/dist/board/tourney.d.ts.map +1 -1
  150. package/dist/board/tourney.js +2 -19
  151. package/dist/board/tourney.js.map +1 -1
  152. package/dist/core/Handles.js +7 -7
  153. package/dist/core/Handles.js.map +1 -1
  154. package/dist/mw_games.global.js +25 -22
  155. package/dist/mwl/conditions.d.ts +12 -0
  156. package/dist/mwl/conditions.d.ts.map +1 -1
  157. package/dist/mwl/conditions.js +49 -8
  158. package/dist/mwl/conditions.js.map +1 -1
  159. package/dist/mwl/index.d.ts +13 -0
  160. package/dist/mwl/index.d.ts.map +1 -1
  161. package/dist/mwl/index.js +7 -0
  162. package/dist/mwl/index.js.map +1 -1
  163. package/dist/mwl/objects.d.ts +31 -0
  164. package/dist/mwl/objects.d.ts.map +1 -0
  165. package/dist/mwl/objects.js +83 -0
  166. package/dist/mwl/objects.js.map +1 -0
  167. package/dist/mwl/package-container.d.ts +185 -0
  168. package/dist/mwl/package-container.d.ts.map +1 -0
  169. package/dist/mwl/package-container.js +446 -0
  170. package/dist/mwl/package-container.js.map +1 -0
  171. package/dist/mwl/package-document.d.ts +217 -0
  172. package/dist/mwl/package-document.d.ts.map +1 -0
  173. package/dist/mwl/package-document.js +639 -0
  174. package/dist/mwl/package-document.js.map +1 -0
  175. package/dist/mwl/package-rom.d.ts +37 -0
  176. package/dist/mwl/package-rom.d.ts.map +1 -0
  177. package/dist/mwl/package-rom.js +96 -0
  178. package/dist/mwl/package-rom.js.map +1 -0
  179. package/dist/mwl/package-verify.d.ts +34 -0
  180. package/dist/mwl/package-verify.d.ts.map +1 -0
  181. package/dist/mwl/package-verify.js +111 -0
  182. package/dist/mwl/package-verify.js.map +1 -0
  183. package/dist/mwl/package.d.ts +184 -0
  184. package/dist/mwl/package.d.ts.map +1 -0
  185. package/dist/mwl/package.js +382 -0
  186. package/dist/mwl/package.js.map +1 -0
  187. package/dist/mwl/schema.d.ts +1 -1
  188. package/dist/mwl/schema.d.ts.map +1 -1
  189. package/dist/mwl/tables.d.ts +2 -0
  190. package/dist/mwl/tables.d.ts.map +1 -1
  191. package/dist/mwl/tables.js +13 -0
  192. package/dist/mwl/tables.js.map +1 -1
  193. package/dist/physics/PhysicsWorld.d.ts.map +1 -1
  194. package/dist/physics/PhysicsWorld.js +4 -3
  195. package/dist/physics/PhysicsWorld.js.map +1 -1
  196. package/dist/physics/XpbdWorld.d.ts +23 -5
  197. package/dist/physics/XpbdWorld.d.ts.map +1 -1
  198. package/dist/physics/XpbdWorld.js +91 -6
  199. package/dist/physics/XpbdWorld.js.map +1 -1
  200. package/dist/testing/FakeAudio.d.ts +149 -0
  201. package/dist/testing/FakeAudio.d.ts.map +1 -0
  202. package/dist/testing/FakeAudio.js +219 -0
  203. package/dist/testing/FakeAudio.js.map +1 -0
  204. package/dist/testing/index.d.ts +18 -0
  205. package/dist/testing/index.d.ts.map +1 -1
  206. package/dist/testing/index.js +22 -0
  207. package/dist/testing/index.js.map +1 -1
  208. package/dist/threads/index.d.ts +2 -2
  209. package/dist/threads/index.d.ts.map +1 -1
  210. package/dist/threads/index.js +1 -1
  211. package/dist/threads/index.js.map +1 -1
  212. package/dist/threads/spawn.d.ts +32 -0
  213. package/dist/threads/spawn.d.ts.map +1 -1
  214. package/dist/threads/spawn.js +35 -11
  215. package/dist/threads/spawn.js.map +1 -1
  216. package/dist/three-d/Collision3D.d.ts +46 -2
  217. package/dist/three-d/Collision3D.d.ts.map +1 -1
  218. package/dist/three-d/Collision3D.js +46 -2
  219. package/dist/three-d/Collision3D.js.map +1 -1
  220. package/dist/three-d/Grid.d.ts +12 -1
  221. package/dist/three-d/Grid.d.ts.map +1 -1
  222. package/dist/three-d/Grid.js +12 -1
  223. package/dist/three-d/Grid.js.map +1 -1
  224. package/dist/three-d/Vox.d.ts +13 -1
  225. package/dist/three-d/Vox.d.ts.map +1 -1
  226. package/dist/three-d/Vox.js +13 -1
  227. package/dist/three-d/Vox.js.map +1 -1
  228. package/dist/two-d/Game.d.ts +32 -1
  229. package/dist/two-d/Game.d.ts.map +1 -1
  230. package/dist/two-d/Game.js +105 -14
  231. package/dist/two-d/Game.js.map +1 -1
  232. package/dist/two-d/Scene2D.d.ts +24 -0
  233. package/dist/two-d/Scene2D.d.ts.map +1 -1
  234. package/dist/two-d/Scene2D.js +30 -0
  235. package/dist/two-d/Scene2D.js.map +1 -1
  236. package/dist/two-d/render/HazeLayer.d.ts.map +1 -1
  237. package/dist/two-d/render/HazeLayer.js +2 -1
  238. package/dist/two-d/render/HazeLayer.js.map +1 -1
  239. package/dist/two-d/render/ImageModifiers.d.ts +4 -2
  240. package/dist/two-d/render/ImageModifiers.d.ts.map +1 -1
  241. package/dist/two-d/render/ImageModifiers.js +13 -8
  242. package/dist/two-d/render/ImageModifiers.js.map +1 -1
  243. package/dist/two-d/render/NeonGlow.d.ts.map +1 -1
  244. package/dist/two-d/render/NeonGlow.js +2 -1
  245. package/dist/two-d/render/NeonGlow.js.map +1 -1
  246. package/dist/two-d/render/Particles.d.ts.map +1 -1
  247. package/dist/two-d/render/Particles.js +2 -1
  248. package/dist/two-d/render/Particles.js.map +1 -1
  249. package/dist/two-d/render/SceneTransition.d.ts +301 -0
  250. package/dist/two-d/render/SceneTransition.d.ts.map +1 -0
  251. package/dist/two-d/render/SceneTransition.js +458 -0
  252. package/dist/two-d/render/SceneTransition.js.map +1 -0
  253. package/dist/two-d/render/ScreenEffects.d.ts.map +1 -1
  254. package/dist/two-d/render/ScreenEffects.js +2 -1
  255. package/dist/two-d/render/ScreenEffects.js.map +1 -1
  256. package/dist/two-d/render/SkeletalSprite.d.ts.map +1 -1
  257. package/dist/two-d/render/SkeletalSprite.js +2 -1
  258. package/dist/two-d/render/SkeletalSprite.js.map +1 -1
  259. package/dist/two-d/render/Types2D.d.ts +2 -2
  260. package/dist/two-d/render/Types2D.d.ts.map +1 -1
  261. package/dist/two-d/render/Types2D.js +2 -2
  262. package/dist/two-d/render/Types2D.js.map +1 -1
  263. package/dist/two-d/render/index.d.ts +2 -0
  264. package/dist/two-d/render/index.d.ts.map +1 -1
  265. package/dist/two-d/render/index.js +1 -0
  266. package/dist/two-d/render/index.js.map +1 -1
  267. package/dist/two-d/ui/Bar.d.ts.map +1 -1
  268. package/dist/two-d/ui/Bar.js +3 -5
  269. package/dist/two-d/ui/Bar.js.map +1 -1
  270. package/dist/two-d/ui/Button.d.ts +23 -0
  271. package/dist/two-d/ui/Button.d.ts.map +1 -1
  272. package/dist/two-d/ui/Button.js +37 -0
  273. package/dist/two-d/ui/Button.js.map +1 -1
  274. package/dist/two-d/ui/Dropdown.d.ts +5 -1
  275. package/dist/two-d/ui/Dropdown.d.ts.map +1 -1
  276. package/dist/two-d/ui/Dropdown.js +8 -1
  277. package/dist/two-d/ui/Dropdown.js.map +1 -1
  278. package/dist/two-d/ui/DropdownView.d.ts +63 -3
  279. package/dist/two-d/ui/DropdownView.d.ts.map +1 -1
  280. package/dist/two-d/ui/DropdownView.js +168 -9
  281. package/dist/two-d/ui/DropdownView.js.map +1 -1
  282. package/dist/two-d/ui/FloatingText.d.ts.map +1 -1
  283. package/dist/two-d/ui/FloatingText.js +2 -1
  284. package/dist/two-d/ui/FloatingText.js.map +1 -1
  285. package/dist/two-d/ui/IconGrid.d.ts.map +1 -1
  286. package/dist/two-d/ui/IconGrid.js +2 -1
  287. package/dist/two-d/ui/IconGrid.js.map +1 -1
  288. package/dist/two-d/ui/ListView.d.ts.map +1 -1
  289. package/dist/two-d/ui/ListView.js +2 -1
  290. package/dist/two-d/ui/ListView.js.map +1 -1
  291. package/dist/two-d/ui/ScrollBox.d.ts +96 -0
  292. package/dist/two-d/ui/ScrollBox.d.ts.map +1 -1
  293. package/dist/two-d/ui/ScrollBox.js +218 -5
  294. package/dist/two-d/ui/ScrollBox.js.map +1 -1
  295. package/dist/two-d/ui/ScrollText.d.ts +131 -0
  296. package/dist/two-d/ui/ScrollText.d.ts.map +1 -0
  297. package/dist/two-d/ui/ScrollText.js +218 -0
  298. package/dist/two-d/ui/ScrollText.js.map +1 -0
  299. package/dist/two-d/ui/Slider.d.ts.map +1 -1
  300. package/dist/two-d/ui/Slider.js +4 -4
  301. package/dist/two-d/ui/Slider.js.map +1 -1
  302. package/dist/two-d/ui/Tooltip.d.ts +70 -1
  303. package/dist/two-d/ui/Tooltip.d.ts.map +1 -1
  304. package/dist/two-d/ui/Tooltip.js +115 -3
  305. package/dist/two-d/ui/Tooltip.js.map +1 -1
  306. package/dist/two-d/ui/Window.d.ts +35 -2
  307. package/dist/two-d/ui/Window.d.ts.map +1 -1
  308. package/dist/two-d/ui/Window.js +58 -3
  309. package/dist/two-d/ui/Window.js.map +1 -1
  310. package/dist/two-d/ui/index.d.ts +7 -5
  311. package/dist/two-d/ui/index.d.ts.map +1 -1
  312. package/dist/two-d/ui/index.js +3 -2
  313. package/dist/two-d/ui/index.js.map +1 -1
  314. package/dist/version.d.ts +1 -1
  315. package/dist/version.js +1 -1
  316. package/package.json +14 -3
  317. package/sbom.cdx.json +19 -260
  318. package/tools/audio.d.mts +75 -0
  319. package/tools/audio.mjs +437 -0
  320. package/tools/browser-driver.mjs +3 -3
  321. package/tools/browser-smoke.mjs +19 -2
  322. package/tools/build-tablebases.mjs +7 -3
  323. package/tools/compile-openings.mjs +7 -3
  324. package/tools/compile-resources.d.mts +2 -0
  325. package/tools/compile-resources.mjs +13 -1
  326. package/tools/emit-page.d.mts +6 -0
  327. package/tools/emit-page.mjs +43 -3
  328. package/tools/find-chrome.mjs +4 -2
  329. package/tools/init.mjs +11 -3
  330. package/tools/mwl.mjs +144 -2
  331. package/tools/play-uci.mjs +9 -5
  332. package/tools/vite.mjs +9 -1
  333. package/tools.md +2 -1
@@ -0,0 +1,218 @@
1
+ import { Container, Graphics } from 'pixi.js';
2
+ import { reducedMotion } from '../../core/Motion.js';
3
+ import { Label } from './Label.js';
4
+ import { ScrollBox } from './ScrollBox.js';
5
+ /**
6
+ * `text` cut to fit `maxWidth`, ending in `ellipsis`, as measured by `measure` (the width of a string
7
+ * in whatever font the caller draws it with). A text that already fits comes back unchanged.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { ellipsize } from '@datamoc/mw_games/two-d/ui';
12
+ *
13
+ * const width = (text: string) => text.length * 10;
14
+ * console.log(ellipsize('3. Le Fleuve profond (verrouillé)', 150, width)); // 3. Le Fleuve…
15
+ * ```
16
+ */
17
+ export function ellipsize(text, maxWidth, measure, ellipsis = '…') {
18
+ if (measure(text) <= maxWidth)
19
+ return text;
20
+ let low = 0;
21
+ let high = text.length;
22
+ while (low < high) {
23
+ const middle = Math.ceil((low + high) / 2);
24
+ if (measure(text.slice(0, middle).trimEnd() + ellipsis) <= maxWidth)
25
+ low = middle;
26
+ else
27
+ high = middle - 1;
28
+ }
29
+ return low === 0 ? ellipsis : text.slice(0, low).trimEnd() + ellipsis;
30
+ }
31
+ /**
32
+ * `text` wrapped at `maxWidth` and cut to `maxLines`, the last kept line ending in an ellipsis when
33
+ * something was dropped. Words are not split unless one alone is wider than a line.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { truncateLines } from '@datamoc/mw_games/two-d/ui';
38
+ *
39
+ * const width = (text: string) => text.length * 10;
40
+ * console.log(truncateLines('build a bridge across the river gorge', 120, 2, width));
41
+ * // ['build a', 'bridge acr…']
42
+ * ```
43
+ */
44
+ export function truncateLines(text, maxWidth, maxLines, measure, ellipsis = '…') {
45
+ const lines = [];
46
+ let line = '';
47
+ for (const word of text.split(/\s+/).filter(Boolean)) {
48
+ const next = line ? `${line} ${word}` : word;
49
+ if (measure(next) <= maxWidth || !line)
50
+ line = next;
51
+ else {
52
+ lines.push(line);
53
+ line = word;
54
+ }
55
+ }
56
+ if (line)
57
+ lines.push(line);
58
+ if (lines.length <= maxLines)
59
+ return lines.map((each) => ellipsize(each, maxWidth, measure, ellipsis));
60
+ const kept = lines.slice(0, maxLines);
61
+ const rest = lines.slice(maxLines - 1).join(' ');
62
+ kept[maxLines - 1] = ellipsize(rest + ellipsis, maxWidth, measure, ellipsis);
63
+ return kept;
64
+ }
65
+ /**
66
+ * How far a line of `textWidth` is shifted to scroll inside `boxWidth`, `time` seconds in: it waits
67
+ * `pause` seconds, slides to its end at `speed` px/s, waits again, then slides back, over and over.
68
+ * A text that fits never moves.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * import { marqueeOffset } from '@datamoc/mw_games/two-d/ui';
73
+ *
74
+ * console.log(marqueeOffset(300, 200, 0)); // 0, waiting at the start
75
+ * console.log(marqueeOffset(300, 200, 3)); // 100, at the far end
76
+ * console.log(marqueeOffset(150, 200, 3)); // 0, it fits
77
+ * ```
78
+ */
79
+ export function marqueeOffset(textWidth, boxWidth, time, speed = 40, pause = 1) {
80
+ const travel = textWidth - boxWidth;
81
+ if (travel <= 0)
82
+ return 0;
83
+ const slide = travel / speed;
84
+ const period = 2 * (pause + slide);
85
+ const at = ((time % period) + period) % period;
86
+ if (at < pause)
87
+ return 0;
88
+ if (at < pause + slide)
89
+ return (at - pause) * speed;
90
+ if (at < 2 * pause + slide)
91
+ return travel;
92
+ return travel - (at - 2 * pause - slide) * speed;
93
+ }
94
+ /**
95
+ * A wrapped `Label` in a `ScrollBox` that sizes itself: the box is as tall as the text up to
96
+ * `maxHeight`, and scrolls (wheel, touch, keys, scrollbar) beyond it, so a long hint, credit list or
97
+ * result message never spills over what is around it. `setText` re-measures and `resize(width)`
98
+ * re-wraps in place; the caller no longer measures the label and feeds `setContentHeight` by hand.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { ScrollText } from '@datamoc/mw_games/two-d/ui';
103
+ *
104
+ * const hint = new ScrollText({ width: 220, maxHeight: 60 });
105
+ * hint.setText('Span the gorge with at most 400 of budget. Cables only pull; beams push as well.');
106
+ * console.log(hint.box.viewportHeight <= 60); // true
107
+ * ```
108
+ */
109
+ export class ScrollText extends Container {
110
+ constructor(options) {
111
+ super();
112
+ this.width_ = options.width;
113
+ this.maxHeight = options.maxHeight;
114
+ this.body = new Label({ ...options.label, text: options.text ?? '', wrapWidth: options.width - 10 });
115
+ this.box = new ScrollBox({
116
+ width: options.width,
117
+ height: options.maxHeight,
118
+ autoHeight: true,
119
+ touch: options.touch ?? true,
120
+ keyboard: true,
121
+ });
122
+ this.box.content.addChild(this.body);
123
+ this.addChild(this.box);
124
+ this.measure();
125
+ }
126
+ /** the text's own height, which sizes the box; its own method so a test can supply it */
127
+ measureHeight() {
128
+ return this.body.height;
129
+ }
130
+ measure() {
131
+ this.box.setContentHeight(this.measureHeight());
132
+ }
133
+ /** the current width, what `resize` last set it to */
134
+ get viewWidth() {
135
+ return this.width_;
136
+ }
137
+ /**
138
+ * Sets the width in place: the text re-wraps at the new width and the box resizes and
139
+ * re-measures, so a layout change does not rebuild the widget.
140
+ */
141
+ resize(width) {
142
+ this.width_ = width;
143
+ this.body.setWrapWidth(width - 10);
144
+ this.box.resize(width, this.maxHeight);
145
+ this.measure();
146
+ }
147
+ setText(text) {
148
+ this.body.setText(text);
149
+ this.measure();
150
+ this.box.scrollTo(0);
151
+ }
152
+ /** call each frame for touch coasting */
153
+ update(dt) {
154
+ this.box.update(dt);
155
+ }
156
+ }
157
+ /**
158
+ * One line of text that stays on one line: when it is wider than `width` it slides back and forth
159
+ * inside a clipped window (`marqueeOffset`), driven by `update(dt)`. Under reduced motion it holds
160
+ * still, cut short with an ellipsis, instead of moving.
161
+ *
162
+ * @example
163
+ * ```ts
164
+ * import { MarqueeLabel } from '@datamoc/mw_games/two-d/ui';
165
+ *
166
+ * const title = new MarqueeLabel({ width: 160, text: 'A very long track title that cannot fit' });
167
+ * title.update(1 / 60); // once a frame from the scene
168
+ * ```
169
+ */
170
+ export class MarqueeLabel extends Container {
171
+ constructor(options) {
172
+ super();
173
+ this.clip = new Graphics();
174
+ this.source = '';
175
+ this.fullWidth = 0;
176
+ this.time = 0;
177
+ this.width_ = options.width;
178
+ this.speed = options.speed ?? 40;
179
+ this.pause = options.pause ?? 1;
180
+ this.labelOptions = options.label ?? {};
181
+ this.body = new Label({ ...this.labelOptions, text: '' });
182
+ this.clip.rect(0, 0, options.width, 4096).fill({ color: 0xffffff });
183
+ this.addChild(this.body, this.clip);
184
+ this.body.mask = this.clip;
185
+ this.setText(options.text ?? '');
186
+ }
187
+ /** the text's width in pixels; its own method so a test can supply it */
188
+ measureWidth(text) {
189
+ const probe = new Label({ ...this.labelOptions, text });
190
+ const width = probe.width;
191
+ probe.destroy();
192
+ return width;
193
+ }
194
+ setText(text) {
195
+ this.source = text;
196
+ this.fullWidth = this.measureWidth(text);
197
+ this.time = 0;
198
+ this.apply();
199
+ }
200
+ apply() {
201
+ if (reducedMotion()) {
202
+ this.body.setText(ellipsize(this.source, this.width_, (text) => this.measureWidth(text)));
203
+ this.body.x = 0;
204
+ return;
205
+ }
206
+ this.body.setText(this.source);
207
+ this.body.x = -marqueeOffset(this.fullWidth, this.width_, this.time, this.speed, this.pause);
208
+ }
209
+ /** where the text is shifted to now (0 until it has waited out its first pause) */
210
+ get shift() {
211
+ return 0 - this.body.x;
212
+ }
213
+ update(dt) {
214
+ this.time += dt;
215
+ this.apply();
216
+ }
217
+ }
218
+ //# sourceMappingURL=ScrollText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollText.js","sourceRoot":"","sources":["../../../src/two-d/ui/ScrollText.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../src/two-d/ui/Slider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAI,EAAE,GAAG,SAAI,GAAG,MAAM,CAGtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAI,EAAE,GAAG,SAAI,EAAE,IAAI,SAAI,GAAG,MAAM,CAOlF;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACpC,QAAQ,CAAC,QAAQ,iBAAwB;IAEzC,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,IAAI,CAAkB;IAE9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAU;IAE3B,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAEnD,YAAY,OAAO,EAAE,aAAa,EAyBjC;IAED,yCAAyC;IACzC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,kCAAkC;IAClC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAInC;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAS5B;IAED,6EAA6E;IAC7E,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAElC;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI1C;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAIzB;IAEF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAGzB;IAEF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAEvB;IAEF,OAAO,CAAC,IAAI;IAyBH,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAGpE;CACD"}
1
+ {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../src/two-d/ui/Slider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,SAAS,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAI,EAAE,GAAG,SAAI,GAAG,MAAM,CAGtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAI,EAAE,GAAG,SAAI,EAAE,IAAI,SAAI,GAAG,MAAM,CAMlF;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACpC,QAAQ,CAAC,QAAQ,iBAAwB;IAEzC,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,IAAI,CAAkB;IAE9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAU;IAE3B,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAEnD,YAAY,OAAO,EAAE,aAAa,EAyBjC;IAED,yCAAyC;IACzC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,kCAAkC;IAClC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAInC;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAS5B;IAED,6EAA6E;IAC7E,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAElC;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI1C;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAIzB;IAEF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAGzB;IAEF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAEvB;IAEF,OAAO,CAAC,IAAI;IAyBH,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAGpE;CACD"}
@@ -1,4 +1,5 @@
1
1
  import { Container, Graphics } from 'pixi.js';
2
+ import { clamp } from '../../core/Math.js';
2
3
  import { Signal } from '../../core/Signal.js';
3
4
  import { theme, themeChanged } from './theme.js';
4
5
  /**
@@ -15,7 +16,7 @@ import { theme, themeChanged } from './theme.js';
15
16
  export function sliderFraction(value, min = 0, max = 1) {
16
17
  if (!(max > min))
17
18
  return 0;
18
- return Math.max(0, Math.min(1, (value - min) / (max - min)));
19
+ return clamp((value - min) / (max - min), 0, 1);
19
20
  }
20
21
  /**
21
22
  * The value at a 0-to-1 position on the track, snapped to `step` and clamped to `[min, max]`.
@@ -30,8 +31,7 @@ export function sliderFraction(value, min = 0, max = 1) {
30
31
  * ```
31
32
  */
32
33
  export function sliderValueAt(fraction, min = 0, max = 1, step = 0) {
33
- const clamped = Math.max(0, Math.min(1, fraction));
34
- const raw = min + clamped * (max - min);
34
+ const raw = min + clamp(fraction, 0, 1) * (max - min);
35
35
  if (!(step > 0))
36
36
  return raw;
37
37
  const decimals = (String(step).split('.')[1] ?? '').length;
@@ -139,7 +139,7 @@ export class Slider extends Container {
139
139
  return sliderValueAt(sliderFraction(value, this.min, this.max), this.min, this.max, this.step);
140
140
  }
141
141
  fractionAt(localX) {
142
- return this.trackLength > 0 ? Math.max(0, Math.min(1, (localX - this.knobSize / 2) / this.trackLength)) : 0;
142
+ return this.trackLength > 0 ? clamp((localX - this.knobSize / 2) / this.trackLength, 0, 1) : 0;
143
143
  }
144
144
  draw() {
145
145
  const t = theme();
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/two-d/ui/Slider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/two-d/ui/Slider.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
1
  import { Container } from 'pixi.js';
2
+ import type { PointerTracker } from '../../core/Input.ts';
3
+ import { Button } from './Button.ts';
2
4
  export interface TooltipOptions {
3
5
  /** seconds the pointer must rest before the tooltip appears; defaults to 0.4 */
4
6
  delay?: number;
@@ -68,11 +70,13 @@ export declare class Tooltip extends Container {
68
70
  /**
69
71
  * The pointer is resting on something with `text` to explain, at `x`/`y`.
70
72
  *
73
+ * `delay` replaces the tooltip's own wait for this one call (a touch long-press waits longer than a hover).
74
+ *
71
75
  * Safe to call every frame with the same arguments: the delay keeps counting rather than
72
76
  * restarting. Calling it with *different* text restarts the wait, so sweeping across a row
73
77
  * of icons shows the one the pointer settles on rather than the first one it crossed.
74
78
  */
75
- hover(text: string, x: number, y: number): void;
79
+ hover(text: string, x: number, y: number, delay?: number): void;
76
80
  /** the pointer left: cancels a pending tooltip and hides a shown one */
77
81
  leave(): void;
78
82
  get isShowing(): boolean;
@@ -105,4 +109,69 @@ export declare class Tooltip extends Container {
105
109
  /** offsets from the anchor, then pulls back inside the viewport if that would overflow it */
106
110
  private place;
107
111
  }
112
+ /** a rectangle on screen that has something to explain, in the same space as the pointer positions fed to the host */
113
+ export interface TooltipTarget {
114
+ bounds(): {
115
+ x: number;
116
+ y: number;
117
+ width: number;
118
+ height: number;
119
+ };
120
+ /** what to say now, or undefined for nothing */
121
+ text(): string | undefined;
122
+ /** false while the target is hidden; a hidden one explains nothing. True when omitted */
123
+ active?(): boolean;
124
+ }
125
+ export interface TooltipHostOptions {
126
+ /** the tooltip to drive; a default one when omitted */
127
+ tooltip?: Tooltip;
128
+ /** seconds a finger or button must rest before the tooltip shows on a press; 0.5 when omitted */
129
+ longPress?: number;
130
+ }
131
+ /**
132
+ * Drives one `Tooltip` from rectangles instead of from each widget's own pointer events, which is
133
+ * what makes it work in the two places hover cannot reach: on a touch screen (a press that rests
134
+ * for `longPress` seconds shows the text, and releasing hides it) and over a disabled `Button`,
135
+ * which has no pointer events to receive (the host tests the button's bounds itself, and a greyed-out
136
+ * button is exactly the one worth explaining).
137
+ *
138
+ * Feed it pointer positions with `pointerMove`, `pointerDown` and `pointerUp` (or `attach` a
139
+ * `PointerTracker`), and call `update(dt)` each frame. The later a target was added, the higher it
140
+ * counts when targets overlap.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * import { Button, TooltipHost } from '@datamoc/mw_games/two-d/ui';
145
+ *
146
+ * const host = new TooltipHost({ longPress: 0.4 });
147
+ * host.tooltip.setViewport(800, 600);
148
+ *
149
+ * const test = new Button({ width: 80, height: 28, text: 'Test', disabled: true,
150
+ * tooltip: () => 'Build a road across the gap first' });
151
+ * host.addButton(test);
152
+ *
153
+ * host.pointerMove(10, 10); // over the disabled button: the text still shows after the hover delay
154
+ * ```
155
+ */
156
+ export declare class TooltipHost extends Container {
157
+ readonly tooltip: Tooltip;
158
+ private readonly longPress;
159
+ private readonly targets;
160
+ constructor(options?: TooltipHostOptions);
161
+ /** @returns a function that removes the target again */
162
+ add(target: TooltipTarget): () => void;
163
+ /** a button's own bounds and `tooltip`, whether or not the button is disabled */
164
+ addButton(button: Button): () => void;
165
+ private targetAt;
166
+ /** a pointer with no button down moved: the usual hover */
167
+ pointerMove(x: number, y: number): void;
168
+ /** a finger or button went down: the tooltip shows once it has rested for `longPress` */
169
+ pointerDown(x: number, y: number): void;
170
+ /** the finger or button came up */
171
+ pointerUp(): void;
172
+ /** wires a `PointerTracker` (`Input.attachPointer`) to the host; returns the function that unwires it */
173
+ attach(pointer: PointerTracker): () => void;
174
+ /** @returns true on the frame the tooltip appears, as `Tooltip.update` does */
175
+ update(dt: number): boolean;
176
+ }
108
177
  //# sourceMappingURL=Tooltip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/two-d/ui/Tooltip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKpC,MAAM,WAAW,cAAc;IAC9B,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,4FAA4F;IAC5F,MAAM,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAElC,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAE7B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAK;IAEvB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAK;IAExB,OAAO,CAAC,OAAO,CAAuD;IACtE,OAAO,CAAC,MAAM,CAAK;IAEnB,YAAY,OAAO,GAAE,cAAmB,EAcvC;IAED,2FAA2F;IAC3F,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI/C;IAED;;;;;;OAMG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAW9C;IAED,wEAAwE;IACxE,KAAK,IAAI,IAAI,CAIZ;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,uFAAuF;IACvF,IAAI,IAAI,IAAI,MAAM,GAAG,IAAI,CAExB;IAED,yFAAyF;IACzF,IAAI,aAAa,IAAI;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAE5C;IAED,IAAI,IAAI,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAE5C;IAED,mGAAmG;IACnG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAmB1B;IAED;;;;;;;;OAQG;IACH,SAAS,CAAC,WAAW,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAEzD;IAED,6FAA6F;IAC7F,OAAO,CAAC,KAAK;CAwBb"}
1
+ {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/two-d/ui/Tooltip.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { Container } from 'pixi.js';
2
+ import { Button } from './Button.js';
2
3
  import { Label } from './Label.js';
3
4
  import { Window } from './Window.js';
4
5
  import { theme } from './theme.js';
@@ -68,11 +69,13 @@ export class Tooltip extends Container {
68
69
  /**
69
70
  * The pointer is resting on something with `text` to explain, at `x`/`y`.
70
71
  *
72
+ * `delay` replaces the tooltip's own wait for this one call (a touch long-press waits longer than a hover).
73
+ *
71
74
  * Safe to call every frame with the same arguments: the delay keeps counting rather than
72
75
  * restarting. Calling it with *different* text restarts the wait, so sweeping across a row
73
76
  * of icons shows the one the pointer settles on rather than the first one it crossed.
74
77
  */
75
- hover(text, x, y) {
78
+ hover(text, x, y, delay = this.delay) {
76
79
  if (this.pending && this.pending.text === text) {
77
80
  this.pending.x = x;
78
81
  this.pending.y = y;
@@ -80,7 +83,7 @@ export class Tooltip extends Container {
80
83
  this.place();
81
84
  return;
82
85
  }
83
- this.pending = { text, x, y };
86
+ this.pending = { text, x, y, delay };
84
87
  this.waited = 0;
85
88
  this.visible = false;
86
89
  }
@@ -109,7 +112,7 @@ export class Tooltip extends Container {
109
112
  if (!this.pending || this.visible)
110
113
  return false;
111
114
  this.waited += dt;
112
- if (this.waited < this.delay)
115
+ if (this.waited < this.pending.delay)
113
116
  return false;
114
117
  this.body.setText(this.pending.text);
115
118
  const t = theme();
@@ -160,4 +163,113 @@ export class Tooltip extends Container {
160
163
  this.panel.y = y;
161
164
  }
162
165
  }
166
+ /**
167
+ * Drives one `Tooltip` from rectangles instead of from each widget's own pointer events, which is
168
+ * what makes it work in the two places hover cannot reach: on a touch screen (a press that rests
169
+ * for `longPress` seconds shows the text, and releasing hides it) and over a disabled `Button`,
170
+ * which has no pointer events to receive (the host tests the button's bounds itself, and a greyed-out
171
+ * button is exactly the one worth explaining).
172
+ *
173
+ * Feed it pointer positions with `pointerMove`, `pointerDown` and `pointerUp` (or `attach` a
174
+ * `PointerTracker`), and call `update(dt)` each frame. The later a target was added, the higher it
175
+ * counts when targets overlap.
176
+ *
177
+ * @example
178
+ * ```ts
179
+ * import { Button, TooltipHost } from '@datamoc/mw_games/two-d/ui';
180
+ *
181
+ * const host = new TooltipHost({ longPress: 0.4 });
182
+ * host.tooltip.setViewport(800, 600);
183
+ *
184
+ * const test = new Button({ width: 80, height: 28, text: 'Test', disabled: true,
185
+ * tooltip: () => 'Build a road across the gap first' });
186
+ * host.addButton(test);
187
+ *
188
+ * host.pointerMove(10, 10); // over the disabled button: the text still shows after the hover delay
189
+ * ```
190
+ */
191
+ export class TooltipHost extends Container {
192
+ constructor(options = {}) {
193
+ super();
194
+ this.targets = [];
195
+ this.tooltip = options.tooltip ?? new Tooltip();
196
+ this.longPress = options.longPress ?? 0.5;
197
+ this.addChild(this.tooltip);
198
+ }
199
+ /** @returns a function that removes the target again */
200
+ add(target) {
201
+ this.targets.push(target);
202
+ return () => {
203
+ const at = this.targets.indexOf(target);
204
+ if (at >= 0)
205
+ this.targets.splice(at, 1);
206
+ };
207
+ }
208
+ /** a button's own bounds and `tooltip`, whether or not the button is disabled */
209
+ addButton(button) {
210
+ return this.add({
211
+ bounds: () => {
212
+ const rect = button.getBounds();
213
+ return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
214
+ },
215
+ text: () => button.tooltip,
216
+ active: () => {
217
+ for (let node = button; node; node = node.parent)
218
+ if (!node.visible)
219
+ return false;
220
+ return true;
221
+ },
222
+ });
223
+ }
224
+ targetAt(x, y) {
225
+ for (let index = this.targets.length - 1; index >= 0; index--) {
226
+ const target = this.targets[index];
227
+ if (target.active && !target.active())
228
+ continue;
229
+ const rect = target.bounds();
230
+ if (x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height) {
231
+ return target.text() === undefined ? null : target;
232
+ }
233
+ }
234
+ return null;
235
+ }
236
+ /** a pointer with no button down moved: the usual hover */
237
+ pointerMove(x, y) {
238
+ const text = this.targetAt(x, y)?.text();
239
+ if (text)
240
+ this.tooltip.hover(text, x, y);
241
+ else
242
+ this.tooltip.leave();
243
+ }
244
+ /** a finger or button went down: the tooltip shows once it has rested for `longPress` */
245
+ pointerDown(x, y) {
246
+ const text = this.targetAt(x, y)?.text();
247
+ if (text)
248
+ this.tooltip.hover(text, x, y, this.longPress);
249
+ else
250
+ this.tooltip.leave();
251
+ }
252
+ /** the finger or button came up */
253
+ pointerUp() {
254
+ this.tooltip.leave();
255
+ }
256
+ /** wires a `PointerTracker` (`Input.attachPointer`) to the host; returns the function that unwires it */
257
+ attach(pointer) {
258
+ const onMove = (p) => this.pointerMove(p.x, p.y);
259
+ const onDown = (p) => this.pointerDown(p.x, p.y);
260
+ const onUp = () => this.pointerUp();
261
+ pointer.move.add(onMove);
262
+ pointer.down.add(onDown);
263
+ pointer.up.add(onUp);
264
+ return () => {
265
+ pointer.move.remove(onMove);
266
+ pointer.down.remove(onDown);
267
+ pointer.up.remove(onUp);
268
+ };
269
+ }
270
+ /** @returns true on the frame the tooltip appears, as `Tooltip.update` does */
271
+ update(dt) {
272
+ return this.tooltip.update(dt);
273
+ }
274
+ }
163
275
  //# sourceMappingURL=Tooltip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sourceRoot":"","sources":["../../../src/two-d/ui/Tooltip.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Tooltip.js","sourceRoot":"","sources":["../../../src/two-d/ui/Tooltip.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,23 @@
1
1
  import { Container } from 'pixi.js';
2
2
  import { Signal } from '../../core/Signal.ts';
3
+ import { type OpenAnimationKind } from '../render/SceneTransition.ts';
3
4
  import type { Action } from '../../core/Input.ts';
4
5
  export interface WindowColors {
5
6
  background?: number;
6
7
  border?: number;
7
8
  title?: number;
8
9
  }
10
+ /** how a window opens or closes: `pop` (springs out), `grow`, `slide` (up from below) or `fade` */
11
+ export interface WindowAnimation {
12
+ animation: OpenAnimationKind;
13
+ /** where `pop` and `grow` come from and go back to, in the window's parent space; the window's centre when omitted */
14
+ from?: {
15
+ x: number;
16
+ y: number;
17
+ };
18
+ /** seconds; 0.25 when omitted */
19
+ duration?: number;
20
+ }
9
21
  export interface WindowOptions {
10
22
  width: number;
11
23
  height: number;
@@ -86,6 +98,7 @@ export declare class Window extends Container {
86
98
  private blocker;
87
99
  private readonly themeListener;
88
100
  private isClosed;
101
+ private motion;
89
102
  private colors;
90
103
  constructor(options: WindowOptions);
91
104
  /** reapplies the current theme to the frame and title, without changing size or content */
@@ -121,13 +134,33 @@ export declare class Window extends Container {
121
134
  */
122
135
  get closed(): boolean;
123
136
  /** called each frame while this window is the top of the stack */
124
- update(_dt: number): void;
137
+ update(dt: number): void;
138
+ /** puts the window at `progress` of its animation: scaled about the origin, faded, pushed down by a slide */
139
+ private applyMotion;
140
+ /**
141
+ * Plays the opening animation from the window's current position. The stack calls `update(dt)`
142
+ * on its top window, which drives it. Under reduced motion the window simply appears.
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * import { Window } from '@datamoc/mw_games/two-d/ui';
147
+ *
148
+ * const window = new Window({ width: 240, height: 120, title: 'Result' });
149
+ * window.open({ animation: 'pop' });
150
+ * window.update(0.25); // normally the WindowStack's update does this
151
+ * console.log(window.scale.x); // 1
152
+ * ```
153
+ */
154
+ open(animation?: WindowAnimation): void;
125
155
  /**
126
156
  * Announces the close and frees this window and its contents. Idempotent, so a second
127
157
  * `close()` (a `pop()` racing a `cancel`, a `closeAll()` after a manual close) is a no-op
128
158
  * rather than a second `destroy`. The instance is spent afterwards; see `closed`.
159
+ *
160
+ * With `animation` it plays the opening backwards first and closes when it ends (driven by
161
+ * `update(dt)`), unless reduced motion is on, when it closes at once.
129
162
  */
130
- close(): void;
163
+ close(animation?: WindowAnimation): void;
131
164
  /** positions the window in a viewport of the given size, per its anchor */
132
165
  place(viewportWidth: number, viewportHeight: number): void;
133
166
  /**