rn-gamekit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +131 -0
  4. package/lib/module/assets/defineAssets.js +48 -0
  5. package/lib/module/assets/defineAssets.js.map +1 -0
  6. package/lib/module/assets/errors.js +38 -0
  7. package/lib/module/assets/errors.js.map +1 -0
  8. package/lib/module/assets/types.js +2 -0
  9. package/lib/module/assets/types.js.map +1 -0
  10. package/lib/module/assets/validation.js +99 -0
  11. package/lib/module/assets/validation.js.map +1 -0
  12. package/lib/module/core/frameDriver.js +20 -0
  13. package/lib/module/core/frameDriver.js.map +1 -0
  14. package/lib/module/core/input/createInputBuffer.js +296 -0
  15. package/lib/module/core/input/createInputBuffer.js.map +1 -0
  16. package/lib/module/core/input/types.js +4 -0
  17. package/lib/module/core/input/types.js.map +1 -0
  18. package/lib/module/core/session/createGameSession.js +554 -0
  19. package/lib/module/core/session/createGameSession.js.map +1 -0
  20. package/lib/module/core/session/deepFreeze.js +155 -0
  21. package/lib/module/core/session/deepFreeze.js.map +1 -0
  22. package/lib/module/core/session/diagnostics.js +2 -0
  23. package/lib/module/core/session/diagnostics.js.map +1 -0
  24. package/lib/module/core/session/types.js +43 -0
  25. package/lib/module/core/session/types.js.map +1 -0
  26. package/lib/module/definition/defineGame.js +57 -0
  27. package/lib/module/definition/defineGame.js.map +1 -0
  28. package/lib/module/definition/types.js +4 -0
  29. package/lib/module/definition/types.js.map +1 -0
  30. package/lib/module/geometry/types.js +2 -0
  31. package/lib/module/geometry/types.js.map +1 -0
  32. package/lib/module/index.js +12 -0
  33. package/lib/module/index.js.map +1 -0
  34. package/lib/module/package.json +1 -0
  35. package/lib/module/react/GamePointerInput.js +385 -0
  36. package/lib/module/react/GamePointerInput.js.map +1 -0
  37. package/lib/module/react/GameView.js +223 -0
  38. package/lib/module/react/GameView.js.map +1 -0
  39. package/lib/module/react/alphaClock.js +42 -0
  40. package/lib/module/react/alphaClock.js.map +1 -0
  41. package/lib/module/react/assets/createGameAssetStore.js +358 -0
  42. package/lib/module/react/assets/createGameAssetStore.js.map +1 -0
  43. package/lib/module/react/assets/decodeSkiaImage.js +54 -0
  44. package/lib/module/react/assets/decodeSkiaImage.js.map +1 -0
  45. package/lib/module/react/assets/errors.js +10 -0
  46. package/lib/module/react/assets/errors.js.map +1 -0
  47. package/lib/module/react/assets/useGameAssets.js +160 -0
  48. package/lib/module/react/assets/useGameAssets.js.map +1 -0
  49. package/lib/module/react/bindAppLifecycle.js +58 -0
  50. package/lib/module/react/bindAppLifecycle.js.map +1 -0
  51. package/lib/module/react/bindGameSession.js +37 -0
  52. package/lib/module/react/bindGameSession.js.map +1 -0
  53. package/lib/module/react/gestureLifecycle.js +68 -0
  54. package/lib/module/react/gestureLifecycle.js.map +1 -0
  55. package/lib/module/react/instrumentation.js +4 -0
  56. package/lib/module/react/instrumentation.js.map +1 -0
  57. package/lib/module/react/pointerBinding.js +196 -0
  58. package/lib/module/react/pointerBinding.js.map +1 -0
  59. package/lib/module/react/pointerCoalescer.js +224 -0
  60. package/lib/module/react/pointerCoalescer.js.map +1 -0
  61. package/lib/module/react/pointerContainment.js +27 -0
  62. package/lib/module/react/pointerContainment.js.map +1 -0
  63. package/lib/module/react/sprites/GameSprite.js +116 -0
  64. package/lib/module/react/sprites/GameSprite.js.map +1 -0
  65. package/lib/module/react/sprites/GameWorld2D.js +44 -0
  66. package/lib/module/react/sprites/GameWorld2D.js.map +1 -0
  67. package/lib/module/react/sprites/Sprite.js +147 -0
  68. package/lib/module/react/sprites/Sprite.js.map +1 -0
  69. package/lib/module/react/sprites/SpriteBatch.js +173 -0
  70. package/lib/module/react/sprites/SpriteBatch.js.map +1 -0
  71. package/lib/module/react/sprites/spriteBatchPolicy.js +25 -0
  72. package/lib/module/react/sprites/spriteBatchPolicy.js.map +1 -0
  73. package/lib/module/react/sprites/spriteTransform.js +135 -0
  74. package/lib/module/react/sprites/spriteTransform.js.map +1 -0
  75. package/lib/module/react/viewportBinding.js +101 -0
  76. package/lib/module/react/viewportBinding.js.map +1 -0
  77. package/lib/module/react.js +13 -0
  78. package/lib/module/react.js.map +1 -0
  79. package/lib/module/scene/defineScene.js +29 -0
  80. package/lib/module/scene/defineScene.js.map +1 -0
  81. package/lib/module/scene/types.js +4 -0
  82. package/lib/module/scene/types.js.map +1 -0
  83. package/lib/module/sprites/sampleSpriteClip.js +50 -0
  84. package/lib/module/sprites/sampleSpriteClip.js.map +1 -0
  85. package/lib/module/sprites/spriteAnimationState.js +165 -0
  86. package/lib/module/sprites/spriteAnimationState.js.map +1 -0
  87. package/lib/module/testing.js +57 -0
  88. package/lib/module/testing.js.map +1 -0
  89. package/lib/module/viewport2d/index.js +4 -0
  90. package/lib/module/viewport2d/index.js.map +1 -0
  91. package/lib/module/viewport2d/math.js +129 -0
  92. package/lib/module/viewport2d/math.js.map +1 -0
  93. package/lib/module/viewport2d/types.js +2 -0
  94. package/lib/module/viewport2d/types.js.map +1 -0
  95. package/lib/typescript/package.json +1 -0
  96. package/lib/typescript/src/assets/defineAssets.d.ts +20 -0
  97. package/lib/typescript/src/assets/defineAssets.d.ts.map +1 -0
  98. package/lib/typescript/src/assets/errors.d.ts +20 -0
  99. package/lib/typescript/src/assets/errors.d.ts.map +1 -0
  100. package/lib/typescript/src/assets/types.d.ts +138 -0
  101. package/lib/typescript/src/assets/types.d.ts.map +1 -0
  102. package/lib/typescript/src/assets/validation.d.ts +15 -0
  103. package/lib/typescript/src/assets/validation.d.ts.map +1 -0
  104. package/lib/typescript/src/core/frameDriver.d.ts +12 -0
  105. package/lib/typescript/src/core/frameDriver.d.ts.map +1 -0
  106. package/lib/typescript/src/core/input/createInputBuffer.d.ts +12 -0
  107. package/lib/typescript/src/core/input/createInputBuffer.d.ts.map +1 -0
  108. package/lib/typescript/src/core/input/types.d.ts +64 -0
  109. package/lib/typescript/src/core/input/types.d.ts.map +1 -0
  110. package/lib/typescript/src/core/session/createGameSession.d.ts +18 -0
  111. package/lib/typescript/src/core/session/createGameSession.d.ts.map +1 -0
  112. package/lib/typescript/src/core/session/deepFreeze.d.ts +27 -0
  113. package/lib/typescript/src/core/session/deepFreeze.d.ts.map +1 -0
  114. package/lib/typescript/src/core/session/diagnostics.d.ts +36 -0
  115. package/lib/typescript/src/core/session/diagnostics.d.ts.map +1 -0
  116. package/lib/typescript/src/core/session/types.d.ts +104 -0
  117. package/lib/typescript/src/core/session/types.d.ts.map +1 -0
  118. package/lib/typescript/src/definition/defineGame.d.ts +66 -0
  119. package/lib/typescript/src/definition/defineGame.d.ts.map +1 -0
  120. package/lib/typescript/src/definition/types.d.ts +56 -0
  121. package/lib/typescript/src/definition/types.d.ts.map +1 -0
  122. package/lib/typescript/src/geometry/types.d.ts +8 -0
  123. package/lib/typescript/src/geometry/types.d.ts.map +1 -0
  124. package/lib/typescript/src/index.d.ts +18 -0
  125. package/lib/typescript/src/index.d.ts.map +1 -0
  126. package/lib/typescript/src/react/GamePointerInput.d.ts +37 -0
  127. package/lib/typescript/src/react/GamePointerInput.d.ts.map +1 -0
  128. package/lib/typescript/src/react/GameView.d.ts +61 -0
  129. package/lib/typescript/src/react/GameView.d.ts.map +1 -0
  130. package/lib/typescript/src/react/alphaClock.d.ts +29 -0
  131. package/lib/typescript/src/react/alphaClock.d.ts.map +1 -0
  132. package/lib/typescript/src/react/assets/createGameAssetStore.d.ts +33 -0
  133. package/lib/typescript/src/react/assets/createGameAssetStore.d.ts.map +1 -0
  134. package/lib/typescript/src/react/assets/decodeSkiaImage.d.ts +12 -0
  135. package/lib/typescript/src/react/assets/decodeSkiaImage.d.ts.map +1 -0
  136. package/lib/typescript/src/react/assets/errors.d.ts +8 -0
  137. package/lib/typescript/src/react/assets/errors.d.ts.map +1 -0
  138. package/lib/typescript/src/react/assets/useGameAssets.d.ts +35 -0
  139. package/lib/typescript/src/react/assets/useGameAssets.d.ts.map +1 -0
  140. package/lib/typescript/src/react/bindAppLifecycle.d.ts +32 -0
  141. package/lib/typescript/src/react/bindAppLifecycle.d.ts.map +1 -0
  142. package/lib/typescript/src/react/bindGameSession.d.ts +14 -0
  143. package/lib/typescript/src/react/bindGameSession.d.ts.map +1 -0
  144. package/lib/typescript/src/react/gestureLifecycle.d.ts +37 -0
  145. package/lib/typescript/src/react/gestureLifecycle.d.ts.map +1 -0
  146. package/lib/typescript/src/react/instrumentation.d.ts +47 -0
  147. package/lib/typescript/src/react/instrumentation.d.ts.map +1 -0
  148. package/lib/typescript/src/react/pointerBinding.d.ts +104 -0
  149. package/lib/typescript/src/react/pointerBinding.d.ts.map +1 -0
  150. package/lib/typescript/src/react/pointerCoalescer.d.ts +106 -0
  151. package/lib/typescript/src/react/pointerCoalescer.d.ts.map +1 -0
  152. package/lib/typescript/src/react/pointerContainment.d.ts +12 -0
  153. package/lib/typescript/src/react/pointerContainment.d.ts.map +1 -0
  154. package/lib/typescript/src/react/sprites/GameSprite.d.ts +75 -0
  155. package/lib/typescript/src/react/sprites/GameSprite.d.ts.map +1 -0
  156. package/lib/typescript/src/react/sprites/GameWorld2D.d.ts +29 -0
  157. package/lib/typescript/src/react/sprites/GameWorld2D.d.ts.map +1 -0
  158. package/lib/typescript/src/react/sprites/Sprite.d.ts +43 -0
  159. package/lib/typescript/src/react/sprites/Sprite.d.ts.map +1 -0
  160. package/lib/typescript/src/react/sprites/SpriteBatch.d.ts +41 -0
  161. package/lib/typescript/src/react/sprites/SpriteBatch.d.ts.map +1 -0
  162. package/lib/typescript/src/react/sprites/spriteBatchPolicy.d.ts +10 -0
  163. package/lib/typescript/src/react/sprites/spriteBatchPolicy.d.ts.map +1 -0
  164. package/lib/typescript/src/react/sprites/spriteTransform.d.ts +86 -0
  165. package/lib/typescript/src/react/sprites/spriteTransform.d.ts.map +1 -0
  166. package/lib/typescript/src/react/viewportBinding.d.ts +42 -0
  167. package/lib/typescript/src/react/viewportBinding.d.ts.map +1 -0
  168. package/lib/typescript/src/react.d.ts +20 -0
  169. package/lib/typescript/src/react.d.ts.map +1 -0
  170. package/lib/typescript/src/scene/defineScene.d.ts +26 -0
  171. package/lib/typescript/src/scene/defineScene.d.ts.map +1 -0
  172. package/lib/typescript/src/scene/types.d.ts +71 -0
  173. package/lib/typescript/src/scene/types.d.ts.map +1 -0
  174. package/lib/typescript/src/sprites/sampleSpriteClip.d.ts +24 -0
  175. package/lib/typescript/src/sprites/sampleSpriteClip.d.ts.map +1 -0
  176. package/lib/typescript/src/sprites/spriteAnimationState.d.ts +45 -0
  177. package/lib/typescript/src/sprites/spriteAnimationState.d.ts.map +1 -0
  178. package/lib/typescript/src/testing.d.ts +28 -0
  179. package/lib/typescript/src/testing.d.ts.map +1 -0
  180. package/lib/typescript/src/viewport2d/index.d.ts +3 -0
  181. package/lib/typescript/src/viewport2d/index.d.ts.map +1 -0
  182. package/lib/typescript/src/viewport2d/math.d.ts +25 -0
  183. package/lib/typescript/src/viewport2d/math.d.ts.map +1 -0
  184. package/lib/typescript/src/viewport2d/types.d.ts +59 -0
  185. package/lib/typescript/src/viewport2d/types.d.ts.map +1 -0
  186. package/package.json +120 -0
  187. package/src/assets/defineAssets.ts +62 -0
  188. package/src/assets/errors.ts +64 -0
  189. package/src/assets/types.ts +164 -0
  190. package/src/assets/validation.ts +158 -0
  191. package/src/core/frameDriver.ts +31 -0
  192. package/src/core/input/createInputBuffer.ts +337 -0
  193. package/src/core/input/types.ts +67 -0
  194. package/src/core/session/createGameSession.ts +652 -0
  195. package/src/core/session/deepFreeze.ts +158 -0
  196. package/src/core/session/diagnostics.ts +35 -0
  197. package/src/core/session/types.ts +122 -0
  198. package/src/definition/defineGame.ts +94 -0
  199. package/src/definition/types.ts +67 -0
  200. package/src/geometry/types.ts +7 -0
  201. package/src/index.ts +84 -0
  202. package/src/react/GamePointerInput.tsx +478 -0
  203. package/src/react/GameView.tsx +317 -0
  204. package/src/react/alphaClock.ts +59 -0
  205. package/src/react/assets/createGameAssetStore.ts +459 -0
  206. package/src/react/assets/decodeSkiaImage.ts +64 -0
  207. package/src/react/assets/errors.ts +7 -0
  208. package/src/react/assets/useGameAssets.ts +171 -0
  209. package/src/react/bindAppLifecycle.ts +79 -0
  210. package/src/react/bindGameSession.ts +41 -0
  211. package/src/react/gestureLifecycle.ts +73 -0
  212. package/src/react/instrumentation.ts +54 -0
  213. package/src/react/pointerBinding.ts +226 -0
  214. package/src/react/pointerCoalescer.ts +234 -0
  215. package/src/react/pointerContainment.ts +23 -0
  216. package/src/react/sprites/GameSprite.tsx +192 -0
  217. package/src/react/sprites/GameWorld2D.tsx +46 -0
  218. package/src/react/sprites/Sprite.tsx +194 -0
  219. package/src/react/sprites/SpriteBatch.tsx +219 -0
  220. package/src/react/sprites/spriteBatchPolicy.ts +21 -0
  221. package/src/react/sprites/spriteTransform.ts +163 -0
  222. package/src/react/viewportBinding.ts +104 -0
  223. package/src/react.ts +37 -0
  224. package/src/scene/defineScene.ts +38 -0
  225. package/src/scene/types.ts +79 -0
  226. package/src/sprites/sampleSpriteClip.ts +51 -0
  227. package/src/sprites/spriteAnimationState.ts +176 -0
  228. package/src/testing.ts +61 -0
  229. package/src/viewport2d/index.ts +7 -0
  230. package/src/viewport2d/math.ts +134 -0
  231. package/src/viewport2d/types.ts +63 -0
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+
3
+ /** The resolved source rectangle for one frame selection. */
4
+
5
+ /**
6
+ * Resolve the source rectangle for a static frame selection.
7
+ *
8
+ * RF4: an absent selection (the dynamic clip/elapsed mode before its first
9
+ * value) presents nothing instead of throwing. The static baseline uses the
10
+ * sheet's first frame so the anchor/scale correction has sane dimensions
11
+ * while the per-frame worklet resolves the real selection.
12
+ */
13
+ export function resolveSpriteFrameRect(source, frame) {
14
+ if (source.descriptor.kind === 'image') {
15
+ const image = source;
16
+ return {
17
+ x: 0,
18
+ y: 0,
19
+ width: image.width,
20
+ height: image.height
21
+ };
22
+ }
23
+ const sheet = source;
24
+ if (frame === undefined) {
25
+ const firstAnimationName = Object.keys(sheet.descriptor.animations)[0];
26
+ const firstAnimation = firstAnimationName === undefined ? undefined : sheet.descriptor.animations[firstAnimationName];
27
+ const firstFrameName = firstAnimation?.frames[0];
28
+ const baseline = firstFrameName === undefined ? undefined : sheet.frames[firstFrameName];
29
+ return baseline ?? {
30
+ x: 0,
31
+ y: 0,
32
+ width: 0,
33
+ height: 0
34
+ };
35
+ }
36
+ const rect = sheet.frames[frame];
37
+ if (rect === undefined) {
38
+ throw new Error(`frame ${JSON.stringify(frame)} does not belong to this sprite sheet (loaded frames: ${Object.keys(sheet.frames).join(', ')})`);
39
+ }
40
+ return rect;
41
+ }
42
+
43
+ /**
44
+ * Sprite transform math (T7.6).
45
+ *
46
+ * Pure, worklet-compatible. A sprite's frame occupies
47
+ * `[0, 0, frameWidth, frameHeight]` in local space and the documented pivot
48
+ * order is:
49
+ *
50
+ * M = T(x, y) · R(rotation) · T(anchor) · S(scaleX, scaleY) · T(-anchor)
51
+ *
52
+ * i.e. scale and explicit flips happen around the anchor, then the frame
53
+ * rotates around the anchor at the world position. The RSXform carries the
54
+ * rotation + position (its 2x2 cannot express flips or non-uniform scale);
55
+ * the wrapping Group applies the scale/flip part around the anchor.
56
+ */
57
+
58
+ /** A sprite's presentation input; numbers or UI-runtime animated values. */
59
+
60
+ /** The computed RSXform (rotation + position, pivot-compensated). */
61
+
62
+ /** A Skia-compatible 3x3 transform element list. */
63
+
64
+ function readNumber(value) {
65
+ 'worklet';
66
+
67
+ return typeof value === 'number' ? value : value.value;
68
+ }
69
+ function readBoolean(value) {
70
+ 'worklet';
71
+
72
+ return typeof value === 'boolean' ? value : value.value;
73
+ }
74
+
75
+ /**
76
+ * The RSXform for the atlas path: rotation + position with the pivot
77
+ * compensated (`tx = x - pivotX·cos + pivotY·sin`). Scale and flips are
78
+ * applied by the wrapping Group (`spriteGroupCorrection`).
79
+ */
80
+ export function computeSpriteRsxform(input) {
81
+ 'worklet';
82
+
83
+ const x = readNumber(input.x);
84
+ const y = readNumber(input.y);
85
+ const rotation = readNumber(input.rotation);
86
+ const pivotX = input.anchorX * input.frameWidth;
87
+ const pivotY = input.anchorY * input.frameHeight;
88
+ const cos = Math.cos(rotation);
89
+ const sin = Math.sin(rotation);
90
+ return {
91
+ scos: cos,
92
+ ssin: sin,
93
+ tx: x - pivotX * cos + pivotY * sin,
94
+ ty: y - pivotX * sin - pivotY * cos
95
+ };
96
+ }
97
+
98
+ /**
99
+ * The scale/flip part around the anchor as a Skia transform element list:
100
+ * `T(anchor) · S(scaleX, scaleY) · T(-anchor)` (the first element is the
101
+ * outermost).
102
+ */
103
+ export function spriteGroupCorrection(input) {
104
+ 'worklet';
105
+
106
+ const scale = readNumber(input.scale);
107
+ const flipX = readBoolean(input.flipX);
108
+ const flipY = readBoolean(input.flipY);
109
+ const pivotX = input.anchorX * input.frameWidth;
110
+ const pivotY = input.anchorY * input.frameHeight;
111
+ return [{
112
+ translateX: pivotX
113
+ }, {
114
+ translateY: pivotY
115
+ }, {
116
+ scaleX: flipX ? -scale : scale
117
+ }, {
118
+ scaleY: flipY ? -scale : scale
119
+ }, {
120
+ translateX: -pivotX
121
+ }, {
122
+ translateY: -pivotY
123
+ }];
124
+ }
125
+
126
+ /** World position of the anchor point (for debugging and overlays). */
127
+ export function spriteAnchorWorld(input) {
128
+ 'worklet';
129
+
130
+ return {
131
+ x: readNumber(input.x),
132
+ y: readNumber(input.y)
133
+ };
134
+ }
135
+ //# sourceMappingURL=spriteTransform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["resolveSpriteFrameRect","source","frame","descriptor","kind","image","x","y","width","height","sheet","undefined","firstAnimationName","Object","keys","animations","firstAnimation","firstFrameName","frames","baseline","rect","Error","JSON","stringify","join","readNumber","value","readBoolean","computeSpriteRsxform","input","rotation","pivotX","anchorX","frameWidth","pivotY","anchorY","frameHeight","cos","Math","sin","scos","ssin","tx","ty","spriteGroupCorrection","scale","flipX","flipY","translateX","translateY","scaleX","scaleY","spriteAnchorWorld"],"sourceRoot":"../../../../src","sources":["react/sprites/spriteTransform.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+
3
+ import { resolveViewport2D } from "../viewport2d/index.js";
4
+
5
+ /**
6
+ * Platform-neutral holder for the resolved viewport of a mounted game
7
+ * surface.
8
+ *
9
+ * It re-resolves whenever the surface size changes, notifies subscribers on
10
+ * each layout revision (so pointer input can cancel an active gesture on
11
+ * layout invalidation), and exposes the latest immutable resolved viewport to
12
+ * both the renderer and the input adapter. It never touches React, Skia, or
13
+ * platform dimensions.
14
+ */
15
+ export class ViewportBinding {
16
+ #config;
17
+ #resolved;
18
+ #lastSurfaceSize;
19
+ #revision = 0;
20
+ #listeners = new Set();
21
+ constructor(config) {
22
+ this.#config = config;
23
+ }
24
+
25
+ /** The authored viewport configuration this binding resolves. */
26
+ get config() {
27
+ return this.#config;
28
+ }
29
+
30
+ /** The latest resolved viewport, or `undefined` while the layout is invalid. */
31
+ get resolved() {
32
+ return this.#resolved;
33
+ }
34
+
35
+ /** The latest native surface measurement, retained across viewport swaps. */
36
+ get surfaceSize() {
37
+ return this.#lastSurfaceSize;
38
+ }
39
+
40
+ /** Monotonic counter incremented on every layout revision. */
41
+ get revision() {
42
+ return this.#revision;
43
+ }
44
+
45
+ /**
46
+ * Resolve the configured viewport against a new surface size.
47
+ *
48
+ * No-op for unchanged sizes. Subscribers are notified only when the layout
49
+ * actually changes.
50
+ */
51
+ setSurfaceSize(size) {
52
+ if (this.#lastSurfaceSize !== undefined && this.#lastSurfaceSize.width === size.width && this.#lastSurfaceSize.height === size.height) {
53
+ return;
54
+ }
55
+ this.#lastSurfaceSize = Object.freeze({
56
+ width: size.width,
57
+ height: size.height
58
+ });
59
+ this.#resolved = resolveViewport2D(this.#config, size);
60
+ this.#revision += 1;
61
+ for (const listener of [...this.#listeners]) {
62
+ listener();
63
+ }
64
+ }
65
+
66
+ /** Observe layout revisions. Returns an idempotent unsubscribe. */
67
+ subscribe(listener) {
68
+ this.#listeners.add(listener);
69
+ let removed = false;
70
+ return () => {
71
+ if (removed) {
72
+ return;
73
+ }
74
+ removed = true;
75
+ this.#listeners.delete(listener);
76
+ };
77
+ }
78
+
79
+ /** Release subscribers. The binding becomes inert. */
80
+ dispose() {
81
+ this.#listeners.clear();
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Return the existing binding when its authored viewport is unchanged, or
87
+ * create a replacement that immediately resolves against the already-mounted
88
+ * native surface. React Native does not guarantee another `onLayout` event
89
+ * when only the game/viewport changes and the View's dimensions stay equal.
90
+ */
91
+ export function bindingForViewport(config, previous) {
92
+ if (previous?.config === config) {
93
+ return previous;
94
+ }
95
+ const replacement = new ViewportBinding(config);
96
+ if (previous?.surfaceSize !== undefined) {
97
+ replacement.setSurfaceSize(previous.surfaceSize);
98
+ }
99
+ return replacement;
100
+ }
101
+ //# sourceMappingURL=viewportBinding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["resolveViewport2D","ViewportBinding","config","resolved","lastSurfaceSize","revision","listeners","Set","constructor","surfaceSize","setSurfaceSize","size","undefined","width","height","Object","freeze","listener","subscribe","add","removed","delete","dispose","clear","bindingForViewport","previous","replacement"],"sourceRoot":"../../../src","sources":["react/viewportBinding.ts"],"mappings":";;AAAA,SAASA,iBAAiB,QAAkE,wBAAe;;AAE3G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,eAAe,CAAC;EAClB,CAACC,MAAM;EAChB,CAACC,QAAQ;EACT,CAACC,eAAe;EAChB,CAACC,QAAQ,GAAG,CAAC;EACb,CAACC,SAAS,GAAG,IAAIC,GAAG,CAAa,CAAC;EAElCC,WAAWA,CAACN,MAAgB,EAAE;IAC5B,IAAI,CAAC,CAACA,MAAM,GAAGA,MAAM;EACvB;;EAEA;EACA,IAAIA,MAAMA,CAAA,EAAa;IACrB,OAAO,IAAI,CAAC,CAACA,MAAM;EACrB;;EAEA;EACA,IAAIC,QAAQA,CAAA,EAAmC;IAC7C,OAAO,IAAI,CAAC,CAACA,QAAQ;EACvB;;EAEA;EACA,IAAIM,WAAWA,CAAA,EAA4B;IACzC,OAAO,IAAI,CAAC,CAACL,eAAe;EAC9B;;EAEA;EACA,IAAIC,QAAQA,CAAA,EAAW;IACrB,OAAO,IAAI,CAAC,CAACA,QAAQ;EACvB;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEK,cAAcA,CAACC,IAAiB,EAAQ;IACtC,IACE,IAAI,CAAC,CAACP,eAAe,KAAKQ,SAAS,IACnC,IAAI,CAAC,CAACR,eAAe,CAACS,KAAK,KAAKF,IAAI,CAACE,KAAK,IAC1C,IAAI,CAAC,CAACT,eAAe,CAACU,MAAM,KAAKH,IAAI,CAACG,MAAM,EAC5C;MACA;IACF;IACA,IAAI,CAAC,CAACV,eAAe,GAAGW,MAAM,CAACC,MAAM,CAAC;MAAEH,KAAK,EAAEF,IAAI,CAACE,KAAK;MAAEC,MAAM,EAAEH,IAAI,CAACG;IAAO,CAAC,CAAC;IACjF,IAAI,CAAC,CAACX,QAAQ,GAAGH,iBAAiB,CAAC,IAAI,CAAC,CAACE,MAAM,EAAES,IAAI,CAAC;IACtD,IAAI,CAAC,CAACN,QAAQ,IAAI,CAAC;IACnB,KAAK,MAAMY,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,CAACX,SAAS,CAAC,EAAE;MAC3CW,QAAQ,CAAC,CAAC;IACZ;EACF;;EAEA;EACAC,SAASA,CAACD,QAAoB,EAAc;IAC1C,IAAI,CAAC,CAACX,SAAS,CAACa,GAAG,CAACF,QAAQ,CAAC;IAC7B,IAAIG,OAAO,GAAG,KAAK;IACnB,OAAO,MAAM;MACX,IAAIA,OAAO,EAAE;QACX;MACF;MACAA,OAAO,GAAG,IAAI;MACd,IAAI,CAAC,CAACd,SAAS,CAACe,MAAM,CAACJ,QAAQ,CAAC;IAClC,CAAC;EACH;;EAEA;EACAK,OAAOA,CAAA,EAAS;IACd,IAAI,CAAC,CAAChB,SAAS,CAACiB,KAAK,CAAC,CAAC;EACzB;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,kBAAkBA,CAChCtB,MAAgB,EAChBuB,QAAgC,EACf;EACjB,IAAIA,QAAQ,EAAEvB,MAAM,KAAKA,MAAM,EAAE;IAC/B,OAAOuB,QAAQ;EACjB;EAEA,MAAMC,WAAW,GAAG,IAAIzB,eAAe,CAACC,MAAM,CAAC;EAC/C,IAAIuB,QAAQ,EAAEhB,WAAW,KAAKG,SAAS,EAAE;IACvCc,WAAW,CAAChB,cAAc,CAACe,QAAQ,CAAChB,WAAW,CAAC;EAClD;EACA,OAAOiB,WAAW;AACpB","ignoreList":[]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ export { GameView } from "./react/GameView.js";
4
+ export { createGameAssetStore } from "./react/assets/decodeSkiaImage.js";
5
+ export { useGameAssets, stableGroupsKey } from "./react/assets/useGameAssets.js";
6
+ export { GameWorld2D, viewportTransform } from "./react/sprites/GameWorld2D.js";
7
+ export { Sprite, resolveSpriteFrameRect } from "./react/sprites/Sprite.js";
8
+ export { GameSprite, spriteFrameNameForClip } from "./react/sprites/GameSprite.js";
9
+ export { SpriteBatch } from "./react/sprites/SpriteBatch.js";
10
+ export { computeSpriteRsxform, spriteAnchorWorld, spriteGroupCorrection } from "./react/sprites/spriteTransform.js";
11
+ export { createGameAssetStoreCore } from "./react/assets/createGameAssetStore.js";
12
+ export { GamePointerInput } from "./react/GamePointerInput.js";
13
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["GameView","createGameAssetStore","useGameAssets","stableGroupsKey","GameWorld2D","viewportTransform","Sprite","resolveSpriteFrameRect","GameSprite","spriteFrameNameForClip","SpriteBatch","computeSpriteRsxform","spriteAnchorWorld","spriteGroupCorrection","createGameAssetStoreCore","GamePointerInput"],"sourceRoot":"../../src","sources":["react.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,qBAAkB;AAC3C,SAASC,oBAAoB,QAAQ,mCAAgC;AACrE,SAASC,aAAa,EAAEC,eAAe,QAAQ,iCAA8B;AAE7E,SAASC,WAAW,EAAEC,iBAAiB,QAAQ,gCAA6B;AAC5E,SAASC,MAAM,EAAEC,sBAAsB,QAAQ,2BAAwB;AAEvE,SAASC,UAAU,EAAEC,sBAAsB,QAAQ,+BAA4B;AAM/E,SAASC,WAAW,QAAQ,gCAA6B;AAEzD,SACEC,oBAAoB,EACpBC,iBAAiB,EACjBC,qBAAqB,QAChB,oCAAiC;AAMxC,SAASC,wBAAwB,QAAQ,wCAAqC;AAS9E,SAASC,gBAAgB,QAAQ,6BAA0B","ignoreList":[]}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Define a synchronous functional scene while inferring its state, snapshot,
5
+ * action, and transition types.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const ready = defineScene({
10
+ * actions: ['primary'],
11
+ * transitions: ['play'],
12
+ * create: () => ({ ready: true }),
13
+ * update: ({ state, input, transition }) => {
14
+ * if (input.pointer('primary').pressed) {
15
+ * transition.setScene('play');
16
+ * }
17
+ * return state;
18
+ * },
19
+ * snapshot: ({ state }) => state,
20
+ * });
21
+ * ```
22
+ */
23
+ export function defineScene(definition) {
24
+ return {
25
+ kind: 'gamekit.scene',
26
+ ...definition
27
+ };
28
+ }
29
+ //# sourceMappingURL=defineScene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["defineScene","definition","kind"],"sourceRoot":"../../../src","sources":["scene/defineScene.ts"],"mappings":";;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,WAAWA,CAMzBC,UAGuE,EACK;EAC5E,OAAO;IACLC,IAAI,EAAE,eAAe;IACrB,GAAGD;EACL,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["scene/types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Deterministic clip frame sampling (T7.3).
5
+ *
6
+ * Pure, allocation-free, worklet-compatible frame selection. The same clip
7
+ * metadata and elapsed time always select the same frame, so equivalent
8
+ * game time produces identical presentation at 30/60/90/120 Hz.
9
+ */
10
+
11
+ /**
12
+ * Select the frame index for `elapsedMs` of playback.
13
+ *
14
+ * Loop clips wrap with modulo — the boundary frame is never duplicated and
15
+ * no zero-length boundary frame exists. One-shot clips clamp to their final
16
+ * frame; completion is reported separately.
17
+ */
18
+ export function sampleSpriteClipFrame(clip, elapsedMs) {
19
+ 'worklet';
20
+
21
+ const frameCount = clip.frames.length;
22
+ const duration = clip.frameDurationMs;
23
+ if (clip.mode === 'loop') {
24
+ const index = Math.floor(elapsedMs / duration) % frameCount;
25
+ return index >= 0 ? index : index + frameCount;
26
+ }
27
+ const index = Math.floor(elapsedMs / duration);
28
+ return index >= frameCount ? frameCount - 1 : index;
29
+ }
30
+
31
+ /**
32
+ * The frame NAME selected for `elapsedMs` of playback (the ordered frame
33
+ * references of the clip).
34
+ */
35
+ export function sampleSpriteClipFrameName(clip, elapsedMs) {
36
+ 'worklet';
37
+
38
+ const frames = clip.frames;
39
+ const index = sampleSpriteClipFrame(clip, elapsedMs);
40
+ const frame = frames[index];
41
+ return frame === undefined ? frames[0] ?? '' : frame;
42
+ }
43
+
44
+ /** Total clip duration in milliseconds (one-shot: its full timeline). */
45
+ export function spriteClipDurationMs(clip) {
46
+ 'worklet';
47
+
48
+ return clip.frames.length * clip.frameDurationMs;
49
+ }
50
+ //# sourceMappingURL=sampleSpriteClip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["sampleSpriteClipFrame","clip","elapsedMs","frameCount","frames","length","duration","frameDurationMs","mode","index","Math","floor","sampleSpriteClipFrameName","frame","undefined","spriteClipDurationMs"],"sourceRoot":"../../../src","sources":["sprites/sampleSpriteClip.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,qBAAqBA,CACnCC,IAAgB,EAChBC,SAAiB,EACT;EACR,SAAS;;EACT,MAAMC,UAAU,GAAGF,IAAI,CAACG,MAAM,CAACC,MAAM;EACrC,MAAMC,QAAQ,GAAGL,IAAI,CAACM,eAAe;EACrC,IAAIN,IAAI,CAACO,IAAI,KAAK,MAAM,EAAE;IACxB,MAAMC,KAAK,GAAGC,IAAI,CAACC,KAAK,CAACT,SAAS,GAAGI,QAAQ,CAAC,GAAGH,UAAU;IAC3D,OAAOM,KAAK,IAAI,CAAC,GAAGA,KAAK,GAAGA,KAAK,GAAGN,UAAU;EAChD;EACA,MAAMM,KAAK,GAAGC,IAAI,CAACC,KAAK,CAACT,SAAS,GAAGI,QAAQ,CAAC;EAC9C,OAAOG,KAAK,IAAIN,UAAU,GAAGA,UAAU,GAAG,CAAC,GAAGM,KAAK;AACrD;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASG,yBAAyBA,CACvCX,IAAgB,EAChBC,SAAiB,EACT;EACR,SAAS;;EACT,MAAME,MAAM,GAAGH,IAAI,CAACG,MAAM;EAC1B,MAAMK,KAAK,GAAGT,qBAAqB,CAACC,IAAI,EAAEC,SAAS,CAAC;EACpD,MAAMW,KAAK,GAAGT,MAAM,CAACK,KAAK,CAAC;EAC3B,OAAOI,KAAK,KAAKC,SAAS,GAAGV,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,GAAGS,KAAK;AACtD;;AAEA;AACA,OAAO,SAASE,oBAAoBA,CAACd,IAAgB,EAAU;EAC7D,SAAS;;EACT,OAAOA,IAAI,CAACG,MAAM,CAACC,MAAM,GAAGJ,IAAI,CAACM,eAAe;AAClD","ignoreList":[]}
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Deterministic sprite animation playback state (T7.3).
5
+ *
6
+ * Animation state is plain serializable data advanced from fixed-step game
7
+ * time: `clip`, elapsed time, pause flag, speed, and completion. Changing,
8
+ * pausing, restarting, or completing a clip returns a NEW state object; it
9
+ * never mutates scene state or emits a side effect. The same input and
10
+ * elapsed game time always select the same presented frame (see
11
+ * `sampleSpriteClip`).
12
+ *
13
+ * Separation of concerns: gameplay-significant animation state lives in the
14
+ * scene snapshot and advances from fixed-step game time; a renderer-only
15
+ * loop may interpolate presentation from the latest committed state plus
16
+ * the interpolation alpha, but must never emit gameplay events from a
17
+ * presentation-only frame.
18
+ */
19
+ import { GameAssetError } from "../assets/errors.js";
20
+ import { spriteClipDurationMs } from "./sampleSpriteClip.js";
21
+
22
+ /** Immutable, serializable animation playback state. */
23
+
24
+ function assertFinitePositiveSpeed(speed) {
25
+ if (typeof speed !== 'number' || !Number.isFinite(speed) || speed <= 0) {
26
+ throw new Error('sprite animation speed must be a finite number greater than zero');
27
+ }
28
+ }
29
+ function assertFiniteDelta(deltaSeconds) {
30
+ if (typeof deltaSeconds !== 'number' || !Number.isFinite(deltaSeconds)) {
31
+ throw new Error('sprite animation delta must be a finite number of seconds');
32
+ }
33
+ }
34
+ /** The clip names of a sprite-sheet descriptor (works through the manifest brand). */
35
+
36
+ /** Runtime clip lookup; throws a structured error for unknown clips. */
37
+ function clipOf(descriptor, clip) {
38
+ 'worklet';
39
+
40
+ const animation = descriptor.animations[clip];
41
+ if (animation === undefined) {
42
+ throw new GameAssetError('ASSET_UNKNOWN_CLIP', ['animations', clip], `unknown animation clip ${JSON.stringify(clip)}`);
43
+ }
44
+ return animation;
45
+ }
46
+
47
+ /**
48
+ * Start playback of `clip` from its beginning. The clip name is preserved
49
+ * as a string literal in the returned state; unknown clips are rejected at
50
+ * runtime (the manifest descriptor keeps the sheet-level frame and clip
51
+ * names literal via the spriteSheet contract).
52
+ */
53
+ export function startSpriteAnimation(descriptor, clip) {
54
+ 'worklet';
55
+
56
+ clipOf(descriptor, clip);
57
+ return {
58
+ clip,
59
+ elapsedMs: 0,
60
+ paused: false,
61
+ speed: 1,
62
+ completed: false
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Advance playback by `deltaSeconds` of fixed-step game time.
68
+ *
69
+ * Finite negative deltas clamp elapsed time to zero; NaN/infinity fail
70
+ * clearly. Loop clips keep their elapsed time bounded within one timeline
71
+ * (modulo), so arbitrarily large deltas cost constant arithmetic.
72
+ */
73
+ export function advanceSpriteAnimation(descriptor, state, deltaSeconds) {
74
+ 'worklet';
75
+
76
+ assertFiniteDelta(deltaSeconds);
77
+ if (state.paused || state.completed) {
78
+ return state;
79
+ }
80
+ const clip = clipOf(descriptor, state.clip);
81
+ const totalMs = spriteClipDurationMs(clip);
82
+ const next = state.elapsedMs + deltaSeconds * 1000 * state.speed;
83
+ if (clip.mode === 'once') {
84
+ if (next >= totalMs) {
85
+ return {
86
+ ...state,
87
+ elapsedMs: totalMs,
88
+ completed: true
89
+ };
90
+ }
91
+ return {
92
+ ...state,
93
+ elapsedMs: next < 0 ? 0 : next
94
+ };
95
+ }
96
+ // Loop: bounded elapsed within one timeline; negative clamps to zero.
97
+ const wrapped = next < 0 ? 0 : next % totalMs;
98
+ return {
99
+ ...state,
100
+ elapsedMs: wrapped
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Switch playback to `clip`, restarting it from the beginning. The clip
106
+ * name is typed against the descriptor's animation table.
107
+ */
108
+ export function playSpriteAnimation(descriptor, state, clip) {
109
+ 'worklet';
110
+
111
+ if (clip === state.clip) {
112
+ return state;
113
+ }
114
+ clipOf(descriptor, clip);
115
+ return {
116
+ clip,
117
+ elapsedMs: 0,
118
+ paused: state.paused,
119
+ speed: state.speed,
120
+ completed: false
121
+ };
122
+ }
123
+
124
+ /** Pause playback; `advance` becomes a no-op while paused. */
125
+ export function pauseSpriteAnimation(state) {
126
+ 'worklet';
127
+
128
+ return state.paused ? state : {
129
+ ...state,
130
+ paused: true
131
+ };
132
+ }
133
+
134
+ /** Resume playback from the paused position. */
135
+ export function resumeSpriteAnimation(state) {
136
+ 'worklet';
137
+
138
+ return state.paused ? {
139
+ ...state,
140
+ paused: false
141
+ } : state;
142
+ }
143
+
144
+ /** Restart the current clip from its beginning. */
145
+ export function resetSpriteAnimation(state) {
146
+ 'worklet';
147
+
148
+ return {
149
+ ...state,
150
+ elapsedMs: 0,
151
+ completed: false
152
+ };
153
+ }
154
+
155
+ /** Set a finite positive speed multiplier. */
156
+ export function setSpriteAnimationSpeed(state, speed) {
157
+ 'worklet';
158
+
159
+ assertFinitePositiveSpeed(speed);
160
+ return state.speed === speed ? state : {
161
+ ...state,
162
+ speed
163
+ };
164
+ }
165
+ //# sourceMappingURL=spriteAnimationState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["GameAssetError","spriteClipDurationMs","assertFinitePositiveSpeed","speed","Number","isFinite","Error","assertFiniteDelta","deltaSeconds","clipOf","descriptor","clip","animation","animations","undefined","JSON","stringify","startSpriteAnimation","elapsedMs","paused","completed","advanceSpriteAnimation","state","totalMs","next","mode","wrapped","playSpriteAnimation","pauseSpriteAnimation","resumeSpriteAnimation","resetSpriteAnimation","setSpriteAnimationSpeed"],"sourceRoot":"../../../src","sources":["sprites/spriteAnimationState.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ import { createGameSessionWithDriver } from "./core/session/createGameSession.js";
4
+ import { createAnimationFrameDriver } from "./core/frameDriver.js";
5
+ export { createAnimationFrameDriver, createGameSessionWithDriver };
6
+ /**
7
+ * Deterministic animation-frame driver for headless tests.
8
+ *
9
+ * Frames are fired manually with explicit timestamps, so games can be driven
10
+ * with a fixed step and exact wall-clock schedules in Node without a
11
+ * simulator.
12
+ */
13
+ export class ManualFrameDriver {
14
+ #callbacks = new Map();
15
+ #allCallbacks = new Map();
16
+ #nextHandle = 1;
17
+
18
+ /** Number of currently scheduled callbacks. */
19
+ get pendingCount() {
20
+ return this.#callbacks.size;
21
+ }
22
+ requestFrame(callback) {
23
+ const handle = this.#nextHandle;
24
+ this.#nextHandle += 1;
25
+ this.#callbacks.set(handle, callback);
26
+ this.#allCallbacks.set(handle, callback);
27
+ return handle;
28
+ }
29
+ cancelFrame(handle) {
30
+ this.#callbacks.delete(handle);
31
+ }
32
+
33
+ /** Fire the next pending callback with the given timestamp. */
34
+ fireNext(timestampMs) {
35
+ const next = this.#callbacks.entries().next();
36
+ if (next.done) {
37
+ throw new Error('No frame is pending');
38
+ }
39
+ const [handle, callback] = next.value;
40
+ this.#callbacks.delete(handle);
41
+ callback(timestampMs);
42
+ return handle;
43
+ }
44
+
45
+ /**
46
+ * Fire a specific handle even if it was already fired, simulating a stale
47
+ * callback racing with a lifecycle change.
48
+ */
49
+ fireCancelled(handle, timestampMs) {
50
+ const callback = this.#allCallbacks.get(handle);
51
+ if (!callback) {
52
+ throw new Error(`Unknown frame handle: ${handle}`);
53
+ }
54
+ callback(timestampMs);
55
+ }
56
+ }
57
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createGameSessionWithDriver","createAnimationFrameDriver","ManualFrameDriver","callbacks","Map","allCallbacks","nextHandle","pendingCount","size","requestFrame","callback","handle","set","cancelFrame","delete","fireNext","timestampMs","next","entries","done","Error","value","fireCancelled","get"],"sourceRoot":"../../src","sources":["testing.ts"],"mappings":";;AAAA,SAASA,2BAA2B,QAAQ,qCAAkC;AAC9E,SAASC,0BAA0B,QAAQ,uBAAoB;AAI/D,SAASA,0BAA0B,EAAED,2BAA2B;AAGhE;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,iBAAiB,CAAwB;EAC3C,CAACC,SAAS,GAAG,IAAIC,GAAG,CAAwC,CAAC;EAC7D,CAACC,YAAY,GAAG,IAAID,GAAG,CAAwC,CAAC;EACzE,CAACE,UAAU,GAAG,CAAC;;EAEf;EACA,IAAIC,YAAYA,CAAA,EAAW;IACzB,OAAO,IAAI,CAAC,CAACJ,SAAS,CAACK,IAAI;EAC7B;EAEAC,YAAYA,CAACC,QAAuC,EAAe;IACjE,MAAMC,MAAM,GAAG,IAAI,CAAC,CAACL,UAAU;IAC/B,IAAI,CAAC,CAACA,UAAU,IAAI,CAAC;IACrB,IAAI,CAAC,CAACH,SAAS,CAACS,GAAG,CAACD,MAAM,EAAED,QAAQ,CAAC;IACrC,IAAI,CAAC,CAACL,YAAY,CAACO,GAAG,CAACD,MAAM,EAAED,QAAQ,CAAC;IACxC,OAAOC,MAAM;EACf;EAEAE,WAAWA,CAACF,MAAmB,EAAQ;IACrC,IAAI,CAAC,CAACR,SAAS,CAACW,MAAM,CAACH,MAAM,CAAC;EAChC;;EAEA;EACAI,QAAQA,CAACC,WAAmB,EAAe;IACzC,MAAMC,IAAI,GAAG,IAAI,CAAC,CAACd,SAAS,CAACe,OAAO,CAAC,CAAC,CAACD,IAAI,CAAC,CAAC;IAC7C,IAAIA,IAAI,CAACE,IAAI,EAAE;MACb,MAAM,IAAIC,KAAK,CAAC,qBAAqB,CAAC;IACxC;IACA,MAAM,CAACT,MAAM,EAAED,QAAQ,CAAC,GAAGO,IAAI,CAACI,KAAK;IACrC,IAAI,CAAC,CAAClB,SAAS,CAACW,MAAM,CAACH,MAAM,CAAC;IAC9BD,QAAQ,CAACM,WAAW,CAAC;IACrB,OAAOL,MAAM;EACf;;EAEA;AACF;AACA;AACA;EACEW,aAAaA,CAACX,MAAmB,EAAEK,WAAmB,EAAQ;IAC5D,MAAMN,QAAQ,GAAG,IAAI,CAAC,CAACL,YAAY,CAACkB,GAAG,CAACZ,MAAM,CAAC;IAC/C,IAAI,CAACD,QAAQ,EAAE;MACb,MAAM,IAAIU,KAAK,CAAC,yBAAyBT,MAAM,EAAE,CAAC;IACpD;IACAD,QAAQ,CAACM,WAAW,CAAC;EACvB;AACF","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { containsSurfacePoint, resolveViewport2D, surfaceToWorld, worldToSurface } from "./math.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["containsSurfacePoint","resolveViewport2D","surfaceToWorld","worldToSurface"],"sourceRoot":"../../../src","sources":["viewport2d/index.ts"],"mappings":";;AACA,SACEA,oBAAoB,EACpBC,iBAAiB,EACjBC,cAAc,EACdC,cAAc,QACT,WAAQ","ignoreList":[]}