1681-engine 0.5.8 → 0.5.9

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 (600) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/1681-engine.js +463 -409
  3. package/dist/ambient/ColorGrade.js +0 -1
  4. package/dist/ambient/DayClock.js +0 -1
  5. package/dist/ambient/WeatherLayer.js +0 -1
  6. package/dist/ambient/grade.js +0 -1
  7. package/dist/ambient/weather.js +0 -1
  8. package/dist/anim/AnimStateMachine.js +0 -1
  9. package/dist/anim/Animator.js +0 -1
  10. package/dist/anim/animStateCompile.js +0 -1
  11. package/dist/anim/animStateSystem.js +0 -1
  12. package/dist/anim/animationSystem.js +0 -1
  13. package/dist/anim/asepriteSlices.js +0 -1
  14. package/dist/anim/asepriteTags.js +0 -1
  15. package/dist/anim/parseAseprite.js +0 -1
  16. package/dist/assets/AssetLoader.js +112 -14
  17. package/dist/assets/loadAseprite.js +0 -1
  18. package/dist/assets/takeCleanerWorker-DTcI_Jqr.js +0 -1
  19. package/dist/assets/textureAtlas.js +58 -0
  20. package/dist/audio/Footsteps.js +0 -1
  21. package/dist/audio/MusicPlayer.js +0 -1
  22. package/dist/audio/SoundEngine.js +13 -7
  23. package/dist/audio/cleanTake.js +0 -1
  24. package/dist/audio/music/ElementVoice.js +0 -1
  25. package/dist/audio/music/GraphVoice.js +0 -1
  26. package/dist/audio/music/MusicChannel.js +0 -1
  27. package/dist/audio/music/musicVoice.js +0 -1
  28. package/dist/audio/sampleBank.js +0 -1
  29. package/dist/audio/soundTable.js +0 -1
  30. package/dist/audio/synth.js +0 -1
  31. package/dist/core/BitmapLabel.js +0 -1
  32. package/dist/core/Camera.js +1 -2
  33. package/dist/core/Clock.js +31 -21
  34. package/dist/core/Graphics.js +0 -1
  35. package/dist/core/Group.js +0 -1
  36. package/dist/core/Image.js +0 -1
  37. package/dist/core/ObjectFactory.js +0 -1
  38. package/dist/core/Pointer.js +46 -24
  39. package/dist/core/Rectangle.js +0 -1
  40. package/dist/core/Stage.js +5 -6
  41. package/dist/core/Text.js +0 -1
  42. package/dist/core/TextureRegistry.js +54 -24
  43. package/dist/core/Timeline.js +0 -1
  44. package/dist/core/TimelineBuilder.js +0 -1
  45. package/dist/core/TimelineChild.js +0 -1
  46. package/dist/core/Tweener.js +0 -1
  47. package/dist/core/atlas.js +0 -1
  48. package/dist/core/atlasPlan.js +0 -1
  49. package/dist/core/blendLayer.js +11 -0
  50. package/dist/core/eases.js +0 -1
  51. package/dist/core/gameObject.js +22 -20
  52. package/dist/core/pixelZoom.js +43 -0
  53. package/dist/core/pixiPatches.js +0 -1
  54. package/dist/core/runDue.js +28 -0
  55. package/dist/core/silhouette.js +49 -0
  56. package/dist/core/timelinePlace.js +0 -1
  57. package/dist/core/tweenProps.js +0 -1
  58. package/dist/debug/DebugOverlay.js +0 -1
  59. package/dist/debug/DrawCallCounter.js +15 -12
  60. package/dist/debug/ErrorLog.js +0 -1
  61. package/dist/debug/FrameStats.js +0 -1
  62. package/dist/debug/inspectWorld.js +0 -1
  63. package/dist/diagnostics/ErrorDeduper.js +0 -1
  64. package/dist/diagnostics/FrameSampler.js +0 -1
  65. package/dist/diagnostics/bootWatch.js +0 -1
  66. package/dist/diagnostics/captureErrors.js +0 -1
  67. package/dist/diagnostics/contextLoss.js +0 -1
  68. package/dist/diagnostics/frameStats.js +0 -1
  69. package/dist/diagnostics/gpuInfo.js +0 -1
  70. package/dist/diagnostics/renderGuard.js +0 -1
  71. package/dist/ecs/SparseSet.js +0 -1
  72. package/dist/ecs/World.js +0 -1
  73. package/dist/ecs/fields.js +0 -1
  74. package/dist/engine/Engine.js +42 -18
  75. package/dist/engine/FixedLoop.js +0 -1
  76. package/dist/engine/HiddenPause.js +27 -0
  77. package/dist/engine/Scene.js +0 -1
  78. package/dist/engine/SceneManager.js +0 -1
  79. package/dist/events/EventBus.js +0 -1
  80. package/dist/fx/Afterimages.js +82 -0
  81. package/dist/fx/FloatingText.js +0 -1
  82. package/dist/fx/hitStop.js +0 -1
  83. package/dist/fx/viewCull.js +0 -1
  84. package/dist/i18n/Translator.js +0 -1
  85. package/dist/i18n/extractStrings.js +0 -1
  86. package/dist/i18n/formatMessage.js +0 -1
  87. package/dist/input/Actions.js +29 -21
  88. package/dist/input/AimGesture.js +0 -1
  89. package/dist/input/Keyboard.js +0 -1
  90. package/dist/input/Keymap.js +0 -1
  91. package/dist/input/TargetLock.js +0 -1
  92. package/dist/input/aimAxis.js +0 -1
  93. package/dist/input/keyChord.js +0 -1
  94. package/dist/input/longPress.js +0 -1
  95. package/dist/input/rumble.js +42 -0
  96. package/dist/input/stickAxis.js +0 -1
  97. package/dist/input/touchDetect.js +0 -1
  98. package/dist/light/LightLayer.js +0 -1
  99. package/dist/nav/MinHeap.js +0 -1
  100. package/dist/nav/findPath.js +0 -1
  101. package/dist/nav/navGrid.js +0 -1
  102. package/dist/nav/nearestOpen.js +0 -1
  103. package/dist/nav/straightenPath.js +0 -1
  104. package/dist/net/Connection.js +39 -16
  105. package/dist/net/InterpolationBuffer.js +0 -1
  106. package/dist/net/PredictedMover.js +0 -1
  107. package/dist/net/Room.js +0 -1
  108. package/dist/net/RoomHost.js +0 -1
  109. package/dist/net/cadence.js +0 -1
  110. package/dist/net/constants.js +0 -1
  111. package/dist/net/lobby/LobbyClient.js +0 -1
  112. package/dist/net/lobby/LobbyHost.js +0 -1
  113. package/dist/net/lobby/LobbyRooms.js +0 -1
  114. package/dist/net/lobby/Matchmaker.js +0 -1
  115. package/dist/net/movement.js +40 -39
  116. package/dist/net/protocol.js +0 -1
  117. package/dist/net/reconnect.js +10 -0
  118. package/dist/net/serverClock.js +0 -1
  119. package/dist/net/snapshotCodec.js +0 -1
  120. package/dist/parallax/Parallax.js +0 -1
  121. package/dist/parallax/ParallaxLayer.js +0 -1
  122. package/dist/parallax/parallaxMath.js +0 -1
  123. package/dist/particles/Emitter.js +0 -1
  124. package/dist/particles/ParticleBudget.js +0 -1
  125. package/dist/particles/ParticleSim.js +0 -1
  126. package/dist/particles/particleCurves.js +0 -1
  127. package/dist/particles/particleSampling.js +0 -1
  128. package/dist/physics/Body.js +0 -1
  129. package/dist/physics/BroadPhase.js +0 -1
  130. package/dist/physics/Contact.js +0 -1
  131. package/dist/physics/ContactSolver.js +0 -1
  132. package/dist/physics/PhysicsWorld.js +0 -1
  133. package/dist/physics/SpatialHash.js +0 -1
  134. package/dist/physics/collide.js +0 -1
  135. package/dist/physics/collidePolygon.js +0 -1
  136. package/dist/physics/contactReport.js +0 -1
  137. package/dist/physics/drawColliders.js +0 -1
  138. package/dist/physics/physicsSystem.js +0 -1
  139. package/dist/physics/polygon.js +0 -1
  140. package/dist/physics/raycast.js +0 -1
  141. package/dist/physics/syncToBody.js +0 -1
  142. package/dist/physics/tileBodies.js +0 -1
  143. package/dist/physics/types.js +0 -1
  144. package/dist/pixel/Darkness.js +50 -47
  145. package/dist/pixel/DitherVignette.js +0 -1
  146. package/dist/pixel/Evaporation.js +0 -1
  147. package/dist/pixel/NightShade.js +0 -1
  148. package/dist/pixel/PixelLayer.js +0 -1
  149. package/dist/pixel/PixelMarks.js +99 -0
  150. package/dist/pixel/SwayProp.js +0 -1
  151. package/dist/pixel/aimPixels.js +67 -0
  152. package/dist/pixel/lights.js +0 -1
  153. package/dist/pixel/nineSlice.js +0 -1
  154. package/dist/pixel/paintLayer.js +0 -1
  155. package/dist/pixel/palette.js +0 -1
  156. package/dist/pixel/pixel.js +0 -1
  157. package/dist/pixel/pixelPaint.js +27 -24
  158. package/dist/pixel/pixelParticles.js +35 -0
  159. package/dist/pixel/pixelTone.js +0 -1
  160. package/dist/pixel/propKit.js +0 -1
  161. package/dist/pixel/ramp.js +0 -1
  162. package/dist/pixel/selout.js +0 -1
  163. package/dist/pixel/spritePixels.js +0 -1
  164. package/dist/pixel/swayRig.js +0 -1
  165. package/dist/pixel/vignetteMask.js +0 -1
  166. package/dist/pixel/weatherArt.js +0 -1
  167. package/dist/pixel.js +71 -65
  168. package/dist/platform/appResume.js +18 -0
  169. package/dist/platform/fullscreen.js +52 -0
  170. package/dist/platform/orientation.js +26 -0
  171. package/dist/platform/pointerLock.js +37 -0
  172. package/dist/platform/reducedMotion.js +23 -0
  173. package/dist/platform/timeoutSignal.js +14 -0
  174. package/dist/platform/touch.js +0 -1
  175. package/dist/postfx/BloomFilter.js +0 -1
  176. package/dist/postfx/ChromaticAberrationFilter.js +0 -1
  177. package/dist/postfx/ColorAdjustFilter.js +0 -1
  178. package/dist/postfx/CrtFilter.js +0 -1
  179. package/dist/postfx/PixelateFilter.js +0 -1
  180. package/dist/postfx/PostFx.js +0 -1
  181. package/dist/postfx/ShockwaveFilter.js +0 -1
  182. package/dist/postfx/VignetteFilter.js +0 -1
  183. package/dist/postfx/fxAnimator.js +0 -1
  184. package/dist/postfx/fxShader.js +0 -1
  185. package/dist/postfx.js +0 -1
  186. package/dist/react/ChoiceDialog.js +0 -1
  187. package/dist/react/ConfirmDialog.js +0 -1
  188. package/dist/react/Glyph.js +0 -1
  189. package/dist/react/Modal.js +0 -1
  190. package/dist/react/Panel.js +0 -1
  191. package/dist/react/PixelImage.js +0 -1
  192. package/dist/react/Select.js +0 -1
  193. package/dist/react/Slider.js +0 -1
  194. package/dist/react/SplitPane.js +0 -1
  195. package/dist/react/TabStrip.js +0 -1
  196. package/dist/react/TitleTips.js +0 -1
  197. package/dist/react/Tooltip.js +0 -1
  198. package/dist/react/UiProvider.js +0 -1
  199. package/dist/react/baseCss.js +0 -1
  200. package/dist/react/choiceStore.js +0 -1
  201. package/dist/react/classNames.js +0 -1
  202. package/dist/react/confirmStore.js +0 -1
  203. package/dist/react/labels.js +0 -1
  204. package/dist/react/placement.js +0 -1
  205. package/dist/react/useFillSheet.js +0 -1
  206. package/dist/react/useFitToViewport.js +0 -1
  207. package/dist/react/usePicked.js +0 -1
  208. package/dist/react/useStore.js +0 -1
  209. package/dist/react/useViewport.js +0 -1
  210. package/dist/react.js +0 -1
  211. package/dist/rig/PosePlayer.js +0 -1
  212. package/dist/rig/RigView.js +0 -1
  213. package/dist/rig/Skeleton.js +0 -1
  214. package/dist/rig/humanoid.js +0 -1
  215. package/dist/rig/humanoid.json.js +0 -1
  216. package/dist/rig/humanoidPoses.js +0 -1
  217. package/dist/rig/poseMath.js +0 -1
  218. package/dist/rig/poses.json.js +0 -1
  219. package/dist/save/Autosaver.js +0 -1
  220. package/dist/save/MemoryBackend.js +0 -1
  221. package/dist/save/SaveStore.js +0 -1
  222. package/dist/save/WebStorageBackend.js +0 -1
  223. package/dist/save/checksum.js +0 -1
  224. package/dist/save/migrateSave.js +0 -1
  225. package/dist/settings.js +0 -1
  226. package/dist/tilemap/TilemapView.js +0 -1
  227. package/dist/tilemap/collision.js +0 -1
  228. package/dist/tilemap/tiled.js +0 -1
  229. package/dist/transitions/CrossfadeTransition.js +0 -1
  230. package/dist/transitions/DitherWipeTransition.js +0 -1
  231. package/dist/transitions/FadeTransition.js +0 -1
  232. package/dist/transitions/Letterbox.js +0 -1
  233. package/dist/transitions/ditherMask.js +0 -1
  234. package/dist/transitions/transitionTo.js +0 -1
  235. package/dist/transitions/tweenDone.js +0 -1
  236. package/dist/types/assets/AssetLoader.d.ts +63 -8
  237. package/dist/types/assets/AssetLoader.d.ts.map +1 -1
  238. package/dist/types/assets/textureAtlas.d.ts +35 -0
  239. package/dist/types/assets/textureAtlas.d.ts.map +1 -0
  240. package/dist/types/audio/SoundEngine.d.ts +5 -0
  241. package/dist/types/audio/SoundEngine.d.ts.map +1 -1
  242. package/dist/types/core/Camera.d.ts +1 -1
  243. package/dist/types/core/Camera.d.ts.map +1 -1
  244. package/dist/types/core/Clock.d.ts +14 -2
  245. package/dist/types/core/Clock.d.ts.map +1 -1
  246. package/dist/types/core/Pointer.d.ts +18 -0
  247. package/dist/types/core/Pointer.d.ts.map +1 -1
  248. package/dist/types/core/Stage.d.ts.map +1 -1
  249. package/dist/types/core/TextureRegistry.d.ts +39 -0
  250. package/dist/types/core/TextureRegistry.d.ts.map +1 -1
  251. package/dist/types/core/blendLayer.d.ts +23 -0
  252. package/dist/types/core/blendLayer.d.ts.map +1 -0
  253. package/dist/types/core/gameObject.d.ts.map +1 -1
  254. package/dist/types/core/pixelZoom.d.ts +45 -0
  255. package/dist/types/core/pixelZoom.d.ts.map +1 -0
  256. package/dist/types/core/runDue.d.ts +15 -0
  257. package/dist/types/core/runDue.d.ts.map +1 -0
  258. package/dist/types/core/silhouette.d.ts +16 -0
  259. package/dist/types/core/silhouette.d.ts.map +1 -0
  260. package/dist/types/debug/DrawCallCounter.d.ts.map +1 -1
  261. package/dist/types/engine/Engine.d.ts +16 -0
  262. package/dist/types/engine/Engine.d.ts.map +1 -1
  263. package/dist/types/engine/HiddenPause.d.ts +22 -0
  264. package/dist/types/engine/HiddenPause.d.ts.map +1 -0
  265. package/dist/types/fx/Afterimages.d.ts +62 -0
  266. package/dist/types/fx/Afterimages.d.ts.map +1 -0
  267. package/dist/types/index.d.ts +18 -3
  268. package/dist/types/index.d.ts.map +1 -1
  269. package/dist/types/input/Actions.d.ts +7 -1
  270. package/dist/types/input/Actions.d.ts.map +1 -1
  271. package/dist/types/input/rumble.d.ts +41 -0
  272. package/dist/types/input/rumble.d.ts.map +1 -0
  273. package/dist/types/net/Connection.d.ts +22 -0
  274. package/dist/types/net/Connection.d.ts.map +1 -1
  275. package/dist/types/net/constants.d.ts +13 -4
  276. package/dist/types/net/constants.d.ts.map +1 -1
  277. package/dist/types/net/movement.d.ts.map +1 -1
  278. package/dist/types/net/reconnect.d.ts +14 -0
  279. package/dist/types/net/reconnect.d.ts.map +1 -0
  280. package/dist/types/pixel/Darkness.d.ts +17 -5
  281. package/dist/types/pixel/Darkness.d.ts.map +1 -1
  282. package/dist/types/pixel/PixelMarks.d.ts +68 -0
  283. package/dist/types/pixel/PixelMarks.d.ts.map +1 -0
  284. package/dist/types/pixel/aimPixels.d.ts +23 -0
  285. package/dist/types/pixel/aimPixels.d.ts.map +1 -0
  286. package/dist/types/pixel/index.d.ts +3 -1
  287. package/dist/types/pixel/index.d.ts.map +1 -1
  288. package/dist/types/pixel/pixelPaint.d.ts +1 -0
  289. package/dist/types/pixel/pixelPaint.d.ts.map +1 -1
  290. package/dist/types/pixel/pixelParticles.d.ts +21 -0
  291. package/dist/types/pixel/pixelParticles.d.ts.map +1 -0
  292. package/dist/types/platform/appResume.d.ts +25 -0
  293. package/dist/types/platform/appResume.d.ts.map +1 -0
  294. package/dist/types/platform/fullscreen.d.ts +37 -0
  295. package/dist/types/platform/fullscreen.d.ts.map +1 -0
  296. package/dist/types/platform/orientation.d.ts +19 -0
  297. package/dist/types/platform/orientation.d.ts.map +1 -0
  298. package/dist/types/platform/pointerLock.d.ts +26 -0
  299. package/dist/types/platform/pointerLock.d.ts.map +1 -0
  300. package/dist/types/platform/reducedMotion.d.ts +20 -0
  301. package/dist/types/platform/reducedMotion.d.ts.map +1 -0
  302. package/dist/types/platform/timeoutSignal.d.ts +6 -0
  303. package/dist/types/platform/timeoutSignal.d.ts.map +1 -0
  304. package/dist/types/ui/index.d.ts +4 -0
  305. package/dist/types/ui/index.d.ts.map +1 -1
  306. package/dist/types/ui/rich/RichText.d.ts +48 -0
  307. package/dist/types/ui/rich/RichText.d.ts.map +1 -0
  308. package/dist/types/ui/rich/richFonts.d.ts +70 -0
  309. package/dist/types/ui/rich/richFonts.d.ts.map +1 -0
  310. package/dist/types/ui/rich/richLayout.d.ts +76 -0
  311. package/dist/types/ui/rich/richLayout.d.ts.map +1 -0
  312. package/dist/types/ui/rich/richMarkup.d.ts +48 -0
  313. package/dist/types/ui/rich/richMarkup.d.ts.map +1 -0
  314. package/dist/ui/Bar.js +0 -1
  315. package/dist/ui/Button.js +0 -1
  316. package/dist/ui/Dialog.js +0 -1
  317. package/dist/ui/FocusManager.js +0 -1
  318. package/dist/ui/Label.js +0 -1
  319. package/dist/ui/List.js +0 -1
  320. package/dist/ui/Panel.js +0 -1
  321. package/dist/ui/ScrollView.js +0 -1
  322. package/dist/ui/Slider.js +0 -1
  323. package/dist/ui/Stack.js +0 -1
  324. package/dist/ui/Toggle.js +0 -1
  325. package/dist/ui/UiHost.js +0 -1
  326. package/dist/ui/UiPointerGate.js +0 -1
  327. package/dist/ui/UiRoot.js +0 -1
  328. package/dist/ui/Widget.js +0 -1
  329. package/dist/ui/dom/DomOverlay.js +0 -1
  330. package/dist/ui/dom/DomWorldAnchors.js +0 -1
  331. package/dist/ui/dom/InputShield.js +0 -1
  332. package/dist/ui/dom/createStore.js +0 -1
  333. package/dist/ui/dom/shieldDecision.js +0 -1
  334. package/dist/ui/dom/worldToScreen.js +0 -1
  335. package/dist/ui/layout/anchor.js +0 -1
  336. package/dist/ui/layout/barDrain.js +0 -1
  337. package/dist/ui/layout/fitToViewport.js +0 -1
  338. package/dist/ui/layout/focusNav.js +0 -1
  339. package/dist/ui/layout/geometry.js +0 -1
  340. package/dist/ui/layout/listWidth.js +0 -1
  341. package/dist/ui/layout/placeTooltip.js +0 -1
  342. package/dist/ui/layout/scroll.js +0 -1
  343. package/dist/ui/layout/slider.js +0 -1
  344. package/dist/ui/layout/stack.js +0 -1
  345. package/dist/ui/layout/wrapRow.js +0 -1
  346. package/dist/ui/rich/RichText.js +87 -0
  347. package/dist/ui/rich/richFonts.js +105 -0
  348. package/dist/ui/rich/richLayout.js +132 -0
  349. package/dist/ui/rich/richMarkup.js +67 -0
  350. package/dist/ui.js +75 -65
  351. package/package.json +1 -4
  352. package/dist/1681-engine.js.map +0 -1
  353. package/dist/ambient/ColorGrade.js.map +0 -1
  354. package/dist/ambient/DayClock.js.map +0 -1
  355. package/dist/ambient/WeatherLayer.js.map +0 -1
  356. package/dist/ambient/grade.js.map +0 -1
  357. package/dist/ambient/weather.js.map +0 -1
  358. package/dist/anim/AnimStateMachine.js.map +0 -1
  359. package/dist/anim/Animator.js.map +0 -1
  360. package/dist/anim/animStateCompile.js.map +0 -1
  361. package/dist/anim/animStateSystem.js.map +0 -1
  362. package/dist/anim/animationSystem.js.map +0 -1
  363. package/dist/anim/asepriteSlices.js.map +0 -1
  364. package/dist/anim/asepriteTags.js.map +0 -1
  365. package/dist/anim/parseAseprite.js.map +0 -1
  366. package/dist/assets/AssetLoader.js.map +0 -1
  367. package/dist/assets/loadAseprite.js.map +0 -1
  368. package/dist/assets/takeCleanerWorker-DTcI_Jqr.js.map +0 -1
  369. package/dist/audio/Footsteps.js.map +0 -1
  370. package/dist/audio/MusicPlayer.js.map +0 -1
  371. package/dist/audio/SoundEngine.js.map +0 -1
  372. package/dist/audio/cleanTake.js.map +0 -1
  373. package/dist/audio/music/ElementVoice.js.map +0 -1
  374. package/dist/audio/music/GraphVoice.js.map +0 -1
  375. package/dist/audio/music/MusicChannel.js.map +0 -1
  376. package/dist/audio/music/musicVoice.js.map +0 -1
  377. package/dist/audio/sampleBank.js.map +0 -1
  378. package/dist/audio/soundTable.js.map +0 -1
  379. package/dist/audio/synth.js.map +0 -1
  380. package/dist/core/BitmapLabel.js.map +0 -1
  381. package/dist/core/Camera.js.map +0 -1
  382. package/dist/core/Clock.js.map +0 -1
  383. package/dist/core/Graphics.js.map +0 -1
  384. package/dist/core/Group.js.map +0 -1
  385. package/dist/core/Image.js.map +0 -1
  386. package/dist/core/ObjectFactory.js.map +0 -1
  387. package/dist/core/Pointer.js.map +0 -1
  388. package/dist/core/Rectangle.js.map +0 -1
  389. package/dist/core/Stage.js.map +0 -1
  390. package/dist/core/Text.js.map +0 -1
  391. package/dist/core/TextureRegistry.js.map +0 -1
  392. package/dist/core/Timeline.js.map +0 -1
  393. package/dist/core/TimelineBuilder.js.map +0 -1
  394. package/dist/core/TimelineChild.js.map +0 -1
  395. package/dist/core/Tweener.js.map +0 -1
  396. package/dist/core/atlas.js.map +0 -1
  397. package/dist/core/atlasPlan.js.map +0 -1
  398. package/dist/core/eases.js.map +0 -1
  399. package/dist/core/gameObject.js.map +0 -1
  400. package/dist/core/pixiPatches.js.map +0 -1
  401. package/dist/core/timelinePlace.js.map +0 -1
  402. package/dist/core/tweenProps.js.map +0 -1
  403. package/dist/debug/DebugOverlay.js.map +0 -1
  404. package/dist/debug/DrawCallCounter.js.map +0 -1
  405. package/dist/debug/ErrorLog.js.map +0 -1
  406. package/dist/debug/FrameStats.js.map +0 -1
  407. package/dist/debug/inspectWorld.js.map +0 -1
  408. package/dist/diagnostics/ErrorDeduper.js.map +0 -1
  409. package/dist/diagnostics/FrameSampler.js.map +0 -1
  410. package/dist/diagnostics/bootWatch.js.map +0 -1
  411. package/dist/diagnostics/captureErrors.js.map +0 -1
  412. package/dist/diagnostics/contextLoss.js.map +0 -1
  413. package/dist/diagnostics/frameStats.js.map +0 -1
  414. package/dist/diagnostics/gpuInfo.js.map +0 -1
  415. package/dist/diagnostics/renderGuard.js.map +0 -1
  416. package/dist/ecs/SparseSet.js.map +0 -1
  417. package/dist/ecs/World.js.map +0 -1
  418. package/dist/ecs/fields.js.map +0 -1
  419. package/dist/engine/Engine.js.map +0 -1
  420. package/dist/engine/FixedLoop.js.map +0 -1
  421. package/dist/engine/Scene.js.map +0 -1
  422. package/dist/engine/SceneManager.js.map +0 -1
  423. package/dist/events/EventBus.js.map +0 -1
  424. package/dist/fx/FloatingText.js.map +0 -1
  425. package/dist/fx/hitStop.js.map +0 -1
  426. package/dist/fx/viewCull.js.map +0 -1
  427. package/dist/i18n/Translator.js.map +0 -1
  428. package/dist/i18n/extractStrings.js.map +0 -1
  429. package/dist/i18n/formatMessage.js.map +0 -1
  430. package/dist/input/Actions.js.map +0 -1
  431. package/dist/input/AimGesture.js.map +0 -1
  432. package/dist/input/Keyboard.js.map +0 -1
  433. package/dist/input/Keymap.js.map +0 -1
  434. package/dist/input/TargetLock.js.map +0 -1
  435. package/dist/input/aimAxis.js.map +0 -1
  436. package/dist/input/keyChord.js.map +0 -1
  437. package/dist/input/longPress.js.map +0 -1
  438. package/dist/input/stickAxis.js.map +0 -1
  439. package/dist/input/touchDetect.js.map +0 -1
  440. package/dist/light/LightLayer.js.map +0 -1
  441. package/dist/nav/MinHeap.js.map +0 -1
  442. package/dist/nav/findPath.js.map +0 -1
  443. package/dist/nav/navGrid.js.map +0 -1
  444. package/dist/nav/nearestOpen.js.map +0 -1
  445. package/dist/nav/straightenPath.js.map +0 -1
  446. package/dist/net/Connection.js.map +0 -1
  447. package/dist/net/InterpolationBuffer.js.map +0 -1
  448. package/dist/net/PredictedMover.js.map +0 -1
  449. package/dist/net/Room.js.map +0 -1
  450. package/dist/net/RoomHost.js.map +0 -1
  451. package/dist/net/cadence.js.map +0 -1
  452. package/dist/net/constants.js.map +0 -1
  453. package/dist/net/lobby/LobbyClient.js.map +0 -1
  454. package/dist/net/lobby/LobbyHost.js.map +0 -1
  455. package/dist/net/lobby/LobbyRooms.js.map +0 -1
  456. package/dist/net/lobby/Matchmaker.js.map +0 -1
  457. package/dist/net/movement.js.map +0 -1
  458. package/dist/net/protocol.js.map +0 -1
  459. package/dist/net/serverClock.js.map +0 -1
  460. package/dist/net/snapshotCodec.js.map +0 -1
  461. package/dist/parallax/Parallax.js.map +0 -1
  462. package/dist/parallax/ParallaxLayer.js.map +0 -1
  463. package/dist/parallax/parallaxMath.js.map +0 -1
  464. package/dist/particles/Emitter.js.map +0 -1
  465. package/dist/particles/ParticleBudget.js.map +0 -1
  466. package/dist/particles/ParticleSim.js.map +0 -1
  467. package/dist/particles/particleCurves.js.map +0 -1
  468. package/dist/particles/particleSampling.js.map +0 -1
  469. package/dist/physics/Body.js.map +0 -1
  470. package/dist/physics/BroadPhase.js.map +0 -1
  471. package/dist/physics/Contact.js.map +0 -1
  472. package/dist/physics/ContactSolver.js.map +0 -1
  473. package/dist/physics/PhysicsWorld.js.map +0 -1
  474. package/dist/physics/SpatialHash.js.map +0 -1
  475. package/dist/physics/collide.js.map +0 -1
  476. package/dist/physics/collidePolygon.js.map +0 -1
  477. package/dist/physics/contactReport.js.map +0 -1
  478. package/dist/physics/drawColliders.js.map +0 -1
  479. package/dist/physics/physicsSystem.js.map +0 -1
  480. package/dist/physics/polygon.js.map +0 -1
  481. package/dist/physics/raycast.js.map +0 -1
  482. package/dist/physics/syncToBody.js.map +0 -1
  483. package/dist/physics/tileBodies.js.map +0 -1
  484. package/dist/physics/types.js.map +0 -1
  485. package/dist/pixel/Darkness.js.map +0 -1
  486. package/dist/pixel/DitherVignette.js.map +0 -1
  487. package/dist/pixel/Evaporation.js.map +0 -1
  488. package/dist/pixel/NightShade.js.map +0 -1
  489. package/dist/pixel/PixelLayer.js.map +0 -1
  490. package/dist/pixel/SwayProp.js.map +0 -1
  491. package/dist/pixel/lights.js.map +0 -1
  492. package/dist/pixel/nineSlice.js.map +0 -1
  493. package/dist/pixel/paintLayer.js.map +0 -1
  494. package/dist/pixel/palette.js.map +0 -1
  495. package/dist/pixel/pixel.js.map +0 -1
  496. package/dist/pixel/pixelPaint.js.map +0 -1
  497. package/dist/pixel/pixelTone.js.map +0 -1
  498. package/dist/pixel/propKit.js.map +0 -1
  499. package/dist/pixel/ramp.js.map +0 -1
  500. package/dist/pixel/selout.js.map +0 -1
  501. package/dist/pixel/spritePixels.js.map +0 -1
  502. package/dist/pixel/swayRig.js.map +0 -1
  503. package/dist/pixel/vignetteMask.js.map +0 -1
  504. package/dist/pixel/weatherArt.js.map +0 -1
  505. package/dist/pixel.js.map +0 -1
  506. package/dist/platform/touch.js.map +0 -1
  507. package/dist/postfx/BloomFilter.js.map +0 -1
  508. package/dist/postfx/ChromaticAberrationFilter.js.map +0 -1
  509. package/dist/postfx/ColorAdjustFilter.js.map +0 -1
  510. package/dist/postfx/CrtFilter.js.map +0 -1
  511. package/dist/postfx/PixelateFilter.js.map +0 -1
  512. package/dist/postfx/PostFx.js.map +0 -1
  513. package/dist/postfx/ShockwaveFilter.js.map +0 -1
  514. package/dist/postfx/VignetteFilter.js.map +0 -1
  515. package/dist/postfx/fxAnimator.js.map +0 -1
  516. package/dist/postfx/fxShader.js.map +0 -1
  517. package/dist/postfx.js.map +0 -1
  518. package/dist/react/ChoiceDialog.js.map +0 -1
  519. package/dist/react/ConfirmDialog.js.map +0 -1
  520. package/dist/react/Glyph.js.map +0 -1
  521. package/dist/react/Modal.js.map +0 -1
  522. package/dist/react/Panel.js.map +0 -1
  523. package/dist/react/PixelImage.js.map +0 -1
  524. package/dist/react/Select.js.map +0 -1
  525. package/dist/react/Slider.js.map +0 -1
  526. package/dist/react/SplitPane.js.map +0 -1
  527. package/dist/react/TabStrip.js.map +0 -1
  528. package/dist/react/TitleTips.js.map +0 -1
  529. package/dist/react/Tooltip.js.map +0 -1
  530. package/dist/react/UiProvider.js.map +0 -1
  531. package/dist/react/baseCss.js.map +0 -1
  532. package/dist/react/choiceStore.js.map +0 -1
  533. package/dist/react/classNames.js.map +0 -1
  534. package/dist/react/confirmStore.js.map +0 -1
  535. package/dist/react/labels.js.map +0 -1
  536. package/dist/react/placement.js.map +0 -1
  537. package/dist/react/useFillSheet.js.map +0 -1
  538. package/dist/react/useFitToViewport.js.map +0 -1
  539. package/dist/react/usePicked.js.map +0 -1
  540. package/dist/react/useStore.js.map +0 -1
  541. package/dist/react/useViewport.js.map +0 -1
  542. package/dist/react.js.map +0 -1
  543. package/dist/rig/PosePlayer.js.map +0 -1
  544. package/dist/rig/RigView.js.map +0 -1
  545. package/dist/rig/Skeleton.js.map +0 -1
  546. package/dist/rig/humanoid.js.map +0 -1
  547. package/dist/rig/humanoid.json.js.map +0 -1
  548. package/dist/rig/humanoidPoses.js.map +0 -1
  549. package/dist/rig/poseMath.js.map +0 -1
  550. package/dist/rig/poses.json.js.map +0 -1
  551. package/dist/save/Autosaver.js.map +0 -1
  552. package/dist/save/MemoryBackend.js.map +0 -1
  553. package/dist/save/SaveStore.js.map +0 -1
  554. package/dist/save/WebStorageBackend.js.map +0 -1
  555. package/dist/save/checksum.js.map +0 -1
  556. package/dist/save/migrateSave.js.map +0 -1
  557. package/dist/settings.js.map +0 -1
  558. package/dist/tilemap/TilemapView.js.map +0 -1
  559. package/dist/tilemap/collision.js.map +0 -1
  560. package/dist/tilemap/tiled.js.map +0 -1
  561. package/dist/transitions/CrossfadeTransition.js.map +0 -1
  562. package/dist/transitions/DitherWipeTransition.js.map +0 -1
  563. package/dist/transitions/FadeTransition.js.map +0 -1
  564. package/dist/transitions/Letterbox.js.map +0 -1
  565. package/dist/transitions/ditherMask.js.map +0 -1
  566. package/dist/transitions/transitionTo.js.map +0 -1
  567. package/dist/transitions/tweenDone.js.map +0 -1
  568. package/dist/ui/Bar.js.map +0 -1
  569. package/dist/ui/Button.js.map +0 -1
  570. package/dist/ui/Dialog.js.map +0 -1
  571. package/dist/ui/FocusManager.js.map +0 -1
  572. package/dist/ui/Label.js.map +0 -1
  573. package/dist/ui/List.js.map +0 -1
  574. package/dist/ui/Panel.js.map +0 -1
  575. package/dist/ui/ScrollView.js.map +0 -1
  576. package/dist/ui/Slider.js.map +0 -1
  577. package/dist/ui/Stack.js.map +0 -1
  578. package/dist/ui/Toggle.js.map +0 -1
  579. package/dist/ui/UiHost.js.map +0 -1
  580. package/dist/ui/UiPointerGate.js.map +0 -1
  581. package/dist/ui/UiRoot.js.map +0 -1
  582. package/dist/ui/Widget.js.map +0 -1
  583. package/dist/ui/dom/DomOverlay.js.map +0 -1
  584. package/dist/ui/dom/DomWorldAnchors.js.map +0 -1
  585. package/dist/ui/dom/InputShield.js.map +0 -1
  586. package/dist/ui/dom/createStore.js.map +0 -1
  587. package/dist/ui/dom/shieldDecision.js.map +0 -1
  588. package/dist/ui/dom/worldToScreen.js.map +0 -1
  589. package/dist/ui/layout/anchor.js.map +0 -1
  590. package/dist/ui/layout/barDrain.js.map +0 -1
  591. package/dist/ui/layout/fitToViewport.js.map +0 -1
  592. package/dist/ui/layout/focusNav.js.map +0 -1
  593. package/dist/ui/layout/geometry.js.map +0 -1
  594. package/dist/ui/layout/listWidth.js.map +0 -1
  595. package/dist/ui/layout/placeTooltip.js.map +0 -1
  596. package/dist/ui/layout/scroll.js.map +0 -1
  597. package/dist/ui/layout/slider.js.map +0 -1
  598. package/dist/ui/layout/stack.js.map +0 -1
  599. package/dist/ui/layout/wrapRow.js.map +0 -1
  600. package/dist/ui.js.map +0 -1
