@arcadekit/render-three 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lucas Thevenet
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,73 @@
1
- # Temporary Holding Version
1
+ # @arcadekit/render-three
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Three.js drawing for arcadekit games. `Stage` is a renderer, scene and camera that fill an element and resize with it; its `"pixel"` camera (`PixelCamera`) looks straight down and keeps sprite pixels whole. `loadSpriteSheet` loads an Aseprite sheet (PNG and JSON) as an Effect, `InstancedSprites` draws many sprites from one sheet in one draw call, and `frameAt` picks a tag's frame at a time.
4
+
5
+ Part of [arcadekit](https://github.com/lucasthevenet/arcadekit#readme). Needs the DOM and WebGL.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @arcadekit/render-three three effect
11
+ pnpm add -D @types/three
12
+ ```
13
+
14
+ Peer dependencies: `three` (^0.187) and `effect` (~4.1). `@types/three` (^0.187, an optional peer) gives Three.js its types.
15
+
16
+ ## Example
17
+
18
+ A view that draws every enemy with its tag's animation, following the hero (a cut-down version of the genres' views). The app loads the sheet with `loadSpriteSheet("/sprites/game.json")` and owns it: the view never frees it.
19
+
20
+ ```ts
21
+ import { InstancedSprites, Stage, frameAt } from "@arcadekit/render-three";
22
+ import type { SpriteSheet } from "@arcadekit/render-three";
23
+
24
+ interface World {
25
+ readonly heroX: number;
26
+ readonly heroZ: number;
27
+ readonly enemies: {
28
+ readonly count: number;
29
+ readonly x: Float32Array;
30
+ readonly z: Float32Array;
31
+ };
32
+ }
33
+
34
+ export class WorldView {
35
+ private readonly stage: Stage<"pixel">;
36
+ private readonly enemies: InstancedSprites;
37
+ private readonly sheet: SpriteSheet;
38
+
39
+ constructor(container: HTMLElement, sheet: SpriteSheet) {
40
+ this.sheet = sheet;
41
+ this.stage = new Stage(container, {
42
+ camera: "pixel",
43
+ pixelsPerUnit: 16,
44
+ background: "#17151f",
45
+ });
46
+ this.enemies = new InstancedSprites(sheet, {
47
+ capacity: 1000,
48
+ unitsPerPixel: 1 / 16,
49
+ });
50
+ this.stage.scene.add(this.enemies.mesh);
51
+ }
52
+
53
+ render(world: World | null, timeSeconds: number): void {
54
+ const walk = this.sheet.data.tags.get("slime/move");
55
+ if (world !== null && walk !== undefined) {
56
+ const frame = frameAt(this.sheet.data, walk, timeSeconds);
57
+ for (let i = 0; i < world.enemies.count; i++) {
58
+ this.enemies.set(i, world.enemies.x[i]!, world.enemies.z[i]!, frame);
59
+ }
60
+ this.enemies.commit(world.enemies.count);
61
+ this.stage.camera.follow(world.heroX, world.heroZ);
62
+ }
63
+ this.stage.render();
64
+ }
65
+
66
+ dispose(): void {
67
+ // Frees everything in the scene except the sheet's texture, which the app frees.
68
+ this.stage.dispose();
69
+ }
70
+ }
71
+ ```
72
+
73
+ See [ADR-0015](https://github.com/lucasthevenet/arcadekit/blob/main/docs/adr/0015-pixel-art-sprites-loaded-by-the-app.md) (pixel-art sprites loaded by the app).
@@ -0,0 +1,374 @@
1
+ import * as THREE from "three";
2
+ import { Data, Effect } from "effect";
3
+ /** Keeps the camera at a fixed offset from a target on the ground plane, looking at it. Top-down and isometric games. */
4
+ export declare const followTarget: (camera: THREE.Camera, target: {
5
+ readonly x: number;
6
+ readonly z: number;
7
+ }, offset: {
8
+ readonly x: number;
9
+ readonly y: number;
10
+ readonly z: number;
11
+ }) => void;
12
+ /**
13
+ * Circles the camera around a point on the ground plane at a fixed height, looking at it.
14
+ * `angle` is in radians; 0 puts the camera on the point's +z side. Menu backdrops and
15
+ * showcase views.
16
+ */
17
+ export declare const orbitAround: (camera: THREE.Camera, center: {
18
+ readonly x: number;
19
+ readonly z: number;
20
+ }, options: {
21
+ readonly radius: number;
22
+ readonly height: number;
23
+ readonly angle: number;
24
+ }) => void;
25
+ /** A rectangle on the ground plane (y = 0), in world units. */
26
+ interface GroundBounds {
27
+ readonly minX: number;
28
+ readonly maxX: number;
29
+ readonly minZ: number;
30
+ readonly maxZ: number;
31
+ }
32
+ interface FitCameraOptions {
33
+ /** World units of space left around the bounds on every side. Defaults to 0. */
34
+ readonly margin?: number;
35
+ /**
36
+ * How far the camera sits back (toward +z) from straight overhead, as a fraction of its
37
+ * height. 0 looks straight down. Defaults to 0.
38
+ */
39
+ readonly tilt?: number;
40
+ }
41
+ /**
42
+ * Places a camera above a rectangle on the ground plane, looking at its center, so that all of
43
+ * it shows at the camera's current aspect ratio. Board, puzzle and arena games. Call it every
44
+ * frame (it allocates nothing), or at least after each resize.
45
+ *
46
+ * A perspective camera keeps its field of view and moves back far enough. An orthographic
47
+ * camera (`Stage` with `camera: "orthographic"`) changes its frustum to fit instead.
48
+ * With a tilt, the fit is still worked out as if looking straight down. That leaves an
49
+ * orthographic camera a little extra room. It does not hold for a perspective camera: a small
50
+ * tilt (below the tangent of half its field of view) can push the near edge of the bounds off
51
+ * the screen, so give it more margin.
52
+ */
53
+ export declare const fitCamera: (camera: THREE.PerspectiveCamera | THREE.OrthographicCamera, bounds: GroundBounds, options?: FitCameraOptions) => void;
54
+ declare const SpriteSheetErrorBase: ReturnType<typeof Data.TaggedError<"SpriteSheetError">>;
55
+ /** A sprite sheet that couldn't be fetched, decoded or checked. `file` is the JSON or image that failed. */
56
+ export declare class SpriteSheetError extends SpriteSheetErrorBase<{
57
+ readonly file: string;
58
+ readonly message: string;
59
+ readonly cause?: unknown;
60
+ }> {}
61
+ /** How a tag's frames play: Aseprite's tag directions. */
62
+ type SpriteTagDirection = "forward" | "reverse" | "pingpong" | "pingpong_reverse";
63
+ /** One frame of a sheet. Every size and offset is in sprite pixels. */
64
+ interface SpriteFrame {
65
+ /** Aseprite's `filename`, or the frame's key in the "hash" form. */
66
+ readonly name: string;
67
+ /** Where the frame's pixels are in the image, from its top-left corner. */
68
+ readonly x: number;
69
+ readonly y: number;
70
+ readonly width: number;
71
+ readonly height: number;
72
+ /** Where those pixels sit in the untrimmed frame. 0, 0 unless the export trimmed it. */
73
+ readonly offsetX: number;
74
+ readonly offsetY: number;
75
+ /** The untrimmed frame's size: what an anchor is a fraction of. */
76
+ readonly sourceWidth: number;
77
+ readonly sourceHeight: number;
78
+ /** How long the frame shows in an animation, in seconds (Aseprite writes ms). */
79
+ readonly duration: number;
80
+ }
81
+ /** A named run of frames: one animation, such as "slime/move". */
82
+ interface SpriteTag {
83
+ readonly name: string;
84
+ /** First and last frame index, both included. */
85
+ readonly from: number;
86
+ readonly to: number;
87
+ readonly direction: SpriteTagDirection;
88
+ /** One whole loop, in seconds. A pingpong loop plays the middle frames twice. */
89
+ readonly duration: number;
90
+ }
91
+ /** A parsed sheet: its frames in order, a lookup by frame name, and its tags by name. */
92
+ interface SpriteSheetData {
93
+ /** `meta.image` as written: the image's path relative to the JSON. */
94
+ readonly image: string;
95
+ /** The image's size in pixels (`meta.size`). */
96
+ readonly width: number;
97
+ readonly height: number;
98
+ readonly frames: readonly SpriteFrame[];
99
+ /** Frame index by name. If two frames share a name, the first wins. */
100
+ readonly frameByName: ReadonlyMap<string, number>;
101
+ readonly tags: ReadonlyMap<string, SpriteTag>;
102
+ }
103
+ /**
104
+ * Parses an Aseprite JSON export (frames as an array or a hash) and checks it: every frame
105
+ * inside the image, every tag inside the frames, no two tags with one name. `file` names the
106
+ * JSON in the error. Rotated frames (a TexturePacker option) aren't supported. A tag's
107
+ * `repeat` is ignored: animations loop.
108
+ */
109
+ export declare const decodeSpriteSheet: (file: string, json: unknown) => Effect.Effect<SpriteSheetData, SpriteSheetError>;
110
+ /**
111
+ * The frame index (into `sheet.frames`) a tag shows `seconds` into its animation, looping,
112
+ * from each frame's duration and the tag's direction. Allocates nothing: call it per sprite
113
+ * per frame. Negative times count back from the end of a loop.
114
+ */
115
+ export declare const frameAt: (sheet: SpriteSheetData, tag: SpriteTag, seconds: number) => number;
116
+ /**
117
+ * A sprite sheet ready to draw: its frames and tags, and its image as a texture.
118
+ * The app loads it and owns it: views draw from it but never free it (`disposeObject` and
119
+ * `Stage.dispose` skip its texture). The app calls `dispose` when it no longer needs it.
120
+ */
121
+ interface SpriteSheet {
122
+ readonly data: SpriteSheetData;
123
+ /** Nearest filtering, no mipmaps, sRGB, `flipY` off: row 0 of the image is v = 0. */
124
+ readonly texture: THREE.Texture;
125
+ readonly dispose: () => void;
126
+ }
127
+ /**
128
+ * Makes a sheet from parsed data and an image that's already in memory, such as a canvas the
129
+ * art was painted on. `loadSpriteSheet` uses it after fetching both files.
130
+ */
131
+ export declare const makeSpriteSheet: (data: SpriteSheetData, image: TexImageSource) => SpriteSheet;
132
+ /**
133
+ * Loads an Aseprite sheet: fetches the JSON at `jsonUrl`, then the image its `meta.image`
134
+ * names, relative to the JSON. Fails with a `SpriteSheetError` naming the file when either
135
+ * can't be fetched, the JSON is invalid, or the image's size isn't `meta.size`.
136
+ */
137
+ export declare const loadSpriteSheet: (jsonUrl: string) => Effect.Effect<SpriteSheet, SpriteSheetError>;
138
+ interface InstancedSpritesOptions {
139
+ /** The most sprites it can draw at once. Fixed. */
140
+ readonly capacity: number;
141
+ /** World units per sprite pixel: 1/16 draws a 16 px sprite one unit wide. Defaults to 1/16. */
142
+ readonly unitsPerPixel?: number;
143
+ /**
144
+ * The point of a frame a sprite's position marks, as a fraction of the frame's untrimmed size
145
+ * from its top-left corner, rounded to a whole pixel. Defaults to the middle, (0.5, 0.5); a
146
+ * character standing on its feet wants about (0.5, 0.9).
147
+ */
148
+ readonly anchor?: {
149
+ readonly x: number;
150
+ readonly y: number;
151
+ };
152
+ /**
153
+ * Layer added to every sprite's own layer. A higher layer draws over a lower one whatever
154
+ * their positions: ground marks below characters, characters below projectiles. Use whole
155
+ * numbers; layer 0 and up draw above anything at y = 0, such as a ground mesh. Defaults to 0.
156
+ */
157
+ readonly layer?: number;
158
+ /**
159
+ * Blend partly transparent pixels, for soft shadows and markers. Off by default: pixel art
160
+ * draws opaque, with pixels below `alphaTest` cut out, and sorts by depth. A transparent batch
161
+ * doesn't write depth, so its own sprites overlap in index order.
162
+ */
163
+ readonly transparent?: boolean;
164
+ /** Pixels with less alpha (after the sprite's own alpha) aren't drawn. Defaults to 0.5, or 0.01 when transparent. */
165
+ readonly alphaTest?: number;
166
+ /** Rounds each sprite's position to whole sprite pixels, so the art never shimmers. Defaults to true. */
167
+ readonly snap?: boolean;
168
+ /**
169
+ * How far from z = 0, in world units, depth still orders sprites within a layer: beyond it,
170
+ * sprites tie. Defaults to 256.
171
+ */
172
+ readonly sortRange?: number;
173
+ }
174
+ /**
175
+ * Draws up to `capacity` sprites from one sheet in a single draw call, as quads on the ground
176
+ * plane facing a straight-down camera (`PixelCamera`). Each sprite has a position, a frame,
177
+ * a horizontal flip, a tint, a flash toward white, an alpha, a lift and a layer. Within a layer
178
+ * a sprite lower on screen (larger z) draws in front.
179
+ *
180
+ * Each frame, call `set` for every sprite to draw (it resets that sprite's look), then the
181
+ * other setters for those that need them, then `commit(count)`. Nothing allocates per frame.
182
+ * Add `mesh` to the scene. `dispose` (or `disposeObject`) frees its own geometry, material and
183
+ * frame table, never the sheet's texture: the sheet's owner frees that.
184
+ */
185
+ export declare class InstancedSprites {
186
+ readonly mesh: THREE.Mesh<THREE.InstancedBufferGeometry, THREE.ShaderMaterial>;
187
+ readonly capacity: number;
188
+ readonly sheet: SpriteSheet;
189
+ private readonly frameCount;
190
+ private readonly place;
191
+ private readonly frame;
192
+ private readonly tint;
193
+ private readonly frameTable;
194
+ constructor(sheet: SpriteSheet, options: InstancedSpritesOptions);
195
+ /**
196
+ * Places sprite `index` with its feet (its anchor) at (x, z) on the ground, showing frame
197
+ * `frame` (an index into `sheet.data.frames`, as `frameAt` gives), mirrored if `flipX`.
198
+ * Resets its tint, alpha, flash, lift and layer. A frame outside the sheet draws frame 0.
199
+ */
200
+ set(index: number, x: number, z: number, frame: number, flipX?: boolean): void;
201
+ /** Multiplies sprite `index`'s colors by `color` (white leaves them), and sets its alpha. */
202
+ setTint(index: number, color: THREE.Color, alpha?: number): void;
203
+ /** Sets sprite `index`'s alpha (0 to 1) and keeps its tint. Opaque sprites hide below `alphaTest`. */
204
+ setAlpha(index: number, alpha: number): void;
205
+ /** Blends sprite `index` toward white: 0 is its own colors, 1 a white silhouette. A hit flash. */
206
+ setFlash(index: number, amount: number): void;
207
+ /**
208
+ * Draws sprite `index` `lift` world units up the screen, as if floating: a bat. Its depth
209
+ * stays where its feet are, so it sorts with the things standing near it.
210
+ */
211
+ setLift(index: number, lift: number): void;
212
+ /** Puts sprite `index` in another layer, added to the batch's own. See `InstancedSpritesOptions.layer`. */
213
+ setLayer(index: number, layer: number): void;
214
+ /** Shows the first `count` sprites and uploads them. */
215
+ commit(count: number): void;
216
+ /** Removes the mesh and frees its geometry, material and frame table. Never the sheet. */
217
+ dispose(): void;
218
+ }
219
+ /**
220
+ * Draws up to `capacity` copies of one mesh in a single draw call.
221
+ * Call `set` (and optionally `setColor`) for the instances that changed, then `commit(count)`
222
+ * to show the first `count` instances and upload the changes.
223
+ */
224
+ export declare class MeshInstances {
225
+ readonly mesh: THREE.InstancedMesh;
226
+ readonly capacity: number;
227
+ private readonly matrix;
228
+ constructor(geometry: THREE.BufferGeometry, material: THREE.Material, capacity: number);
229
+ /**
230
+ * Places instance `index` at (x, y, z) with a uniform `scale` and a rotation around the vertical axis.
231
+ * For a fixed tilt every instance shares (a flat ring lying on the floor), rotate the geometry once instead.
232
+ */
233
+ set(index: number, x: number, y: number, z: number, scale?: number, rotationY?: number): void;
234
+ setColor(index: number, color: THREE.Color): void;
235
+ /** Shows the first `count` instances and uploads this frame's changes. */
236
+ commit(count: number): void;
237
+ dispose(): void;
238
+ }
239
+ /**
240
+ * Screen pixels per sprite pixel that best shows `viewHeight` world units on a drawing buffer
241
+ * `bufferHeight` pixels tall: the nearest whole number, at least 1.
242
+ */
243
+ export declare const pixelScale: (bufferHeight: number, viewHeight: number, pixelsPerUnit: number) => number;
244
+ /**
245
+ * The largest whole number of screen pixels per sprite pixel at which a `width` x `depth` world
246
+ * unit area fits a `bufferWidth` x `bufferHeight` drawing buffer, at least 1 (a buffer too
247
+ * small for the area at 1 crops it).
248
+ */
249
+ export declare const fitPixelScale: (bufferWidth: number, bufferHeight: number, width: number, depth: number, pixelsPerUnit: number) => number;
250
+ /**
251
+ * Rounds a world position to the nearest pixel edge, at `pixelsPerUnit` pixels per world unit:
252
+ * sprite pixels with the sheet's density, or screen pixels with the camera's.
253
+ */
254
+ export declare const snapToPixel: (value: number, pixelsPerUnit: number) => number;
255
+ /**
256
+ * The frustum for a `bufferWidth` x `bufferHeight` drawing buffer at `pixelsPerWorldUnit`
257
+ * screen pixels per world unit, around a camera at the origin. An odd size gets its spare
258
+ * pixel on the right or bottom, so the camera's position stays on a screen pixel's corner.
259
+ */
260
+ export declare const pixelFrustum: (bufferWidth: number, bufferHeight: number, pixelsPerWorldUnit: number) => {
261
+ readonly left: number;
262
+ readonly right: number;
263
+ readonly top: number;
264
+ readonly bottom: number;
265
+ };
266
+ interface PixelCameraOptions {
267
+ /** Sprite pixels per world unit: 16 draws a 16 px enemy one unit wide. Defaults to 16. */
268
+ readonly pixelsPerUnit?: number;
269
+ /**
270
+ * About how many world units of ground to show top to bottom. The camera picks the whole
271
+ * number of screen pixels per sprite pixel that comes nearest. Defaults to 20.
272
+ */
273
+ readonly viewHeight?: number;
274
+ }
275
+ /**
276
+ * An orthographic camera looking straight down at the ground plane (y = 0), with +x to the
277
+ * right and +z down the screen, so a larger z is lower on screen. It keeps sprite pixels whole:
278
+ * `pixelScale` screen pixels per sprite pixel, a whole number, and a position on whole screen
279
+ * pixels. Give it the drawing buffer's size with `setBufferSize` (a `Stage` made with
280
+ * `camera: "pixel"` does, on every resize), then `follow` a point or `fit` an area each frame.
281
+ * Don't move it with `fitCamera` or `lookAt`: they undo the snapping.
282
+ */
283
+ export declare class PixelCamera extends THREE.OrthographicCamera {
284
+ readonly isPixelCamera = true;
285
+ private pixelsPerUnitValue;
286
+ private viewHeightValue;
287
+ private screenScale;
288
+ private bufferWidth;
289
+ private bufferHeight;
290
+ private targetX;
291
+ private targetZ;
292
+ /** Set by `fit`, cleared by `follow`. */
293
+ private fitted;
294
+ constructor(options?: PixelCameraOptions);
295
+ /** Sprite pixels per world unit. */
296
+ get pixelsPerUnit(): number;
297
+ /** Screen pixels per sprite pixel: a whole number, at least 1. */
298
+ get pixelScale(): number;
299
+ /** Screen (drawing buffer) pixels per world unit. */
300
+ get screenPixelsPerUnit(): number;
301
+ /** The ground height to aim for, in world units. Takes effect at once. */
302
+ setViewHeight(viewHeight: number): void;
303
+ /** The drawing buffer's size in pixels (`renderer.getDrawingBufferSize`), not CSS pixels. */
304
+ setBufferSize(width: number, height: number): void;
305
+ /** Centres the view on a ground point, snapped to the nearest screen pixel. Survivors' hero. */
306
+ follow(x: number, z: number): void;
307
+ /**
308
+ * Shows all of an area plus `margin` world units around it, at the largest whole pixel scale
309
+ * that fits, centred on it. It keeps fitting on resize until the next `follow`. A puzzle board.
310
+ */
311
+ fit(bounds: GroundBounds, margin?: number): void;
312
+ private update;
313
+ }
314
+ /** Which camera a Stage builds. */
315
+ type StageCameraKind = "perspective" | "orthographic" | "pixel";
316
+ /** The camera type for a kind: what `Stage.camera` is. */
317
+ type StageCamera<K extends StageCameraKind> = K extends "pixel" ? PixelCamera : K extends "orthographic" ? THREE.OrthographicCamera : THREE.PerspectiveCamera;
318
+ interface StageOptions<K extends StageCameraKind = "perspective"> {
319
+ /**
320
+ * "perspective" (the default) for a 3D world seen from a point. "orthographic" for a flat
321
+ * board, where sizes shouldn't shrink with distance; place it with `fitCamera`. "pixel" for
322
+ * pixel art seen straight down (a `PixelCamera`); the stage keeps it told the drawing buffer's size.
323
+ */
324
+ readonly camera?: K;
325
+ /**
326
+ * Height of an orthographic camera's view, in world units, until `fitCamera` changes it.
327
+ * Defaults to 10. For a pixel camera, the height it aims for (defaults to 20).
328
+ */
329
+ readonly viewHeight?: number;
330
+ /** Pixel camera only: sprite pixels per world unit. Defaults to 16. */
331
+ readonly pixelsPerUnit?: number;
332
+ readonly background?: THREE.ColorRepresentation;
333
+ }
334
+ /**
335
+ * A renderer, scene and camera that fill a container element and resize with it.
336
+ * The camera is perspective unless `camera: "orthographic"` or `"pixel"` is passed; on resize, an
337
+ * orthographic camera keeps its view height and widens or narrows to the new aspect ratio, and a
338
+ * pixel camera picks its pixel scale again. The pixel ratio is read again on every resize, and
339
+ * a pixel stage sizes its drawing buffer to the canvas's exact device pixels, where the others
340
+ * cap the ratio at 2 (see `drawingBuffer`). The camera is public: change its fields (a
341
+ * perspective camera's `fov`, `near` and `far`) and call `updateProjectionMatrix()`. So is the
342
+ * scene: set `stage.scene.fog` for fog.
343
+ * `dispose()` frees every GPU resource in the scene, except kept textures (see `keepTexture`),
344
+ * and removes the canvas.
345
+ */
346
+ export declare class Stage<K extends StageCameraKind = "perspective"> {
347
+ readonly renderer: THREE.WebGLRenderer;
348
+ readonly scene: THREE.Scene;
349
+ readonly camera: StageCamera<K>;
350
+ private readonly container;
351
+ private readonly resizeObserver;
352
+ constructor(container: HTMLElement, options?: StageOptions<K>);
353
+ render(): void;
354
+ dispose(): void;
355
+ private resize;
356
+ }
357
+ /**
358
+ * Marks a texture that something outside the scene owns, such as a sprite sheet the app
359
+ * loaded: `disposeObject` and `Stage.dispose` leave it alone, and its owner disposes it.
360
+ * Returns the texture.
361
+ */
362
+ export declare const keepTexture: <T extends THREE.Texture>(texture: T) => T;
363
+ /** Whether `keepTexture` marked this texture. */
364
+ export declare const isKeptTexture: (texture: THREE.Texture) => boolean;
365
+ /**
366
+ * Frees the geometries, materials and textures of `root` and everything under it: the textures
367
+ * a material holds (its maps, and a shader material's texture uniforms) and, for a scene, its
368
+ * background and environment. Textures marked with `keepTexture` are skipped.
369
+ * `Stage.dispose` calls it on the whole scene. A view that removes an object from the
370
+ * scene calls it on that object, which `Stage.dispose` no longer reaches.
371
+ */
372
+ export declare const disposeObject: (root: THREE.Object3D) => void;
373
+ export type { FitCameraOptions, GroundBounds, InstancedSpritesOptions, PixelCameraOptions, SpriteFrame, SpriteSheet, SpriteSheetData, SpriteTag, SpriteTagDirection, StageCamera, StageCameraKind, StageOptions };
374
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/camera.ts","../src/sprite-sheet.ts","../src/sprite-loader.ts","../src/instanced-sprites.ts","../src/mesh-instances.ts","../src/pixel-camera.ts","../src/stage.ts"],"mappings":";;;qBAMa,eACX,QAAQ,MAAM,QACd;WAAmB;WAAoB;GACvC;WAAmB;WAAoB;WAAoB;;;;;;;qBAWhD,cACX,QAAQ,MAAM,QACd;WAAmB;WAAoB;GACvC;WACW;WACA;WACA;;;UAYI;WACN;WACA;WACA;WACA;;UAGM;;WAEN;;;;;WAKA;;;;;;;;;;;;;;qBAeE,YACX,QAAQ,MAAM,oBAAoB,MAAM,oBACxC,QAAQ,cACR,UAAS;cChEL,sBAAsB,kBACnB,KAAK;;qBAID,yBAAyB;WAC3B;WACA;WACA;;;KAIC;;UAOK;;WAEN;;WAEA;WACA;WACA;WACA;;WAEA;WACA;;WAEA;WACA;;WAEA;;;UAIM;WACN;;WAEA;WACA;WACA,WAAW;;WAEX;;;UAIM;;WAEN;;WAEA;WACA;WACA,iBAAiB;;WAEjB,aAAa;WACb,MAAM,oBAAoB;;;;;;;;qBAqDxB,oBACX,cACA,kBACC,OAAO,OAAO,iBAAiB;;;;;;qBAyKrB,UACX,OAAO,iBACP,KAAK,WACL;;;;;;UCxRe;WACN,MAAM;;WAEN,SAAS,MAAM;WACf;;;;;;qBAOE,kBACX,MAAM,iBACN,OAAO,mBACN;;;;;;qBA4BU,kBACX,oBACC,OAAO,OAAO,aAAa;UCoBb;;WAEN;;WAEA;;;;;;WAMA;aAAoB;aAAoB;;;;;;;WAMxC;;;;;;WAMA;;WAEA;;WAEA;;;;;WAKA;;;;;;;;;;;;;qBAcE;WACF,MAAM,MAAM,KACnB,MAAM,yBACN,MAAM;WAEC;WACA,OAAO;mBACC;mBACA;mBACA;mBACA;mBACA;EAEjB,YAAY,OAAO,aAAa,SAAS;;;;;;EAqDzC,IAAI,eAAe,WAAW,WAAW,eAAe;;EAQxD,QAAQ,eAAe,OAAO,MAAM,OAAO;;EAK3C,SAAS,eAAe;;EAKxB,SAAS,eAAe;;;;;EAQxB,QAAQ,eAAe;;EAKvB,SAAS,eAAe;;EAKxB,OAAO;;EAWP;;;;;;;qBCjOW;WACF,MAAM,MAAM;WACZ;mBACQ;EAEjB,YACE,UAAU,MAAM,gBAChB,UAAU,MAAM,UAChB;;;;;EAgBF,IACE,eACA,WACA,WACA,WACA,gBACA;EAcF,SAAS,eAAe,OAAO,MAAM;;EAKrC,OAAO;EAQP;;;;;;qBCpDW,aACX,sBACA,oBACA;;;;;;qBASW,gBACX,qBACA,sBACA,eACA,eACA;;;;;qBAgBW,cAAe,eAAe;;;;;;qBAQ9B,eACX,qBACA,sBACA;WAES;WACA;WACA;WACA;;UAYM;;WAEN;;;;;WAKA;;;;;;;;;;qBAWE,oBAAoB,MAAM;WAC5B;UACD;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;EAER,YAAY,UAAS;;MAUjB;;MAKA;;MAKA;;EAKJ,cAAc;;EAMd,cAAc,eAAe;;EAO7B,OAAO,WAAW;;;;;EAWlB,IAAI,QAAQ,cAAc;UAYlB;;;KCjKE;;KAGA,YAAY,UAAU,mBAAmB,oBACjD,cACA,2BACE,MAAM,qBACN,MAAM;UAEK,aAAa,UAAU;;;;;;WAM7B,SAAS;;;;;WAKT;;WAEA;WACA,aAAa,MAAM;;;;;;;;;;;;;;qBA0BjB,MAAM,UAAU;WAClB,UAAU,MAAM;WAChB,OAAO,MAAM;WACb,QAAQ,YAAY;mBACZ;mBACA;EAEjB,YAAY,WAAW,aAAa,UAAS,aAAa;EA8D1D;EAIA;UAOQ;;;;;;;qBAyEG,cAAe,UAAU,MAAM,SAAS,SAAS,MAAI;;qBAMrD,gBAAiB,SAAS,MAAM;;;;;;;;qBAUhC,gBAAiB,MAAM,MAAM"}