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,116 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * `GameSprite` — the common GameKit sprite integration (T7.6).
5
+ *
6
+ * Accepts the renderer's commit/alpha shared values, narrows the snapshot
7
+ * by `scene`, invokes one worklet `select` mapper, and drives the
8
+ * underlying `Sprite` through coherent derived values. The selector's scene
9
+ * typing is exact — a `scene="play"` selector receives only the play
10
+ * snapshot without casts.
11
+ */
12
+ import { useDerivedValue } from 'react-native-reanimated';
13
+ import { Sprite } from "./Sprite.js";
14
+
15
+ /** Interpolation context for the select mapper. */
16
+
17
+ /** The discrete + interpolated presentation selection. */
18
+ import { jsx as _jsx } from "react/jsx-runtime";
19
+ /**
20
+ * Select the frame name for a clip + elapsed time (loop/once semantics).
21
+ * Reads the descriptor's animation table; the result is resolved against
22
+ * the frame rectangles by the caller. Reuses the pure sampler's semantics.
23
+ */
24
+ export function spriteFrameNameForClip(animations, clip, elapsedMs) {
25
+ 'worklet';
26
+
27
+ const animation = animations[clip];
28
+ if (animation === undefined || animation.frames.length === 0) {
29
+ return clip;
30
+ }
31
+ const duration = animation.frameDurationMs;
32
+ const count = animation.frames.length;
33
+ const index = animation.mode === 'once' ? Math.min(Math.floor(elapsedMs / duration), count - 1) : Math.floor(elapsedMs / duration) % count;
34
+ return animation.frames[index] ?? animation.frames[0] ?? clip;
35
+ }
36
+ export function GameSprite({
37
+ scene,
38
+ commit,
39
+ alpha,
40
+ source,
41
+ anchor,
42
+ select
43
+ }) {
44
+ const selection = useDerivedValue(() => {
45
+ 'worklet';
46
+
47
+ const envelope = commit.value;
48
+ if (envelope.scene !== scene) {
49
+ return undefined;
50
+ }
51
+ const current = envelope.current;
52
+ if (current === undefined) {
53
+ // The frame has not been seeded for this session yet (session swap on
54
+ // the persistent surface): present nothing until the first commit.
55
+ return undefined;
56
+ }
57
+ const context = {
58
+ // The first commit has no previous snapshot; the current one stands in
59
+ // so the initial presentation interpolates from itself (alpha 0).
60
+ previous: envelope.previous ?? envelope.current,
61
+ current,
62
+ alpha: alpha.value
63
+ };
64
+ return select(context);
65
+ }, [commit, alpha, scene, select]);
66
+ const x = useDerivedValue(() => selection.value?.x ?? 0);
67
+ const y = useDerivedValue(() => selection.value?.y ?? 0);
68
+ const rotation = useDerivedValue(() => selection.value?.rotation ?? 0);
69
+ const scale = useDerivedValue(() => selection.value?.scale ?? 1);
70
+ const opacity = useDerivedValue(() => selection.value?.opacity ?? 1);
71
+ const flipX = useDerivedValue(() => selection.value?.flipX ?? false);
72
+ const flipY = useDerivedValue(() => selection.value?.flipY ?? false);
73
+ const visible = useDerivedValue(() => selection.value?.visible ?? true);
74
+ const frameName = useDerivedValue(() => {
75
+ 'worklet';
76
+
77
+ const selectionValue = selection.value;
78
+ if (selectionValue === undefined) {
79
+ return undefined;
80
+ }
81
+ if (selectionValue.frame !== undefined) {
82
+ return selectionValue.frame;
83
+ }
84
+ if (selectionValue.clip === undefined) {
85
+ return undefined;
86
+ }
87
+ if (source.descriptor.kind !== 'sprite-sheet') {
88
+ return undefined;
89
+ }
90
+ // R3: the sampler reads the descriptor's animation table (clips), never
91
+ // the frame-rectangle map; the returned frame name is resolved against
92
+ // the frame rectangles in the Sprite's rect modifier.
93
+ const sheet = source;
94
+ return spriteFrameNameForClip(sheet.descriptor.animations, selectionValue.clip, selectionValue.elapsedMs ?? 0);
95
+ });
96
+ const animated = {
97
+ x: x,
98
+ y: y,
99
+ rotation: rotation,
100
+ scale: scale,
101
+ opacity: opacity,
102
+ flipX: flipX,
103
+ flipY: flipY,
104
+ visible: visible
105
+ };
106
+ const props = {
107
+ source,
108
+ frame: source.descriptor.kind === 'sprite-sheet' ? frameName : undefined,
109
+ anchor,
110
+ ...animated
111
+ };
112
+ return /*#__PURE__*/_jsx(Sprite, {
113
+ ...props
114
+ });
115
+ }
116
+ //# sourceMappingURL=GameSprite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useDerivedValue","Sprite","jsx","_jsx","spriteFrameNameForClip","animations","clip","elapsedMs","animation","undefined","frames","length","duration","frameDurationMs","count","index","mode","Math","min","floor","GameSprite","scene","commit","alpha","source","anchor","select","selection","envelope","value","current","context","previous","x","y","rotation","scale","opacity","flipX","flipY","visible","frameName","selectionValue","frame","descriptor","kind","sheet","animated","props"],"sourceRoot":"../../../../src","sources":["react/sprites/GameSprite.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * `GameWorld2D` — the viewport transform group (T7.6).
5
+ *
6
+ * Applies the resolved viewport offset/scale exactly once to all child
7
+ * sprites. It adds no camera state, subscribes no React per frame, and is
8
+ * not a camera API. Raw Skia nodes may be nested inside.
9
+ */
10
+
11
+ import { Group } from '@shopify/react-native-skia';
12
+ import { useDerivedValue } from 'react-native-reanimated';
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ /**
15
+ * The viewport transform as a Skia element list:
16
+ * `T(offset) · S(scale)` — logical units map to surface points.
17
+ */
18
+ export function viewportTransform(viewport) {
19
+ 'worklet';
20
+
21
+ if (viewport === undefined) {
22
+ return [];
23
+ }
24
+ return [{
25
+ translateX: viewport.offsetX
26
+ }, {
27
+ translateY: viewport.offsetY
28
+ }, {
29
+ scaleX: viewport.scale
30
+ }, {
31
+ scaleY: viewport.scale
32
+ }];
33
+ }
34
+ export function GameWorld2D({
35
+ viewport,
36
+ children
37
+ }) {
38
+ const transform = useDerivedValue(() => viewportTransform(viewport.value));
39
+ return /*#__PURE__*/_jsx(Group, {
40
+ transform: transform,
41
+ children: children
42
+ });
43
+ }
44
+ //# sourceMappingURL=GameWorld2D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Group","useDerivedValue","jsx","_jsx","viewportTransform","viewport","undefined","translateX","offsetX","translateY","offsetY","scaleX","scale","scaleY","GameWorld2D","children","transform","value"],"sourceRoot":"../../../../src","sources":["react/sprites/GameWorld2D.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,KAAK,QAAQ,4BAA4B;AAClD,SAASC,eAAe,QAA0B,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAI5E;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAACC,QAAwC,EAKtE;EACF,SAAS;;EACT,IAAIA,QAAQ,KAAKC,SAAS,EAAE;IAC1B,OAAO,EAAE;EACX;EACA,OAAO,CACL;IAAEC,UAAU,EAAEF,QAAQ,CAACG;EAAQ,CAAC,EAChC;IAAEC,UAAU,EAAEJ,QAAQ,CAACK;EAAQ,CAAC,EAChC;IAAEC,MAAM,EAAEN,QAAQ,CAACO;EAAM,CAAC,EAC1B;IAAEC,MAAM,EAAER,QAAQ,CAACO;EAAM,CAAC,CAC3B;AACH;AAEA,OAAO,SAASE,WAAWA,CAAC;EAC1BT,QAAQ;EACRU;AAKF,CAAC,EAAE;EACD,MAAMC,SAAS,GAAGf,eAAe,CAAC,MAAMG,iBAAiB,CAACC,QAAQ,CAACY,KAAK,CAAC,CAAC;EAC1E,oBAAOd,IAAA,CAACH,KAAK;IAACgB,SAAS,EAAEA,SAAmB;IAAAD,QAAA,EAAEA;EAAQ,CAAQ,CAAC;AACjE","ignoreList":[]}
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * `Sprite` — the retained sprite primitive (T7.6).
5
+ *
6
+ * Renders one full-image sprite or one sprite-sheet frame through a
7
+ * source-verified Skia path: full images use `<Image>`; sheet frames use a
8
+ * single-entry Atlas (the RSXform carries rotation + position, a wrapping
9
+ * Group applies the scale/flip part around the anchor). All animatable
10
+ * properties accept plain numbers or Reanimated shared/derived values
11
+ * without mirroring them through React state. Drawing order is React child
12
+ * order. The sprite never subscribes React to the game frame.
13
+ */
14
+ import { useMemo } from 'react';
15
+ import { Atlas, Group } from '@shopify/react-native-skia';
16
+ import { useDerivedValue } from 'react-native-reanimated';
17
+ import { useRectBuffer, useRSXformBuffer } from '@shopify/react-native-skia';
18
+ import { computeSpriteRsxform, resolveSpriteFrameRect, spriteGroupCorrection } from "./spriteTransform.js";
19
+ import { jsx as _jsx } from "react/jsx-runtime";
20
+ export { resolveSpriteFrameRect } from "./spriteTransform.js";
21
+ export function Sprite({
22
+ source,
23
+ frame,
24
+ clip,
25
+ elapsedMs = 0,
26
+ x = 0,
27
+ y = 0,
28
+ rotation = 0,
29
+ scale = 1,
30
+ anchor = {
31
+ x: 0,
32
+ y: 0
33
+ },
34
+ flipX = false,
35
+ flipY = false,
36
+ opacity = 1,
37
+ tint,
38
+ sampling,
39
+ visible = true
40
+ }) {
41
+ const image = source.image;
42
+
43
+ // Worklet-safe frame resolution: an explicit `frame` wins; otherwise the
44
+ // clip + elapsed time select the frame (the clip/elapsed may be animated
45
+ // shared values, so the resolution happens inside the rect modifier).
46
+ const resolveFrameRectWorklet = rect => {
47
+ 'worklet';
48
+
49
+ const clipValue = typeof clip === 'string' ? clip : clip?.value;
50
+ const elapsedValue = typeof elapsedMs === 'number' ? elapsedMs : elapsedMs?.value;
51
+ let name = typeof frame === 'string' ? frame : frame?.value;
52
+ if (name === undefined && source.descriptor.kind === 'sprite-sheet' && clipValue !== undefined) {
53
+ const sheet = source;
54
+ // R3: resolve the clip through the descriptor's animation table, then
55
+ // the returned frame name through the frame rectangles below.
56
+ const animation = sheet.descriptor.animations[clipValue];
57
+ if (animation !== undefined && animation.frames.length > 0) {
58
+ const duration = animation.frameDurationMs;
59
+ const count = animation.frames.length;
60
+ const index = animation.mode === 'once' ? Math.min(Math.floor((elapsedValue ?? 0) / duration), count - 1) : Math.floor((elapsedValue ?? 0) / duration) % count;
61
+ name = animation.frames[index] ?? animation.frames[0];
62
+ }
63
+ }
64
+ const frameRect = source.descriptor.kind === 'image' ? {
65
+ x: 0,
66
+ y: 0,
67
+ width: source.width,
68
+ height: source.height
69
+ } : name === undefined ? undefined : source.frames[name];
70
+ if (frameRect === undefined) {
71
+ if (name === undefined) {
72
+ // RF4: the selection has not been published yet (scene mismatch or a
73
+ // shared frame before its first value): present nothing, never throw.
74
+ rect.setXYWH(0, 0, 0, 0);
75
+ return;
76
+ }
77
+ throw new Error(`frame ${JSON.stringify(name)} does not belong to this sprite sheet (loaded frames: ${Object.keys(source.frames).join(', ')})`);
78
+ }
79
+ rect.setXYWH(frameRect.x, frameRect.y, frameRect.width, frameRect.height);
80
+ };
81
+ const staticFrame = typeof frame === 'string' ? frame : undefined;
82
+ const frameSize = useMemo(() => resolveSpriteFrameRect(source, staticFrame), [source, staticFrame]);
83
+ const input = {
84
+ x,
85
+ y,
86
+ rotation,
87
+ scale,
88
+ flipX,
89
+ flipY,
90
+ anchorX: anchor.x,
91
+ anchorY: anchor.y,
92
+ frameWidth: frameSize.width,
93
+ frameHeight: frameSize.height
94
+ };
95
+ const rects = useRectBuffer(1, resolveFrameRectWorklet);
96
+ const xforms = useRSXformBuffer(1, xform => {
97
+ 'worklet';
98
+
99
+ // RF4: resolve the selected frame's rectangle and dimensions in the same
100
+ // worklet update so the anchor math always uses the current frame size.
101
+ const name = typeof frame === 'string' ? frame : frame?.value;
102
+ let width = frameSize.width;
103
+ let height = frameSize.height;
104
+ if (name !== undefined && source.descriptor.kind === 'sprite-sheet') {
105
+ const rect = source.frames[name];
106
+ if (rect !== undefined) {
107
+ width = rect.width;
108
+ height = rect.height;
109
+ }
110
+ }
111
+ const result = computeSpriteRsxform({
112
+ ...input,
113
+ frameWidth: width,
114
+ frameHeight: height
115
+ });
116
+ xform.set(result.scos, result.ssin, result.tx, result.ty);
117
+ });
118
+ const groupTransform = useMemo(() => spriteGroupCorrection(input),
119
+ // The correction reads animated values at draw time; the element list
120
+ // identity is stable (values are shared-value reads inside the group).
121
+ [anchor.x, anchor.y, frameSize.width, frameSize.height]);
122
+ const colors = useMemo(() => tint === undefined ? undefined : [tint], [tint]);
123
+
124
+ // The Skia Group has no `visible` prop: hiding is expressed as a combined
125
+ // opacity so the component stays mounted (topology is never remounted per
126
+ // frame) while the draw is fully transparent. RF4: derived on the UI
127
+ // runtime for every static/shared combination of opacity and visible.
128
+ const effectiveOpacity = useDerivedValue(() => {
129
+ 'worklet';
130
+
131
+ const o = typeof opacity === 'number' ? opacity : opacity.value;
132
+ const v = typeof visible === 'boolean' ? visible : visible.value;
133
+ return v ? o : 0;
134
+ }, [opacity, visible]);
135
+ return /*#__PURE__*/_jsx(Group, {
136
+ transform: groupTransform,
137
+ opacity: effectiveOpacity,
138
+ children: /*#__PURE__*/_jsx(Atlas, {
139
+ image: image,
140
+ sprites: rects,
141
+ transforms: xforms,
142
+ colors: colors,
143
+ sampling: sampling ?? 'nearest'
144
+ })
145
+ });
146
+ }
147
+ //# sourceMappingURL=Sprite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useMemo","Atlas","Group","useDerivedValue","useRectBuffer","useRSXformBuffer","computeSpriteRsxform","resolveSpriteFrameRect","spriteGroupCorrection","jsx","_jsx","Sprite","source","frame","clip","elapsedMs","x","y","rotation","scale","anchor","flipX","flipY","opacity","tint","sampling","visible","image","resolveFrameRectWorklet","rect","clipValue","value","elapsedValue","name","undefined","descriptor","kind","sheet","animation","animations","frames","length","duration","frameDurationMs","count","index","mode","Math","min","floor","frameRect","width","height","setXYWH","Error","JSON","stringify","Object","keys","join","staticFrame","frameSize","input","anchorX","anchorY","frameWidth","frameHeight","rects","xforms","xform","result","set","scos","ssin","tx","ty","groupTransform","colors","effectiveOpacity","o","v","transform","children","sprites","transforms"],"sourceRoot":"../../../../src","sources":["react/sprites/Sprite.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SAASC,KAAK,EAAEC,KAAK,QAA4C,4BAA4B;AAC7F,SAASC,eAAe,QAA0B,yBAAyB;AAC3E,SAASC,aAAa,EAAEC,gBAAgB,QAAQ,4BAA4B;AAG5E,SACEC,oBAAoB,EACpBC,sBAAsB,EACtBC,qBAAqB,QAEhB,sBAAmB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAE3B,SAASH,sBAAsB,QAA8B,sBAAmB;AAsChF,OAAO,SAASI,MAAMA,CAAC;EACrBC,MAAM;EACNC,KAAK;EACLC,IAAI;EACJC,SAAS,GAAG,CAAC;EACbC,CAAC,GAAG,CAAC;EACLC,CAAC,GAAG,CAAC;EACLC,QAAQ,GAAG,CAAC;EACZC,KAAK,GAAG,CAAC;EACTC,MAAM,GAAG;IAAEJ,CAAC,EAAE,CAAC;IAAEC,CAAC,EAAE;EAAE,CAAC;EACvBI,KAAK,GAAG,KAAK;EACbC,KAAK,GAAG,KAAK;EACbC,OAAO,GAAG,CAAC;EACXC,IAAI;EACJC,QAAQ;EACRC,OAAO,GAAG;AACC,CAAC,EAAE;EACd,MAAMC,KAAK,GAAGf,MAAM,CAACe,KAAgB;;EAErC;EACA;EACA;EACA,MAAMC,uBAAuB,GAC3BC,IAA4E,IACnE;IACT,SAAS;;IACT,MAAMC,SAAS,GAAG,OAAOhB,IAAI,KAAK,QAAQ,GAAGA,IAAI,GAAGA,IAAI,EAAEiB,KAAK;IAC/D,MAAMC,YAAY,GAAG,OAAOjB,SAAS,KAAK,QAAQ,GAAGA,SAAS,GAAGA,SAAS,EAAEgB,KAAK;IACjF,IAAIE,IAAwB,GAAG,OAAOpB,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAGA,KAAK,EAAEkB,KAAK;IAC/E,IAAIE,IAAI,KAAKC,SAAS,IAAItB,MAAM,CAACuB,UAAU,CAACC,IAAI,KAAK,cAAc,IAAIN,SAAS,KAAKI,SAAS,EAAE;MAC9F,MAAMG,KAAK,GAAGzB,MAA2B;MACzC;MACA;MACA,MAAM0B,SAAS,GAAGD,KAAK,CAACF,UAAU,CAACI,UAAU,CAACT,SAAS,CAAC;MACxD,IAAIQ,SAAS,KAAKJ,SAAS,IAAII,SAAS,CAACE,MAAM,CAACC,MAAM,GAAG,CAAC,EAAE;QAC1D,MAAMC,QAAQ,GAAGJ,SAAS,CAACK,eAAe;QAC1C,MAAMC,KAAK,GAAGN,SAAS,CAACE,MAAM,CAACC,MAAM;QACrC,MAAMI,KAAK,GACTP,SAAS,CAACQ,IAAI,KAAK,MAAM,GACrBC,IAAI,CAACC,GAAG,CAACD,IAAI,CAACE,KAAK,CAAC,CAACjB,YAAY,IAAI,CAAC,IAAIU,QAAQ,CAAC,EAAEE,KAAK,GAAG,CAAC,CAAC,GAC/DG,IAAI,CAACE,KAAK,CAAC,CAACjB,YAAY,IAAI,CAAC,IAAIU,QAAQ,CAAC,GAAGE,KAAK;QACxDX,IAAI,GAAGK,SAAS,CAACE,MAAM,CAACK,KAAK,CAAC,IAAIP,SAAS,CAACE,MAAM,CAAC,CAAC,CAAC;MACvD;IACF;IACA,MAAMU,SAAS,GACbtC,MAAM,CAACuB,UAAU,CAACC,IAAI,KAAK,OAAO,GAC9B;MAAEpB,CAAC,EAAE,CAAC;MAAEC,CAAC,EAAE,CAAC;MAAEkC,KAAK,EAAGvC,MAAM,CAAiBuC,KAAK;MAAEC,MAAM,EAAGxC,MAAM,CAAiBwC;IAAO,CAAC,GAC5FnB,IAAI,KAAKC,SAAS,GAChBA,SAAS,GACRtB,MAAM,CAAuB4B,MAAM,CAACP,IAAI,CAAC;IAClD,IAAIiB,SAAS,KAAKhB,SAAS,EAAE;MAC3B,IAAID,IAAI,KAAKC,SAAS,EAAE;QACtB;QACA;QACAL,IAAI,CAACwB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACxB;MACF;MACA,MAAM,IAAIC,KAAK,CACb,SAASC,IAAI,CAACC,SAAS,CAACvB,IAAI,CAAC,yDAAyDwB,MAAM,CAACC,IAAI,CAAE9C,MAAM,CAAuB4B,MAAM,CAAC,CAACmB,IAAI,CAAC,IAAI,CAAC,GACpJ,CAAC;IACH;IACA9B,IAAI,CAACwB,OAAO,CAACH,SAAS,CAAClC,CAAC,EAAEkC,SAAS,CAACjC,CAAC,EAAEiC,SAAS,CAACC,KAAK,EAAED,SAAS,CAACE,MAAM,CAAC;EAC3E,CAAC;EAED,MAAMQ,WAAW,GAAG,OAAO/C,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAGqB,SAAS;EACjE,MAAM2B,SAAS,GAAG7D,OAAO,CAAC,MAAMO,sBAAsB,CAACK,MAAM,EAAEgD,WAAW,CAAC,EAAE,CAAChD,MAAM,EAAEgD,WAAW,CAAC,CAAC;EACnG,MAAME,KAA2B,GAAG;IAClC9C,CAAC;IACDC,CAAC;IACDC,QAAQ;IACRC,KAAK;IACLE,KAAK;IACLC,KAAK;IACLyC,OAAO,EAAE3C,MAAM,CAACJ,CAAC;IACjBgD,OAAO,EAAE5C,MAAM,CAACH,CAAC;IACjBgD,UAAU,EAAEJ,SAAS,CAACV,KAAK;IAC3Be,WAAW,EAAEL,SAAS,CAACT;EACzB,CAAC;EAED,MAAMe,KAAK,GAAG/D,aAAa,CAAC,CAAC,EAAEwB,uBAAuB,CAAC;EACvD,MAAMwC,MAAM,GAAG/D,gBAAgB,CAAC,CAAC,EAAGgE,KAAK,IAAK;IAC5C,SAAS;;IACT;IACA;IACA,MAAMpC,IAAI,GAAG,OAAOpB,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAGA,KAAK,EAAEkB,KAAK;IAC7D,IAAIoB,KAAK,GAAGU,SAAS,CAACV,KAAK;IAC3B,IAAIC,MAAM,GAAGS,SAAS,CAACT,MAAM;IAC7B,IAAInB,IAAI,KAAKC,SAAS,IAAItB,MAAM,CAACuB,UAAU,CAACC,IAAI,KAAK,cAAc,EAAE;MACnE,MAAMP,IAAI,GAAIjB,MAAM,CAAuB4B,MAAM,CAACP,IAAI,CAAC;MACvD,IAAIJ,IAAI,KAAKK,SAAS,EAAE;QACtBiB,KAAK,GAAGtB,IAAI,CAACsB,KAAK;QAClBC,MAAM,GAAGvB,IAAI,CAACuB,MAAM;MACtB;IACF;IACA,MAAMkB,MAAM,GAAGhE,oBAAoB,CAAC;MAClC,GAAGwD,KAAK;MACRG,UAAU,EAAEd,KAAK;MACjBe,WAAW,EAAEd;IACf,CAAC,CAAC;IACFiB,KAAK,CAACE,GAAG,CAACD,MAAM,CAACE,IAAI,EAAEF,MAAM,CAACG,IAAI,EAAEH,MAAM,CAACI,EAAE,EAAEJ,MAAM,CAACK,EAAE,CAAC;EAC3D,CAAC,CAAC;EACF,MAAMC,cAAc,GAAG5E,OAAO,CAC5B,MAAMQ,qBAAqB,CAACsD,KAAK,CAAwD;EACzF;EACA;EACA,CAAC1C,MAAM,CAACJ,CAAC,EAAEI,MAAM,CAACH,CAAC,EAAE4C,SAAS,CAACV,KAAK,EAAEU,SAAS,CAACT,MAAM,CACxD,CAAC;EACD,MAAMyB,MAAM,GAAG7E,OAAO,CAAC,MAAOwB,IAAI,KAAKU,SAAS,GAAGA,SAAS,GAAG,CAACV,IAAI,CAAE,EAAE,CAACA,IAAI,CAAC,CAAC;;EAE/E;EACA;EACA;EACA;EACA,MAAMsD,gBAAgB,GAAG3E,eAAe,CAAC,MAAM;IAC7C,SAAS;;IACT,MAAM4E,CAAC,GAAG,OAAOxD,OAAO,KAAK,QAAQ,GAAGA,OAAO,GAAGA,OAAO,CAACQ,KAAK;IAC/D,MAAMiD,CAAC,GAAG,OAAOtD,OAAO,KAAK,SAAS,GAAGA,OAAO,GAAGA,OAAO,CAACK,KAAK;IAChE,OAAOiD,CAAC,GAAGD,CAAC,GAAG,CAAC;EAClB,CAAC,EAAE,CAACxD,OAAO,EAAEG,OAAO,CAAC,CAAC;EAEtB,oBACEhB,IAAA,CAACR,KAAK;IAAC+E,SAAS,EAAEL,cAAwB;IAACrD,OAAO,EAAEuD,gBAAiB;IAAAI,QAAA,eACnExE,IAAA,CAACT,KAAK;MACJ0B,KAAK,EAAEA,KAAM;MACbwD,OAAO,EAAEhB,KAAM;MACfiB,UAAU,EAAEhB,MAAO;MACnBS,MAAM,EAAEA,MAAgB;MACxBpD,QAAQ,EAAGA,QAAQ,IAAI;IAAoB,CAC5C;EAAC,CACG,CAAC;AAEZ","ignoreList":[]}
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * `SpriteBatch` — the Atlas-backed shared-texture batch (T7.7).
5
+ *
6
+ * Draws many instances of one decoded sprite-sheet image through Skia's
7
+ * `Atlas` with fixed-capacity, UI-owned buffers. The normal path owns all
8
+ * derived-value plumbing: `select` maps the committed snapshot to the item
9
+ * array and `write` is a UI-runtime setter that writes transforms in place —
10
+ * no per-frame allocation, no per-frame React, no author-written
11
+ * `useDerivedValue` side effects.
12
+ *
13
+ * Contract:
14
+ * - `capacity` is fixed for the mounted batch; active count is explicit.
15
+ * - Writes past capacity are rejected in development; inactive slots are
16
+ * hidden (zero-size) and never remount topology.
17
+ * - Item order is the drawing order; the anchor is uniform per batch.
18
+ * - The batch never disposes the image (the asset lease owns it).
19
+ */
20
+ import { useMemo } from 'react';
21
+ import { Atlas } from '@shopify/react-native-skia';
22
+ import { useDerivedValue } from 'react-native-reanimated';
23
+ import { useRectBuffer, useRSXformBuffer } from '@shopify/react-native-skia';
24
+ import { computeSpriteRsxform } from "./spriteTransform.js";
25
+ import { batchUpdatePolicy } from "./spriteBatchPolicy.js";
26
+
27
+ /** The per-item write surface handed to the author's `write` mapper. */
28
+ import { jsx as _jsx } from "react/jsx-runtime";
29
+ function frameRectOf(source, frame) {
30
+ 'worklet';
31
+
32
+ if (source.descriptor.kind === 'image') {
33
+ const image = source;
34
+ return {
35
+ x: 0,
36
+ y: 0,
37
+ width: image.width,
38
+ height: image.height
39
+ };
40
+ }
41
+ return source.frames[frame];
42
+ }
43
+ export function SpriteBatch({
44
+ scene,
45
+ commit,
46
+ alpha,
47
+ source,
48
+ capacity,
49
+ select,
50
+ write,
51
+ anchor = {
52
+ x: 0,
53
+ y: 0
54
+ }
55
+ }) {
56
+ const image = source.image;
57
+ if (!Number.isInteger(capacity) || capacity <= 0) {
58
+ throw new Error(`SpriteBatch capacity must be a positive integer, got ${String(capacity)}`);
59
+ }
60
+ const rects = useRectBuffer(capacity, rect => {
61
+ 'worklet';
62
+
63
+ rect.setXYWH(0, 0, 0, 0);
64
+ });
65
+ const xforms = useRSXformBuffer(capacity, xform => {
66
+ 'worklet';
67
+
68
+ xform.set(1, 0, 0, 0);
69
+ });
70
+
71
+ // R7: one stable write coordinator for the batch lifetime; the per-update
72
+ // worklet only calls it (no per-frame coordinator allocation).
73
+ const writeApi = useMemo(() => ({
74
+ set: (index, frame, x, y, rotation, scale, visible = true) => {
75
+ 'worklet';
76
+
77
+ if (index < 0 || index >= capacity) {
78
+ throw new Error(`SpriteBatch write index ${index} is outside the capacity ${capacity}`);
79
+ }
80
+ const rectSlot = rects.value[index];
81
+ const xformSlot = xforms.value[index];
82
+ if (rectSlot === undefined || xformSlot === undefined) {
83
+ return;
84
+ }
85
+ if (!visible) {
86
+ rectSlot.setXYWH(0, 0, 0, 0);
87
+ return;
88
+ }
89
+ const rect = frameRectOf(source, frame);
90
+ if (rect === undefined) {
91
+ throw new Error(`frame ${JSON.stringify(frame)} does not belong to this sprite sheet`);
92
+ }
93
+ rectSlot.setXYWH(rect.x, rect.y, rect.width, rect.height);
94
+ const rsxform = computeSpriteRsxform({
95
+ x,
96
+ y,
97
+ rotation,
98
+ scale,
99
+ flipX: false,
100
+ flipY: false,
101
+ anchorX: anchor.x,
102
+ anchorY: anchor.y,
103
+ frameWidth: rect.width,
104
+ frameHeight: rect.height
105
+ });
106
+ xformSlot.set(rsxform.scos, rsxform.ssin, rsxform.tx, rsxform.ty);
107
+ }
108
+ }),
109
+ // The buffers, source, and anchor are stable for the mounted batch.
110
+ [capacity, rects, xforms, source, anchor.x, anchor.y]);
111
+
112
+ // The batch's own UI mapper: one derived value reads the committed
113
+ // snapshot, runs the author's select + write per item, and reports the
114
+ // active count. Buffers are mutated in place; no objects are allocated
115
+ // per item per frame beyond the item array the select returns.
116
+ const activeCount = useDerivedValue(() => {
117
+ 'worklet';
118
+
119
+ const envelope = commit.value;
120
+ if (envelope.scene !== scene) {
121
+ // RF8: leaving the scene clears every previously active slot so no
122
+ // stale sprite from the old scene stays visible.
123
+ for (let index = 0; index < capacity; index += 1) {
124
+ const slot = rects.value[index];
125
+ if (slot !== undefined) {
126
+ slot.setXYWH(0, 0, 0, 0);
127
+ }
128
+ }
129
+ return 0;
130
+ }
131
+ const items = select({
132
+ current: envelope.current,
133
+ alpha: alpha.value
134
+ });
135
+ const policy = batchUpdatePolicy(items.length, capacity, __DEV__);
136
+ if (policy.overflow) {
137
+ // RF8: production never crashes the UI runtime for ordinary data
138
+ // growth: hide the overflowing items.
139
+ for (let index = capacity; index < items.length; index += 1) {
140
+ const slot = rects.value[index];
141
+ if (slot !== undefined) {
142
+ slot.setXYWH(0, 0, 0, 0);
143
+ }
144
+ }
145
+ }
146
+ const count = policy.activeCount;
147
+ for (let index = 0; index < items.length; index += 1) {
148
+ const item = items[index];
149
+ if (item !== undefined) {
150
+ write(writeApi, item, index);
151
+ }
152
+ }
153
+ // Hide every inactive slot.
154
+ for (let index = count; index < capacity; index += 1) {
155
+ const slot = rects.value[index];
156
+ if (slot !== undefined) {
157
+ slot.setXYWH(0, 0, 0, 0);
158
+ }
159
+ }
160
+ return count;
161
+ }, [commit, alpha, scene, select, write, writeApi]);
162
+ void activeCount;
163
+
164
+ // The atlas renders the full buffer; the UI mapper keeps slots aligned.
165
+ const sampling = useMemo(() => 'nearest', []);
166
+ return /*#__PURE__*/_jsx(Atlas, {
167
+ image: image,
168
+ sprites: rects,
169
+ transforms: xforms,
170
+ sampling: sampling
171
+ });
172
+ }
173
+ //# sourceMappingURL=SpriteBatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useMemo","Atlas","useDerivedValue","useRectBuffer","useRSXformBuffer","computeSpriteRsxform","batchUpdatePolicy","jsx","_jsx","frameRectOf","source","frame","descriptor","kind","image","x","y","width","height","frames","SpriteBatch","scene","commit","alpha","capacity","select","write","anchor","Number","isInteger","Error","String","rects","rect","setXYWH","xforms","xform","set","writeApi","index","rotation","scale","visible","rectSlot","value","xformSlot","undefined","JSON","stringify","rsxform","flipX","flipY","anchorX","anchorY","frameWidth","frameHeight","scos","ssin","tx","ty","activeCount","envelope","slot","items","current","policy","length","__DEV__","overflow","count","item","sampling","sprites","transforms"],"sourceRoot":"../../../../src","sources":["react/sprites/SpriteBatch.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ /** Pure SpriteBatch update policy (RF8): the overflow decision and the
4
+ * active count. Development reports a structured error; production clamps
5
+ * and hides the overflow so the UI runtime never crashes for ordinary data
6
+ * growth. Runs inside the batch's update worklet, so it carries the worklet
7
+ * directive. */
8
+ export function batchUpdatePolicy(itemsCount, capacity, dev) {
9
+ 'worklet';
10
+
11
+ if (itemsCount <= capacity) {
12
+ return {
13
+ overflow: false,
14
+ activeCount: itemsCount
15
+ };
16
+ }
17
+ if (dev) {
18
+ throw new Error(`SpriteBatch overflow: ${itemsCount} items selected with capacity ${capacity}`);
19
+ }
20
+ return {
21
+ overflow: true,
22
+ activeCount: capacity
23
+ };
24
+ }
25
+ //# sourceMappingURL=spriteBatchPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["batchUpdatePolicy","itemsCount","capacity","dev","overflow","activeCount","Error"],"sourceRoot":"../../../../src","sources":["react/sprites/spriteBatchPolicy.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,iBAAiBA,CAC/BC,UAAkB,EAClBC,QAAgB,EAChBC,GAAY,EACkD;EAC9D,SAAS;;EACT,IAAIF,UAAU,IAAIC,QAAQ,EAAE;IAC1B,OAAO;MAAEE,QAAQ,EAAE,KAAK;MAAEC,WAAW,EAAEJ;IAAW,CAAC;EACrD;EACA,IAAIE,GAAG,EAAE;IACP,MAAM,IAAIG,KAAK,CACb,yBAAyBL,UAAU,iCAAiCC,QAAQ,EAC9E,CAAC;EACH;EACA,OAAO;IAAEE,QAAQ,EAAE,IAAI;IAAEC,WAAW,EAAEH;EAAS,CAAC;AAClD","ignoreList":[]}