@@ -0,0 +1,105 @@
1
+ import { BitmapFontManager as l, BitmapText as h, TextStyle as f, CanvasTextMetrics as c, Text as m } from "pixi.js";
2
+ import { installLabelFont as u } from "../../core/BitmapLabel.js";
3
+ function a(o) {
4
+ return `${o.color ?? ""}|${o.bold ? 1 : 0}|${o.italic ? 1 : 0}|${o.size ?? ""}`;
5
+ }
6
+ class x {
7
+ constructor(t) {
8
+ this.options = t;
9
+ }
10
+ options;
11
+ styles = /* @__PURE__ */ new Map();
12
+ metrics = /* @__PURE__ */ new Map();
13
+ textWidth(t, s) {
14
+ return c.measureText(t, this.pixiStyle(s), void 0, !1).width;
15
+ }
16
+ lineHeight(t) {
17
+ return this.metricsOf(t).lineHeight;
18
+ }
19
+ ascent(t) {
20
+ return this.metricsOf(t).ascent;
21
+ }
22
+ createRun() {
23
+ return new m({ text: "", style: this.pixiStyle({ bold: !1, italic: !1 }), resolution: this.options.resolution ?? 1 });
24
+ }
25
+ updateRun(t, s, i) {
26
+ const e = t, n = this.pixiStyle(i);
27
+ e.style !== n && (e.style = n), e.text !== s && (e.text = s);
28
+ }
29
+ metricsOf(t) {
30
+ const s = a(t);
31
+ let i = this.metrics.get(s);
32
+ if (!i) {
33
+ const e = c.measureText("M", this.pixiStyle(t), void 0, !1);
34
+ i = { lineHeight: e.lineHeight, ascent: e.fontProperties.ascent }, this.metrics.set(s, i);
35
+ }
36
+ return i;
37
+ }
38
+ pixiStyle(t) {
39
+ const s = a(t);
40
+ let i = this.styles.get(s);
41
+ if (!i) {
42
+ const e = this.options;
43
+ i = new f({
44
+ fontFamily: e.fontFamily,
45
+ fontSize: t.size ?? e.fontSize,
46
+ fill: t.color ?? e.color ?? "#ffffff",
47
+ fontWeight: t.bold ? "bold" : "normal",
48
+ fontStyle: t.italic ? "italic" : "normal",
49
+ ...e.stroke ? { stroke: { color: e.stroke, width: e.strokeWidth ?? 1, join: "round" } } : {}
50
+ }), this.styles.set(s, i);
51
+ }
52
+ return i;
53
+ }
54
+ }
55
+ class d {
56
+ constructor(t) {
57
+ this.options = t;
58
+ }
59
+ options;
60
+ styles = /* @__PURE__ */ new Map();
61
+ metrics = /* @__PURE__ */ new Map();
62
+ textWidth(t, s) {
63
+ const i = l.measureText(t, this.pixiStyle(s), !1);
64
+ return i.width * i.scale;
65
+ }
66
+ lineHeight(t) {
67
+ return this.metricsOf(t).lineHeight;
68
+ }
69
+ ascent(t) {
70
+ return this.metricsOf(t).ascent;
71
+ }
72
+ createRun() {
73
+ return new h({ text: "", style: this.pixiStyle({ bold: !1, italic: !1 }) });
74
+ }
75
+ updateRun(t, s, i) {
76
+ const e = t, n = this.pixiStyle(i);
77
+ e.style !== n && (e.style = n), e.text !== s && (e.text = s);
78
+ }
79
+ metricsOf(t) {
80
+ const s = this.fontKey(t);
81
+ let i = this.metrics.get(s);
82
+ if (!i) {
83
+ const e = this.pixiStyle(t), n = l.getFont("M", e), r = e.fontSize / n.baseMeasurementFontSize;
84
+ i = { lineHeight: n.lineHeight * r, ascent: n.fontMetrics.ascent * r }, this.metrics.set(s, i);
85
+ }
86
+ return i;
87
+ }
88
+ /** Bold and italic do not reach a bitmap font: styles differing only by them share one. */
89
+ fontKey(t) {
90
+ return `${t.color ?? ""}|${t.size ?? ""}`;
91
+ }
92
+ pixiStyle(t) {
93
+ const s = this.fontKey(t);
94
+ let i = this.styles.get(s);
95
+ if (!i) {
96
+ const e = this.options, n = t.size ?? e.fontSize, r = u(e.fontFamily, n, t.color ?? e.color ?? "#ffffff", e.stroke ?? "#000000", e.strokeWidth ?? 0, e.resolution ?? 1, e.glyphs ?? "");
97
+ i = new f({ fontFamily: r, fontSize: n }), this.styles.set(s, i);
98
+ }
99
+ return i;
100
+ }
101
+ }
102
+ export {
103
+ d as BitmapRichFont,
104
+ x as CanvasRichFont
105
+ };
@@ -0,0 +1,132 @@
1
+ function W(l, n, o = {}) {
2
+ const t = O(l, n, o), e = o.wrapWidth, i = [];
3
+ let s = [], h = 0, y = [], g = !1, x = l[0]?.style ?? { bold: !1, italic: !1 };
4
+ const w = () => {
5
+ i.push({ atoms: s, empty: x }), s = [], h = 0, y = [];
6
+ };
7
+ for (let c = 0; c < t.length; ) {
8
+ const f = t[c];
9
+ if (f.t === "br") {
10
+ x = f.style, w(), g = !1, c++;
11
+ continue;
12
+ }
13
+ if (f.t === "space") {
14
+ y.push(f), c++;
15
+ continue;
16
+ }
17
+ const r = [];
18
+ for (; c < t.length && (t[c].t === "word" || t[c].t === "icon"); ) r.push(t[c++]);
19
+ const d = b(r);
20
+ s.length === 0 && g && (y = []), e !== void 0 && s.length > 0 && h + b(y) + d > e + 1e-6 && (w(), g = !0);
21
+ for (const u of y) s.push(u);
22
+ if (h += b(y), y = [], e !== void 0 && h + d > e + 1e-6)
23
+ for (const u of r)
24
+ for (const p of L(u, n, e, () => h)) {
25
+ if (p === "break") {
26
+ w(), g = !0;
27
+ continue;
28
+ }
29
+ s.push(p), h += p.w;
30
+ }
31
+ else {
32
+ for (const u of r) s.push(u);
33
+ h += d;
34
+ }
35
+ }
36
+ return (s.length > 0 || i.length === 0 || t[t.length - 1]?.t === "br") && w(), N(i, n, o);
37
+ }
38
+ function O(l, n, o) {
39
+ const t = [];
40
+ for (const e of l) {
41
+ if (e.kind === "icon") {
42
+ const i = n.iconSize(e.key, e.frame), s = I(i.height, n.lineHeight(e.style), o), h = { t: "icon", key: e.key, style: e.style, w: i.width * s, h: i.height * s };
43
+ e.frame !== void 0 && (h.frame = e.frame), t.push(h);
44
+ continue;
45
+ }
46
+ for (const i of e.text.matchAll(/(\r?\n)|([ \t]+)|([^ \t\r\n]+)/g))
47
+ i[1] ? t.push({ t: "br", style: e.style }) : i[2] ? t.push({ t: "space", text: i[2], style: e.style, w: n.textWidth(i[2], e.style) }) : t.push({ t: "word", text: i[3], style: e.style, w: n.textWidth(i[3], e.style) });
48
+ }
49
+ return t;
50
+ }
51
+ function I(l, n, o) {
52
+ if (typeof o.iconScale == "number") return o.iconScale;
53
+ if (l <= 0) return 1;
54
+ const t = n / l;
55
+ return o.pixelPerfect ? Math.max(1, Math.floor(t)) : t;
56
+ }
57
+ function* L(l, n, o, t) {
58
+ if (l.t !== "word") {
59
+ t() > 0 && t() + l.w > o + 1e-6 && (yield "break"), yield l;
60
+ return;
61
+ }
62
+ const e = Array.from(l.text);
63
+ let i = 0;
64
+ for (; i < e.length; ) {
65
+ let s = i, h = 0;
66
+ for (; s < e.length; ) {
67
+ const y = n.textWidth(e.slice(i, s + 1).join(""), l.style);
68
+ if (t() + y > o + 1e-6 && !(s === i && t() === 0)) break;
69
+ h = y, s++;
70
+ }
71
+ if (s === i) {
72
+ yield "break";
73
+ continue;
74
+ }
75
+ yield { t: "word", text: e.slice(i, s).join(""), style: l.style, w: h }, i = s, i < e.length && (yield "break");
76
+ }
77
+ }
78
+ function N(l, n, o) {
79
+ const t = o.pixelPerfect ? Math.round : (c) => c, e = o.lineSpacing ?? 0, i = (c, f) => n.ascent?.(c) ?? f * 0.8, s = [];
80
+ let h = 0;
81
+ for (const c of l) {
82
+ for (; c.atoms.length > 0 && c.atoms[c.atoms.length - 1].t === "space"; ) c.atoms.pop();
83
+ const f = v(c.atoms, n);
84
+ let r = 0, d = 0;
85
+ const u = [];
86
+ if (f.length === 0) {
87
+ const a = n.lineHeight(c.empty);
88
+ r = -i(c.empty, a), d = r + a;
89
+ }
90
+ f.forEach((a, m) => {
91
+ const E = n.lineHeight(a.style), M = i(a.style, E), k = a.kind === "text" ? -M : -M + (E - a.height) / 2;
92
+ u[m] = k, (m === 0 || k < r) && (r = k), (m === 0 || k + a.height > d) && (d = k + a.height);
93
+ });
94
+ const p = t(-r), P = o.pixelPerfect ? Math.ceil(d - r) : d - r;
95
+ let S = 0;
96
+ f.forEach((a, m) => {
97
+ a.x = S, a.y = h + t(p + u[m]), S += a.width;
98
+ }), s.push({ y: h, width: S, height: P, baseline: p, items: f }), h += P + e;
99
+ }
100
+ const y = s.length === 0 ? 0 : h - e, g = s.reduce((c, f) => Math.max(c, f.width), 0), x = o.wrapWidth ?? g, w = o.align === "center" ? 0.5 : o.align === "right" ? 1 : 0;
101
+ for (const c of s) {
102
+ const f = (x - c.width) * w;
103
+ for (const r of c.items) r.x = t(r.x + f);
104
+ }
105
+ return { width: o.pixelPerfect ? Math.ceil(x) : x, height: y, lines: s };
106
+ }
107
+ function v(l, n) {
108
+ const o = [];
109
+ for (const t of l) {
110
+ if (t.t === "icon") {
111
+ const i = { kind: "icon", key: t.key, style: t.style, x: 0, y: 0, width: t.w, height: t.h };
112
+ t.frame !== void 0 && (i.frame = t.frame), o.push(i);
113
+ continue;
114
+ }
115
+ const e = o[o.length - 1];
116
+ e && e.kind === "text" && z(e.style, t.style) ? e.text += t.text : o.push({ kind: "text", text: t.text, style: t.style, x: 0, y: 0, width: 0, height: n.lineHeight(t.style) });
117
+ }
118
+ for (const t of o) t.kind === "text" && (t.width = n.textWidth(t.text, t.style));
119
+ return o;
120
+ }
121
+ function z(l, n) {
122
+ return l === n || l.color === n.color && l.bold === n.bold && l.italic === n.italic && l.size === n.size;
123
+ }
124
+ function b(l) {
125
+ let n = 0;
126
+ for (const o of l) n += o.w;
127
+ return n;
128
+ }
129
+ export {
130
+ W as layoutRichText,
131
+ z as sameStyle
132
+ };
@@ -0,0 +1,67 @@
1
+ const f = Object.freeze({ bold: !1, italic: !1 }), d = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i, h = /^\d+(?:\.\d+)?$/;
2
+ function m(s) {
3
+ return s.replace(/\[/g, "[[");
4
+ }
5
+ function x(s, c = {}) {
6
+ const n = [], r = [], u = () => r[r.length - 1]?.style ?? f, o = (l) => {
7
+ if (!l) return;
8
+ const i = u(), a = n[n.length - 1];
9
+ a && a.kind === "text" && a.style === i ? a.text += l : n.push({ kind: "text", text: l, style: i });
10
+ };
11
+ let e = 0, t = 0;
12
+ for (; e < s.length; ) {
13
+ if (s[e] !== "[") {
14
+ e++;
15
+ continue;
16
+ }
17
+ if (o(s.slice(t, e)), s[e + 1] === "[") {
18
+ o("["), e += 2, t = e;
19
+ continue;
20
+ }
21
+ const l = s.indexOf("]", e + 1), i = l < 0 ? null : s.slice(e + 1, l);
22
+ if (i === null || i.includes("[") || !y(i, r, u(), n, c)) {
23
+ o("["), e += 1, t = e;
24
+ continue;
25
+ }
26
+ e = l + 1, t = e;
27
+ }
28
+ return o(s.slice(t)), n;
29
+ }
30
+ function p(s, c = {}) {
31
+ let n = "";
32
+ for (const r of x(s, c)) r.kind === "text" && (n += r.text);
33
+ return n;
34
+ }
35
+ function y(s, c, n, r, u) {
36
+ if (s.startsWith("/")) {
37
+ const l = s.slice(1).trim().toLowerCase();
38
+ for (let i = c.length - 1; i >= 0; i--)
39
+ if (c[i].name === l)
40
+ return c.length = i, !0;
41
+ return !1;
42
+ }
43
+ const o = s.indexOf("="), e = (o < 0 ? s : s.slice(0, o)).trim().toLowerCase(), t = o < 0 ? null : s.slice(o + 1).trim();
44
+ switch (e) {
45
+ case "b":
46
+ case "i":
47
+ return t !== null ? !1 : (c.push({ name: e, style: { ...n, [e === "b" ? "bold" : "italic"]: !0 } }), !0);
48
+ case "color": {
49
+ const l = t === null ? void 0 : d.test(t) ? t : u.colors?.[t];
50
+ return l ? (c.push({ name: e, style: { ...n, color: l } }), !0) : !1;
51
+ }
52
+ case "size":
53
+ return t === null || !h.test(t) || Number(t) <= 0 ? !1 : (c.push({ name: e, style: { ...n, size: Number(t) } }), !0);
54
+ case "icon": {
55
+ if (!t) return !1;
56
+ const l = t.lastIndexOf(":"), i = l > 0 ? { kind: "icon", key: t.slice(0, l), frame: t.slice(l + 1), style: n } : { kind: "icon", key: t, style: n };
57
+ return r.push(i), !0;
58
+ }
59
+ default:
60
+ return !1;
61
+ }
62
+ }
63
+ export {
64
+ m as escapeRichText,
65
+ x as parseRichText,
66
+ p as stripRichText
67
+ };
package/dist/ui.js CHANGED
@@ -1,85 +1,95 @@
1
- import { clamp as e, insets as t, snapPx as p, snapRect as m } from "./ui/layout/geometry.js";
2
- import { stackLayout as i } from "./ui/layout/stack.js";
3
- import { anchorPosition as l } from "./ui/layout/anchor.js";
1
+ import { clamp as e, insets as t, snapPx as p, snapRect as i } from "./ui/layout/geometry.js";
2
+ import { stackLayout as m } from "./ui/layout/stack.js";
3
+ import { anchorPosition as a } from "./ui/layout/anchor.js";
4
4
  import { fitToViewport as s } from "./ui/layout/fitToViewport.js";
5
- import { placeTooltip as c } from "./ui/layout/placeTooltip.js";
6
- import { wrapRow as u } from "./ui/layout/wrapRow.js";
7
- import { listWidth as F } from "./ui/layout/listWidth.js";
8
- import { FLING_STOP as h, clampScroll as w, maxScroll as D, scrollIntoView as T, stepFling as V } from "./ui/layout/scroll.js";
9
- import { quantize as P, sliderFraction as A, sliderValueAt as I } from "./ui/layout/slider.js";
10
- import { drainState as R, setDrainValue as U, stepDrain as W } from "./ui/layout/barDrain.js";
11
- import { firstFocus as k, linearFocus as y, nextFocus as z } from "./ui/layout/focusNav.js";
12
- import { UiRoot as E } from "./ui/UiRoot.js";
13
- import { uiHostOf as N } from "./ui/UiHost.js";
14
- import { UiPointerGate as q } from "./ui/UiPointerGate.js";
15
- import { DEFAULT_NAV as H, FocusManager as M } from "./ui/FocusManager.js";
16
- import { Widget as C, sizeOf as J } from "./ui/Widget.js";
5
+ import { placeTooltip as n } from "./ui/layout/placeTooltip.js";
6
+ import { wrapRow as h } from "./ui/layout/wrapRow.js";
7
+ import { listWidth as S } from "./ui/layout/listWidth.js";
8
+ import { FLING_STOP as F, clampScroll as R, maxScroll as g, scrollIntoView as w, stepFling as D } from "./ui/layout/scroll.js";
9
+ import { quantize as L, sliderFraction as P, sliderValueAt as A } from "./ui/layout/slider.js";
10
+ import { drainState as O, setDrainValue as y, stepDrain as B } from "./ui/layout/barDrain.js";
11
+ import { firstFocus as W, linearFocus as b, nextFocus as k } from "./ui/layout/focusNav.js";
12
+ import { UiRoot as z } from "./ui/UiRoot.js";
13
+ import { uiHostOf as G } from "./ui/UiHost.js";
14
+ import { UiPointerGate as _ } from "./ui/UiPointerGate.js";
15
+ import { DEFAULT_NAV as C, FocusManager as H } from "./ui/FocusManager.js";
16
+ import { Widget as j, sizeOf as J } from "./ui/Widget.js";
17
17
  import { Panel as Q } from "./ui/Panel.js";
18
18
  import { Label as Y } from "./ui/Label.js";
19
19
  import { Button as $ } from "./ui/Button.js";
20
20
  import { Bar as ro } from "./ui/Bar.js";
21
21
  import { Slider as to } from "./ui/Slider.js";
22
- import { Toggle as mo } from "./ui/Toggle.js";
23
- import { Stack as io } from "./ui/Stack.js";
24
- import { ScrollView as lo } from "./ui/ScrollView.js";
22
+ import { Toggle as io } from "./ui/Toggle.js";
23
+ import { Stack as mo } from "./ui/Stack.js";
24
+ import { ScrollView as ao } from "./ui/ScrollView.js";
25
25
  import { List as so } from "./ui/List.js";
26
- import { Dialog as co } from "./ui/Dialog.js";
27
- import { DomOverlay as So } from "./ui/dom/DomOverlay.js";
28
- import { DomWorldAnchors as go } from "./ui/dom/DomWorldAnchors.js";
29
- import { onScreen as wo, worldToScreen as Do } from "./ui/dom/worldToScreen.js";
30
- import { createStore as Vo } from "./ui/dom/createStore.js";
31
- import { InputShield as Po } from "./ui/dom/InputShield.js";
32
- import { isEditable as Io, isInside as Oo, shouldShield as Ro } from "./ui/dom/shieldDecision.js";
26
+ import { Dialog as no } from "./ui/Dialog.js";
27
+ import { DomOverlay as uo } from "./ui/dom/DomOverlay.js";
28
+ import { DomWorldAnchors as To } from "./ui/dom/DomWorldAnchors.js";
29
+ import { onScreen as Ro, worldToScreen as go } from "./ui/dom/worldToScreen.js";
30
+ import { createStore as Do } from "./ui/dom/createStore.js";
31
+ import { InputShield as Lo } from "./ui/dom/InputShield.js";
32
+ import { isEditable as Ao, isInside as Io, shouldShield as Oo } from "./ui/dom/shieldDecision.js";
33
+ import { RichText as Bo } from "./ui/rich/RichText.js";
34
+ import { BitmapRichFont as Wo, CanvasRichFont as bo } from "./ui/rich/richFonts.js";
35
+ import { escapeRichText as vo, parseRichText as zo, stripRichText as Eo } from "./ui/rich/richMarkup.js";
36
+ import { layoutRichText as No } from "./ui/rich/richLayout.js";
33
37
  export {
34
38
  ro as Bar,
39
+ Wo as BitmapRichFont,
35
40
  $ as Button,
36
- H as DEFAULT_NAV,
37
- co as Dialog,
38
- So as DomOverlay,
39
- go as DomWorldAnchors,
40
- h as FLING_STOP,
41
- M as FocusManager,
42
- Po as InputShield,
41
+ bo as CanvasRichFont,
42
+ C as DEFAULT_NAV,
43
+ no as Dialog,
44
+ uo as DomOverlay,
45
+ To as DomWorldAnchors,
46
+ F as FLING_STOP,
47
+ H as FocusManager,
48
+ Lo as InputShield,
43
49
  Y as Label,
44
50
  so as List,
45
51
  Q as Panel,
46
- lo as ScrollView,
52
+ Bo as RichText,
53
+ ao as ScrollView,
47
54
  to as Slider,
48
- io as Stack,
49
- mo as Toggle,
50
- q as UiPointerGate,
51
- E as UiRoot,
52
- C as Widget,
53
- l as anchorPosition,
55
+ mo as Stack,
56
+ io as Toggle,
57
+ _ as UiPointerGate,
58
+ z as UiRoot,
59
+ j as Widget,
60
+ a as anchorPosition,
54
61
  e as clamp,
55
- w as clampScroll,
56
- Vo as createStore,
57
- R as drainState,
58
- k as firstFocus,
62
+ R as clampScroll,
63
+ Do as createStore,
64
+ O as drainState,
65
+ vo as escapeRichText,
66
+ W as firstFocus,
59
67
  s as fitToViewport,
60
68
  t as insets,
61
- Io as isEditable,
62
- Oo as isInside,
63
- y as linearFocus,
64
- F as listWidth,
65
- D as maxScroll,
66
- z as nextFocus,
67
- wo as onScreen,
68
- c as placeTooltip,
69
- P as quantize,
70
- T as scrollIntoView,
71
- U as setDrainValue,
72
- Ro as shouldShield,
69
+ Ao as isEditable,
70
+ Io as isInside,
71
+ No as layoutRichText,
72
+ b as linearFocus,
73
+ S as listWidth,
74
+ g as maxScroll,
75
+ k as nextFocus,
76
+ Ro as onScreen,
77
+ zo as parseRichText,
78
+ n as placeTooltip,
79
+ L as quantize,
80
+ w as scrollIntoView,
81
+ y as setDrainValue,
82
+ Oo as shouldShield,
73
83
  J as sizeOf,
74
- A as sliderFraction,
75
- I as sliderValueAt,
84
+ P as sliderFraction,
85
+ A as sliderValueAt,
76
86
  p as snapPx,
77
- m as snapRect,
78
- i as stackLayout,
79
- W as stepDrain,
80
- V as stepFling,
81
- N as uiHostOf,
82
- Do as worldToScreen,
83
- u as wrapRow
87
+ i as snapRect,
88
+ m as stackLayout,
89
+ B as stepDrain,
90
+ D as stepFling,
91
+ Eo as stripRichText,
92
+ G as uiHostOf,
93
+ go as worldToScreen,
94
+ h as wrapRow
84
95
  };
85
- //# sourceMappingURL=ui.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "1681-engine",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "A 2D game engine on PixiJS 8 for any art style: scenes and a fast ECS, a fixed-step loop, asset loading, Tiled maps, sprite animation, input actions, camera follow, audio and deterministic, server-replayable movement, plus Dither, an optional pixel-art module (pixel-perfect effects, dithered lighting).",
5
5
  "type": "module",
6
6
  "types": "./dist/types/index.d.ts",
@@ -89,9 +89,6 @@
89
89
  "LICENSE",
90
90
  "CHANGELOG.md"
91
91
  ],
