@expofp/renderer 3.2.5 → 3.27.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.
- package/README.md +111 -0
- package/dist/Renderer.d.ts +88 -0
- package/dist/Renderer.js +53 -0
- package/dist/controls/CameraControls.d.ts +102 -0
- package/dist/controls/CameraControls.js +239 -0
- package/dist/controls/camera-api.d.ts +206 -0
- package/dist/controls/camera-api.js +181 -0
- package/dist/controls/camera-move.d.ts +13 -0
- package/dist/controls/camera-move.js +18 -0
- package/dist/controls/camera-state.d.ts +40 -0
- package/dist/controls/camera-state.js +65 -0
- package/dist/controls/gestures.d.ts +70 -0
- package/dist/controls/gestures.js +84 -0
- package/dist/controls/handlers/Inertia.d.ts +111 -0
- package/dist/controls/handlers/Inertia.js +215 -0
- package/dist/controls/handlers/Pan.d.ts +23 -0
- package/dist/controls/handlers/Pan.js +32 -0
- package/dist/controls/handlers/Pitch.d.ts +94 -0
- package/dist/controls/handlers/Pitch.js +191 -0
- package/dist/controls/handlers/Roll.d.ts +103 -0
- package/dist/controls/handlers/Roll.js +182 -0
- package/dist/controls/handlers/Zoom.d.ts +15 -0
- package/dist/controls/handlers/Zoom.js +26 -0
- package/dist/controls/index.d.ts +56 -0
- package/dist/controls/index.js +58 -0
- package/dist/controls/zoom-to.d.ts +89 -0
- package/dist/controls/zoom-to.js +91 -0
- package/dist/core/InstanceUniforms.d.ts +93 -0
- package/dist/core/InstanceUniforms.js +266 -0
- package/dist/core/SquareDataTexture.d.ts +277 -0
- package/dist/core/SquareDataTexture.js +476 -0
- package/dist/core/batch/BatchedMesh.d.ts +74 -0
- package/dist/core/batch/BatchedMesh.js +149 -0
- package/dist/core/instanced/FrustumCulling.d.ts +141 -0
- package/dist/core/instanced/FrustumCulling.js +246 -0
- package/dist/core/instanced/InstancedMesh.d.ts +302 -0
- package/dist/core/instanced/InstancedMesh.js +497 -0
- package/dist/core/instanced/Instances.d.ts +119 -0
- package/dist/core/instanced/Instances.js +230 -0
- package/dist/core/instanced/Raycasting.d.ts +118 -0
- package/dist/core/instanced/Raycasting.js +134 -0
- package/dist/core/instanced/instanced-material.d.ts +77 -0
- package/dist/core/instanced/instanced-material.js +224 -0
- package/dist/core/lines/BatchedLines.d.ts +135 -0
- package/dist/core/lines/BatchedLines.js +213 -0
- package/dist/core/lines/FrustumCulling.d.ts +43 -0
- package/dist/core/lines/FrustumCulling.js +85 -0
- package/dist/core/lines/Raycasting.d.ts +44 -0
- package/dist/core/lines/Raycasting.js +91 -0
- package/dist/core/lines/lines-material.d.ts +47 -0
- package/dist/core/lines/lines-material.js +115 -0
- package/dist/core/shader-source.d.ts +50 -0
- package/dist/core/shader-source.js +84 -0
- package/dist/core/text/BatchedText.d.ts +227 -0
- package/dist/core/text/BatchedText.js +467 -0
- package/dist/core/text/MemberTexture.d.ts +90 -0
- package/dist/core/text/MemberTexture.js +194 -0
- package/dist/core/text/Text.d.ts +73 -0
- package/dist/core/text/Text.js +215 -0
- package/dist/core/text/batched-text-material.d.ts +56 -0
- package/dist/core/text/batched-text-material.js +121 -0
- package/dist/core/text/glyph-packing.d.ts +17 -0
- package/dist/core/text/glyph-packing.js +61 -0
- package/dist/core/typed-array.d.ts +16 -0
- package/dist/core/typed-array.js +20 -0
- package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
- package/dist/debug/components/DebugPanelProvider.js +38 -0
- package/dist/debug/components/DebugTools.d.ts +22 -0
- package/dist/debug/components/DebugTools.js +28 -0
- package/dist/debug/components/Gui.d.ts +20 -0
- package/dist/debug/components/Gui.js +32 -0
- package/dist/debug/components/MemoryInfo.d.ts +22 -0
- package/dist/debug/components/MemoryInfo.js +42 -0
- package/dist/debug/components/Panel.d.ts +31 -0
- package/dist/debug/components/Panel.js +98 -0
- package/dist/debug/components/Stats.d.ts +9 -0
- package/dist/debug/components/Stats.js +24 -0
- package/dist/debug/debug-context.d.ts +41 -0
- package/dist/debug/debug-context.js +59 -0
- package/dist/debug/index.d.ts +51 -0
- package/dist/debug/index.js +64 -0
- package/dist/events/LayoutDriver.d.ts +31 -0
- package/dist/events/LayoutDriver.js +88 -0
- package/dist/events/PointerMissed.d.ts +23 -0
- package/dist/events/PointerMissed.js +58 -0
- package/dist/events/def-culling.d.ts +46 -0
- package/dist/events/def-culling.js +69 -0
- package/dist/events/layout-targets.d.ts +104 -0
- package/dist/events/layout-targets.js +245 -0
- package/dist/events/pointer.d.ts +118 -0
- package/dist/events/pointer.js +168 -0
- package/dist/external/ExternalCanvas.d.ts +56 -0
- package/dist/external/ExternalCanvas.js +178 -0
- package/dist/external/external-camera.d.ts +17 -0
- package/dist/external/external-camera.js +82 -0
- package/dist/external/external-events.d.ts +14 -0
- package/dist/external/external-events.js +33 -0
- package/dist/index.d.ts +11 -783
- package/dist/index.js +12 -8031
- package/dist/objects/Background.d.ts +31 -0
- package/dist/objects/Background.js +37 -0
- package/dist/objects/Lighting.d.ts +20 -0
- package/dist/objects/Lighting.js +85 -0
- package/dist/objects/containers/SlotContainer.d.ts +266 -0
- package/dist/objects/containers/SlotContainer.js +251 -0
- package/dist/objects/containers/hooks.d.ts +46 -0
- package/dist/objects/containers/hooks.js +118 -0
- package/dist/objects/containers/index.d.ts +6 -0
- package/dist/objects/containers/index.js +4 -0
- package/dist/objects/containers/keys.d.ts +10 -0
- package/dist/objects/containers/keys.js +18 -0
- package/dist/objects/containers/mesh-writes.d.ts +106 -0
- package/dist/objects/containers/mesh-writes.js +97 -0
- package/dist/objects/containers/props.d.ts +23 -0
- package/dist/objects/containers/props.js +1 -0
- package/dist/objects/images/ImageInstance.d.ts +29 -0
- package/dist/objects/images/ImageInstance.js +83 -0
- package/dist/objects/images/Images.d.ts +37 -0
- package/dist/objects/images/Images.js +204 -0
- package/dist/objects/images/atlas-packer.d.ts +128 -0
- package/dist/objects/images/atlas-packer.js +315 -0
- package/dist/objects/images/image-container.d.ts +51 -0
- package/dist/objects/images/image-container.js +70 -0
- package/dist/objects/images/index.d.ts +2 -0
- package/dist/objects/images/index.js +1 -0
- package/dist/objects/images/texture-budget.d.ts +120 -0
- package/dist/objects/images/texture-budget.js +215 -0
- package/dist/objects/layer/Layer.d.ts +27 -0
- package/dist/objects/layer/Layer.js +114 -0
- package/dist/objects/layer/index.d.ts +2 -0
- package/dist/objects/layer/index.js +1 -0
- package/dist/objects/layer/mount-scheduler.d.ts +102 -0
- package/dist/objects/layer/mount-scheduler.js +145 -0
- package/dist/objects/layer/visibility-gui.d.ts +19 -0
- package/dist/objects/layer/visibility-gui.js +93 -0
- package/dist/objects/lines/LineInstance.d.ts +21 -0
- package/dist/objects/lines/LineInstance.js +73 -0
- package/dist/objects/lines/Lines.d.ts +17 -0
- package/dist/objects/lines/Lines.js +29 -0
- package/dist/objects/lines/index.d.ts +2 -0
- package/dist/objects/lines/index.js +1 -0
- package/dist/objects/lines/line-container.d.ts +35 -0
- package/dist/objects/lines/line-container.js +40 -0
- package/dist/objects/materials/ColorMaterial.d.ts +85 -0
- package/dist/objects/materials/ColorMaterial.js +89 -0
- package/dist/objects/materials/LineMaterial.d.ts +44 -0
- package/dist/objects/materials/LineMaterial.js +72 -0
- package/dist/objects/materials/ModelMaterial.d.ts +41 -0
- package/dist/objects/materials/ModelMaterial.js +84 -0
- package/dist/objects/materials/TextureMaterial.d.ts +30 -0
- package/dist/objects/materials/TextureMaterial.js +29 -0
- package/dist/objects/materials/dim.d.ts +123 -0
- package/dist/objects/materials/dim.js +213 -0
- package/dist/objects/materials/shared.d.ts +6 -0
- package/dist/objects/materials/shared.js +51 -0
- package/dist/objects/models/ModelInstance.d.ts +22 -0
- package/dist/objects/models/ModelInstance.js +33 -0
- package/dist/objects/models/Models.d.ts +22 -0
- package/dist/objects/models/Models.js +177 -0
- package/dist/objects/models/gltf-cache.d.ts +17 -0
- package/dist/objects/models/gltf-cache.js +50 -0
- package/dist/objects/models/index.d.ts +2 -0
- package/dist/objects/models/index.js +1 -0
- package/dist/objects/models/model-asset.d.ts +48 -0
- package/dist/objects/models/model-asset.js +77 -0
- package/dist/objects/models/model-container.d.ts +139 -0
- package/dist/objects/models/model-container.js +227 -0
- package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
- package/dist/objects/shapes/ShapeInstance.js +40 -0
- package/dist/objects/shapes/Shapes.d.ts +21 -0
- package/dist/objects/shapes/Shapes.js +120 -0
- package/dist/objects/shapes/index.d.ts +2 -0
- package/dist/objects/shapes/index.js +1 -0
- package/dist/objects/shapes/shape-container.d.ts +165 -0
- package/dist/objects/shapes/shape-container.js +272 -0
- package/dist/objects/shapes/shape-geometry.d.ts +27 -0
- package/dist/objects/shapes/shape-geometry.js +94 -0
- package/dist/objects/text/TextInstance.d.ts +22 -0
- package/dist/objects/text/TextInstance.js +95 -0
- package/dist/objects/text/Texts.d.ts +30 -0
- package/dist/objects/text/Texts.js +41 -0
- package/dist/objects/text/index.d.ts +2 -0
- package/dist/objects/text/index.js +1 -0
- package/dist/objects/text/text-container.d.ts +105 -0
- package/dist/objects/text/text-container.js +206 -0
- package/dist/objects/text/text-layout.d.ts +83 -0
- package/dist/objects/text/text-layout.js +154 -0
- package/dist/space/Camera.d.ts +103 -0
- package/dist/space/Camera.js +321 -0
- package/dist/space/Scene.d.ts +44 -0
- package/dist/space/Scene.js +112 -0
- package/dist/space/Space.d.ts +288 -0
- package/dist/space/Space.js +329 -0
- package/dist/space/VisibleRect.d.ts +72 -0
- package/dist/space/VisibleRect.js +129 -0
- package/dist/space/camera-handle.d.ts +67 -0
- package/dist/space/camera-handle.js +63 -0
- package/dist/space/camera-kind.d.ts +26 -0
- package/dist/space/camera-kind.js +30 -0
- package/dist/space/canvas-size.d.ts +24 -0
- package/dist/space/canvas-size.js +20 -0
- package/dist/space/clipping.d.ts +55 -0
- package/dist/space/clipping.js +108 -0
- package/dist/space/layout-measure.d.ts +65 -0
- package/dist/space/layout-measure.js +173 -0
- package/dist/space/viewport.d.ts +112 -0
- package/dist/space/viewport.js +67 -0
- package/dist/types/defs.d.ts +169 -0
- package/dist/types/defs.js +1 -0
- package/dist/types/events.d.ts +183 -0
- package/dist/types/events.js +1 -0
- package/dist/types/guards.d.ts +14 -0
- package/dist/types/guards.js +42 -0
- package/dist/update/index.d.ts +3 -0
- package/dist/update/index.js +2 -0
- package/dist/update/slot-writers.d.ts +30 -0
- package/dist/update/slot-writers.js +72 -0
- package/dist/update/store.d.ts +41 -0
- package/dist/update/store.js +98 -0
- package/dist/utils/arrays.d.ts +13 -0
- package/dist/utils/arrays.js +20 -0
- package/dist/utils/colors.d.ts +19 -0
- package/dist/utils/colors.js +27 -0
- package/dist/utils/logging.d.ts +26 -0
- package/dist/utils/logging.js +47 -0
- package/dist/utils/math.d.ts +24 -0
- package/dist/utils/math.js +27 -0
- package/package.json +67 -19
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type RenderableDef } from '../../types/defs';
|
|
2
|
+
/** Props for a component drawing one layer's defs. */
|
|
3
|
+
export interface DefsProps<T extends RenderableDef> {
|
|
4
|
+
/**
|
|
5
|
+
* The defs to draw, in paint order. Layer-level concerns (`hidden`, `dim`, pointer handlers)
|
|
6
|
+
* belong to `<Layer>`, not here.
|
|
7
|
+
*
|
|
8
|
+
* A **new array identity means the collection may have changed** — that is the whole contract.
|
|
9
|
+
* Callers must not pass a layer's `children` directly: it is mutated in place, so its identity
|
|
10
|
+
* never changes and a memoizing compiler would keep serving a stale instance list. Pass the
|
|
11
|
+
* version-keyed snapshot from `useStagedChildren`, whose identity changes exactly when the layer is
|
|
12
|
+
* updated.
|
|
13
|
+
*/
|
|
14
|
+
defs: readonly T[];
|
|
15
|
+
}
|
|
16
|
+
/** Props for a component keeping one def's instance in sync. */
|
|
17
|
+
export interface InstanceProps<T extends RenderableDef, C> {
|
|
18
|
+
/** The def this instance draws. */
|
|
19
|
+
def: T;
|
|
20
|
+
/** The container holding the instance. */
|
|
21
|
+
container: C;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=props.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type ImageDef } from '../../types/defs';
|
|
2
|
+
import { type InstanceProps } from '../containers';
|
|
3
|
+
import { type PackedImage } from './atlas-packer';
|
|
4
|
+
import { type ImageContainer } from './image-container';
|
|
5
|
+
/** Props for {@link ImageInstance}. */
|
|
6
|
+
export interface ImageInstanceProps extends InstanceProps<ImageDef, ImageContainer> {
|
|
7
|
+
/**
|
|
8
|
+
* The atlas placement this instance draws — the whole image, or one tile of a split one. A def
|
|
9
|
+
* whose source was cut across atlases has several instances, one per {@link PackedImage}.
|
|
10
|
+
*/
|
|
11
|
+
packed: PackedImage;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Keeps one image placement current: claims a slot on mount (where the container writes the fixed
|
|
15
|
+
* uv region), writes the def's transform and visibility on mount and after every `update(def)`, and
|
|
16
|
+
* releases the slot on unmount.
|
|
17
|
+
*
|
|
18
|
+
* Renders no scene node — the mesh belongs to the container. Only the transform lives here:
|
|
19
|
+
* visibility is `useDefSync`'s, the uv region is written once at claim (a def's source cannot
|
|
20
|
+
* change), and color has no analogue for a textured quad. Memoized for the same reason as
|
|
21
|
+
* `ShapeInstance`: a structural change hands the atlas a fresh placement list, rebuilding every
|
|
22
|
+
* instance element, so only prop-equality keeps the unchanged siblings from re-rendering. Both props
|
|
23
|
+
* are identity-stable across a membership's lifetime — a change repacks into a fresh container and
|
|
24
|
+
* fresh placements — so the bailout holds.
|
|
25
|
+
* @param props - The def, its placement, and its container.
|
|
26
|
+
* @returns `null`; the instance lives in the mesh, not the scene graph.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ImageInstance: import("react").MemoExoticComponent<(props: ImageInstanceProps) => null>;
|
|
29
|
+
//# sourceMappingURL=ImageInstance.d.ts.map
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { memo } from 'react';
|
|
2
|
+
import { Matrix4 } from 'three';
|
|
3
|
+
import { shapeToMatrix, useDefSync, writeMatrixIfChanged } from '../containers';
|
|
4
|
+
import { imageSourceSize } from './atlas-packer';
|
|
5
|
+
/**
|
|
6
|
+
* Keeps one image placement current: claims a slot on mount (where the container writes the fixed
|
|
7
|
+
* uv region), writes the def's transform and visibility on mount and after every `update(def)`, and
|
|
8
|
+
* releases the slot on unmount.
|
|
9
|
+
*
|
|
10
|
+
* Renders no scene node — the mesh belongs to the container. Only the transform lives here:
|
|
11
|
+
* visibility is `useDefSync`'s, the uv region is written once at claim (a def's source cannot
|
|
12
|
+
* change), and color has no analogue for a textured quad. Memoized for the same reason as
|
|
13
|
+
* `ShapeInstance`: a structural change hands the atlas a fresh placement list, rebuilding every
|
|
14
|
+
* instance element, so only prop-equality keeps the unchanged siblings from re-rendering. Both props
|
|
15
|
+
* are identity-stable across a membership's lifetime — a change repacks into a fresh container and
|
|
16
|
+
* fresh placements — so the bailout holds.
|
|
17
|
+
* @param props - The def, its placement, and its container.
|
|
18
|
+
* @returns `null`; the instance lives in the mesh, not the scene graph.
|
|
19
|
+
*/
|
|
20
|
+
export const ImageInstance = memo(function ImageInstance(props) {
|
|
21
|
+
const { def, packed, container } = props;
|
|
22
|
+
useDefSync(container, def, packed, (slot) => {
|
|
23
|
+
writeImageMatrix(container.mesh, slot, def, packed);
|
|
24
|
+
});
|
|
25
|
+
return null;
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Writes an image placement's transform into its instance, skipping the write when nothing moved.
|
|
29
|
+
*
|
|
30
|
+
* `bounds` is a rect, so the quad's placement composes exactly as a rect shape's does; the image's
|
|
31
|
+
* own offsets are then post-multiplied onto it, innermost last. The origin shifts the quad within
|
|
32
|
+
* its own unit square so the anchor — not the quad's center — lands on `bounds.center`, which also
|
|
33
|
+
* makes the anchor the point rotation pivots about. A split source draws as several instances, so
|
|
34
|
+
* this instance's quad is finally shrunk onto the fraction of the image its tile covers.
|
|
35
|
+
* @param mesh - The mesh holding the instance.
|
|
36
|
+
* @param slot - The instance's slot.
|
|
37
|
+
* @param def - The image def supplying the transform.
|
|
38
|
+
* @param packed - This instance's placement, whose `source` region marks it as a tile.
|
|
39
|
+
*/
|
|
40
|
+
function writeImageMatrix(mesh, slot, def, packed) {
|
|
41
|
+
// The shared scratch `shapeToMatrix` returns, adjusted in place below and uploaded before any
|
|
42
|
+
// other write can claim it.
|
|
43
|
+
const matrix = shapeToMatrix(def.bounds);
|
|
44
|
+
// Unit-plane axes run the same way as image axes — x right, y down, matching the atlas uv and the
|
|
45
|
+
// scene's y-down coordinates — so an origin of `[0, 0]` (top-left) shifts the quad by a positive
|
|
46
|
+
// half in both, putting its top-left corner on the bounds' center.
|
|
47
|
+
const [originX, originY] = def.origin ?? DEFAULT_ORIGIN;
|
|
48
|
+
matrix.multiply(_origin.makeTranslation(0.5 - originX, 0.5 - originY, 0));
|
|
49
|
+
if (packed.source)
|
|
50
|
+
applyTile(matrix, packed.source, def);
|
|
51
|
+
writeMatrixIfChanged(mesh, slot, matrix);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Post-multiplies the image transform by the local sub-quad a tile occupies, so a split source's
|
|
55
|
+
* tiles reassemble into the whole image. The tile's fraction of the source (in source pixels) is
|
|
56
|
+
* its fraction of the image, so the sub-quad is that fraction of the unit plane — scaled to the
|
|
57
|
+
* tile's size and translated to its center, both in unit-plane coordinates.
|
|
58
|
+
* @param matrix - The image transform, multiplied in place.
|
|
59
|
+
* @param source - The tile's region of the source, in source pixels.
|
|
60
|
+
* @param def - The def whose source supplies the total pixel dimensions.
|
|
61
|
+
*/
|
|
62
|
+
function applyTile(matrix, source, def) {
|
|
63
|
+
const { width, height } = imageSourceSize(def.source);
|
|
64
|
+
if (width <= 0 || height <= 0)
|
|
65
|
+
return;
|
|
66
|
+
const fx0 = source.x / width;
|
|
67
|
+
const fy0 = source.y / height;
|
|
68
|
+
const fx1 = (source.x + source.width) / width;
|
|
69
|
+
const fy1 = (source.y + source.height) / height;
|
|
70
|
+
_tile
|
|
71
|
+
.makeScale(fx1 - fx0, fy1 - fy0, 1)
|
|
72
|
+
.setPosition((fx0 + fx1) / 2 - 0.5, (fy0 + fy1) / 2 - 0.5, 0);
|
|
73
|
+
matrix.multiply(_tile);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The anchor a def leaves unset: the image's center, so `bounds.center` is where the middle of the
|
|
77
|
+
* image sits. Matches {@link ImageDef.origin}'s documented default.
|
|
78
|
+
*/
|
|
79
|
+
const DEFAULT_ORIGIN = [0.5, 0.5];
|
|
80
|
+
// Scratch shared by every instance and every write: filled and uploaded within a single
|
|
81
|
+
// synchronous statement, so an instance costs a texture write and no allocation.
|
|
82
|
+
const _origin = new Matrix4();
|
|
83
|
+
const _tile = new Matrix4();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ImageDef } from '../../types/defs';
|
|
2
|
+
import { type DefsProps } from '../containers';
|
|
3
|
+
/** Props for {@link Images}. */
|
|
4
|
+
export interface ImagesProps extends DefsProps<ImageDef> {
|
|
5
|
+
/**
|
|
6
|
+
* Largest atlas edge in pixels, capping how big a source can be before it is split into tiles.
|
|
7
|
+
* Defaults to the GPU's `maxTextureSize`, which is the true hardware ceiling; pass a smaller
|
|
8
|
+
* value to cap atlas memory below it, or to force splitting deterministically in a test.
|
|
9
|
+
*/
|
|
10
|
+
maxAtlasSize?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Draws a collection of images as textured quads, packing their pixels into one or more atlases and
|
|
14
|
+
* drawing each atlas as a single `InstancedMesh` — so a layer of many images costs a handful of
|
|
15
|
+
* draw calls, not one per image.
|
|
16
|
+
*
|
|
17
|
+
* Unlike a shape layer, an image layer can span **several meshes**: bin-packing splits the images
|
|
18
|
+
* across as many atlases as their pixels need, and each atlas gets its own mesh, batch, and
|
|
19
|
+
* texture (an {@link ImageAtlas}). A def whose source is too big for one atlas is cut into tiles
|
|
20
|
+
* that may land on different atlases, so one def can drive several instances — the atlas iterates
|
|
21
|
+
* its packed placements, not the defs.
|
|
22
|
+
*
|
|
23
|
+
* Packing has no incremental path, so a change to the **set** of images **repacks from scratch**: a
|
|
24
|
+
* fresh atlas set under fresh keys, remounting every mesh and instance. A **reorder** of the same
|
|
25
|
+
* set does not — packing is order-independent, so the atlases stand and each simply re-labels its
|
|
26
|
+
* instances' paint order in place. A per-def `update()` flows straight to the instance's slot, never
|
|
27
|
+
* through here.
|
|
28
|
+
*
|
|
29
|
+
* Paint order holds **within** an atlas (each mesh sorts its instances by the def's membership
|
|
30
|
+
* index) but is best-effort **across** atlases: separate meshes draw in atlas order, which packing
|
|
31
|
+
* decides, not paint order. Overlapping images in one layer that pack onto different atlases is the
|
|
32
|
+
* one case this does not order — rare for the markers, dots, and logos an image layer holds.
|
|
33
|
+
* @param props - The images to draw.
|
|
34
|
+
* @returns One {@link ImageAtlas} per packed atlas.
|
|
35
|
+
*/
|
|
36
|
+
export declare function Images(props: ImagesProps): import("react").JSX.Element;
|
|
37
|
+
//# sourceMappingURL=Images.d.ts.map
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useThree } from '@react-three/fiber';
|
|
3
|
+
import { use, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { CanvasTexture, SRGBColorSpace } from 'three';
|
|
5
|
+
import { InstancedMesh } from '../../core/instanced/InstancedMesh';
|
|
6
|
+
import { defKey, useContainer } from '../containers';
|
|
7
|
+
import { TextureMaterial } from '../materials/TextureMaterial';
|
|
8
|
+
import { packAtlases } from './atlas-packer';
|
|
9
|
+
import { ImageContainer, UV_OFFSET_UNIFORM } from './image-container';
|
|
10
|
+
import { ImageInstance } from './ImageInstance';
|
|
11
|
+
import { TextureBudgetContext, useResizeFactor } from './texture-budget';
|
|
12
|
+
/**
|
|
13
|
+
* Draws a collection of images as textured quads, packing their pixels into one or more atlases and
|
|
14
|
+
* drawing each atlas as a single `InstancedMesh` — so a layer of many images costs a handful of
|
|
15
|
+
* draw calls, not one per image.
|
|
16
|
+
*
|
|
17
|
+
* Unlike a shape layer, an image layer can span **several meshes**: bin-packing splits the images
|
|
18
|
+
* across as many atlases as their pixels need, and each atlas gets its own mesh, batch, and
|
|
19
|
+
* texture (an {@link ImageAtlas}). A def whose source is too big for one atlas is cut into tiles
|
|
20
|
+
* that may land on different atlases, so one def can drive several instances — the atlas iterates
|
|
21
|
+
* its packed placements, not the defs.
|
|
22
|
+
*
|
|
23
|
+
* Packing has no incremental path, so a change to the **set** of images **repacks from scratch**: a
|
|
24
|
+
* fresh atlas set under fresh keys, remounting every mesh and instance. A **reorder** of the same
|
|
25
|
+
* set does not — packing is order-independent, so the atlases stand and each simply re-labels its
|
|
26
|
+
* instances' paint order in place. A per-def `update()` flows straight to the instance's slot, never
|
|
27
|
+
* through here.
|
|
28
|
+
*
|
|
29
|
+
* Paint order holds **within** an atlas (each mesh sorts its instances by the def's membership
|
|
30
|
+
* index) but is best-effort **across** atlases: separate meshes draw in atlas order, which packing
|
|
31
|
+
* decides, not paint order. Overlapping images in one layer that pack onto different atlases is the
|
|
32
|
+
* one case this does not order — rare for the markers, dots, and logos an image layer holds.
|
|
33
|
+
* @param props - The images to draw.
|
|
34
|
+
* @returns One {@link ImageAtlas} per packed atlas.
|
|
35
|
+
*/
|
|
36
|
+
export function Images(props) {
|
|
37
|
+
const { defs, maxAtlasSize } = props;
|
|
38
|
+
const gl = useThree((state) => state.gl);
|
|
39
|
+
const maxTextureSize = maxAtlasSize ?? gl.capabilities.maxTextureSize;
|
|
40
|
+
// Repack when the *set* of images changes, via the "adjust state on prop change" pattern. The
|
|
41
|
+
// comparison is by content, not identity: `useStagedChildren` rebuilds its snapshot on *every*
|
|
42
|
+
// `update(layer)` — including one that only flipped the layer's own `hidden` — so identity alone
|
|
43
|
+
// would repack for changes that touched no image at all. Order is excluded on purpose: packing
|
|
44
|
+
// reads only pixels, so a reorder produces the same atlases and needs no repack, only the
|
|
45
|
+
// paint-order relabel each atlas does below. Set equality is O(n) over a list already in cache,
|
|
46
|
+
// against a repack that redraws every canvas.
|
|
47
|
+
const [packed, setPacked] = useState(() => packImages(defs, maxTextureSize, 0));
|
|
48
|
+
if (!sameSet(packed.defs, defs)) {
|
|
49
|
+
setPacked((current) => packImages(defs, maxTextureSize, current.generation + 1));
|
|
50
|
+
}
|
|
51
|
+
return (_jsx(_Fragment, { children: packed.atlases.map((atlas) => (_jsx(ImageAtlas, { atlas: atlas, defs: defs }, atlasKey(atlas, packed.generation)))) }));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Draws one atlas as an `InstancedMesh`: the R3F-owned mesh with the atlas texture as its
|
|
55
|
+
* `TextureMaterial`, plus one {@link ImageInstance} per placement on the atlas. Its set of images is
|
|
56
|
+
* fixed for its lifetime — a repack remounts the whole component — so the batch and texture are
|
|
57
|
+
* built once from state and released together on unmount. Paint order is not fixed: a reorder keeps
|
|
58
|
+
* this atlas and re-labels its instances through the effect below.
|
|
59
|
+
*
|
|
60
|
+
* The uploaded texture is not fixed either: a resizable atlas registers with the scene's texture
|
|
61
|
+
* budget and re-derives a downscaled copy of its canvas whenever the shared resize factor moves (see
|
|
62
|
+
* {@link resizeTexture}). That is a texture re-upload, not a repack — the mesh, container,
|
|
63
|
+
* instances, and their normalized uv regions all stand, since uv is invariant to the canvas's pixel
|
|
64
|
+
* size.
|
|
65
|
+
* @param props - The atlas and the layer's images in paint order.
|
|
66
|
+
* @returns The mesh and one instance component per placement.
|
|
67
|
+
*/
|
|
68
|
+
function ImageAtlas(props) {
|
|
69
|
+
const { atlas, defs } = props;
|
|
70
|
+
const [texture] = useState(() => makeAtlasTexture(atlas.canvas));
|
|
71
|
+
const container = useContainer(() => new ImageContainer(atlas), defs);
|
|
72
|
+
const invalidate = useThree((state) => state.invalidate);
|
|
73
|
+
const budget = use(TextureBudgetContext);
|
|
74
|
+
const factor = useResizeFactor(budget, atlas);
|
|
75
|
+
const displayRef = useRef(undefined);
|
|
76
|
+
// Only the texture is ours to free — the mesh, its quad, and its material are all R3F's.
|
|
77
|
+
// StrictMode's simulated unmount disposes then remounts, but three's `dispose` only frees GPU
|
|
78
|
+
// resources — the state-retained texture re-uploads from its canvas on the next render — so the
|
|
79
|
+
// double is a harmless dev-only reupload, not a use-after-free.
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
invalidate();
|
|
82
|
+
return () => texture.dispose();
|
|
83
|
+
}, [texture, invalidate]);
|
|
84
|
+
// Re-derive the uploaded pixels for the current resize factor. Runs on mount and every factor
|
|
85
|
+
// move; a fixed atlas reads `1` forever, so this settles once for it and never fires again.
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
resizeTexture(texture, atlas.canvas, displayRef, factor);
|
|
88
|
+
invalidate();
|
|
89
|
+
}, [texture, atlas, factor, invalidate]);
|
|
90
|
+
// `args` is a frozen snapshot so R3F never rebuilds the mesh; the `ref` arrow (not
|
|
91
|
+
// `ref={container.bind}`) keeps the React Compiler from inferring `container` itself as a ref and
|
|
92
|
+
// rejecting its render reads.
|
|
93
|
+
// The quad and the material are children so R3F creates, attaches, and disposes both — the args
|
|
94
|
+
// pair are placeholders the constructor demands (see `ImageMeshArgs`). The material has to be per
|
|
95
|
+
// mesh: `InstancedMeshExt` wraps whatever it draws with in a closure over its own textures, and two
|
|
96
|
+
// instanced meshes on one material would both render against the first one's.
|
|
97
|
+
return (_jsxs(_Fragment, { children: [_jsxs(InstancedMesh, { args: container.args, ref: (mesh) => container.bind(mesh), sortObjects: true, customSort: container.customSort, perObjectFrustumCulled: true, children: [_jsx("planeGeometry", {}), _jsx(TextureMaterial, { map: texture, uvOffset: UV_OFFSET_UNIFORM })] }), atlas.images.map((packed) => (_jsx(ImageInstance, { def: packed.def, packed: packed, container: container }, `${defKey(packed.def)}:${packed.uv.u0}:${packed.uv.v0}`)))] }));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Whether two snapshots hold the same *set* of images, order aside — the question "does this need a
|
|
101
|
+
* repack". Order is excluded on purpose: packing reads only pixels, so a reorder produces the same
|
|
102
|
+
* atlases and needs only a paint-order relabel, not a repack. Array identity answers neither
|
|
103
|
+
* question, because the store hands out a fresh snapshot on every layer update.
|
|
104
|
+
* @param a - The packed set.
|
|
105
|
+
* @param b - The incoming set.
|
|
106
|
+
* @returns Whether they hold the same defs.
|
|
107
|
+
*/
|
|
108
|
+
function sameSet(a, b) {
|
|
109
|
+
if (a.length !== b.length)
|
|
110
|
+
return false;
|
|
111
|
+
const set = new Set(a);
|
|
112
|
+
return b.every((def) => set.has(def));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* A stable React key for an atlas: the repack generation, so a repack remounts every atlas, plus
|
|
116
|
+
* its first placement's def, uv origin, and — for a split source — tile region, which together no
|
|
117
|
+
* other atlas in the same generation can repeat (a placement lands on exactly one atlas). Packing
|
|
118
|
+
* never returns an empty atlas, so the first placement always exists.
|
|
119
|
+
* @param atlas - The atlas to key.
|
|
120
|
+
* @param generation - The repack counter this atlas belongs to.
|
|
121
|
+
* @returns The key.
|
|
122
|
+
*/
|
|
123
|
+
function atlasKey(atlas, generation) {
|
|
124
|
+
const first = atlas.images[0];
|
|
125
|
+
// A def keys by identity and uv origin, but a source split into one-tile-per-atlas puts the same
|
|
126
|
+
// def at uv origin (0, 0) on every one of its atlases; the tile's source region is what tells
|
|
127
|
+
// those atlases apart. Absent for an unsplit image, whose uv origin already differs per atlas.
|
|
128
|
+
const region = first.source ? `:${first.source.x},${first.source.y}` : '';
|
|
129
|
+
return `${generation}:${defKey(first.def)}:${first.uv.u0}:${first.uv.v0}${region}`;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Packs a set of images into atlases. Paint order is not recorded here — it is a layer-wide property
|
|
133
|
+
* the atlases relabel from the current `defs` on every update, so a reorder never repacks.
|
|
134
|
+
* @param defs - The images to pack.
|
|
135
|
+
* @param maxDimension - Largest atlas edge, the GPU's max texture size.
|
|
136
|
+
* @param generation - The repack counter for this pack.
|
|
137
|
+
* @returns The pack.
|
|
138
|
+
*/
|
|
139
|
+
function packImages(defs, maxDimension, generation) {
|
|
140
|
+
return { defs, atlases: packAtlases(defs, maxDimension), generation };
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Points an atlas texture at the pixels it should upload for the current resize factor: the full
|
|
144
|
+
* canvas at `factor >= 1`, or a downscaled copy of it below that.
|
|
145
|
+
*
|
|
146
|
+
* The copy lives in `displayRef`, created on first need and resized in place after — so a factor that
|
|
147
|
+
* later climbs back (a budget freed up) re-derives from the untouched full canvas, never upscaling
|
|
148
|
+
* pixels already thrown away. The full canvas is retained regardless (the atlas holds it), so this
|
|
149
|
+
* costs one extra canvas only while actually scaling. UVs are untouched throughout: they are
|
|
150
|
+
* normalized, so the same regions address the smaller canvas unchanged.
|
|
151
|
+
* @param texture - The atlas texture to re-point.
|
|
152
|
+
* @param full - The full-resolution atlas canvas, never mutated.
|
|
153
|
+
* @param displayRef - Holds the downscaled copy across factor changes.
|
|
154
|
+
* @param factor - The linear factor to scale by, in `(0, 1]`.
|
|
155
|
+
*/
|
|
156
|
+
function resizeTexture(texture, full, displayRef, factor) {
|
|
157
|
+
if (factor >= 1) {
|
|
158
|
+
// Point back at the full canvas; a copy from an earlier, smaller factor is left for GC.
|
|
159
|
+
if (texture.image !== full) {
|
|
160
|
+
texture.image = full;
|
|
161
|
+
texture.needsUpdate = true;
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const width = Math.max(1, Math.round(full.width * factor));
|
|
166
|
+
const height = Math.max(1, Math.round(full.height * factor));
|
|
167
|
+
const display = (displayRef.current ??= document.createElement('canvas'));
|
|
168
|
+
// Setting the size also clears the canvas, so the downscale draws onto a blank surface.
|
|
169
|
+
display.width = width;
|
|
170
|
+
display.height = height;
|
|
171
|
+
const context = display.getContext('2d');
|
|
172
|
+
// No 2d context is the same dead end as a blank atlas: fall back to the full canvas so the images
|
|
173
|
+
// still draw — over budget — rather than not at all.
|
|
174
|
+
if (!context) {
|
|
175
|
+
texture.image = full;
|
|
176
|
+
texture.needsUpdate = true;
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
context.drawImage(full, 0, 0, width, height);
|
|
180
|
+
texture.image = display;
|
|
181
|
+
texture.needsUpdate = true;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Wraps an atlas canvas as a texture for `MeshBasicMaterial.map`.
|
|
185
|
+
*
|
|
186
|
+
* Mipmaps stay on: a floor plan is zoomed far out as readily as far in, and without them every
|
|
187
|
+
* image shimmers under minification. The cost is that neighbors can bleed through the deeper mip
|
|
188
|
+
* levels, where the packer's one-pixel gutter no longer separates them.
|
|
189
|
+
* @param canvas - The packed atlas canvas.
|
|
190
|
+
* @returns The texture.
|
|
191
|
+
*/
|
|
192
|
+
function makeAtlasTexture(canvas) {
|
|
193
|
+
const texture = new CanvasTexture(canvas);
|
|
194
|
+
// The atlas holds sRGB pixels; tagging the color space is what makes `MeshBasicMaterial` sample
|
|
195
|
+
// and display them without a gamma shift.
|
|
196
|
+
texture.colorSpace = SRGBColorSpace;
|
|
197
|
+
// Upload the canvas rows in their own order rather than three's default vertical flip, so v runs
|
|
198
|
+
// down the atlas — the same direction as the packer's uv regions and as the scene's y axis. Every
|
|
199
|
+
// axis in the chain then points the same way; flip at one end only and images come out upside
|
|
200
|
+
// down.
|
|
201
|
+
texture.flipY = false;
|
|
202
|
+
texture.generateMipmaps = true;
|
|
203
|
+
return texture;
|
|
204
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { type ImageDef, type ImageSource } from '../../types/defs';
|
|
2
|
+
/** A canvas an atlas is drawn onto. `OffscreenCanvas` included so packing can move to a worker. */
|
|
3
|
+
export type AtlasCanvas = HTMLCanvasElement | OffscreenCanvas;
|
|
4
|
+
/**
|
|
5
|
+
* Creates the backing canvas for one atlas, sized to that atlas exactly.
|
|
6
|
+
* @param width - The atlas width in pixels.
|
|
7
|
+
* @param height - The atlas height in pixels.
|
|
8
|
+
* @returns The canvas to draw on.
|
|
9
|
+
*/
|
|
10
|
+
export type CreateAtlasCanvas = (width: number, height: number) => AtlasCanvas;
|
|
11
|
+
/**
|
|
12
|
+
* A region of a source image, in **source pixels with a top-left origin** — the same axes as
|
|
13
|
+
* `ImageDef.bounds`, and literally the `sx, sy, sw, sh` the packer hands to `drawImage`. Kept in
|
|
14
|
+
* pixels rather than normalized so it cannot be mistaken for a {@link UvRect}, whose origin is the
|
|
15
|
+
* other corner.
|
|
16
|
+
*/
|
|
17
|
+
export interface SourceRect {
|
|
18
|
+
/** Distance from the source's left edge, in pixels. */
|
|
19
|
+
x: number;
|
|
20
|
+
/** Distance from the source's top edge, in pixels. */
|
|
21
|
+
y: number;
|
|
22
|
+
/** Region width in pixels. */
|
|
23
|
+
width: number;
|
|
24
|
+
/** Region height in pixels. */
|
|
25
|
+
height: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A region of an atlas, **normalized in the canvas's own axes: a top-left origin, v running down**.
|
|
29
|
+
*
|
|
30
|
+
* Consumed by a texture uploaded with `flipY = false`, which maps canvas row 0 to `v = 0`, so these
|
|
31
|
+
* numbers feed a uv transform directly with no vertical inversion. That is deliberate: the scene's
|
|
32
|
+
* y axis already points down (SVG coordinates, and the camera is placed to match), so a uv space
|
|
33
|
+
* that also runs down keeps every axis in the pipeline pointing the same way — invert at one end
|
|
34
|
+
* only and images come out upside down.
|
|
35
|
+
*/
|
|
36
|
+
export interface UvRect {
|
|
37
|
+
/** Left edge, `0` at the atlas's left. */
|
|
38
|
+
u0: number;
|
|
39
|
+
/** Top edge, `0` at the atlas's top. */
|
|
40
|
+
v0: number;
|
|
41
|
+
/** Right edge. */
|
|
42
|
+
u1: number;
|
|
43
|
+
/** Bottom edge. */
|
|
44
|
+
v1: number;
|
|
45
|
+
}
|
|
46
|
+
/** One image — or one tile of a split image — placed in an atlas. */
|
|
47
|
+
export interface PackedImage {
|
|
48
|
+
/**
|
|
49
|
+
* The def these pixels belong to. Defs whose sources dedupe appear as separate entries sharing
|
|
50
|
+
* one region, so the list maps one-to-one onto the instances an atlas has to draw.
|
|
51
|
+
*/
|
|
52
|
+
def: ImageDef;
|
|
53
|
+
/** Where the pixels sit in the atlas. */
|
|
54
|
+
uv: UvRect;
|
|
55
|
+
/**
|
|
56
|
+
* Which part of `def.source` this entry holds. Undefined when the source was small enough to
|
|
57
|
+
* pack whole, which is the common case; set only on the tiles of a split source, where a
|
|
58
|
+
* consumer needs it to work out the fraction of `def.bounds` this tile covers.
|
|
59
|
+
*/
|
|
60
|
+
source?: SourceRect;
|
|
61
|
+
}
|
|
62
|
+
/** One packed atlas: a canvas of pixels, and what landed where on it. */
|
|
63
|
+
export interface Atlas {
|
|
64
|
+
/** The canvas holding the packed pixels. Its `width`/`height` are the atlas's size. */
|
|
65
|
+
canvas: AtlasCanvas;
|
|
66
|
+
/** Every def placement on this atlas. */
|
|
67
|
+
images: PackedImage[];
|
|
68
|
+
/**
|
|
69
|
+
* Whether this atlas's pixels may be downscaled to fit a memory budget. Image and bitmap sources
|
|
70
|
+
* pack into resizable atlases; canvas sources into fixed ones. An atlas never mixes the two (they
|
|
71
|
+
* are packed as separate groups), so this one flag speaks for every placement on it — which is
|
|
72
|
+
* what lets a memory budget scale the whole canvas at once without dragging a canvas source down
|
|
73
|
+
* with the images. See {@link isResizableSource}.
|
|
74
|
+
*/
|
|
75
|
+
resizable: boolean;
|
|
76
|
+
}
|
|
77
|
+
/** Options for {@link packAtlases}. */
|
|
78
|
+
export interface AtlasPackerOptions {
|
|
79
|
+
/** Creates each atlas canvas. Defaults to a DOM canvas. */
|
|
80
|
+
createCanvas?: CreateAtlasCanvas;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether a source's pixels may be downscaled to fit a memory budget. `true` for decoded images and
|
|
84
|
+
* bitmaps, `false` for canvases — a canvas's pixels are the caller's, counted at full size but never
|
|
85
|
+
* compressed (see the scene's `memoryLimit`).
|
|
86
|
+
*
|
|
87
|
+
* Detected by the absence of `getContext`: `HTMLCanvasElement` and `OffscreenCanvas` both have it,
|
|
88
|
+
* `HTMLImageElement` and `ImageBitmap` do not. A property test rather than `instanceof`, because the
|
|
89
|
+
* SDK runs in WebViews where `OffscreenCanvas`/`ImageBitmap` may be missing as globals and an
|
|
90
|
+
* `instanceof` against an absent one throws.
|
|
91
|
+
* @param source - The source to classify.
|
|
92
|
+
* @returns Whether the source can be downscaled.
|
|
93
|
+
*/
|
|
94
|
+
export declare function isResizableSource(source: ImageSource): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Packs image defs into atlas canvases and reports where every def's pixels landed.
|
|
97
|
+
*
|
|
98
|
+
* Sources are split by kind first — resizable (image/bitmap) from fixed (canvas) — and each kind is
|
|
99
|
+
* packed on its own, so no atlas ever mixes the two and a memory budget can scale a resizable atlas
|
|
100
|
+
* whole without touching a canvas's pixels. Within a kind, sources are deduped — two defs pointing
|
|
101
|
+
* at the same URL, or holding the same canvas object, are drawn once and share one region — and then
|
|
102
|
+
* offered to the packer whole. Anything too big for an atlas comes back parked in a natural-size bin
|
|
103
|
+
* of its own, which the packer flags; those are the only sources cut into tiles, and the tiles go
|
|
104
|
+
* back through the same packer. Letting the packer decide is what keeps the guarantee that no atlas
|
|
105
|
+
* exceeds `maxDimension` without measuring every image up front.
|
|
106
|
+
*
|
|
107
|
+
* Packing reads only the sources' pixel dimensions, never `bounds`, so a def that later moves or
|
|
108
|
+
* resizes keeps its region: the quad's matrix scales it, and nothing needs repacking. Membership
|
|
109
|
+
* changes do, though — this is a batch call with no incremental path.
|
|
110
|
+
* @param defs - The images to pack.
|
|
111
|
+
* @param maxDimension - Largest atlas edge in pixels, floored to a positive integer.
|
|
112
|
+
* @param options - Overrides for how atlas canvases are made.
|
|
113
|
+
* @returns One entry per atlas, in packing order — resizable atlases first, then fixed.
|
|
114
|
+
*/
|
|
115
|
+
export declare function packAtlases(defs: readonly ImageDef[], maxDimension: number, options?: AtlasPackerOptions): Atlas[];
|
|
116
|
+
/**
|
|
117
|
+
* The pixel size of an image source.
|
|
118
|
+
*
|
|
119
|
+
* Duck-typed rather than `instanceof`: the SDK runs in WebViews where `OffscreenCanvas` and
|
|
120
|
+
* `ImageBitmap` may be missing as globals, and an `instanceof` against an absent global throws.
|
|
121
|
+
* @param source - The source to measure.
|
|
122
|
+
* @returns Its intrinsic size, `0 × 0` for an image element that has not decoded yet.
|
|
123
|
+
*/
|
|
124
|
+
export declare function imageSourceSize(source: ImageSource): {
|
|
125
|
+
width: number;
|
|
126
|
+
height: number;
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=atlas-packer.d.ts.map
|