@expofp/renderer 0.0.0-experimental.2d6c681

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 (280) hide show
  1. package/README.md +145 -0
  2. package/dist/Renderer.d.ts +102 -0
  3. package/dist/Renderer.js +96 -0
  4. package/dist/controls/CameraControls.d.ts +108 -0
  5. package/dist/controls/CameraControls.js +203 -0
  6. package/dist/controls/Controls.d.ts +53 -0
  7. package/dist/controls/Controls.js +54 -0
  8. package/dist/controls/camera-api.d.ts +226 -0
  9. package/dist/controls/camera-api.js +179 -0
  10. package/dist/controls/gestures.d.ts +71 -0
  11. package/dist/controls/gestures.js +98 -0
  12. package/dist/controls/handlers/DoubleTapZoom.d.ts +23 -0
  13. package/dist/controls/handlers/DoubleTapZoom.js +82 -0
  14. package/dist/controls/handlers/Inertia.d.ts +60 -0
  15. package/dist/controls/handlers/Inertia.js +222 -0
  16. package/dist/controls/handlers/Pan.d.ts +23 -0
  17. package/dist/controls/handlers/Pan.js +212 -0
  18. package/dist/controls/handlers/Pitch.d.ts +19 -0
  19. package/dist/controls/handlers/Pitch.js +200 -0
  20. package/dist/controls/handlers/Roll.d.ts +30 -0
  21. package/dist/controls/handlers/Roll.js +196 -0
  22. package/dist/controls/handlers/Zoom.d.ts +28 -0
  23. package/dist/controls/handlers/Zoom.js +34 -0
  24. package/dist/controls/hooks.d.ts +136 -0
  25. package/dist/controls/hooks.js +200 -0
  26. package/dist/controls/index.d.ts +9 -0
  27. package/dist/controls/index.js +7 -0
  28. package/dist/controls/zoom-to.d.ts +89 -0
  29. package/dist/controls/zoom-to.js +91 -0
  30. package/dist/core/InstanceUniforms.d.ts +108 -0
  31. package/dist/core/InstanceUniforms.js +298 -0
  32. package/dist/core/SquareDataTexture.d.ts +277 -0
  33. package/dist/core/SquareDataTexture.js +476 -0
  34. package/dist/core/batch/BatchedMesh.d.ts +74 -0
  35. package/dist/core/batch/BatchedMesh.js +155 -0
  36. package/dist/core/instanced/FrustumCulling.d.ts +141 -0
  37. package/dist/core/instanced/FrustumCulling.js +246 -0
  38. package/dist/core/instanced/InstancedMesh.d.ts +302 -0
  39. package/dist/core/instanced/InstancedMesh.js +497 -0
  40. package/dist/core/instanced/Instances.d.ts +119 -0
  41. package/dist/core/instanced/Instances.js +230 -0
  42. package/dist/core/instanced/Raycasting.d.ts +118 -0
  43. package/dist/core/instanced/Raycasting.js +134 -0
  44. package/dist/core/instanced/instanced-material.d.ts +77 -0
  45. package/dist/core/instanced/instanced-material.js +228 -0
  46. package/dist/core/lines/BatchedLines.d.ts +137 -0
  47. package/dist/core/lines/BatchedLines.js +215 -0
  48. package/dist/core/lines/FrustumCullingLines.d.ts +44 -0
  49. package/dist/core/lines/FrustumCullingLines.js +85 -0
  50. package/dist/core/lines/RaycastingLines.d.ts +45 -0
  51. package/dist/core/lines/RaycastingLines.js +91 -0
  52. package/dist/core/lines/lines-material.d.ts +47 -0
  53. package/dist/core/lines/lines-material.js +124 -0
  54. package/dist/core/shader-source.d.ts +70 -0
  55. package/dist/core/shader-source.js +110 -0
  56. package/dist/core/sprites/BatchedSprites.d.ts +115 -0
  57. package/dist/core/sprites/BatchedSprites.js +173 -0
  58. package/dist/core/sprites/RaycastingSprites.d.ts +41 -0
  59. package/dist/core/sprites/RaycastingSprites.js +71 -0
  60. package/dist/core/sprites/sprite-material.d.ts +59 -0
  61. package/dist/core/sprites/sprite-material.js +192 -0
  62. package/dist/core/text/BatchedText.d.ts +233 -0
  63. package/dist/core/text/BatchedText.js +473 -0
  64. package/dist/core/text/MemberTexture.d.ts +90 -0
  65. package/dist/core/text/MemberTexture.js +289 -0
  66. package/dist/core/text/Text.d.ts +88 -0
  67. package/dist/core/text/Text.js +230 -0
  68. package/dist/core/text/batched-text-material.d.ts +56 -0
  69. package/dist/core/text/batched-text-material.js +123 -0
  70. package/dist/core/text/glyph-packing.d.ts +17 -0
  71. package/dist/core/text/glyph-packing.js +61 -0
  72. package/dist/core/typed-array.d.ts +16 -0
  73. package/dist/core/typed-array.js +20 -0
  74. package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
  75. package/dist/debug/components/DebugPanelProvider.js +50 -0
  76. package/dist/debug/components/DebugTools.d.ts +22 -0
  77. package/dist/debug/components/DebugTools.js +28 -0
  78. package/dist/debug/components/Gui.d.ts +22 -0
  79. package/dist/debug/components/Gui.js +42 -0
  80. package/dist/debug/components/MemoryInfo.d.ts +22 -0
  81. package/dist/debug/components/MemoryInfo.js +42 -0
  82. package/dist/debug/components/Panel.d.ts +31 -0
  83. package/dist/debug/components/Panel.js +104 -0
  84. package/dist/debug/components/Stats.d.ts +9 -0
  85. package/dist/debug/components/Stats.js +24 -0
  86. package/dist/debug/debug-chunk.d.ts +26 -0
  87. package/dist/debug/debug-chunk.js +32 -0
  88. package/dist/debug/debug-context.d.ts +41 -0
  89. package/dist/debug/debug-context.js +59 -0
  90. package/dist/debug/index.d.ts +41 -0
  91. package/dist/debug/index.js +43 -0
  92. package/dist/events/LayoutDriver.d.ts +36 -0
  93. package/dist/events/LayoutDriver.js +192 -0
  94. package/dist/events/PointerMissed.d.ts +23 -0
  95. package/dist/events/PointerMissed.js +58 -0
  96. package/dist/events/def-culling.d.ts +46 -0
  97. package/dist/events/def-culling.js +69 -0
  98. package/dist/events/layout-targets.d.ts +151 -0
  99. package/dist/events/layout-targets.js +397 -0
  100. package/dist/events/placement/box.d.ts +59 -0
  101. package/dist/events/placement/box.js +96 -0
  102. package/dist/events/placement/grid.d.ts +161 -0
  103. package/dist/events/placement/grid.js +235 -0
  104. package/dist/events/placement/index.d.ts +2 -0
  105. package/dist/events/placement/index.js +1 -0
  106. package/dist/events/placement/pass.d.ts +70 -0
  107. package/dist/events/placement/pass.js +617 -0
  108. package/dist/events/pointer.d.ts +194 -0
  109. package/dist/events/pointer.js +356 -0
  110. package/dist/external/ExternalCanvas.d.ts +56 -0
  111. package/dist/external/ExternalCanvas.js +177 -0
  112. package/dist/external/external-camera.d.ts +18 -0
  113. package/dist/external/external-camera.js +103 -0
  114. package/dist/external/external-events.d.ts +14 -0
  115. package/dist/external/external-events.js +33 -0
  116. package/dist/index.d.ts +13 -0
  117. package/dist/index.js +14 -0
  118. package/dist/objects/Background.d.ts +31 -0
  119. package/dist/objects/Background.js +37 -0
  120. package/dist/objects/containers/SlotContainer.d.ts +312 -0
  121. package/dist/objects/containers/SlotContainer.js +311 -0
  122. package/dist/objects/containers/hooks.d.ts +61 -0
  123. package/dist/objects/containers/hooks.js +196 -0
  124. package/dist/objects/containers/index.d.ts +6 -0
  125. package/dist/objects/containers/index.js +4 -0
  126. package/dist/objects/containers/keys.d.ts +10 -0
  127. package/dist/objects/containers/keys.js +18 -0
  128. package/dist/objects/containers/mesh-writes.d.ts +106 -0
  129. package/dist/objects/containers/mesh-writes.js +97 -0
  130. package/dist/objects/containers/props.d.ts +33 -0
  131. package/dist/objects/containers/props.js +1 -0
  132. package/dist/objects/images/ImageInstance.d.ts +29 -0
  133. package/dist/objects/images/ImageInstance.js +152 -0
  134. package/dist/objects/images/Images.d.ts +49 -0
  135. package/dist/objects/images/Images.js +394 -0
  136. package/dist/objects/images/atlas-packer.d.ts +129 -0
  137. package/dist/objects/images/atlas-packer.js +287 -0
  138. package/dist/objects/images/image-container.d.ts +74 -0
  139. package/dist/objects/images/image-container.js +100 -0
  140. package/dist/objects/images/index.d.ts +2 -0
  141. package/dist/objects/images/index.js +1 -0
  142. package/dist/objects/images/pack-sources.d.ts +190 -0
  143. package/dist/objects/images/pack-sources.js +272 -0
  144. package/dist/objects/images/texture-budget.d.ts +120 -0
  145. package/dist/objects/images/texture-budget.js +215 -0
  146. package/dist/objects/images/worker/atlas-worker.d.ts +56 -0
  147. package/dist/objects/images/worker/atlas-worker.js +123 -0
  148. package/dist/objects/images/worker/client.d.ts +62 -0
  149. package/dist/objects/images/worker/client.js +249 -0
  150. package/dist/objects/images/worker/index.d.ts +10 -0
  151. package/dist/objects/images/worker/index.js +1 -0
  152. package/dist/objects/layer/Layer.d.ts +28 -0
  153. package/dist/objects/layer/Layer.js +134 -0
  154. package/dist/objects/layer/index.d.ts +2 -0
  155. package/dist/objects/layer/index.js +1 -0
  156. package/dist/objects/layer/layer-context.d.ts +74 -0
  157. package/dist/objects/layer/layer-context.js +82 -0
  158. package/dist/objects/layer/mount-scheduler.d.ts +131 -0
  159. package/dist/objects/layer/mount-scheduler.js +289 -0
  160. package/dist/objects/layer/visibility-gui.d.ts +19 -0
  161. package/dist/objects/layer/visibility-gui.js +93 -0
  162. package/dist/objects/lighting/Lighting.d.ts +92 -0
  163. package/dist/objects/lighting/Lighting.js +384 -0
  164. package/dist/objects/lighting/OcclusionPasses.d.ts +23 -0
  165. package/dist/objects/lighting/OcclusionPasses.js +271 -0
  166. package/dist/objects/lighting/index.d.ts +11 -0
  167. package/dist/objects/lighting/index.js +10 -0
  168. package/dist/objects/lighting/lighting-gui.d.ts +24 -0
  169. package/dist/objects/lighting/lighting-gui.js +114 -0
  170. package/dist/objects/lighting/occluder.d.ts +34 -0
  171. package/dist/objects/lighting/occluder.js +62 -0
  172. package/dist/objects/lighting/occlusion-targets.d.ts +143 -0
  173. package/dist/objects/lighting/occlusion-targets.js +276 -0
  174. package/dist/objects/lines/LineInstance.d.ts +21 -0
  175. package/dist/objects/lines/LineInstance.js +73 -0
  176. package/dist/objects/lines/Lines.d.ts +17 -0
  177. package/dist/objects/lines/Lines.js +31 -0
  178. package/dist/objects/lines/index.d.ts +2 -0
  179. package/dist/objects/lines/index.js +1 -0
  180. package/dist/objects/lines/line-container.d.ts +35 -0
  181. package/dist/objects/lines/line-container.js +40 -0
  182. package/dist/objects/materials/ColorMaterial.d.ts +92 -0
  183. package/dist/objects/materials/ColorMaterial.js +124 -0
  184. package/dist/objects/materials/LineMaterial.d.ts +44 -0
  185. package/dist/objects/materials/LineMaterial.js +74 -0
  186. package/dist/objects/materials/ModelMaterial.d.ts +53 -0
  187. package/dist/objects/materials/ModelMaterial.js +111 -0
  188. package/dist/objects/materials/TextureMaterial.d.ts +33 -0
  189. package/dist/objects/materials/TextureMaterial.js +48 -0
  190. package/dist/objects/materials/effects/ao/ambient-occlusion-pass.d.ts +77 -0
  191. package/dist/objects/materials/effects/ao/ambient-occlusion-pass.js +296 -0
  192. package/dist/objects/materials/effects/ao/ambient-occlusion-patch.d.ts +29 -0
  193. package/dist/objects/materials/effects/ao/ambient-occlusion-patch.js +115 -0
  194. package/dist/objects/materials/effects/ao/blur-pass.d.ts +61 -0
  195. package/dist/objects/materials/effects/ao/blur-pass.js +101 -0
  196. package/dist/objects/materials/effects/ao/index.d.ts +129 -0
  197. package/dist/objects/materials/effects/ao/index.js +72 -0
  198. package/dist/objects/materials/effects/color-dim.d.ts +115 -0
  199. package/dist/objects/materials/effects/color-dim.js +206 -0
  200. package/dist/objects/materials/effects/contact-shadow.d.ts +100 -0
  201. package/dist/objects/materials/effects/contact-shadow.js +167 -0
  202. package/dist/objects/materials/effects/effects-context.d.ts +53 -0
  203. package/dist/objects/materials/effects/effects-context.js +24 -0
  204. package/dist/objects/materials/shared.d.ts +24 -0
  205. package/dist/objects/materials/shared.js +72 -0
  206. package/dist/objects/models/ModelInstance.d.ts +22 -0
  207. package/dist/objects/models/ModelInstance.js +33 -0
  208. package/dist/objects/models/Models.d.ts +22 -0
  209. package/dist/objects/models/Models.js +186 -0
  210. package/dist/objects/models/gltf-cache.d.ts +17 -0
  211. package/dist/objects/models/gltf-cache.js +50 -0
  212. package/dist/objects/models/index.d.ts +2 -0
  213. package/dist/objects/models/index.js +1 -0
  214. package/dist/objects/models/model-asset.d.ts +48 -0
  215. package/dist/objects/models/model-asset.js +77 -0
  216. package/dist/objects/models/model-container.d.ts +123 -0
  217. package/dist/objects/models/model-container.js +207 -0
  218. package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
  219. package/dist/objects/shapes/ShapeInstance.js +39 -0
  220. package/dist/objects/shapes/Shapes.d.ts +21 -0
  221. package/dist/objects/shapes/Shapes.js +131 -0
  222. package/dist/objects/shapes/index.d.ts +2 -0
  223. package/dist/objects/shapes/index.js +1 -0
  224. package/dist/objects/shapes/shape-container.d.ts +141 -0
  225. package/dist/objects/shapes/shape-container.js +242 -0
  226. package/dist/objects/shapes/shape-geometry.d.ts +27 -0
  227. package/dist/objects/shapes/shape-geometry.js +94 -0
  228. package/dist/objects/text/TextInstance.d.ts +22 -0
  229. package/dist/objects/text/TextInstance.js +95 -0
  230. package/dist/objects/text/Texts.d.ts +30 -0
  231. package/dist/objects/text/Texts.js +43 -0
  232. package/dist/objects/text/index.d.ts +2 -0
  233. package/dist/objects/text/index.js +1 -0
  234. package/dist/objects/text/text-container.d.ts +121 -0
  235. package/dist/objects/text/text-container.js +229 -0
  236. package/dist/objects/text/text-layout.d.ts +92 -0
  237. package/dist/objects/text/text-layout.js +180 -0
  238. package/dist/space/Camera.d.ts +103 -0
  239. package/dist/space/Camera.js +321 -0
  240. package/dist/space/Scene.d.ts +47 -0
  241. package/dist/space/Scene.js +127 -0
  242. package/dist/space/Space.d.ts +325 -0
  243. package/dist/space/Space.js +359 -0
  244. package/dist/space/VisibleRect.d.ts +45 -0
  245. package/dist/space/VisibleRect.js +129 -0
  246. package/dist/space/camera-handle.d.ts +67 -0
  247. package/dist/space/camera-handle.js +63 -0
  248. package/dist/space/camera-kind.d.ts +26 -0
  249. package/dist/space/camera-kind.js +30 -0
  250. package/dist/space/canvas-size.d.ts +24 -0
  251. package/dist/space/canvas-size.js +20 -0
  252. package/dist/space/clipping.d.ts +69 -0
  253. package/dist/space/clipping.js +130 -0
  254. package/dist/space/layout-measure.d.ts +67 -0
  255. package/dist/space/layout-measure.js +175 -0
  256. package/dist/space/viewport.d.ts +112 -0
  257. package/dist/space/viewport.js +67 -0
  258. package/dist/types/defs.d.ts +234 -0
  259. package/dist/types/defs.js +1 -0
  260. package/dist/types/events.d.ts +198 -0
  261. package/dist/types/events.js +1 -0
  262. package/dist/types/guards.d.ts +21 -0
  263. package/dist/types/guards.js +52 -0
  264. package/dist/update/index.d.ts +3 -0
  265. package/dist/update/index.js +2 -0
  266. package/dist/update/slot-writers.d.ts +30 -0
  267. package/dist/update/slot-writers.js +76 -0
  268. package/dist/update/store.d.ts +41 -0
  269. package/dist/update/store.js +104 -0
  270. package/dist/utils/arrays.d.ts +13 -0
  271. package/dist/utils/arrays.js +20 -0
  272. package/dist/utils/colors.d.ts +19 -0
  273. package/dist/utils/colors.js +27 -0
  274. package/dist/utils/hot-state.d.ts +41 -0
  275. package/dist/utils/hot-state.js +37 -0
  276. package/dist/utils/logging.d.ts +29 -0
  277. package/dist/utils/logging.js +55 -0
  278. package/dist/utils/math.d.ts +52 -0
  279. package/dist/utils/math.js +76 -0
  280. package/package.json +79 -0