92
- "engines": {
93
- "node": ">=22"
94
- },
95
92
  "peerDependencies": {
96
93
  "pixi.js": "^8.6.0",
97
94
  "react": "^19.0.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"1681-engine.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ColorGrade.js","sources":["../../src/ambient/ColorGrade.ts"],"sourcesContent":["import { Sprite, Texture, type Container } from 'pixi.js';\nimport type { Stage } from '../core/Stage';\nimport { mixToWhite, type GradeState } from './grade';\n\n/** Where the sheet goes among its parent's children. */\nexport type GradePlacement = 'top' | 'bottom';\n\nexport interface ColorGradeOptions {\n /** How often (ms) the grade is read again: the hour moves slowly, so not every frame (default 500). */\n readEveryMs?: number;\n /** The container the sheet is added to (default the stage's screen layer). */\n parent?: Container;\n /**\n * `'top'` (the default) adds the sheet over everything already in `parent`, so it tints a HUD made before it and\n * not one made after. `'bottom'` puts it under every child `parent` has or will have: on the screen layer that is\n * over the world and under every HUD, whatever order they were made in — usually what a grade wants.\n */\n placement?: GradePlacement;\n}\n\n/**\n * A colour laid over the whole screen in **multiply**, so it tints the world (a marsh mossy, a peak ember, a dead\n * land pale) without washing the art toward white the way a normal-blend sheet would. One white quad, tinted: no\n * filter pass, which is what a phone can spare every frame.\n *\n * `read` returns the grade now (`gradeAt` from a place's `Grade` and `DayClock`'s night, say); it is asked a few\n * times a second, and a grade that comes to white is not drawn at all. Give `placement: 'bottom'` to keep it off the\n * HUD (see `ColorGradeOptions.placement`).\n */\nexport class ColorGrade {\n private readonly sheet = new Sprite({ texture: Texture.WHITE });\n private readAt = -Infinity;\n private blank = false;\n private readonly every: number;\n\n constructor(\n private readonly stage: Stage,\n private readonly read: () => GradeState | null,\n options: ColorGradeOptions = {},\n ) {\n this.every = options.readEveryMs ?? 500;\n this.sheet.blendMode = 'multiply';\n this.sheet.visible = false;\n const parent = options.parent ?? stage.screen;\n if (options.placement === 'bottom') parent.addChildAt(this.sheet, 0);\n else parent.addChild(this.sheet);\n }\n\n /** Reads the grade again on the next update (the place changed). */\n invalidate(): void {\n this.readAt = -Infinity;\n }\n\n /** `enabled`: the game's setting, and off under a battery saver — a full-screen blend is a cost on a phone. */\n update(now: number, enabled = true): void {\n if (!enabled) {\n this.sheet.visible = false;\n this.readAt = -Infinity;\n return;\n }\n if (now - this.readAt >= this.every) {\n this.readAt = now;\n const g = this.read();\n const tint = g ? mixToWhite(g.color, g.alpha) : 0xffffff;\n this.blank = tint === 0xffffff;\n this.sheet.tint = tint;\n }\n this.sheet.visible = !this.blank;\n if (this.blank) return;\n const { width, height } = this.stage;\n if (this.sheet.width !== width) this.sheet.width = width;\n if (this.sheet.height !== height) this.sheet.height = height;\n }\n\n destroy(): void {\n this.sheet.destroy();\n }\n}\n"],"names":["ColorGrade","stage","read","options","parent","Sprite","Texture","now","enabled","g","tint","mixToWhite","width","height"],"mappings":";;AA6BO,MAAMA,EAAW;AAAA,EAMtB,YACmBC,GACAC,GACjBC,IAA6B,CAAA,GAC7B;AAHiB,SAAA,QAAAF,GACA,KAAA,OAAAC,GAGjB,KAAK,QAAQC,EAAQ,eAAe,KACpC,KAAK,MAAM,YAAY,YACvB,KAAK,MAAM,UAAU;AACrB,UAAMC,IAASD,EAAQ,UAAUF,EAAM;AACvC,IAAIE,EAAQ,cAAc,aAAiB,WAAW,KAAK,OAAO,CAAC,IAC9DC,EAAO,SAAS,KAAK,KAAK;AAAA,EACjC;AAAA,EAVmB;AAAA,EACA;AAAA,EAPF,QAAQ,IAAIC,EAAO,EAAE,SAASC,EAAQ,OAAO;AAAA,EACtD,SAAS;AAAA,EACT,QAAQ;AAAA,EACC;AAAA;AAAA,EAgBjB,aAAmB;AACjB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGA,OAAOC,GAAaC,IAAU,IAAY;AACxC,QAAI,CAACA,GAAS;AACZ,WAAK,MAAM,UAAU,IACrB,KAAK,SAAS;AACd;AAAA,IACF;AACA,QAAID,IAAM,KAAK,UAAU,KAAK,OAAO;AACnC,WAAK,SAASA;AACd,YAAME,IAAI,KAAK,KAAA,GACTC,IAAOD,IAAIE,EAAWF,EAAE,OAAOA,EAAE,KAAK,IAAI;AAChD,WAAK,QAAQC,MAAS,UACtB,KAAK,MAAM,OAAOA;AAAA,IACpB;AAEA,QADA,KAAK,MAAM,UAAU,CAAC,KAAK,OACvB,KAAK,MAAO;AAChB,UAAM,EAAE,OAAAE,GAAO,QAAAC,EAAA,IAAW,KAAK;AAC/B,IAAI,KAAK,MAAM,UAAUD,MAAO,KAAK,MAAM,QAAQA,IAC/C,KAAK,MAAM,WAAWC,MAAQ,KAAK,MAAM,SAASA;AAAA,EACxD;AAAA,EAEA,UAAgB;AACd,SAAK,MAAM,QAAA;AAAA,EACb;AACF;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"DayClock.js","sources":["../../src/ambient/DayClock.ts"],"sourcesContent":["/**\n * A time of day read off a wall clock, so every client that agrees on the time (`serverNow`) stands in the same dusk\n * without a packet between them. Pure: no Pixi, no clock of its own — the caller hands in the time, and what draws\n * the night (a `LightLayer`, the pixel `NightShade`) or a HUD badge reads what this returns.\n *\n * ```ts\n * const clock = new DayClock({\n * periodMs: 2 * 3600_000, // a game day every two real hours\n * keys: [\n * { at: 0, color: 0x0a1030, alpha: 0.52 },\n * { at: 0.3, color: 0xfff0d8, alpha: 0 },\n * { at: 0.7, color: 0xffb070, alpha: 0 },\n * { at: 0.86, color: 0x0a1030, alpha: 0.52 },\n * ],\n * phases: [{ id: 'dawn', from: 0.2 }, { id: 'day', from: 0.3 }, { id: 'dusk', from: 0.7 }, { id: 'night', from: 0.8 }],\n * });\n * const day = clock.at(serverNow()); // { phase, id, color, alpha, night }\n * ```\n *\n * Phase 0 is midnight and 0.5 noon. Keys are the grade laid over the outdoor world at points of the day, mixed\n * between neighbours; a key at 0 and one at 1 with the same values make midnight seamless.\n */\n\n/** The world's grade at one point of the day: its colour (0xRRGGBB) and how strongly it is laid (0 by day). */\nexport interface DayKey {\n at: number;\n color: number;\n alpha: number;\n}\n\n/** A named part of the day starting at `from` (0..1); the last one runs on through midnight. */\nexport interface DayPhase<P extends string = string> {\n id: P;\n from: number;\n}\n\nexport interface DayClockOptions<P extends string = string> {\n /** Real milliseconds a whole game day lasts. */\n periodMs: number;\n /** Shifts the day against the wall clock (the same offset on every client keeps them together). */\n offsetMs?: number;\n /** At least one key. */\n keys: readonly DayKey[];\n /** Optional names for parts of the day; without them `id` is ''. */\n phases?: readonly DayPhase<P>[];\n}\n\nexport interface DayState<P extends string = string> {\n /** 0..1 through the game day: 0 midnight, 0.5 noon. */\n phase: number;\n /** The part of the day `phase` falls in. */\n id: P | '';\n /** The grade over the outdoor world, 0xRRGGBB. */\n color: number;\n /** How strongly the grade is laid (0 at full day). */\n alpha: number;\n /** 0 by day, 1 at the darkest key: how much lamps matter. */\n night: number;\n}\n\n/** `a` taken `t` of the way to `b`, per channel, 0xRRGGBB. */\nexport function mixRgb(a: number, b: number, t: number): number {\n const ch = (s: number) => Math.round(((a >> s) & 255) * (1 - t) + ((b >> s) & 255) * t);\n return (ch(16) << 16) | (ch(8) << 8) | ch(0);\n}\n\nexport class DayClock<P extends string = string> {\n private readonly periodMs: number;\n private readonly offsetMs: number;\n private readonly keys: DayKey[];\n private readonly phases: DayPhase<P>[];\n private readonly maxAlpha: number;\n /** A phase held still (a debug command, a cut scene at midnight); null follows the clock. */\n private held: number | null = null;\n\n constructor(options: DayClockOptions<P>) {\n if (!(options.periodMs > 0)) throw new Error('DayClock: periodMs must be above 0');\n if (!options.keys.length) throw new Error('DayClock: at least one key');\n this.periodMs = options.periodMs;\n this.offsetMs = options.offsetMs ?? 0;\n this.keys = [...options.keys].sort((a, b) => a.at - b.at);\n this.phases = [...(options.phases ?? [])].sort((a, b) => a.from - b.from);\n // a clock whose darkest key is barely dark still reaches night 1 there, and one with no dark never divides by 0\n this.maxAlpha = Math.max(0.01, ...this.keys.map((k) => k.alpha));\n }\n\n /** Holds the day at `phase` (0..1), or lets it run again with null. */\n hold(phase: number | null): void {\n this.held = phase === null ? null : ((phase % 1) + 1) % 1;\n }\n\n /** Where the day stands at wall time `ms` (0..1). */\n phaseAt(ms: number): number {\n if (this.held !== null) return this.held;\n const p = this.periodMs;\n return ((((ms + this.offsetMs) % p) + p) % p) / p;\n }\n\n at(ms: number): DayState<P> {\n const phase = this.phaseAt(ms);\n const keys = this.keys;\n let key = keys[0]!;\n let color = key.color;\n let alpha = key.alpha;\n // past the last key it holds; before the first it holds the first\n if (phase >= keys[keys.length - 1]!.at) {\n key = keys[keys.length - 1]!;\n color = key.color;\n alpha = key.alpha;\n }\n for (let i = 0; i < keys.length - 1; i++) {\n const a = keys[i]!;\n const b = keys[i + 1]!;\n if (phase < a.at || phase > b.at) continue;\n const t = b.at > a.at ? (phase - a.at) / (b.at - a.at) : 0;\n color = mixRgb(a.color, b.color, t);\n alpha = a.alpha + (b.alpha - a.alpha) * t;\n break;\n }\n // the stretch before the first `from` belongs to the last phase: night runs through midnight\n let id: P | '' = this.phases.length ? this.phases[this.phases.length - 1]!.id : '';\n for (const ph of this.phases) if (phase >= ph.from) id = ph.id;\n return { phase, id, color, alpha, night: Math.min(1, alpha / this.maxAlpha) };\n }\n}\n\n/** A day's phase as a 24-hour clock, \"HH:MM\" (phase 0 is midnight). */\nexport function clockText(phase: number): string {\n const minutes = Math.floor((((phase % 1) + 1) % 1) * 24 * 60);\n return `${String(Math.floor(minutes / 60)).padStart(2, '0')}:${String(minutes % 60).padStart(2, '0')}`;\n}\n\n/**\n * The night's colour pulled toward a place's own (a marsh mossy, a wood blue) as it deepens: `share` of the way at\n * full night, nothing by day.\n */\nexport function tintNight(day: Pick<DayState, 'color' | 'night'>, tint: number | undefined, share = 0.6): number {\n return tint === undefined ? day.color : mixRgb(day.color, tint, day.night * share);\n}\n"],"names":["mixRgb","a","b","ch","s","DayClock","options","k","phase","ms","p","keys","key","color","alpha","i","t","id","ph","clockText","minutes","tintNight","day","tint","share"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"WeatherLayer.js","sources":["../../src/ambient/WeatherLayer.ts"],"sourcesContent":["import { Sprite, Texture } from 'pixi.js';\nimport type { ViewRect } from '../core/Camera';\nimport type { Image } from '../core/Image';\nimport type { Stage } from '../core/Stage';\nimport type { WeatherState } from './weather';\n\n/**\n * How one kind of weather moves:\n * - `fall`: streaks falling at a slant onto a ground line somewhere in view, half of them leaving a two-frame splash\n * (rain);\n * - `flake`: bits drifting down and swaying as they fall, each on its own phase (snow, ash, petals);\n * - `bank`: a few wide sprites drifting slowly sideways, laid over the bodies (fog, mist, smoke).\n */\nexport type WeatherMotion = 'fall' | 'flake' | 'bank';\n\nexport interface WeatherLook {\n motion: WeatherMotion;\n /** Particles at full strength; fewer show as the weather thins. Keep it in the low hundreds on a phone. */\n max: number;\n /** Texture keys, handed out in turn (repeat a key to make it commoner). */\n keys: readonly string[];\n /** `fall` only: the splash's two frames. Without them a drop simply vanishes where it lands. */\n splash?: readonly [string, string];\n /** World px a second, [lo, hi] each (defaults suit each motion). */\n vx?: readonly [number, number];\n vy?: readonly [number, number];\n /** `flake` only: how far (px) a flake sways either side as it falls (default 4). */\n sway?: number;\n /** A screen-wide tint the kind lays over everything (fog is mostly tint), at `tintAlpha` × strength. */\n tint?: number;\n tintAlpha?: number;\n}\n\nexport interface WeatherLayerOptions<K extends string> {\n looks: Readonly<Partial<Record<K, WeatherLook>>>;\n /** Depth of falling particles in the world layer: over the bodies, under the names (default 900_001). */\n depth?: number;\n /** Depth of fog banks (default 900_010). */\n bankDepth?: number;\n /** Depth of splashes: with the ground effects, so a body standing in the rain is not splashed over (default 0). */\n splashDepth?: number;\n /** Round positions to whole world pixels (default true): pixel art wants it, smooth art may not. */\n snap?: boolean;\n /** Where randomness comes from (default `Math.random`); the look of a shower need not be shared between clients. */\n random?: () => number;\n}\n\ninterface Drop {\n img: Image;\n key: string;\n x: number;\n y: number;\n vx: number;\n vy: number;\n /** `fall`: the ground line it lands on. `flake`: its sway's phase. */\n ground: number;\n /** `fall`: when its splash began (0 while it still falls). */\n splashAt: number;\n}\n\nconst SPLASH_MS = 80;\nconst DEFAULT_V: Record<WeatherMotion, { vx: readonly [number, number]; vy: readonly [number, number] }> = {\n fall: { vx: [-48, -38], vy: [250, 320] },\n flake: { vx: [4, 12], vy: [14, 30] },\n bank: { vx: [3, 8], vy: [0, 0] },\n};\n\n/**\n * The weather on screen: a capped pool of particles that lives only inside the camera's view, plus a light screen\n * tint for the kinds that change the air. Feed it a `WeatherState` each frame (from `weatherAt`, so it fades in and\n * out exactly when every other client's does); the pool is rebuilt only when the kind changes, and a thinning shower\n * hides particles rather than freeing them.\n *\n * The art is the game's: name texture keys per kind (the pixel module's `paintWeatherArt` paints a set in whole\n * pixels).\n */\nexport class WeatherLayer<K extends string> {\n private readonly drops: Drop[] = [];\n private kind: K | 'clear' = 'clear';\n private look: WeatherLook | undefined;\n private readonly tint = new Sprite({ texture: Texture.WHITE });\n private readonly depth: number;\n private readonly bankDepth: number;\n private readonly splashDepth: number;\n private readonly snap: boolean;\n private readonly random: () => number;\n\n constructor(\n private readonly stage: Stage,\n private readonly options: WeatherLayerOptions<K>,\n ) {\n this.depth = options.depth ?? 900_001;\n this.bankDepth = options.bankDepth ?? 900_010;\n this.splashDepth = options.splashDepth ?? 0;\n this.snap = options.snap ?? true;\n this.random = options.random ?? Math.random;\n this.tint.visible = false;\n stage.screen.addChild(this.tint);\n }\n\n /**\n * `now` in ms, `dt` the frame's ms, `view` the camera's world view. `share` (0..1) thins the pool on top of the\n * weather's own strength (a reduced-effects setting keeps half).\n */\n update(now: number, dt: number, view: ViewRect, weather: WeatherState<K>, share = 1): void {\n if (weather.kind !== this.kind) this.rebuild(weather.kind, view);\n const look = this.look;\n const tintAlpha = (look?.tintAlpha ?? 0) * weather.intensity;\n this.tint.visible = tintAlpha > 0.004;\n if (this.tint.visible) {\n this.tint.tint = look?.tint ?? 0xffffff;\n this.tint.alpha = tintAlpha;\n this.tint.width = this.stage.width;\n this.tint.height = this.stage.height;\n }\n if (!look) return;\n const active = Math.round(this.drops.length * weather.intensity * Math.max(0, Math.min(1, share)));\n const s = dt / 1000;\n for (let i = 0; i < this.drops.length; i++) {\n const d = this.drops[i]!;\n if (i >= active) {\n if (d.img.visible) d.img.setVisible(false);\n continue;\n }\n if (!d.img.visible) this.spawn(d, look, view, false);\n if (look.motion === 'fall') this.stepFall(d, look, now, s, view);\n else if (look.motion === 'bank') this.stepBank(d, look, s, view, weather.intensity);\n else this.stepFlake(d, look, now, s, view);\n }\n }\n\n private rebuild(kind: K | 'clear', view: ViewRect): void {\n for (const d of this.drops) d.img.destroy();\n this.drops.length = 0;\n this.kind = kind;\n this.look = kind === 'clear' ? undefined : this.options.looks[kind];\n const look = this.look;\n if (!look || !look.keys.length) return;\n for (let i = 0; i < look.max; i++) {\n const key = look.keys[i % look.keys.length]!;\n const img = this.stage.add.image(0, 0, key).setOrigin(0, 0).setVisible(false);\n const d: Drop = { img, key, x: 0, y: 0, vx: 0, vy: 0, ground: 0, splashAt: 0 };\n this.drops.push(d);\n // the first fill is spread over the whole view, so a shower starting does not arrive as one falling sheet\n this.spawn(d, look, view, true);\n img.setVisible(false);\n }\n }\n\n private between(r: readonly [number, number]): number {\n return r[0] + (r[1] - r[0]) * this.random();\n }\n\n private place(d: Drop): void {\n d.img.setPosition(this.snap ? Math.round(d.x) : d.x, this.snap ? Math.round(d.y) : d.y);\n }\n\n private spawn(d: Drop, look: WeatherLook, view: ViewRect, anywhere: boolean): void {\n const r = this.random;\n const v = DEFAULT_V[look.motion];\n const x = view.x - 30 + r() * (view.width + 60);\n d.vx = this.between(look.vx ?? v.vx);\n d.vy = this.between(look.vy ?? v.vy);\n if (look.motion === 'fall') {\n d.ground = view.y + r() * (view.height + 12);\n d.y = anywhere ? view.y - 10 + r() * (d.ground - view.y + 10) : d.ground - 30 - r() * view.height;\n d.x = x;\n d.splashAt = 0;\n d.img.setTexture(d.key).setDepth(this.depth).setAlpha(1);\n } else if (look.motion === 'bank') {\n d.x = anywhere ? x : view.x - d.img.width;\n d.y = view.y + r() * view.height;\n d.img.setDepth(this.bankDepth);\n } else {\n d.x = x;\n d.y = anywhere ? view.y + r() * view.height : view.y - 4 - r() * 20;\n d.ground = r() * Math.PI * 2;\n d.img.setDepth(this.depth);\n }\n d.img.setVisible(true);\n }\n\n private stepFall(d: Drop, look: WeatherLook, now: number, s: number, view: ViewRect): void {\n if (d.splashAt) {\n const t = now - d.splashAt;\n if (t > SPLASH_MS * 2) this.spawn(d, look, view, false);\n else if (t > SPLASH_MS && look.splash) d.img.setTexture(look.splash[1]);\n return;\n }\n d.x += d.vx * s;\n d.y += d.vy * s;\n if (d.y >= d.ground) {\n // every other drop splashes on the ground it hit; the rest vanish into it\n if (look.splash && this.random() < 0.5) {\n d.splashAt = now;\n d.img.setTexture(look.splash[0]).setDepth(this.splashDepth);\n d.x -= d.img.width / 2;\n d.y = d.ground - 1;\n this.place(d);\n } else this.spawn(d, look, view, false);\n return;\n }\n this.place(d);\n }\n\n private stepFlake(d: Drop, look: WeatherLook, now: number, s: number, view: ViewRect): void {\n d.x += d.vx * s;\n d.y += d.vy * s;\n if (d.y > view.bottom + 4 || d.x > view.right + 30 || d.x < view.x - 40) {\n this.spawn(d, look, view, false);\n return;\n }\n // the sway is added at draw time, so it never drifts the flake off its line\n const sway = Math.sin(now / 900 + d.ground) * (look.sway ?? 4);\n const x = d.x + sway;\n d.img.setPosition(this.snap ? Math.round(x) : x, this.snap ? Math.round(d.y) : d.y);\n }\n\n private stepBank(d: Drop, look: WeatherLook, s: number, view: ViewRect, intensity: number): void {\n d.x += d.vx * s;\n if (d.x > view.right + 10 || d.y < view.y - 20 || d.y > view.bottom + 10) this.spawn(d, look, view, d.x <= view.right + 10);\n d.img.setAlpha(0.35 + 0.5 * intensity);\n this.place(d);\n }\n\n destroy(): void {\n for (const d of this.drops) d.img.destroy();\n this.drops.length = 0;\n this.tint.destroy();\n }\n}\n"],"names":["SPLASH_MS","DEFAULT_V","WeatherLayer","stage","options","Sprite","Texture","now","dt","view","weather","share","look","tintAlpha","active","s","i","d","kind","key","img","r","anywhere","v","x","t","sway","intensity"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"grade.js","sources":["../../src/ambient/grade.ts"],"sourcesContent":["/**\n * The pure half of a colour grade: how strong a place's colour is laid at a point of the day, and the multiply colour\n * that leaves the same result. `ColorGrade` draws it.\n */\n\n/** A place's grade: its colour (0xRRGGBB) and how strongly it is laid by day and by night (0..1). */\nexport interface Grade {\n color: number;\n day: number;\n night: number;\n}\n\nexport interface GradeState {\n color: number;\n alpha: number;\n}\n\n/**\n * The grade at `night` (0 by day, 1 at full night, `DayClock`'s `night`), never past `max`: a grade is a light\n * tint, and one laid too strong washes every sprite toward one colour.\n */\nexport function gradeAt(grade: Grade, night: number, max = 0.14): GradeState {\n const n = Math.max(0, Math.min(1, night));\n return { color: grade.color, alpha: Math.max(0, Math.min(max, grade.day + (grade.night - grade.day) * n)) };\n}\n\n/** `color` taken `share` of the way from white: what a multiply sheet of that colour at that opacity leaves. */\nexport function mixToWhite(color: number, share: number): number {\n const s = Math.max(0, Math.min(1, share));\n const ch = (shift: number) => Math.round(255 - (255 - ((color >> shift) & 255)) * s) << shift;\n return ch(16) | ch(8) | ch(0);\n}\n"],"names":["gradeAt","grade","night","max","mixToWhite","color","share","s","ch","shift"],"mappings":"AAqBO,SAASA,EAAQC,GAAcC,GAAeC,IAAM,MAAkB;AAC3E,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGD,CAAK,CAAC;AACxC,SAAO,EAAE,OAAOD,EAAM,OAAO,OAAO,KAAK,IAAI,GAAG,KAAK,IAAIE,GAAKF,EAAM,OAAOA,EAAM,QAAQA,EAAM,OAAO,CAAC,CAAC,EAAA;AAC1G;AAGO,SAASG,EAAWC,GAAeC,GAAuB;AAC/D,QAAMC,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGD,CAAK,CAAC,GAClCE,IAAK,CAACC,MAAkB,KAAK,MAAM,OAAO,OAAQJ,KAASI,IAAS,QAAQF,CAAC,KAAKE;AACxF,SAAOD,EAAG,EAAE,IAAIA,EAAG,CAAC,IAAIA,EAAG,CAAC;AAC9B;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"weather.js","sources":["../../src/ambient/weather.ts"],"sourcesContent":["/**\n * Weather rolled from wall time alone, so two players standing in the same place are rained on together without a\n * packet between them. Pure and deterministic: the same key, time and table give the same sky on every machine.\n *\n * Time is cut into slots; each slot rolls one entry of a weighted list from a hash of the key and the slot number,\n * and a change of kind fades out at the end of its slot and in at the start of the next. Places can share one sky:\n * a key listed in a `skies` group takes its kind from the group's roll (so the rain does not stop at a map's edge)\n * and only its strength from its own list. The kind `'clear'` means no weather and has no strength.\n *\n * ```ts\n * const TABLE: WeatherTable = {\n * slotMs: 12 * 60_000,\n * fadeMs: 40_000,\n * places: { meadow: [{ kind: 'clear', weight: 4 }, { kind: 'rain', weight: 3, intensity: [0.4, 1] }] },\n * };\n * const w = weatherAt('meadow', serverNow(), TABLE); // { kind: 'rain', intensity: 0.7 }\n * ```\n */\n\nexport interface WeatherEntry<K extends string = string> {\n kind: K | 'clear';\n weight: number;\n /** The strength range rolled for this kind, [lo, hi] in 0..1 (default [1, 1]). */\n intensity?: readonly [number, number];\n}\n\nexport interface WeatherSky<K extends string = string> {\n /** The place keys under this sky. */\n places: readonly string[];\n entries: readonly WeatherEntry<K>[];\n}\n\nexport interface WeatherTable<K extends string = string> {\n /** How long one roll of the sky lasts. */\n slotMs: number;\n /** How long a change of kind takes to fade out and in. */\n fadeMs: number;\n /** Each place's own list; a place with none (a cave) has no weather, even inside a sky. */\n places: Readonly<Record<string, readonly WeatherEntry<K>[]>>;\n /** Groups of neighbouring places that share one sky, by group id. */\n skies?: Readonly<Record<string, WeatherSky<K>>>;\n}\n\nexport interface WeatherState<K extends string = string> {\n kind: K | 'clear';\n /** 0..1, already faded round a change of kind; 0 when clear. */\n intensity: number;\n}\n\nconst CLEAR: WeatherState<never> = { kind: 'clear', intensity: 0 };\n\n/** FNV-1a over the text, then an avalanche: a stable number in [0, 1). */\nexport function hash01(text: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < text.length; i++) {\n h ^= text.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n h ^= h >>> 16;\n h = Math.imul(h, 0x85ebca6b);\n h ^= h >>> 13;\n return (h >>> 0) / 4294967296;\n}\n\n/** The sky group each place belongs to, worked out once per table. */\nconst SKY_OF = new WeakMap<object, Map<string, string>>();\n\nfunction skyOf(table: WeatherTable<string>, key: string): string | undefined {\n if (!table.skies) return undefined;\n let map = SKY_OF.get(table);\n if (!map) {\n map = new Map();\n for (const [id, sky] of Object.entries(table.skies)) for (const p of sky.places) map.set(p, id);\n SKY_OF.set(table, map);\n }\n return map.get(key);\n}\n\nfunction roll<K extends string>(seed: string, entries: readonly WeatherEntry<K>[], slot: number): WeatherState<K> {\n const total = entries.reduce((s, e) => s + e.weight, 0);\n if (total <= 0) return CLEAR;\n let r = hash01(`${seed}:${slot}`) * total;\n let pick = entries[entries.length - 1]!;\n for (const e of entries) {\n r -= e.weight;\n if (r < 0) {\n pick = e;\n break;\n }\n }\n if (pick.kind === 'clear') return CLEAR;\n const [lo, hi] = pick.intensity ?? [1, 1];\n return { kind: pick.kind, intensity: lo + (hi - lo) * hash01(`${seed}:${slot}:i`) };\n}\n\n/** The weather over place `key` at wall time `ms`. */\nexport function weatherAt<K extends string>(key: string, ms: number, table: WeatherTable<K>): WeatherState<K> {\n const own = table.places[key] ?? [];\n if (!own.length) return CLEAR;\n const group = skyOf(table, key);\n const seed = group === undefined ? key : `sky:${group}`;\n const entries = group === undefined ? own : table.skies![group]!.entries;\n if (!entries.length) return CLEAR;\n const slot = Math.floor(ms / table.slotMs);\n let now = roll(seed, entries, slot);\n if (now.kind === 'clear') return now;\n // a shared sky's kind at the strength this place feels it: its own range for that kind when its list has one\n if (group !== undefined) {\n const range = own.find((e) => e.kind === now.kind)?.intensity;\n if (range) now = { kind: now.kind, intensity: range[0] + (range[1] - range[0]) * hash01(`${seed}:${slot}:i`) };\n }\n const into = ms - slot * table.slotMs;\n const left = table.slotMs - into;\n let fade = 1;\n if (table.fadeMs > 0) {\n if (roll(seed, entries, slot - 1).kind !== now.kind) fade = Math.min(fade, into / table.fadeMs);\n if (roll(seed, entries, slot + 1).kind !== now.kind) fade = Math.min(fade, left / table.fadeMs);\n }\n return { kind: now.kind, intensity: now.intensity * Math.max(0, Math.min(1, fade)) };\n}\n"],"names":["CLEAR","hash01","text","h","i","SKY_OF","skyOf","table","key","map","id","sky","p","roll","seed","entries","slot","total","s","e","r","pick","lo","hi","weatherAt","ms","own","group","now","range","into","left","fade"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"AnimStateMachine.js","sources":["../../src/anim/AnimStateMachine.ts"],"sourcesContent":["import { Animator, type AnimationClip } from './Animator';\nimport {\n OP_EQ,\n OP_GE,\n OP_GT,\n OP_LE,\n OP_LT,\n OP_NE,\n PARAM_BOOL,\n PARAM_TRIGGER,\n compileParams,\n compileStates,\n compileTransitions,\n type CompiledParams,\n type CompiledStates,\n type CompiledTransitions,\n} from './animStateCompile';\nimport type { AnimParams, AnimStateMachineOptions } from './animStateTypes';\n\n/**\n * Chooses which clip an `Animator` plays from named states and the transitions between them, the way an animation\n * graph in a larger engine does: the game sets parameters (a bool, a number, a one-shot trigger) and the machine\n * moves between states when a transition's conditions hold, when a clip has played through, or from any state at\n * all by priority. Frame markers fire events (a footstep on frame 3) for the game to hang sounds and effects on.\n *\n * Pure and driven by `update(dt)`, so it runs under node with a fake clock. The definition is compiled into typed\n * arrays once; an update allocates nothing.\n *\n * ```ts\n * const sm = new AnimStateMachine(sheet.clips, {\n * initial: 'idle',\n * params: { speed: 0, grounded: true, jump: 'trigger' },\n * states: { idle: { clip: 'idle' }, run: { clip: 'run', markers: [{ frame: 2, name: 'step' }] }, jump: { clip: 'jump' } },\n * transitions: [\n * { from: 'idle', to: 'run', when: { speed: ['>', 0] } },\n * { from: 'run', to: 'idle', when: { speed: 0 } },\n * { from: '*', to: 'jump', when: { jump: true, grounded: true }, priority: 10 },\n * ],\n * });\n * sm.onEvent = (name) => name === 'step' && sound.play('step');\n * sm.set('speed', 3);\n * sm.update(dt); // seconds; then show sm.frame\n * ```\n */\nexport class AnimStateMachine<State extends string = string, Clip extends string = string, P extends AnimParams = AnimParams> {\n /** The animator it drives; read `frame` off it (or off the machine). */\n readonly animator: Animator<Clip>;\n /** Fired for every marker playback reaches, the state's first frame's on entering it. */\n onEvent: ((event: string, state: State, frame: number) => void) | null = null;\n /** Fired after each change of state. */\n onStateChange: ((from: State, to: State) => void) | null = null;\n\n private readonly params: CompiledParams;\n private readonly states: CompiledStates;\n private readonly tr: CompiledTransitions;\n private readonly keepTriggers: boolean;\n private stateIndex: number;\n /** Time played in this state, ms, scaled by speed as the animator scales it. */\n private time = 0;\n\n constructor(clips: Record<Clip, AnimationClip>, options: AnimStateMachineOptions<State, Clip, P>) {\n const opts = options as unknown as AnimStateMachineOptions<string, string, AnimParams>;\n this.params = compileParams(options.params ?? {});\n this.states = compileStates(opts, clips, this.params);\n this.tr = compileTransitions(opts, this.states, this.params);\n this.keepTriggers = options.keepTriggers === true;\n this.stateIndex = this.states.index.get(options.initial)!;\n this.animator = new Animator(clips, this.states.clips[this.stateIndex] as Clip);\n this.applySpeed();\n }\n\n /** The state playing. */\n get state(): State {\n return this.states.names[this.stateIndex] as State;\n }\n\n /** The frame to show now (a sheet frame index or name, as the clip lists it). */\n get frame(): string | number {\n return this.animator.frame;\n }\n\n /** How much of this state's clip has played: 0 at entry, 1 after one pass, 2 after two loops. */\n get normalizedTime(): number {\n return this.time / this.states.lengths[this.stateIndex]!;\n }\n\n /** Sets a bool or number parameter. */\n set(name: keyof P & string, value: boolean | number): this {\n const i = this.paramIndex(name);\n if (this.params.kinds[i] === PARAM_TRIGGER) throw new Error(`AnimStateMachine: \"${name}\" is a trigger; use trigger()`);\n this.params.values[i] = typeof value === 'boolean' ? (value ? 1 : 0) : value;\n return this;\n }\n\n /** A parameter's value: bools as booleans, triggers as whether they are set. */\n get(name: keyof P & string): boolean | number {\n const i = this.paramIndex(name);\n const v = this.params.values[i]!;\n return this.params.kinds[i] === PARAM_BOOL || this.params.kinds[i] === PARAM_TRIGGER ? v !== 0 : v;\n }\n\n /** Fires a trigger: the next update's transitions see it once. */\n trigger(name: keyof P & string): this {\n this.params.values[this.triggerIndex(name)] = 1;\n return this;\n }\n\n resetTrigger(name: keyof P & string): this {\n this.params.values[this.triggerIndex(name)] = 0;\n return this;\n }\n\n /** Goes to `state` now, whatever the transitions say (a respawn, a cut scene). */\n play(state: State): this {\n const i = this.states.index.get(state);\n if (i === undefined) throw new Error(`AnimStateMachine: no state \"${state}\"`);\n this.enter(i);\n return this;\n }\n\n /** Back to the initial values of every parameter (triggers cleared). */\n resetParams(): this {\n this.params.values.set(this.params.initial);\n return this;\n }\n\n /**\n * Advances the clip by `dt` seconds, fires the markers it passed, then takes at most one transition (so a chain of\n * them never runs through several states in one frame). `update(0)` only checks the transitions.\n */\n update(dt: number): void {\n const s = this.stateIndex;\n this.applySpeed();\n const a = this.animator;\n const before = a.frameIndex;\n const wasFinished = a.finished;\n a.update(dt);\n if (dt > 0 && a.speed > 0) {\n const delta = dt * 1000 * a.speed;\n this.time += delta;\n if (!wasFinished) this.firePassed(s, before, a.frameIndex, delta);\n }\n // a marker's listener may have changed state: the transitions are the state's now playing\n const t = this.pick(this.stateIndex);\n if (t >= 0) {\n this.consumeTriggers(t);\n this.enter(this.tr.to[t]!);\n }\n if (!this.keepTriggers) this.clearTriggers();\n }\n\n private pick(s: number): number {\n const cands = this.states.candidates[s]!;\n const tr = this.tr;\n const ended = this.animator.finished || this.time >= this.states.lengths[s]!;\n for (let k = 0; k < cands.length; k++) {\n const t = cands[k]!;\n if (tr.to[t] === s && tr.anyState[t] && !tr.self[t]) continue;\n if (tr.onEnd[t] && !ended) continue;\n if (tr.exitTime[t]! >= 0 && this.normalizedTime < tr.exitTime[t]!) continue;\n if (this.holds(t)) return t;\n }\n return -1;\n }\n\n private holds(t: number): boolean {\n const tr = this.tr;\n const values = this.params.values;\n for (let c = tr.condStart[t]!; c < tr.condEnd[t]!; c++) {\n const v = values[tr.condParam[c]!]!;\n const want = tr.condValue[c]!;\n let ok: boolean;\n switch (tr.condOp[c]) {\n case OP_EQ: ok = v === want; break;\n case OP_NE: ok = v !== want; break;\n case OP_GT: ok = v > want; break;\n case OP_GE: ok = v >= want; break;\n case OP_LT: ok = v < want; break;\n case OP_LE: ok = v <= want; break;\n default: ok = false;\n }\n if (!ok) return false;\n }\n return true;\n }\n\n private enter(i: number): void {\n const from = this.stateIndex;\n this.stateIndex = i;\n this.time = 0;\n this.animator.play(this.states.clips[i] as Clip, true);\n this.applySpeed();\n this.onStateChange?.(this.states.names[from] as State, this.states.names[i] as State);\n // a marker on the first frame (a jump's whoosh) belongs to entering the state\n this.fire(i, 0);\n }\n\n /**\n * Fires the markers of every frame after `from` up to `to`. The animator skips frames on a long step, so they are\n * walked rather than only the one landed on; a step long enough to loop the whole clip fires each frame once.\n */\n private firePassed(s: number, from: number, to: number, deltaMs: number): void {\n const n = this.states.frameCounts[s]!;\n let steps = (to - from + n) % n;\n if (steps === 0 && deltaMs >= this.states.lengths[s]!) steps = n;\n for (let k = 1; k <= steps; k++) {\n this.fire(s, (from + k) % n);\n if (this.stateIndex !== s) return; // a listener changed state: the rest belong to a clip no longer playing\n }\n }\n\n private fire(s: number, frame: number): void {\n const names = this.states.markers[s]![frame];\n if (!names || !this.onEvent) return;\n const state = this.states.names[s] as State;\n for (let i = 0; i < names.length; i++) this.onEvent(names[i]!, state, frame);\n }\n\n private applySpeed(): void {\n const s = this.stateIndex;\n const p = this.states.speedParams[s]!;\n this.animator.speed = this.states.speeds[s]! * (p >= 0 ? Math.abs(this.params.values[p]!) : 1);\n }\n\n private consumeTriggers(t: number): void {\n const tr = this.tr;\n for (let c = tr.condStart[t]!; c < tr.condEnd[t]!; c++) {\n if (this.params.kinds[tr.condParam[c]!] === PARAM_TRIGGER) this.params.values[tr.condParam[c]!] = 0;\n }\n }\n\n private clearTriggers(): void {\n const { kinds, values } = this.params;\n for (let i = 0; i < kinds.length; i++) if (kinds[i] === PARAM_TRIGGER) values[i] = 0;\n }\n\n private paramIndex(name: string): number {\n const i = this.params.index.get(name);\n if (i === undefined) throw new Error(`AnimStateMachine: no parameter \"${name}\"`);\n return i;\n }\n\n private triggerIndex(name: string): number {\n const i = this.paramIndex(name);\n if (this.params.kinds[i] !== PARAM_TRIGGER) throw new Error(`AnimStateMachine: \"${name}\" is not a trigger`);\n return i;\n }\n}\n"],"names":["AnimStateMachine","clips","options","opts","compileParams","compileStates","compileTransitions","Animator","name","value","i","PARAM_TRIGGER","v","PARAM_BOOL","state","dt","a","before","wasFinished","delta","t","s","cands","tr","ended","k","values","c","want","ok","OP_EQ","OP_NE","OP_GT","OP_GE","OP_LT","OP_LE","from","to","deltaMs","n","steps","frame","names","p","kinds"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Animator.js","sources":["../../src/anim/Animator.ts"],"sourcesContent":["/**\n * Frame animation of one sprite: which clip plays, which frame it is on. Pure state, advanced by time; a system copies\n * `frame` onto the sprite (`animationSystem`).\n *\n * ```ts\n * const clips = { idle: { frames: [0, 1], fps: 2 }, walk: { frames: [2, 3, 4, 5], fps: 10 }, die: { frames: [6, 7, 8], fps: 8, loop: false } };\n * const a = new Animator(clips, 'idle');\n * a.play('walk'); // switching to the clip already playing keeps its place\n * a.update(dt); // seconds\n * sprite.setFrame(a.frame);\n * ```\n */\nexport interface AnimationClip {\n /** Frame names or indices of the sprite sheet, in order. */\n frames: readonly (string | number)[];\n /** Frames per second (default 10). Pixel art usually wants 8–12. */\n fps?: number;\n /** Start over at the end (default true); otherwise hold the last frame and report it finished. */\n loop?: boolean;\n /** Per-frame lengths in ms, overriding `fps` (a held key pose, a quick smear). */\n durations?: readonly number[];\n}\n\nexport type AnimationClips = Record<string, AnimationClip>;\n\nexport class Animator<Name extends string = string> {\n private clip: AnimationClip;\n private index = 0;\n private elapsed = 0;\n private ended = false;\n private name: Name;\n /** Called when a clip that does not loop reaches its last frame. */\n onComplete: ((clip: Name) => void) | null = null;\n /** Playback speed multiplier (1 normal, 0 paused). */\n speed = 1;\n\n constructor(\n private readonly clips: Record<Name, AnimationClip>,\n initial: NoInfer<Name>,\n ) {\n const clip = clips[initial];\n if (!clip) throw new Error(`Animator: no clip \"${initial}\"`);\n if (clip.frames.length === 0) throw new Error(`Animator: clip \"${initial}\" has no frames`);\n this.clip = clip;\n this.name = initial;\n }\n\n /** The clip playing. */\n get current(): Name {\n return this.name;\n }\n\n /** The frame to show now. */\n get frame(): string | number {\n return this.clip.frames[this.index]!;\n }\n\n /** Which frame of the clip (0-based). */\n get frameIndex(): number {\n return this.index;\n }\n\n /** A non-looping clip has reached its last frame. */\n get finished(): boolean {\n return this.ended;\n }\n\n /** Plays `name`. The clip already playing keeps its place unless `restart`. */\n play(name: Name, restart = false): this {\n if (name === this.name && !restart) return this;\n const clip = this.clips[name];\n if (!clip) throw new Error(`Animator: no clip \"${name}\"`);\n if (clip.frames.length === 0) throw new Error(`Animator: clip \"${name}\" has no frames`);\n this.clip = clip;\n this.name = name;\n this.index = 0;\n this.elapsed = 0;\n this.ended = false;\n return this;\n }\n\n /** Advances by `dt` seconds; returns true when the frame changed. */\n update(dt: number): boolean {\n if (this.ended || !(dt > 0) || this.speed <= 0) return false;\n this.elapsed += dt * 1000 * this.speed;\n const before = this.index;\n const n = this.clip.frames.length;\n for (let len = this.lengthOf(this.index); this.elapsed >= len; len = this.lengthOf(this.index)) {\n this.elapsed -= len;\n if (this.index < n - 1) {\n this.index++;\n } else if (this.clip.loop !== false) {\n this.index = 0;\n } else {\n this.ended = true;\n this.elapsed = 0;\n this.onComplete?.(this.name);\n break;\n }\n }\n return this.index !== before;\n }\n\n private lengthOf(i: number): number {\n const ms = this.clip.durations?.[i] ?? 1000 / (this.clip.fps ?? 10);\n return Math.max(1, ms);\n }\n}\n"],"names":["Animator","clips","initial","clip","name","restart","dt","before","n","len","i","ms"],"mappings":"AAyBO,MAAMA,EAAuC;AAAA,EAWlD,YACmBC,GACjBC,GACA;AAFiB,SAAA,QAAAD;AAGjB,UAAME,IAAOF,EAAMC,CAAO;AAC1B,QAAI,CAACC,EAAM,OAAM,IAAI,MAAM,sBAAsBD,CAAO,GAAG;AAC3D,QAAIC,EAAK,OAAO,WAAW,SAAS,IAAI,MAAM,mBAAmBD,CAAO,iBAAiB;AACzF,SAAK,OAAOC,GACZ,KAAK,OAAOD;AAAA,EACd;AAAA,EARmB;AAAA,EAXX;AAAA,EACA,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AAAA,EACR;AAAA;AAAA,EAER,aAA4C;AAAA;AAAA,EAE5C,QAAQ;AAAA;AAAA,EAcR,IAAI,UAAgB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,QAAyB;AAC3B,WAAO,KAAK,KAAK,OAAO,KAAK,KAAK;AAAA,EACpC;AAAA;AAAA,EAGA,IAAI,aAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,KAAKE,GAAYC,IAAU,IAAa;AACtC,QAAID,MAAS,KAAK,QAAQ,CAACC,EAAS,QAAO;AAC3C,UAAMF,IAAO,KAAK,MAAMC,CAAI;AAC5B,QAAI,CAACD,EAAM,OAAM,IAAI,MAAM,sBAAsBC,CAAI,GAAG;AACxD,QAAID,EAAK,OAAO,WAAW,SAAS,IAAI,MAAM,mBAAmBC,CAAI,iBAAiB;AACtF,gBAAK,OAAOD,GACZ,KAAK,OAAOC,GACZ,KAAK,QAAQ,GACb,KAAK,UAAU,GACf,KAAK,QAAQ,IACN;AAAA,EACT;AAAA;AAAA,EAGA,OAAOE,GAAqB;AAC1B,QAAI,KAAK,SAAS,EAAEA,IAAK,MAAM,KAAK,SAAS,EAAG,QAAO;AACvD,SAAK,WAAWA,IAAK,MAAO,KAAK;AACjC,UAAMC,IAAS,KAAK,OACdC,IAAI,KAAK,KAAK,OAAO;AAC3B,aAASC,IAAM,KAAK,SAAS,KAAK,KAAK,GAAG,KAAK,WAAWA,GAAKA,IAAM,KAAK,SAAS,KAAK,KAAK;AAE3F,UADA,KAAK,WAAWA,GACZ,KAAK,QAAQD,IAAI;AACnB,aAAK;AAAA,eACI,KAAK,KAAK,SAAS;AAC5B,aAAK,QAAQ;AAAA,WACR;AACL,aAAK,QAAQ,IACb,KAAK,UAAU,GACf,KAAK,aAAa,KAAK,IAAI;AAC3B;AAAA,MACF;AAEF,WAAO,KAAK,UAAUD;AAAA,EACxB;AAAA,EAEQ,SAASG,GAAmB;AAClC,UAAMC,IAAK,KAAK,KAAK,YAAYD,CAAC,KAAK,OAAQ,KAAK,KAAK,OAAO;AAChE,WAAO,KAAK,IAAI,GAAGC,CAAE;AAAA,EACvB;AACF;"}