@@ -0,0 +1,190 @@
1
+ /**
2
+ * A source that the packer can draw from without decoding it further. It is already decoded, and
3
+ * it reports its own pixel size. A `Blob` is the one image source that meets neither condition, so
4
+ * code decodes each `Blob` into one of these types before it reaches this module.
5
+ */
6
+ export type DecodedSource = ImageBitmap | HTMLCanvasElement | OffscreenCanvas;
7
+ /**
8
+ * A canvas that one atlas is drawn onto. This type includes `OffscreenCanvas`, so packing can
9
+ * later move into a worker.
10
+ */
11
+ export type AtlasCanvas = HTMLCanvasElement | OffscreenCanvas;
12
+ /**
13
+ * Creates the backing canvas for one atlas, sized to that atlas exactly.
14
+ * @param width - The atlas width in pixels.
15
+ * @param height - The atlas height in pixels.
16
+ * @returns The canvas to draw on.
17
+ */
18
+ export type CreateAtlasCanvas = (width: number, height: number) => AtlasCanvas;
19
+ /**
20
+ * A region of a source image, in **source pixels with a top-left origin**. These are the same axes
21
+ * as `ImageDef.bounds`, and they are the exact `sx, sy, sw, sh` values that the packer passes to
22
+ * `drawImage`. This type keeps pixels instead of normalized values, so code cannot mistake it for
23
+ * a {@link UvRect}, whose origin is the opposite corner.
24
+ */
25
+ export interface SourceRect {
26
+ /** Distance from the source's left edge, in pixels. */
27
+ x: number;
28
+ /** Distance from the source's top edge, in pixels. */
29
+ y: number;
30
+ /** Region width in pixels. */
31
+ width: number;
32
+ /** Region height in pixels. */
33
+ height: number;
34
+ }
35
+ /**
36
+ * A region of an atlas, **normalized in the canvas's own axes: a top-left origin, with v running
37
+ * down**.
38
+ *
39
+ * A texture with `flipY = false` consumes these values. That setting maps canvas row 0 to `v = 0`,
40
+ * so these numbers feed a uv transform directly, with no vertical inversion. This is deliberate.
41
+ * The scene already uses a y axis that points down, because it follows SVG coordinates and the
42
+ * camera matches them. A uv space that also runs down keeps every axis in the pipeline pointing
43
+ * the same way. If only one end inverts, images come out upside down.
44
+ */
45
+ export interface UvRect {
46
+ /** Left edge, `0` at the atlas's left. */
47
+ u0: number;
48
+ /** Top edge, `0` at the atlas's top. */
49
+ v0: number;
50
+ /** Right edge. */
51
+ u1: number;
52
+ /** Bottom edge. */
53
+ v1: number;
54
+ }
55
+ /**
56
+ * One source, or one tile of a split source, placed on an atlas. Each placement carries an array
57
+ * index instead of the source object as its address, because this data crosses a `postMessage`
58
+ * boundary, and object identity does not survive that boundary.
59
+ */
60
+ export interface Placement {
61
+ /** Index into the `sources` array that the caller gave {@link packSources}. */
62
+ index: number;
63
+ /** Where the pixels sit on the atlas. */
64
+ uv: UvRect;
65
+ /**
66
+ * Which part of the source this placement holds. This is undefined when the source packs
67
+ * whole, which is the common case. It is set only on the tiles of a split source.
68
+ */
69
+ source?: SourceRect;
70
+ }
71
+ /** One packed atlas, before its placements are mapped back onto the defs that wanted them. */
72
+ export interface SourceAtlas {
73
+ /** The canvas holding the packed pixels. Its `width`/`height` are the atlas's size. */
74
+ canvas: AtlasCanvas;
75
+ /** Every placement on this atlas. */
76
+ placements: Placement[];
77
+ /**
78
+ * Whether this atlas's pixels can shrink to fit a memory budget. Bitmaps pack into resizable
79
+ * atlases, canvases pack into fixed ones, and an atlas never mixes the two.
80
+ */
81
+ resizable: boolean;
82
+ }
83
+ /**
84
+ * What one source contributed to a pack. The caller holds the defs, so only the caller can warn
85
+ * about them. This report gives the caller the measurements it needs to do that.
86
+ */
87
+ export interface SourceReport {
88
+ /** The source's intrinsic width in pixels. */
89
+ width: number;
90
+ /** The source's intrinsic height in pixels. */
91
+ height: number;
92
+ /**
93
+ * How many rects this source packed into. It is `0` when the source had no pixels and code
94
+ * dropped it. It is `1` when the source packed whole. Otherwise it is the tile count, for a
95
+ * source too big for one atlas that code had to cut.
96
+ */
97
+ tiles: number;
98
+ }
99
+ /**
100
+ * Whether a source is a `Blob`, which is also true of a `File`.
101
+ *
102
+ * The test looks for `slice`, and it must keep looking for `slice`. `slice` is Chrome 21, Chrome
103
+ * Android 25, Safari 7 and iOS Safari 7, so every build target has it. `arrayBuffer` reads better
104
+ * and is wrong: it is Chrome 76 and Chrome Android 76, above this package's `chrome66` floor, so on
105
+ * the old Android WebViews it is `undefined` and every real `Blob` would fail this test and reach
106
+ * the packer undecoded (`packages/floorplan/src/components/Maplibre/utils/pmtiles-range-fallback.ts`
107
+ * works around the same floor). No other image source carries either method: not an `<img>`, a
108
+ * canvas, an offscreen canvas or a bitmap.
109
+ *
110
+ * A property test rather than `instanceof`, so this never reaches for a global that can be absent.
111
+ *
112
+ * This is the one home of the test. It decides both what needs a decode and what may cross to the
113
+ * atlas worker, so a second copy could drift from this one, and the drift would only show on the
114
+ * oldest targets.
115
+ * @param source - The source to classify.
116
+ * @returns Whether the source needs a decode.
117
+ */
118
+ export declare function isBlob(source: object): source is Blob;
119
+ /**
120
+ * Whether a source's pixels can shrink to fit a memory budget. This is `true` for decoded images
121
+ * and bitmaps. It is `false` for canvases, because a canvas's pixels belong to the caller. The
122
+ * code counts a canvas at full size and never compresses it (see the scene's `memoryLimit`).
123
+ *
124
+ * The check looks for the absence of `getContext`. `HTMLCanvasElement` and `OffscreenCanvas` both
125
+ * have it. `ImageBitmap` and `Blob` do not. This is a property test, not an
126
+ * `instanceof` check, because the SDK runs in WebViews. There, `OffscreenCanvas` and `ImageBitmap`
127
+ * can be missing as globals, and an `instanceof` check against a missing global throws an error.
128
+ * @param source - The source to classify.
129
+ * @returns Whether the source can shrink.
130
+ */
131
+ export declare function isResizableSource(source: object): boolean;
132
+ /**
133
+ * Makes the canvas that one atlas draws onto. The function returns an `OffscreenCanvas` where one
134
+ * exists, and a DOM canvas otherwise.
135
+ *
136
+ * This is the only place in the package that builds an atlas canvas, so the `OffscreenCanvas`
137
+ * guard lives here alone. The guard uses this plain form because `eslint-plugin-compat`
138
+ * understands it and flags only an unguarded construction. Nothing here needs hiding from the
139
+ * linter.
140
+ * @param width - The canvas width in pixels.
141
+ * @param height - The canvas height in pixels.
142
+ * @returns The canvas.
143
+ */
144
+ export declare function createAtlasCanvas(width: number, height: number): AtlasCanvas;
145
+ /**
146
+ * Packs decoded sources into atlas canvases and reports where each one landed.
147
+ *
148
+ * The code splits sources by kind first: resizable ones (bitmaps and images) apart from fixed ones
149
+ * (canvases). Each kind packs on its own, so no atlas ever mixes the two kinds. This lets a memory
150
+ * budget scale a whole resizable atlas without touching a canvas's pixels. Within one kind, the
151
+ * code offers each source to the packer whole. Anything too big for an atlas comes back parked in
152
+ * a bin of its own natural size, and the packer flags that bin. Those are the only sources that get
153
+ * cut into tiles, and the tiles go back through the same packer. Letting the packer decide keeps
154
+ * the guarantee that no atlas exceeds `maxDimension`, with no need to measure every image up
155
+ * front.
156
+ *
157
+ * This function does **not** deduplicate sources. The caller must collect unique sources before it
158
+ * decodes them, so every entry in `sources` is already distinct.
159
+ *
160
+ * This module runs unchanged on the main thread and inside the atlas worker. It must not use
161
+ * `document`, the def types, or the logger.
162
+ * @param sources - The decoded sources to pack, in the order the caller gives them.
163
+ * @param maxDimension - The largest atlas edge in pixels. The function floors this to a positive
164
+ * integer.
165
+ * @param createCanvas - Makes each atlas canvas. Defaults to {@link createAtlasCanvas}.
166
+ * @returns The atlases in packing order (resizable first, then fixed), and one report for each
167
+ * source, aligned by index with `sources`.
168
+ */
169
+ export declare function packSources(sources: readonly (DecodedSource | null)[], maxDimension: number, createCanvas?: CreateAtlasCanvas): {
170
+ atlases: SourceAtlas[];
171
+ reports: SourceReport[];
172
+ };
173
+ /**
174
+ * Resolves an atlas canvas's 2D context, asking one canvas kind at a time.
175
+ *
176
+ * Deliberately not `canvas.getContext('2d')` on the union. The two kinds' overload lists disagree
177
+ * at the end — `HTMLCanvasElement` closes with `getContext(id: string): RenderingContext | null`,
178
+ * `OffscreenCanvas` with an `OffscreenRenderingContextId` one — and resolving across the union can
179
+ * combine one kind's `"2d"` overload with the other's catch-all, yielding
180
+ * `OffscreenCanvasRenderingContext2D | RenderingContext`: a type covering bitmap and WebGL contexts
181
+ * that have no `drawImage`. It surfaces only on incremental rebuilds (any compile error in this
182
+ * file leaves the bad resolution cached in `.tsbuildinfo`, where it outlives the error that caused
183
+ * it), so a clean build hides it and a working tree quietly breaks. Narrowed first, each branch has
184
+ * one concrete type whose `"2d"` overload is the only candidate, and the result is stable either
185
+ * way.
186
+ * @param canvas - The atlas canvas.
187
+ * @returns Its 2D context, or `null` when the canvas cannot provide one.
188
+ */
189
+ export declare function contextOf(canvas: AtlasCanvas): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;
190
+ //# sourceMappingURL=pack-sources.d.ts.map
@@ -0,0 +1,272 @@
1
+ import { MaxRectsPacker } from 'maxrects-packer';
2
+ /**
3
+ * Whether a source is a `Blob`, which is also true of a `File`.
4
+ *
5
+ * The test looks for `slice`, and it must keep looking for `slice`. `slice` is Chrome 21, Chrome
6
+ * Android 25, Safari 7 and iOS Safari 7, so every build target has it. `arrayBuffer` reads better
7
+ * and is wrong: it is Chrome 76 and Chrome Android 76, above this package's `chrome66` floor, so on
8
+ * the old Android WebViews it is `undefined` and every real `Blob` would fail this test and reach
9
+ * the packer undecoded (`packages/floorplan/src/components/Maplibre/utils/pmtiles-range-fallback.ts`
10
+ * works around the same floor). No other image source carries either method: not an `<img>`, a
11
+ * canvas, an offscreen canvas or a bitmap.
12
+ *
13
+ * A property test rather than `instanceof`, so this never reaches for a global that can be absent.
14
+ *
15
+ * This is the one home of the test. It decides both what needs a decode and what may cross to the
16
+ * atlas worker, so a second copy could drift from this one, and the drift would only show on the
17
+ * oldest targets.
18
+ * @param source - The source to classify.
19
+ * @returns Whether the source needs a decode.
20
+ */
21
+ export function isBlob(source) {
22
+ return typeof source.slice === 'function';
23
+ }
24
+ /**
25
+ * Whether a source's pixels can shrink to fit a memory budget. This is `true` for decoded images
26
+ * and bitmaps. It is `false` for canvases, because a canvas's pixels belong to the caller. The
27
+ * code counts a canvas at full size and never compresses it (see the scene's `memoryLimit`).
28
+ *
29
+ * The check looks for the absence of `getContext`. `HTMLCanvasElement` and `OffscreenCanvas` both
30
+ * have it. `ImageBitmap` and `Blob` do not. This is a property test, not an
31
+ * `instanceof` check, because the SDK runs in WebViews. There, `OffscreenCanvas` and `ImageBitmap`
32
+ * can be missing as globals, and an `instanceof` check against a missing global throws an error.
33
+ * @param source - The source to classify.
34
+ * @returns Whether the source can shrink.
35
+ */
36
+ export function isResizableSource(source) {
37
+ return !('getContext' in source);
38
+ }
39
+ /**
40
+ * Makes the canvas that one atlas draws onto. The function returns an `OffscreenCanvas` where one
41
+ * exists, and a DOM canvas otherwise.
42
+ *
43
+ * This is the only place in the package that builds an atlas canvas, so the `OffscreenCanvas`
44
+ * guard lives here alone. The guard uses this plain form because `eslint-plugin-compat`
45
+ * understands it and flags only an unguarded construction. Nothing here needs hiding from the
46
+ * linter.
47
+ * @param width - The canvas width in pixels.
48
+ * @param height - The canvas height in pixels.
49
+ * @returns The canvas.
50
+ */
51
+ export function createAtlasCanvas(width, height) {
52
+ if (typeof OffscreenCanvas !== 'undefined')
53
+ return new OffscreenCanvas(width, height);
54
+ const canvas = document.createElement('canvas');
55
+ canvas.width = width;
56
+ canvas.height = height;
57
+ return canvas;
58
+ }
59
+ /**
60
+ * Packs decoded sources into atlas canvases and reports where each one landed.
61
+ *
62
+ * The code splits sources by kind first: resizable ones (bitmaps and images) apart from fixed ones
63
+ * (canvases). Each kind packs on its own, so no atlas ever mixes the two kinds. This lets a memory
64
+ * budget scale a whole resizable atlas without touching a canvas's pixels. Within one kind, the
65
+ * code offers each source to the packer whole. Anything too big for an atlas comes back parked in
66
+ * a bin of its own natural size, and the packer flags that bin. Those are the only sources that get
67
+ * cut into tiles, and the tiles go back through the same packer. Letting the packer decide keeps
68
+ * the guarantee that no atlas exceeds `maxDimension`, with no need to measure every image up
69
+ * front.
70
+ *
71
+ * This function does **not** deduplicate sources. The caller must collect unique sources before it
72
+ * decodes them, so every entry in `sources` is already distinct.
73
+ *
74
+ * This module runs unchanged on the main thread and inside the atlas worker. It must not use
75
+ * `document`, the def types, or the logger.
76
+ * @param sources - The decoded sources to pack, in the order the caller gives them.
77
+ * @param maxDimension - The largest atlas edge in pixels. The function floors this to a positive
78
+ * integer.
79
+ * @param createCanvas - Makes each atlas canvas. Defaults to {@link createAtlasCanvas}.
80
+ * @returns The atlases in packing order (resizable first, then fixed), and one report for each
81
+ * source, aligned by index with `sources`.
82
+ */
83
+ export function packSources(sources, maxDimension, createCanvas = createAtlasCanvas) {
84
+ const limit = Math.max(1, Math.floor(maxDimension));
85
+ // Every member of `DecodedSource` reports its own pixel size, so nothing here needs to duck-type
86
+ // a size. That was only ever needed because an `<img>` reports its layout size as `width`. A
87
+ // source that fails to decode arrives as `null` and reports `0 x 0`. Code skips that source the
88
+ // same way it skips a zero-sized canvas.
89
+ const reports = sources.map((source) => source
90
+ ? { width: source.width, height: source.height, tiles: 0 }
91
+ : { width: 0, height: 0, tiles: 0 });
92
+ const resizable = [];
93
+ const fixed = [];
94
+ for (let index = 0; index < sources.length; index++) {
95
+ const source = sources[index];
96
+ // A source that failed to decode is dropped later by the size check in `packGroup`. Code
97
+ // groups it with the resizable sources, so it never lands in an atlas of canvases on its way
98
+ // to being skipped.
99
+ (!source || isResizableSource(source) ? resizable : fixed).push(index);
100
+ }
101
+ // One packer serves both groups, reset between them. The configuration (size, padding, options)
102
+ // is the same for each, so reusing the packer spares an allocation per pack. The packer cannot
103
+ // carry over across pack calls, though, because `limit` is fixed at construction and changes
104
+ // from call to call.
105
+ // `pot: false`, because WebGL 2 samples non-power-of-two textures without restriction. Rounding
106
+ // each atlas up only wastes memory. `smart` stays on (the default), which shrinks every bin to
107
+ // its content. That is why the code reads the size back off the bin instead of assuming
108
+ // `limit`.
109
+ const packer = new MaxRectsPacker(limit, limit, PADDING, { pot: false });
110
+ const atlases = [
111
+ ...packGroup(packer, sources, resizable, reports, limit, createCanvas, true),
112
+ ...packGroup(packer, sources, fixed, reports, limit, createCanvas, false),
113
+ ];
114
+ return { atlases, reports };
115
+ }
116
+ /**
117
+ * The gap between neighboring images on an atlas. This gap stops linear filtering at one image's
118
+ * edge from reaching into the next image's pixels. The packer applies this gap *between* rects
119
+ * only, so atlas edges stay flush against the pixels. This is also why a tile exactly
120
+ * `maxDimension` across still fits in a bin.
121
+ */
122
+ const PADDING = 1;
123
+ /**
124
+ * Packs one kind of source, either all resizable or all fixed, into atlases. The function tags
125
+ * each atlas with the group's kind and records each source's tile count in `reports`.
126
+ * @param packer - The shared packer. It is reset to empty before this group is added.
127
+ * @param sources - Every source, indexed by the entries in `indices`.
128
+ * @param indices - The indices of this kind. This list can be empty, and then nothing packs.
129
+ * @param reports - Per-source reports. This function fills in each report's `tiles` count.
130
+ * @param limit - The largest atlas edge, in pixels.
131
+ * @param createCanvas - Makes each atlas canvas.
132
+ * @param resizable - The kind, stamped onto every atlas that this call produces.
133
+ * @returns The atlases this group produced.
134
+ */
135
+ function packGroup(packer, sources, indices, reports, limit, createCanvas, resizable) {
136
+ const rects = [];
137
+ for (const index of indices) {
138
+ const { width, height } = reports[index];
139
+ // A `drawImage` call throws in some browsers when the source region has zero width or zero
140
+ // height. So code drops an image that has not decoded, or a canvas sized to nothing, instead
141
+ // of drawing it. Its report keeps `tiles: 0`, and that value tells the caller to warn about
142
+ // it.
143
+ if (width <= 0 || height <= 0)
144
+ continue;
145
+ rects.push({ width, height, x: 0, y: 0, hash: `${index}`, data: { index } });
146
+ }
147
+ // Clear whatever the previous group left in the packer, keeping its configuration.
148
+ packer.reset();
149
+ // `addArray` sorts by longest edge before it places rects, which packs far tighter than
150
+ // insertion order.
151
+ packer.addArray(rects);
152
+ // The packer tags whatever it must park in an oversized bin. The packer decides what needs
153
+ // cutting, not a separate measurement in this code. The tiles are ordinary rects, and they pack
154
+ // into the bins that the first pass already opened.
155
+ const oversized = rects.filter((rect) => rect.oversized);
156
+ if (oversized.length > 0) {
157
+ packer.addArray(oversized.flatMap((rect) => cutTiles(rect, reports[rect.data.index], limit)));
158
+ }
159
+ // Every oversized bin now has its tiles standing in for it, so the code drops the bin instead of
160
+ // returning it. Handing back a canvas larger than the caller's limit is the exact problem this
161
+ // code exists to prevent.
162
+ const bins = packer.bins.filter((bin) => !bin.rects.some((rect) => rect.oversized));
163
+ const atlases = bins.map((bin) => ({
164
+ ...renderAtlas(bin, sources, reports, createCanvas),
165
+ resizable,
166
+ }));
167
+ // Count what actually landed. This lets code tell a dropped source apart from a split one.
168
+ for (const bin of bins)
169
+ for (const rect of bin.rects)
170
+ reports[rect.data.index].tiles++;
171
+ return atlases;
172
+ }
173
+ /**
174
+ * Cuts a source that did not fit in the packer into a grid of tiles. No tile is larger than one
175
+ * atlas. Tiles are exact and do not overlap. Each tile ends up alone, or beside its own sibling
176
+ * tiles, in an atlas. Nothing can bleed across the cut, so the code needs no overlap column to
177
+ * hide a seam.
178
+ * @param rect - The oversized rect that names the source to cut.
179
+ * @param report - That source's measured size.
180
+ * @param limit - The largest tile edge, in pixels.
181
+ * @returns The tiles to pack in its place.
182
+ */
183
+ function cutTiles(rect, report, limit) {
184
+ const columns = Math.ceil(report.width / limit);
185
+ const rows = Math.ceil(report.height / limit);
186
+ const tiles = [];
187
+ for (let row = 0; row < rows; row++) {
188
+ const y = row * limit;
189
+ const height = Math.min(limit, report.height - y);
190
+ for (let column = 0; column < columns; column++) {
191
+ const x = column * limit;
192
+ const width = Math.min(limit, report.width - x);
193
+ tiles.push({
194
+ width,
195
+ height,
196
+ x: 0,
197
+ y: 0,
198
+ hash: `${rect.hash}:${column},${row}`,
199
+ data: { index: rect.data.index, source: { x, y, width, height } },
200
+ });
201
+ }
202
+ }
203
+ return tiles;
204
+ }
205
+ /**
206
+ * Draws one packed bin onto a canvas and records where each rect landed.
207
+ * @param bin - The packed bin, already sized to its content.
208
+ * @param sources - Every source, indexed by each rect's tile.
209
+ * @param reports - Per-source sizes, for the whole-image draw region.
210
+ * @param createCanvas - Makes the canvas to draw on.
211
+ * @returns The atlas, less its `resizable` flag.
212
+ */
213
+ function renderAtlas(bin, sources, reports, createCanvas) {
214
+ const canvas = createCanvas(bin.width, bin.height);
215
+ const context = contextOf(canvas);
216
+ // Nothing downstream can recover from a missing context. Every atlas then uploads blank, and
217
+ // the images silently draw as nothing at all. It is better to fail here, where the cause stays
218
+ // visible.
219
+ if (!context)
220
+ throw new Error(`pack-sources: no 2d context for a ${bin.width}x${bin.height} atlas`);
221
+ const placements = [];
222
+ for (const rect of bin.rects) {
223
+ const { index, source } = rect.data;
224
+ // The copied region is the tile when the rect has one, and the whole image otherwise. Both
225
+ // read from the source's own axes. This region happens to match the packed rect's size today,
226
+ // because tiles are placed 1:1 and unrotated. Reading the size from the destination instead
227
+ // is correct only by accident, not by design. The code keeps this region apart from `source`
228
+ // itself, which stays undefined for an unsplit image, so the placement below does not report
229
+ // a region that the caller has no use for.
230
+ const { width, height } = reports[index];
231
+ const region = source ?? { x: 0, y: 0, width, height };
232
+ // This value is never null, by construction. A source that fails to decode reports `0 x 0`
233
+ // and never reaches the packer, so every rect in a bin has a drawable source behind it.
234
+ const decoded = sources[index];
235
+ if (!decoded)
236
+ continue;
237
+ context.drawImage(decoded, region.x, region.y, region.width, region.height, rect.x, rect.y, rect.width, rect.height);
238
+ // The rect uses canvas pixels, and uv keeps the canvas's axes, so this is a plain
239
+ // normalization with no vertical inversion (see {@link UvRect}).
240
+ const uv = {
241
+ u0: rect.x / bin.width,
242
+ v0: rect.y / bin.height,
243
+ u1: (rect.x + rect.width) / bin.width,
244
+ v1: (rect.y + rect.height) / bin.height,
245
+ };
246
+ placements.push(source ? { index, uv, source } : { index, uv });
247
+ }
248
+ return { canvas, placements };
249
+ }
250
+ /**
251
+ * Resolves an atlas canvas's 2D context, asking one canvas kind at a time.
252
+ *
253
+ * Deliberately not `canvas.getContext('2d')` on the union. The two kinds' overload lists disagree
254
+ * at the end — `HTMLCanvasElement` closes with `getContext(id: string): RenderingContext | null`,
255
+ * `OffscreenCanvas` with an `OffscreenRenderingContextId` one — and resolving across the union can
256
+ * combine one kind's `"2d"` overload with the other's catch-all, yielding
257
+ * `OffscreenCanvasRenderingContext2D | RenderingContext`: a type covering bitmap and WebGL contexts
258
+ * that have no `drawImage`. It surfaces only on incremental rebuilds (any compile error in this
259
+ * file leaves the bad resolution cached in `.tsbuildinfo`, where it outlives the error that caused
260
+ * it), so a clean build hides it and a working tree quietly breaks. Narrowed first, each branch has
261
+ * one concrete type whose `"2d"` overload is the only candidate, and the result is stable either
262
+ * way.
263
+ * @param canvas - The atlas canvas.
264
+ * @returns Its 2D context, or `null` when the canvas cannot provide one.
265
+ */
266
+ export function contextOf(canvas) {
267
+ // `in` rather than `instanceof`: in a worker there is no `HTMLCanvasElement` global to test
268
+ // against, and an `instanceof` against a missing global throws.
269
+ if ('convertToBlob' in canvas)
270
+ return canvas.getContext('2d');
271
+ return canvas.getContext('2d');
272
+ }
@@ -0,0 +1,120 @@
1
+ import { type Atlas } from './atlas-packer';
2
+ /**
3
+ * The GPU footprint of an atlas of the given pixel size: RGBA, with the mipmap chain counted. Reads
4
+ * the atlas's full (packed) dimensions — the resize factor scales this down, so budgeting against
5
+ * the full size is what the factor is solved from.
6
+ * @param width - Atlas width in pixels.
7
+ * @param height - Atlas height in pixels.
8
+ * @returns The size in bytes.
9
+ */
10
+ export declare function getAtlasSizeBytes(width: number, height: number): number;
11
+ /**
12
+ * One atlas's contribution to the budget: its full size, and whether it may be scaled to fit. The
13
+ * object doubles as its own registration handle — {@link TextureBudget.unregister} takes the very
14
+ * object {@link TextureBudget.register} was given, so identity alone distinguishes two atlases of
15
+ * equal size and no separate key is needed.
16
+ */
17
+ interface AtlasBudgetEntry {
18
+ /** Full atlas width in pixels. */
19
+ width: number;
20
+ /** Full atlas height in pixels. */
21
+ height: number;
22
+ /** Whether this atlas's bytes shrink with the resize factor, or count at full size always. */
23
+ resizable: boolean;
24
+ }
25
+ /**
26
+ * The scene's shared texture-memory budget. Every image atlas registers its full size here, and the
27
+ * store solves for one linear resize factor that brings the resizable atlases within `memoryLimit` —
28
+ * shared by all of them, so their relative sizes are preserved with no priority.
29
+ *
30
+ * The factor is exposed through `useSyncExternalStore`: an atlas that mounts, unmounts, or a limit
31
+ * that changes recomputes it, and a material move re-derives only the resizable atlases' textures —
32
+ * never a repack, since uv regions are normalized and so invariant to the canvas's pixel size.
33
+ * Recompute runs synchronously per registration; the render churn that would cause is left to
34
+ * React's automatic batching to coalesce, and the `FACTOR_EPSILON` gate keeps sub-pixel nudges from
35
+ * notifying at all. When no cap is set the whole apparatus stands down: {@link TextureBudget.isActive}
36
+ * is false, atlases skip registration entirely (see {@link useResizeFactor}), and the factor is 1.
37
+ */
38
+ export declare class TextureBudget {
39
+ /** The cap in megabytes, or undefined/`0` for no cap — a falsy value scales nothing. */
40
+ private memoryLimitMb;
41
+ /** Every registered atlas; the entry object is its own handle. */
42
+ private readonly atlases;
43
+ /** Subscribers to the resize factor — the mounted resizable atlases. */
44
+ private readonly listeners;
45
+ /** The current shared linear resize factor; `1` means no scaling. */
46
+ private factor;
47
+ /**
48
+ * @param memoryLimitMb - The cap in megabytes, or undefined/`0` for no cap.
49
+ */
50
+ constructor(memoryLimitMb?: number);
51
+ /**
52
+ * Whether a cap is in force. False for an absent or zero limit — nothing can be compressed, so
53
+ * consumers skip the budget entirely rather than do work that resolves to "no scaling".
54
+ * @returns Whether a positive limit is set.
55
+ */
56
+ isActive(): boolean;
57
+ /**
58
+ * Changes the cap. Called when the renderer's `memoryLimit` prop changes, so a caller can raise,
59
+ * lower, or clear it at runtime and the resizable atlases re-derive their textures live.
60
+ * @param memoryLimitMb - The new cap, or undefined/`0` for no cap.
61
+ */
62
+ setMemoryLimit(memoryLimitMb: number | undefined): void;
63
+ /**
64
+ * Registers one atlas's full size, recomputing the factor. Only called while {@link isActive}, so
65
+ * an uncapped scene never populates this set.
66
+ * @param entry - The atlas's dimensions and kind; pass the same object back to unregister.
67
+ */
68
+ register(entry: AtlasBudgetEntry): void;
69
+ /**
70
+ * Drops an atlas's contribution, recomputing the factor.
71
+ * @param entry - The object {@link register} was given.
72
+ */
73
+ unregister(entry: AtlasBudgetEntry): void;
74
+ /**
75
+ * The current shared resize factor.
76
+ * @returns The factor in `(0, 1]`.
77
+ */
78
+ getResizeFactor(): number;
79
+ /**
80
+ * Subscribes to factor and active-state changes.
81
+ * @param listener - Called when the factor moves past {@link FACTOR_EPSILON} or the cap toggles.
82
+ * @returns The unsubscribe function.
83
+ */
84
+ subscribe(listener: () => void): () => void;
85
+ /** Recomputes the factor and, if it moved materially, notifies subscribers. */
86
+ private recompute;
87
+ /** Notifies every subscriber. */
88
+ private notify;
89
+ /**
90
+ * Solves for the linear factor that fits the resizable atlases in the budget the fixed ones leave.
91
+ *
92
+ * Every degenerate case falls back to `1` — no scaling — rather than forcing a fit: no cap, nothing
93
+ * resizable to scale, or a cap the fixed atlases alone already exceed (canvases cannot be
94
+ * compressed, so there is nothing to give). The factor is only ever clamped up to `1`, never down
95
+ * to a floor: an image is scaled by however much the budget demands.
96
+ * @returns The factor in `(0, 1]`.
97
+ */
98
+ private computeResizeFactor;
99
+ }
100
+ /**
101
+ * The scene's texture budget, provided by `Renderer`. The default is an uncapped budget, so an image
102
+ * layer rendered outside a `Renderer` (a test, a story) behaves exactly as before this existed —
103
+ * everything uploads at full size.
104
+ */
105
+ export declare const TextureBudgetContext: import("react").Context<TextureBudget>;
106
+ /**
107
+ * Registers an atlas with the scene budget for its mounted lifetime and returns the resize factor it
108
+ * should upload at: the shared factor for a resizable atlas, always `1` for a fixed one (its pixels
109
+ * still count toward the budget, they just never scale).
110
+ *
111
+ * When the budget is inactive — no `memoryLimit` — the atlas is not registered at all: there is
112
+ * nothing to solve, so an uncapped scene does no per-atlas budget work. Turning a cap on at runtime
113
+ * flips `isActive`, which re-runs the registration effect.
114
+ * @param budget - The scene budget from context.
115
+ * @param atlas - The atlas to register and read a factor for.
116
+ * @returns The linear factor this atlas's canvas should be scaled by before upload, in `(0, 1]`.
117
+ */
118
+ export declare function useResizeFactor(budget: TextureBudget, atlas: Atlas): number;
119
+ export {};
120
+ //# sourceMappingURL=texture-budget.d.ts.map