@expofp/renderer 3.35.0 → 3.35.1
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/dist/core/SquareDataTexture.d.ts +2 -2
- package/dist/core/SquareDataTexture.js +2 -2
- package/dist/core/batch/BatchedMesh.d.ts +3 -3
- package/dist/core/batch/BatchedMesh.js +3 -3
- package/dist/core/instanced/InstancedMesh.d.ts +7 -7
- package/dist/core/instanced/InstancedMesh.js +4 -4
- package/dist/core/instanced/instanced-material.js +1 -1
- package/dist/core/lines/BatchedLines.d.ts +4 -4
- package/dist/core/lines/BatchedLines.js +4 -4
- package/dist/core/text/BatchedText.d.ts +14 -14
- package/dist/core/text/BatchedText.js +9 -9
- package/dist/core/text/MemberTexture.d.ts +2 -2
- package/dist/core/text/Text.d.ts +5 -5
- package/dist/core/text/Text.js +4 -4
- package/dist/core/text/glyph-packing.d.ts +2 -2
- package/dist/events/layout-targets.d.ts +7 -3
- package/dist/events/layout-targets.js +13 -1
- package/dist/objects/containers/SlotContainer.d.ts +27 -2
- package/dist/objects/containers/SlotContainer.js +29 -0
- package/dist/objects/containers/mesh-writes.d.ts +1 -1
- package/dist/objects/images/Images.js +1 -1
- package/dist/objects/images/image-container.d.ts +5 -5
- package/dist/objects/images/image-container.js +1 -1
- package/dist/objects/lines/line-container.d.ts +4 -4
- package/dist/objects/materials/LineMaterial.d.ts +1 -1
- package/dist/objects/materials/effects/color-dim.d.ts +1 -1
- package/dist/objects/materials/effects/color-dim.js +1 -1
- package/dist/objects/models/Models.js +2 -2
- package/dist/objects/models/model-container.d.ts +4 -20
- package/dist/objects/models/model-container.js +1 -21
- package/dist/objects/shapes/shape-container.d.ts +3 -20
- package/dist/objects/shapes/shape-container.js +0 -21
- package/dist/objects/text/text-container.d.ts +6 -6
- package/dist/objects/text/text-container.js +3 -3
- package/dist/objects/text/text-layout.d.ts +2 -2
- package/package.json +2 -2
|
@@ -91,8 +91,8 @@ export declare function getSquareTextureInfo(arrayType: TypedArrayConstructor, c
|
|
|
91
91
|
* 2. **The index varying is always `float`**, so `getUniformsGLSL` no longer takes an index type.
|
|
92
92
|
* It follows from the first: GLSL ES 3.00 requires integer varyings to be `flat`, so an index
|
|
93
93
|
* that is not float could not have the qualifier removed. **Callers must therefore hand it a float
|
|
94
|
-
* index** — `
|
|
95
|
-
* `
|
|
94
|
+
* index** — `BatchedMeshImpl` does, from three's own `getIndirectIndex( gl_DrawID )`, and
|
|
95
|
+
* `InstancedMeshImpl` does, from the float index texture that replaced upstream's `uint` attribute.
|
|
96
96
|
* 3. **`clone` and `copy` produce an independent texture.** See each method.
|
|
97
97
|
*/
|
|
98
98
|
export declare class SquareDataTexture extends DataTexture {
|
|
@@ -68,8 +68,8 @@ export function getSquareTextureInfo(arrayType, channels, pixelsPerInstance, cap
|
|
|
68
68
|
* 2. **The index varying is always `float`**, so `getUniformsGLSL` no longer takes an index type.
|
|
69
69
|
* It follows from the first: GLSL ES 3.00 requires integer varyings to be `flat`, so an index
|
|
70
70
|
* that is not float could not have the qualifier removed. **Callers must therefore hand it a float
|
|
71
|
-
* index** — `
|
|
72
|
-
* `
|
|
71
|
+
* index** — `BatchedMeshImpl` does, from three's own `getIndirectIndex( gl_DrawID )`, and
|
|
72
|
+
* `InstancedMeshImpl` does, from the float index texture that replaced upstream's `uint` attribute.
|
|
73
73
|
* 3. **`clone` and `copy` produce an independent texture.** See each method.
|
|
74
74
|
*/
|
|
75
75
|
export class SquareDataTexture extends DataTexture {
|
|
@@ -19,8 +19,8 @@ import { type UniformValue, type UniformValueObj } from '../SquareDataTexture';
|
|
|
19
19
|
* - **Bounds invalidate themselves.** Every mutation that can move the mesh's extents nulls the
|
|
20
20
|
* cached bounds, so callers cannot forget; three's frustum test recomputes a null one on demand.
|
|
21
21
|
*/
|
|
22
|
-
export declare class
|
|
23
|
-
/** Per-instance uniform store, shared with {@link
|
|
22
|
+
export declare class BatchedMeshImpl extends BatchedMeshBase {
|
|
23
|
+
/** Per-instance uniform store, shared with {@link InstancedMeshImpl}. */
|
|
24
24
|
private readonly uniforms;
|
|
25
25
|
/** The material whose `onBeforeCompile` is already wrapped, so it is wrapped exactly once. */
|
|
26
26
|
private patchedMaterial;
|
|
@@ -70,5 +70,5 @@ export declare class BatchedMeshExt extends BatchedMeshBase {
|
|
|
70
70
|
* Registers the class as an R3F element, by value so the generated key cannot collide with the
|
|
71
71
|
* `BatchedMesh` three already puts in the catalog when the canvas mounts.
|
|
72
72
|
*/
|
|
73
|
-
export declare const BatchedMesh: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<
|
|
73
|
+
export declare const BatchedMesh: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<BatchedMeshImpl, import("@react-three/fiber").MathProps<BatchedMeshImpl> & import("@react-three/fiber").ReactProps<BatchedMeshImpl> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<BatchedMeshImpl, typeof BatchedMeshImpl>, "object">>>>;
|
|
74
74
|
//# sourceMappingURL=BatchedMesh.d.ts.map
|
|
@@ -20,8 +20,8 @@ import { openMain } from '../shader-source';
|
|
|
20
20
|
* - **Bounds invalidate themselves.** Every mutation that can move the mesh's extents nulls the
|
|
21
21
|
* cached bounds, so callers cannot forget; three's frustum test recomputes a null one on demand.
|
|
22
22
|
*/
|
|
23
|
-
export class
|
|
24
|
-
/** Per-instance uniform store, shared with {@link
|
|
23
|
+
export class BatchedMeshImpl extends BatchedMeshBase {
|
|
24
|
+
/** Per-instance uniform store, shared with {@link InstancedMeshImpl}. */
|
|
25
25
|
uniforms = new InstanceUniforms();
|
|
26
26
|
/** The material whose `onBeforeCompile` is already wrapped, so it is wrapped exactly once. */
|
|
27
27
|
patchedMaterial = null;
|
|
@@ -146,4 +146,4 @@ export class BatchedMeshExt extends BatchedMeshBase {
|
|
|
146
146
|
* Registers the class as an R3F element, by value so the generated key cannot collide with the
|
|
147
147
|
* `BatchedMesh` three already puts in the catalog when the canvas mounts.
|
|
148
148
|
*/
|
|
149
|
-
export const BatchedMesh = extend(
|
|
149
|
+
export const BatchedMesh = extend(BatchedMeshImpl);
|
|
@@ -3,8 +3,8 @@ import { type UniformSchemaShader } from '../InstanceUniforms';
|
|
|
3
3
|
import { type UniformValue, type UniformValueObj } from '../SquareDataTexture';
|
|
4
4
|
import { FrustumCulling } from './FrustumCulling';
|
|
5
5
|
import { Raycasting } from './Raycasting';
|
|
6
|
-
/** Constructor options for {@link
|
|
7
|
-
export interface
|
|
6
|
+
/** Constructor options for {@link InstancedMeshImpl}. */
|
|
7
|
+
export interface InstancedMeshImplParams {
|
|
8
8
|
/** Initial instance capacity; the buffers grow past it on demand. */
|
|
9
9
|
capacity?: number;
|
|
10
10
|
}
|
|
@@ -34,10 +34,10 @@ export type CustomSortFn = (list: InstancedRenderItem[]) => void;
|
|
|
34
34
|
* - **Batched-style texture handling.** The data textures bind as ordinary shader uniforms and
|
|
35
35
|
* flush through {@link SquareDataTexture.update}, so there is no manual texture-unit binding,
|
|
36
36
|
* `updateTextures`/`bindTextures` split, or `PropertiesOverride` — the vendored texture already
|
|
37
|
-
* works this way for `
|
|
37
|
+
* works this way for `BatchedMeshImpl`.
|
|
38
38
|
* - **The draw list is a texture, not a vertex attribute.** Upstream stamps a `uint` index attribute
|
|
39
39
|
* onto whatever geometry it is handed; this fetches the instance id by `gl_InstanceID` from a texture of
|
|
40
|
-
* its own, the way `
|
|
40
|
+
* its own, the way `BatchedMeshImpl` resolves `gl_DrawID`. So the mesh never writes to a geometry it
|
|
41
41
|
* does not own — several may draw one cached geometry — and the cull list flushes through
|
|
42
42
|
* {@link SquareDataTexture.update} in `onBeforeRender` like every other per-instance buffer, rather
|
|
43
43
|
* than needing an attribute that owns its GL buffer to beat three's upload in `projectObject`. It
|
|
@@ -53,7 +53,7 @@ export type CustomSortFn = (list: InstancedRenderItem[]) => void;
|
|
|
53
53
|
*
|
|
54
54
|
* Render it with {@link InstancedMesh}.
|
|
55
55
|
*/
|
|
56
|
-
export declare class
|
|
56
|
+
export declare class InstancedMeshImpl extends Mesh<BufferGeometry, Material | Material[], Object3DEventMap & {
|
|
57
57
|
dispose: object;
|
|
58
58
|
}> {
|
|
59
59
|
/**
|
|
@@ -110,7 +110,7 @@ export declare class InstancedMeshExt extends Mesh<BufferGeometry, Material | Ma
|
|
|
110
110
|
private drawList;
|
|
111
111
|
/** Puts back what {@link patchInstancedMaterial} wrapped; null between draws. */
|
|
112
112
|
private _unpatchMaterial;
|
|
113
|
-
constructor(params?:
|
|
113
|
+
constructor(params?: InstancedMeshImplParams);
|
|
114
114
|
/**
|
|
115
115
|
* The instance capacity the textures currently hold.
|
|
116
116
|
*/
|
|
@@ -298,5 +298,5 @@ export declare class InstancedMeshExt extends Mesh<BufferGeometry, Material | Ma
|
|
|
298
298
|
* Registers the class as an R3F element, by value so the generated key cannot collide with the
|
|
299
299
|
* `InstancedMesh` three already puts in the catalog when the canvas mounts.
|
|
300
300
|
*/
|
|
301
|
-
export declare const InstancedMesh: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<
|
|
301
|
+
export declare const InstancedMesh: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<InstancedMeshImpl, import("@react-three/fiber").MathProps<InstancedMeshImpl> & import("@react-three/fiber").ReactProps<InstancedMeshImpl> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<InstancedMeshImpl, typeof InstancedMeshImpl>, "object">>>>;
|
|
302
302
|
//# sourceMappingURL=InstancedMesh.d.ts.map
|
|
@@ -26,10 +26,10 @@ patchInstancedShaderChunks();
|
|
|
26
26
|
* - **Batched-style texture handling.** The data textures bind as ordinary shader uniforms and
|
|
27
27
|
* flush through {@link SquareDataTexture.update}, so there is no manual texture-unit binding,
|
|
28
28
|
* `updateTextures`/`bindTextures` split, or `PropertiesOverride` — the vendored texture already
|
|
29
|
-
* works this way for `
|
|
29
|
+
* works this way for `BatchedMeshImpl`.
|
|
30
30
|
* - **The draw list is a texture, not a vertex attribute.** Upstream stamps a `uint` index attribute
|
|
31
31
|
* onto whatever geometry it is handed; this fetches the instance id by `gl_InstanceID` from a texture of
|
|
32
|
-
* its own, the way `
|
|
32
|
+
* its own, the way `BatchedMeshImpl` resolves `gl_DrawID`. So the mesh never writes to a geometry it
|
|
33
33
|
* does not own — several may draw one cached geometry — and the cull list flushes through
|
|
34
34
|
* {@link SquareDataTexture.update} in `onBeforeRender` like every other per-instance buffer, rather
|
|
35
35
|
* than needing an attribute that owns its GL buffer to beat three's upload in `projectObject`. It
|
|
@@ -45,7 +45,7 @@ patchInstancedShaderChunks();
|
|
|
45
45
|
*
|
|
46
46
|
* Render it with {@link InstancedMesh}.
|
|
47
47
|
*/
|
|
48
|
-
export class
|
|
48
|
+
export class InstancedMeshImpl extends Mesh {
|
|
49
49
|
/**
|
|
50
50
|
* The number of instances rendered in the last frame.
|
|
51
51
|
* @default 0
|
|
@@ -489,7 +489,7 @@ export class InstancedMeshExt extends Mesh {
|
|
|
489
489
|
* Registers the class as an R3F element, by value so the generated key cannot collide with the
|
|
490
490
|
* `InstancedMesh` three already puts in the catalog when the canvas mounts.
|
|
491
491
|
*/
|
|
492
|
-
export const InstancedMesh = extend(
|
|
492
|
+
export const InstancedMesh = extend(InstancedMeshImpl);
|
|
493
493
|
const DEFAULT_CAPACITY = 1000;
|
|
494
494
|
const _matrix = new Matrix4();
|
|
495
495
|
const _color = new Color();
|
|
@@ -55,7 +55,7 @@ const INSTANCED_DECLARATIONS = /* glsl */ `
|
|
|
55
55
|
* The matrix is declared here rather than where the transform chunks use it, so it lands in `main`
|
|
56
56
|
* whether or not the material includes those chunks. It shadows the `attribute mat4 instanceMatrix`
|
|
57
57
|
* three declares for any `isInstancedMesh` object — which is what the placeholder attribute on
|
|
58
|
-
* `
|
|
58
|
+
* `InstancedMeshImpl` exists to satisfy — and a material doing its own transform simply never reads
|
|
59
59
|
* it.
|
|
60
60
|
*/
|
|
61
61
|
const INSTANCED_RESOLVE = /* glsl */ `
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Box3, type BufferGeometry, type Camera, type Group, type Material, type Scene, type Sphere, Vector3, type Vector3Like, type WebGLRenderer } from 'three';
|
|
2
2
|
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
|
|
3
3
|
import { LineSegmentsGeometry } from 'three/addons/lines/LineSegmentsGeometry.js';
|
|
4
|
-
import {
|
|
4
|
+
import { InstancedMeshImpl, type InstancedMeshImplParams } from '../instanced/InstancedMesh';
|
|
5
5
|
import { FrustumCulling } from './FrustumCulling';
|
|
6
6
|
import { Raycasting } from './Raycasting';
|
|
7
7
|
/**
|
|
@@ -31,7 +31,7 @@ import { Raycasting } from './Raycasting';
|
|
|
31
31
|
*
|
|
32
32
|
* Render it with {@link BatchedLines}.
|
|
33
33
|
*/
|
|
34
|
-
export declare class
|
|
34
|
+
export declare class BatchedLinesImpl extends InstancedMeshImpl {
|
|
35
35
|
/**
|
|
36
36
|
* The segment template every member is drawn from, and the whole of what the geometry carries: the
|
|
37
37
|
* per-instance data three would put in instanced attributes is in the uniforms instead.
|
|
@@ -58,7 +58,7 @@ export declare class BatchedLinesExt extends InstancedMeshExt {
|
|
|
58
58
|
/**
|
|
59
59
|
* @param params - Instance capacity; the buffers grow past it on demand.
|
|
60
60
|
*/
|
|
61
|
-
constructor(params?:
|
|
61
|
+
constructor(params?: InstancedMeshImplParams);
|
|
62
62
|
/**
|
|
63
63
|
* Reads a member's endpoints.
|
|
64
64
|
* @param id - The member to read.
|
|
@@ -131,5 +131,5 @@ export declare class BatchedLinesExt extends InstancedMeshExt {
|
|
|
131
131
|
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
132
132
|
* three puts in the catalog when the canvas mounts.
|
|
133
133
|
*/
|
|
134
|
-
export declare const BatchedLines: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<
|
|
134
|
+
export declare const BatchedLines: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<BatchedLinesImpl, import("@react-three/fiber").MathProps<BatchedLinesImpl> & import("@react-three/fiber").ReactProps<BatchedLinesImpl> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<BatchedLinesImpl, typeof BatchedLinesImpl>, "object">>>>;
|
|
135
135
|
//# sourceMappingURL=BatchedLines.d.ts.map
|
|
@@ -2,7 +2,7 @@ import { extend } from '@react-three/fiber';
|
|
|
2
2
|
import { Vector3, Vector4, } from 'three';
|
|
3
3
|
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
|
|
4
4
|
import { LineSegmentsGeometry } from 'three/addons/lines/LineSegmentsGeometry.js';
|
|
5
|
-
import {
|
|
5
|
+
import { InstancedMeshImpl } from '../instanced/InstancedMesh';
|
|
6
6
|
import { FrustumCulling } from './FrustumCulling';
|
|
7
7
|
import { END_UNIFORM, patchLineMaterial, START_UNIFORM, WIDTH_UNIFORM } from './lines-material';
|
|
8
8
|
import { Raycasting } from './Raycasting';
|
|
@@ -33,7 +33,7 @@ import { Raycasting } from './Raycasting';
|
|
|
33
33
|
*
|
|
34
34
|
* Render it with {@link BatchedLines}.
|
|
35
35
|
*/
|
|
36
|
-
export class
|
|
36
|
+
export class BatchedLinesImpl extends InstancedMeshImpl {
|
|
37
37
|
/**
|
|
38
38
|
* The segment template every member is drawn from, and the whole of what the geometry carries: the
|
|
39
39
|
* per-instance data three would put in instanced attributes is in the uniforms instead.
|
|
@@ -188,7 +188,7 @@ export class BatchedLinesExt extends InstancedMeshExt {
|
|
|
188
188
|
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
189
189
|
* three puts in the catalog when the canvas mounts.
|
|
190
190
|
*/
|
|
191
|
-
export const BatchedLines = extend(
|
|
191
|
+
export const BatchedLines = extend(BatchedLinesImpl);
|
|
192
192
|
/**
|
|
193
193
|
* Whether a material is one three's line shader compiles from.
|
|
194
194
|
* @param material - The material three is about to draw with.
|
|
@@ -199,7 +199,7 @@ function isLineMaterial(material) {
|
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
201
|
* The width a member starts at: negative, which is how "none of its own" is marked, so it draws at
|
|
202
|
-
* the material's. See {@link
|
|
202
|
+
* the material's. See {@link BatchedLinesImpl.setWidthAt} for why the marker is a negative value and
|
|
203
203
|
* not zero.
|
|
204
204
|
*/
|
|
205
205
|
const MATERIAL_WIDTH = -1;
|
|
@@ -2,7 +2,7 @@ import { type BufferGeometry, type Camera, type Intersection, type Material, typ
|
|
|
2
2
|
import { BatchedText as TroikaBatchedText, type TextMaterial } from 'troika-three-text';
|
|
3
3
|
import { type UniformSchemaShader } from '../InstanceUniforms';
|
|
4
4
|
import { type UniformValue, type UniformValueObj } from '../SquareDataTexture';
|
|
5
|
-
import { type
|
|
5
|
+
import { type TextImpl } from './Text';
|
|
6
6
|
/**
|
|
7
7
|
* troika's `BatchedText` with stable member ids, explicit paint order, and per-instance uniforms.
|
|
8
8
|
*
|
|
@@ -24,7 +24,7 @@ import { type TextExt } from './Text';
|
|
|
24
24
|
* Other departures from upstream:
|
|
25
25
|
*
|
|
26
26
|
* - **Sync is flag-driven, not scanned.** Members report property writes through
|
|
27
|
-
* `
|
|
27
|
+
* `TextImpl._batchParent`, so an idle frame costs nothing instead of walking every member.
|
|
28
28
|
* - **Per-member frustum culling and visibility**, by zeroing a hidden member's matrix so its glyphs
|
|
29
29
|
* collapse to a degenerate triangle. See {@link MemberTexture}.
|
|
30
30
|
* - **Bounds are cached**, recomputed only when {@link invalidateBounds} says they moved, where
|
|
@@ -34,7 +34,7 @@ import { type TextExt } from './Text';
|
|
|
34
34
|
* - **The derived material inherits the base's `transparent`**, rather than troika forcing it true.
|
|
35
35
|
* See {@link configureDerivedMaterial}.
|
|
36
36
|
*
|
|
37
|
-
* **Not built on {@link
|
|
37
|
+
* **Not built on {@link InstancedMeshImpl}'s machinery**, despite the family resemblance. That mesh
|
|
38
38
|
* draws one shared geometry through a per-frame list of instance ids, so it culls and sorts by
|
|
39
39
|
* rewriting the list; here draw order *is* the order glyph runs sit in the attributes, so a reorder
|
|
40
40
|
* costs a repack and culling collapses a matrix row instead. Its members are real objects carrying
|
|
@@ -42,14 +42,14 @@ import { type TextExt } from './Text';
|
|
|
42
42
|
* per member rather than in bulk by count, and visibility rides on the member's own `visible`. What
|
|
43
43
|
* the two genuinely share is {@link InstanceUniforms}.
|
|
44
44
|
*
|
|
45
|
-
* Members must be {@link
|
|
45
|
+
* Members must be {@link TextImpl}, and are assumed to agree on `orientation` and `sdfGlyphSize`:
|
|
46
46
|
* both feed uniforms that are batch-wide rather than per-member, so mixing them across a batch
|
|
47
47
|
* leaves whichever member was written last in charge.
|
|
48
48
|
*
|
|
49
49
|
* Render it with {@link BatchedText}.
|
|
50
50
|
*/
|
|
51
|
-
export declare class
|
|
52
|
-
/** Per-instance uniform store, shared with {@link
|
|
51
|
+
export declare class BatchedTextImpl extends TroikaBatchedText {
|
|
52
|
+
/** Per-instance uniform store, shared with {@link BatchedMeshImpl} and {@link InstancedMeshImpl}. */
|
|
53
53
|
private readonly uniforms;
|
|
54
54
|
/** The per-member transform and style rows the batch's shader draws from. */
|
|
55
55
|
private readonly memberTexture;
|
|
@@ -76,7 +76,7 @@ export declare class BatchedTextExt extends TroikaBatchedText {
|
|
|
76
76
|
* hole.
|
|
77
77
|
*
|
|
78
78
|
* **A pure high-water mark: removing a member never pulls it back in**, unlike `Instances`, the
|
|
79
|
-
* equivalent for {@link
|
|
79
|
+
* equivalent for {@link InstancedMeshImpl}, which shrinks past trailing dead ids. Converting either
|
|
80
80
|
* to the other buys nothing. A dead row costs the sweeps here one array read and a `continue`; and
|
|
81
81
|
* this same number also sizes both textures, where `Instances` has a separate `capacity` for that
|
|
82
82
|
* — so shrinking it would reallocate the matrix and uniform textures every time the last member
|
|
@@ -85,10 +85,10 @@ export declare class BatchedTextExt extends TroikaBatchedText {
|
|
|
85
85
|
get addedMembersCount(): number;
|
|
86
86
|
/** The material whose `onBeforeCompile` is already wrapped, so it is wrapped exactly once. */
|
|
87
87
|
private patchedMaterial;
|
|
88
|
-
/** Marks the batch as needing a sync pass. Members call this through `
|
|
88
|
+
/** Marks the batch as needing a sync pass. Members call this through `TextImpl._batchParent`. */
|
|
89
89
|
requestSync(): void;
|
|
90
90
|
/**
|
|
91
|
-
* Marks the batch's bounds as stale. Members call this through `
|
|
91
|
+
* Marks the batch's bounds as stale. Members call this through `TextImpl._batchParent` whenever
|
|
92
92
|
* their transform changes, so no caller has to remember to.
|
|
93
93
|
*/
|
|
94
94
|
invalidateBounds(): void;
|
|
@@ -97,7 +97,7 @@ export declare class BatchedTextExt extends TroikaBatchedText {
|
|
|
97
97
|
* @param memberId - The member to read.
|
|
98
98
|
* @returns The member, or `undefined` when the id holds none.
|
|
99
99
|
*/
|
|
100
|
-
getText(memberId: number):
|
|
100
|
+
getText(memberId: number): TextImpl | undefined;
|
|
101
101
|
/**
|
|
102
102
|
* Shows or hides a member. A hidden member keeps its id and its glyphs; it is collapsed at draw
|
|
103
103
|
* time rather than repacked out, so hiding costs no repack.
|
|
@@ -119,7 +119,7 @@ export declare class BatchedTextExt extends TroikaBatchedText {
|
|
|
119
119
|
* @param texts - Every member, in paint order. Members missing from it are not drawn, and anything
|
|
120
120
|
* that is not a member is dropped.
|
|
121
121
|
*/
|
|
122
|
-
setOrder(texts: readonly
|
|
122
|
+
setOrder(texts: readonly TextImpl[]): void;
|
|
123
123
|
/**
|
|
124
124
|
* Declares per-instance uniforms, merging with any already declared and rebuilding the backing
|
|
125
125
|
* texture (existing values carried across). See {@link InstanceUniforms.add}.
|
|
@@ -147,8 +147,8 @@ export declare class BatchedTextExt extends TroikaBatchedText {
|
|
|
147
147
|
* @returns The member’s id — stable for as long as it stays in the batch, and the index every
|
|
148
148
|
* other method here takes.
|
|
149
149
|
*/
|
|
150
|
-
addText(text:
|
|
151
|
-
removeText(text:
|
|
150
|
+
addText(text: TextImpl): number;
|
|
151
|
+
removeText(text: TextImpl): void;
|
|
152
152
|
/**
|
|
153
153
|
* Copies the text-level properties, and deliberately not the membership.
|
|
154
154
|
*
|
|
@@ -223,5 +223,5 @@ export declare class BatchedTextExt extends TroikaBatchedText {
|
|
|
223
223
|
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
224
224
|
* three puts in the catalog when the canvas mounts.
|
|
225
225
|
*/
|
|
226
|
-
export declare const BatchedText: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<
|
|
226
|
+
export declare const BatchedText: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<BatchedTextImpl, import("@react-three/fiber").MathProps<BatchedTextImpl> & import("@react-three/fiber").ReactProps<BatchedTextImpl> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<BatchedTextImpl, typeof BatchedTextImpl>, "object">>>>;
|
|
227
227
|
//# sourceMappingURL=BatchedText.d.ts.map
|
|
@@ -26,7 +26,7 @@ import { MemberTexture } from './MemberTexture';
|
|
|
26
26
|
* Other departures from upstream:
|
|
27
27
|
*
|
|
28
28
|
* - **Sync is flag-driven, not scanned.** Members report property writes through
|
|
29
|
-
* `
|
|
29
|
+
* `TextImpl._batchParent`, so an idle frame costs nothing instead of walking every member.
|
|
30
30
|
* - **Per-member frustum culling and visibility**, by zeroing a hidden member's matrix so its glyphs
|
|
31
31
|
* collapse to a degenerate triangle. See {@link MemberTexture}.
|
|
32
32
|
* - **Bounds are cached**, recomputed only when {@link invalidateBounds} says they moved, where
|
|
@@ -36,7 +36,7 @@ import { MemberTexture } from './MemberTexture';
|
|
|
36
36
|
* - **The derived material inherits the base's `transparent`**, rather than troika forcing it true.
|
|
37
37
|
* See {@link configureDerivedMaterial}.
|
|
38
38
|
*
|
|
39
|
-
* **Not built on {@link
|
|
39
|
+
* **Not built on {@link InstancedMeshImpl}'s machinery**, despite the family resemblance. That mesh
|
|
40
40
|
* draws one shared geometry through a per-frame list of instance ids, so it culls and sorts by
|
|
41
41
|
* rewriting the list; here draw order *is* the order glyph runs sit in the attributes, so a reorder
|
|
42
42
|
* costs a repack and culling collapses a matrix row instead. Its members are real objects carrying
|
|
@@ -44,14 +44,14 @@ import { MemberTexture } from './MemberTexture';
|
|
|
44
44
|
* per member rather than in bulk by count, and visibility rides on the member's own `visible`. What
|
|
45
45
|
* the two genuinely share is {@link InstanceUniforms}.
|
|
46
46
|
*
|
|
47
|
-
* Members must be {@link
|
|
47
|
+
* Members must be {@link TextImpl}, and are assumed to agree on `orientation` and `sdfGlyphSize`:
|
|
48
48
|
* both feed uniforms that are batch-wide rather than per-member, so mixing them across a batch
|
|
49
49
|
* leaves whichever member was written last in charge.
|
|
50
50
|
*
|
|
51
51
|
* Render it with {@link BatchedText}.
|
|
52
52
|
*/
|
|
53
|
-
export class
|
|
54
|
-
/** Per-instance uniform store, shared with {@link
|
|
53
|
+
export class BatchedTextImpl extends TroikaBatchedText {
|
|
54
|
+
/** Per-instance uniform store, shared with {@link BatchedMeshImpl} and {@link InstancedMeshImpl}. */
|
|
55
55
|
uniforms = new InstanceUniforms();
|
|
56
56
|
/** The per-member transform and style rows the batch's shader draws from. */
|
|
57
57
|
memberTexture = new MemberTexture();
|
|
@@ -85,7 +85,7 @@ export class BatchedTextExt extends TroikaBatchedText {
|
|
|
85
85
|
* hole.
|
|
86
86
|
*
|
|
87
87
|
* **A pure high-water mark: removing a member never pulls it back in**, unlike `Instances`, the
|
|
88
|
-
* equivalent for {@link
|
|
88
|
+
* equivalent for {@link InstancedMeshImpl}, which shrinks past trailing dead ids. Converting either
|
|
89
89
|
* to the other buys nothing. A dead row costs the sweeps here one array read and a `continue`; and
|
|
90
90
|
* this same number also sizes both textures, where `Instances` has a separate `capacity` for that
|
|
91
91
|
* — so shrinking it would reallocate the matrix and uniform textures every time the last member
|
|
@@ -96,12 +96,12 @@ export class BatchedTextExt extends TroikaBatchedText {
|
|
|
96
96
|
}
|
|
97
97
|
/** The material whose `onBeforeCompile` is already wrapped, so it is wrapped exactly once. */
|
|
98
98
|
patchedMaterial = null;
|
|
99
|
-
/** Marks the batch as needing a sync pass. Members call this through `
|
|
99
|
+
/** Marks the batch as needing a sync pass. Members call this through `TextImpl._batchParent`. */
|
|
100
100
|
requestSync() {
|
|
101
101
|
this.batchNeedsSync = true;
|
|
102
102
|
}
|
|
103
103
|
/**
|
|
104
|
-
* Marks the batch's bounds as stale. Members call this through `
|
|
104
|
+
* Marks the batch's bounds as stale. Members call this through `TextImpl._batchParent` whenever
|
|
105
105
|
* their transform changes, so no caller has to remember to.
|
|
106
106
|
*/
|
|
107
107
|
invalidateBounds() {
|
|
@@ -456,7 +456,7 @@ export class BatchedTextExt extends TroikaBatchedText {
|
|
|
456
456
|
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
457
457
|
* three puts in the catalog when the canvas mounts.
|
|
458
458
|
*/
|
|
459
|
-
export const BatchedText = extend(
|
|
459
|
+
export const BatchedText = extend(BatchedTextImpl);
|
|
460
460
|
// Reused rather than built per dispatch: three's `dispatchEvent` stamps `target` on the object it
|
|
461
461
|
// is handed, so these are one allocation for the batch's lifetime instead of one per event.
|
|
462
462
|
const syncStartEvent = { type: 'syncstart' };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Camera, type ColorRepresentation, Matrix4 } from 'three';
|
|
2
2
|
import { type BatchTextMaterial } from 'troika-three-text';
|
|
3
|
-
import { type
|
|
3
|
+
import { type TextImpl } from './Text';
|
|
4
4
|
/** What {@link MemberTexture} reads off the batch it fills for. */
|
|
5
5
|
export interface MemberTextureHost {
|
|
6
6
|
/**
|
|
@@ -18,7 +18,7 @@ export interface MemberTextureHost {
|
|
|
18
18
|
* @param memberId - The member to read.
|
|
19
19
|
* @returns The member, or `undefined` when the id holds none.
|
|
20
20
|
*/
|
|
21
|
-
getText(memberId: number):
|
|
21
|
+
getText(memberId: number): TextImpl | undefined;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* The data texture a batch's shader reads each member's transform and style from: one 32-float row
|
package/dist/core/text/Text.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Matrix4 } from 'three';
|
|
2
2
|
import { Text as TroikaText, type TextMaterial } from 'troika-three-text';
|
|
3
|
-
import { type
|
|
3
|
+
import { type BatchedTextImpl } from './BatchedText';
|
|
4
4
|
/**
|
|
5
5
|
* troika's `Text` with the deviations a batched, 2D-painter renderer needs.
|
|
6
6
|
*
|
|
@@ -30,13 +30,13 @@ import { type BatchedTextExt } from './BatchedText';
|
|
|
30
30
|
*
|
|
31
31
|
* Render it with {@link Text}.
|
|
32
32
|
*/
|
|
33
|
-
export declare class
|
|
33
|
+
export declare class TextImpl extends TroikaText {
|
|
34
34
|
/**
|
|
35
|
-
* The batch this text belongs to, set by {@link
|
|
35
|
+
* The batch this text belongs to, set by {@link BatchedTextImpl.addText}. It is how a member
|
|
36
36
|
* reaches its batch without the batch scanning for changes: property writes invalidate the sync
|
|
37
37
|
* through it, and transform writes invalidate the bounds.
|
|
38
38
|
*/
|
|
39
|
-
_batchParent:
|
|
39
|
+
_batchParent: BatchedTextImpl | undefined;
|
|
40
40
|
/**
|
|
41
41
|
* Backing store for the `_needsSync` accessor installed on the prototype below.
|
|
42
42
|
*
|
|
@@ -69,5 +69,5 @@ export declare class TextExt extends TroikaText {
|
|
|
69
69
|
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
70
70
|
* three puts in the catalog when the canvas mounts.
|
|
71
71
|
*/
|
|
72
|
-
export declare const Text: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<
|
|
72
|
+
export declare const Text: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<TextImpl, import("@react-three/fiber").MathProps<TextImpl> & import("@react-three/fiber").ReactProps<TextImpl> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<TextImpl, typeof TextImpl>, "object">>>>;
|
|
73
73
|
//# sourceMappingURL=Text.d.ts.map
|
package/dist/core/text/Text.js
CHANGED
|
@@ -30,9 +30,9 @@ import { Text as TroikaText } from 'troika-three-text';
|
|
|
30
30
|
*
|
|
31
31
|
* Render it with {@link Text}.
|
|
32
32
|
*/
|
|
33
|
-
export class
|
|
33
|
+
export class TextImpl extends TroikaText {
|
|
34
34
|
/**
|
|
35
|
-
* The batch this text belongs to, set by {@link
|
|
35
|
+
* The batch this text belongs to, set by {@link BatchedTextImpl.addText}. It is how a member
|
|
36
36
|
* reaches its batch without the batch scanning for changes: property writes invalidate the sync
|
|
37
37
|
* through it, and transform writes invalidate the bounds.
|
|
38
38
|
*/
|
|
@@ -189,7 +189,7 @@ export class TextExt extends TroikaText {
|
|
|
189
189
|
* Runs during `super()` — the base constructor seeds the syncable properties — at which point the
|
|
190
190
|
* `_batchParent` field initializer has not run yet, so the optional call is doing real work.
|
|
191
191
|
*/
|
|
192
|
-
Object.defineProperty(
|
|
192
|
+
Object.defineProperty(TextImpl.prototype, '_needsSync', {
|
|
193
193
|
configurable: true,
|
|
194
194
|
get() {
|
|
195
195
|
return this._syncFlag;
|
|
@@ -206,7 +206,7 @@ Object.defineProperty(TextExt.prototype, '_needsSync', {
|
|
|
206
206
|
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
207
207
|
* three puts in the catalog when the canvas mounts.
|
|
208
208
|
*/
|
|
209
|
-
export const Text = extend(
|
|
209
|
+
export const Text = extend(TextImpl);
|
|
210
210
|
// Scratch reused across calls, each filled and consumed within a single synchronous block.
|
|
211
211
|
const _matrix = new Matrix4();
|
|
212
212
|
const _horizontal = new Vector3();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type GlyphsGeometry, type TextRenderInfo } from 'troika-three-text';
|
|
2
|
-
import { type
|
|
2
|
+
import { type TextImpl } from './Text';
|
|
3
3
|
/**
|
|
4
4
|
* Rewrites a batch's glyph attributes from its members' render info.
|
|
5
5
|
*
|
|
@@ -13,5 +13,5 @@ import { type TextExt } from './Text';
|
|
|
13
13
|
* @returns The render info the batch should adopt as its own — any member's will do, since a batch
|
|
14
14
|
* shares one SDF atlas — or `undefined` when no member has synced.
|
|
15
15
|
*/
|
|
16
|
-
export declare function packGlyphs(geometry: GlyphsGeometry, ordered: readonly number[], textAt: (memberId: number) =>
|
|
16
|
+
export declare function packGlyphs(geometry: GlyphsGeometry, ordered: readonly number[], textAt: (memberId: number) => TextImpl | undefined): TextRenderInfo | undefined;
|
|
17
17
|
//# sourceMappingURL=glyph-packing.d.ts.map
|
|
@@ -57,9 +57,13 @@ export interface LayoutTargets {
|
|
|
57
57
|
* Two passes, in the legacy `UpdatesSystem`'s shape: the stale defs first, except that a hidden
|
|
58
58
|
* def or one the frustum rejects is *deferred* rather than laid out; then the deferred ones, with
|
|
59
59
|
* whatever budget is left. Priority is all deferral buys — every def is still laid out before the
|
|
60
|
-
* sweep ends, because whether a def draws can be exactly what its rule decides.
|
|
61
|
-
*
|
|
62
|
-
*
|
|
60
|
+
* sweep ends, because whether a def draws can be exactly what its rule decides.
|
|
61
|
+
*
|
|
62
|
+
* **A drain always takes at least one def**, across the two passes together, however little
|
|
63
|
+
* budget is left — including none, which is what a worker descheduled before the first check
|
|
64
|
+
* leaves. That is what makes a sweep unable to stall: each drain shortens the backlog, so the
|
|
65
|
+
* frames the driver keeps asking for eventually end it. Without the guarantee a drain can dequeue
|
|
66
|
+
* nothing, return "more to do", and be asked again on the next frame with the same result.
|
|
63
67
|
* @param frustum - The camera's frustum in plan space, when the caller has one; without it only
|
|
64
68
|
* hidden defs are deferred.
|
|
65
69
|
* @param budgetMs - How much of the frame a call may spend. Non-positive means no limit.
|
|
@@ -208,14 +208,25 @@ export function createLayoutTargets(invalidate, pixelSize, roll = 0) {
|
|
|
208
208
|
if (pending.size === 0 && deferred.size === 0)
|
|
209
209
|
return false;
|
|
210
210
|
const start = performance.now();
|
|
211
|
-
const overBudget = () => budgetMs > 0 && performance.now() - start >= budgetMs;
|
|
212
211
|
let wrote = 0;
|
|
212
|
+
/**
|
|
213
|
+
* Defs this drain has taken off a queue, laid out or deferred.
|
|
214
|
+
*
|
|
215
|
+
* It gates the budget so that the **first** def of a drain is always taken. Without that, a
|
|
216
|
+
* budget already spent before the loop began — the worker descheduled between `start` and the
|
|
217
|
+
* check, which a loaded machine does routinely — dequeues nothing at all, and a drain that
|
|
218
|
+
* dequeues nothing is the stall this budget exists to prevent. Shared across both passes, so
|
|
219
|
+
* the guarantee is one def per drain rather than one per pass.
|
|
220
|
+
*/
|
|
221
|
+
let processed = 0;
|
|
222
|
+
const overBudget = () => processed > 0 && budgetMs > 0 && performance.now() - start >= budgetMs;
|
|
213
223
|
// Sets iterate in insertion order and tolerate deletion mid-walk, which is what makes the two
|
|
214
224
|
// passes below plain loops: the order moves arrived is the priority within a pass, and a
|
|
215
225
|
// processed def leaves its set before its rules run.
|
|
216
226
|
for (const def of pending) {
|
|
217
227
|
if (overBudget())
|
|
218
228
|
break;
|
|
229
|
+
processed++;
|
|
219
230
|
pending.delete(def);
|
|
220
231
|
// Deferral is priority, never a skip: a hidden def, or one the camera cannot see, joins the
|
|
221
232
|
// second pass rather than being laid out now. `def.hidden` needs no frustum — hidden is not
|
|
@@ -230,6 +241,7 @@ export function createLayoutTargets(invalidate, pixelSize, roll = 0) {
|
|
|
230
241
|
for (const def of deferred) {
|
|
231
242
|
if (overBudget())
|
|
232
243
|
break;
|
|
244
|
+
processed++;
|
|
233
245
|
deferred.delete(def);
|
|
234
246
|
if (layOutStale(def))
|
|
235
247
|
wrote++;
|
|
@@ -5,8 +5,8 @@ import { type RenderableDef } from '../../types/defs';
|
|
|
5
5
|
/**
|
|
6
6
|
* What a container needs from the mesh it writes into.
|
|
7
7
|
*
|
|
8
|
-
* A capability rather than a union of our mesh classes: `
|
|
9
|
-
* `
|
|
8
|
+
* A capability rather than a union of our mesh classes: `BatchedMeshImpl`, `InstancedMeshImpl`,
|
|
9
|
+
* `BatchedLinesImpl` and `BatchedTextImpl` share no base below `Object3D`, yet every one of them
|
|
10
10
|
* declares per-instance uniforms and hides an instance the same way — which is all a container
|
|
11
11
|
* touches generically. Everything else it reaches through its own mesh type, which the subclass
|
|
12
12
|
* names.
|
|
@@ -148,6 +148,8 @@ export declare abstract class SlotContainer<R, M extends SlotMesh = SlotMesh, T
|
|
|
148
148
|
private readonly sortDirection;
|
|
149
149
|
/** Set by {@link bind}, which runs before any effect can claim a slot. */
|
|
150
150
|
private boundMesh;
|
|
151
|
+
/** What to run when a member turns out to belong in a sibling container; see {@link reportKindMismatch}. */
|
|
152
|
+
private kindMismatchHandler;
|
|
151
153
|
/**
|
|
152
154
|
* @param options - How this container differs from the default.
|
|
153
155
|
*/
|
|
@@ -201,6 +203,29 @@ export declare abstract class SlotContainer<R, M extends SlotMesh = SlotMesh, T
|
|
|
201
203
|
* @returns The def, or `undefined` when the hit cannot be traced to one.
|
|
202
204
|
*/
|
|
203
205
|
defFromHit(hit: Intersection): RenderableDef | undefined;
|
|
206
|
+
/**
|
|
207
|
+
* Registers what to do when a member turns out to belong in a sibling container; `undefined`
|
|
208
|
+
* clears it.
|
|
209
|
+
*
|
|
210
|
+
* Here rather than on each subclass because the situation is one situation: a layer is split
|
|
211
|
+
* across several containers by some property of the def, and that property can move after the def
|
|
212
|
+
* was placed. What splits them differs — a shape's color crossing alpha 1, a model's `opacity`,
|
|
213
|
+
* an image's orientation — but what a container does about it does not, and the component that
|
|
214
|
+
* owns the split is always the one that can repair it.
|
|
215
|
+
*
|
|
216
|
+
* A method rather than an assignable field because the container is held in `useState`, and the
|
|
217
|
+
* React Compiler rejects writing to a property of a state value ("This value cannot be modified").
|
|
218
|
+
* Calling a method is fine, which is how {@link reserve} already mutates.
|
|
219
|
+
* @param handler - The re-split to run, or `undefined` to clear it.
|
|
220
|
+
*/
|
|
221
|
+
setKindMismatchHandler(handler: (() => void) | undefined): void;
|
|
222
|
+
/**
|
|
223
|
+
* Reports that a member no longer belongs in this container, so it is drawing from the wrong mesh.
|
|
224
|
+
* Runs the registered handler, if any; a container mounted without one — in a spec, or bare —
|
|
225
|
+
* drops the report rather than failing, since nothing it could do would be more correct than
|
|
226
|
+
* carrying on.
|
|
227
|
+
*/
|
|
228
|
+
reportKindMismatch(): void;
|
|
204
229
|
/**
|
|
205
230
|
* Shows or hides one instance. Every def type carries `hidden`, so `useDefSync` drives this for
|
|
206
231
|
* all of them.
|
|
@@ -79,6 +79,8 @@ export class SlotContainer {
|
|
|
79
79
|
sortDirection;
|
|
80
80
|
/** Set by {@link bind}, which runs before any effect can claim a slot. */
|
|
81
81
|
boundMesh;
|
|
82
|
+
/** What to run when a member turns out to belong in a sibling container; see {@link reportKindMismatch}. */
|
|
83
|
+
kindMismatchHandler;
|
|
82
84
|
/**
|
|
83
85
|
* @param options - How this container differs from the default.
|
|
84
86
|
*/
|
|
@@ -175,6 +177,33 @@ export class SlotContainer {
|
|
|
175
177
|
defFromHit(hit) {
|
|
176
178
|
return this.defAt(hit.instanceId);
|
|
177
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Registers what to do when a member turns out to belong in a sibling container; `undefined`
|
|
182
|
+
* clears it.
|
|
183
|
+
*
|
|
184
|
+
* Here rather than on each subclass because the situation is one situation: a layer is split
|
|
185
|
+
* across several containers by some property of the def, and that property can move after the def
|
|
186
|
+
* was placed. What splits them differs — a shape's color crossing alpha 1, a model's `opacity`,
|
|
187
|
+
* an image's orientation — but what a container does about it does not, and the component that
|
|
188
|
+
* owns the split is always the one that can repair it.
|
|
189
|
+
*
|
|
190
|
+
* A method rather than an assignable field because the container is held in `useState`, and the
|
|
191
|
+
* React Compiler rejects writing to a property of a state value ("This value cannot be modified").
|
|
192
|
+
* Calling a method is fine, which is how {@link reserve} already mutates.
|
|
193
|
+
* @param handler - The re-split to run, or `undefined` to clear it.
|
|
194
|
+
*/
|
|
195
|
+
setKindMismatchHandler(handler) {
|
|
196
|
+
this.kindMismatchHandler = handler;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Reports that a member no longer belongs in this container, so it is drawing from the wrong mesh.
|
|
200
|
+
* Runs the registered handler, if any; a container mounted without one — in a spec, or bare —
|
|
201
|
+
* drops the report rather than failing, since nothing it could do would be more correct than
|
|
202
|
+
* carrying on.
|
|
203
|
+
*/
|
|
204
|
+
reportKindMismatch() {
|
|
205
|
+
this.kindMismatchHandler?.();
|
|
206
|
+
}
|
|
178
207
|
/**
|
|
179
208
|
* Shows or hides one instance. Every def type carries `hidden`, so `useDefSync` drives this for
|
|
180
209
|
* all of them.
|
|
@@ -6,7 +6,7 @@ import { type Logger } from '../../utils/logging';
|
|
|
6
6
|
* A mesh whose instances carry a transform.
|
|
7
7
|
*
|
|
8
8
|
* Named as a capability rather than listed as a union of our mesh classes, because not every batch
|
|
9
|
-
* has one: `
|
|
9
|
+
* has one: `BatchedLinesImpl` places its members by their endpoints and has no per-instance matrix
|
|
10
10
|
* at all, yet still writes colors through the helper below. A class that satisfies only one of
|
|
11
11
|
* these two interfaces is the point — the alternative was no-op matrix methods on a class that has
|
|
12
12
|
* no transforms, which would read as a capability it does not have.
|
|
@@ -99,7 +99,7 @@ function ImageAtlas(props) {
|
|
|
99
99
|
// rejecting its render reads.
|
|
100
100
|
// The quad and the material are children so R3F creates, attaches, and disposes both — the args
|
|
101
101
|
// pair are placeholders the constructor demands (see `ImageMeshArgs`). The material has to be per
|
|
102
|
-
// mesh: `
|
|
102
|
+
// mesh: `InstancedMeshImpl` wraps whatever it draws with in a closure over its own textures, and two
|
|
103
103
|
// instanced meshes on one material would both render against the first one's.
|
|
104
104
|
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.slice(0, mounted).map((packed) => (_jsx(ImageInstance, { def: packed.def, packed: packed, container: container }, `${defKey(packed.def)}:${packed.uv.u0}:${packed.uv.v0}`)))] }));
|
|
105
105
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type InstancedMeshImpl, type InstancedMeshImplParams } from '../../core/instanced/InstancedMesh';
|
|
2
2
|
import { type ImageDef } from '../../types/defs';
|
|
3
3
|
import { SlotContainer } from '../containers';
|
|
4
4
|
import { type Atlas, type PackedImage } from './atlas-packer';
|
|
@@ -15,16 +15,16 @@ export declare const UV_OFFSET_UNIFORM = "uvOffset";
|
|
|
15
15
|
* R3F diffs `args` element-wise and rebuilds the object when any element changes, so this is
|
|
16
16
|
* snapshotted once and never mutated.
|
|
17
17
|
*
|
|
18
|
-
* Only the options: `
|
|
18
|
+
* Only the options: `InstancedMeshImpl` takes no geometry or material, seeding throwaways that the
|
|
19
19
|
* element's `<planeGeometry>` and `<TextureMaterial>` children replace (R3F creates, attaches, and
|
|
20
20
|
* disposes those).
|
|
21
21
|
*/
|
|
22
|
-
export type ImageMeshArgs = [params:
|
|
22
|
+
export type ImageMeshArgs = [params: InstancedMeshImplParams];
|
|
23
23
|
/**
|
|
24
24
|
* One atlas's mesh bookkeeping.
|
|
25
25
|
*
|
|
26
26
|
* Simpler than a shape container, and deliberately so: an atlas draws one shared quad, so there is
|
|
27
|
-
* no geometry cache and no geometry-id juggling, and `
|
|
27
|
+
* no geometry cache and no geometry-id juggling, and `InstancedMeshImpl` grows its own buffers, so
|
|
28
28
|
* there is no capacity pre-scan — the mesh is merely sized to the atlas's packed-image count and
|
|
29
29
|
* left to resize itself if a claim ever overflows it. What remains is a slot per packed image and
|
|
30
30
|
* the uv region each one samples, written once at claim since a def's source never changes.
|
|
@@ -34,7 +34,7 @@ export type ImageMeshArgs = [params: InstancedMeshExtParams];
|
|
|
34
34
|
* change to the *set* of images is the harder case and still repacks into a fresh container —
|
|
35
35
|
* packing has no incremental path for that — but a pure reorder does not.
|
|
36
36
|
*/
|
|
37
|
-
export declare class ImageContainer extends SlotContainer<PackedImage,
|
|
37
|
+
export declare class ImageContainer extends SlotContainer<PackedImage, InstancedMeshImpl, ImageDef> {
|
|
38
38
|
/** The constructor args R3F builds the mesh from; a frozen snapshot, never mutated. */
|
|
39
39
|
readonly args: ImageMeshArgs;
|
|
40
40
|
/**
|
|
@@ -13,7 +13,7 @@ export const UV_OFFSET_UNIFORM = 'uvOffset';
|
|
|
13
13
|
* One atlas's mesh bookkeeping.
|
|
14
14
|
*
|
|
15
15
|
* Simpler than a shape container, and deliberately so: an atlas draws one shared quad, so there is
|
|
16
|
-
* no geometry cache and no geometry-id juggling, and `
|
|
16
|
+
* no geometry cache and no geometry-id juggling, and `InstancedMeshImpl` grows its own buffers, so
|
|
17
17
|
* there is no capacity pre-scan — the mesh is merely sized to the atlas's packed-image count and
|
|
18
18
|
* left to resize itself if a claim ever overflows it. What remains is a slot per packed image and
|
|
19
19
|
* the uv region each one samples, written once at claim since a def's source never changes.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type
|
|
1
|
+
import { type InstancedMeshImplParams } from '../../core/instanced/InstancedMesh';
|
|
2
|
+
import { type BatchedLinesImpl } from '../../core/lines/BatchedLines';
|
|
3
3
|
import { type LineDef } from '../../types/defs';
|
|
4
4
|
import { SlotContainer } from '../containers';
|
|
5
5
|
/**
|
|
@@ -10,7 +10,7 @@ import { SlotContainer } from '../containers';
|
|
|
10
10
|
* Only the options: the batch builds its own segment template and takes its material from the
|
|
11
11
|
* `<LineMaterial>` child R3F mounts under it.
|
|
12
12
|
*/
|
|
13
|
-
export type LineMeshArgs = [params:
|
|
13
|
+
export type LineMeshArgs = [params: InstancedMeshImplParams];
|
|
14
14
|
/**
|
|
15
15
|
* One line layer's bookkeeping.
|
|
16
16
|
*
|
|
@@ -19,7 +19,7 @@ export type LineMeshArgs = [params: InstancedMeshExtParams];
|
|
|
19
19
|
* endpoints. That is why the resource type is `null` here: nothing about a `LineDef` can force a
|
|
20
20
|
* re-claim, so a def keeps its slot for as long as it is mounted, `points` included.
|
|
21
21
|
*/
|
|
22
|
-
export declare class LineContainer extends SlotContainer<null,
|
|
22
|
+
export declare class LineContainer extends SlotContainer<null, BatchedLinesImpl, LineDef> {
|
|
23
23
|
/** The constructor args R3F builds the batch from; a frozen snapshot, never mutated. */
|
|
24
24
|
readonly args: LineMeshArgs;
|
|
25
25
|
/**
|
|
@@ -4,7 +4,7 @@ export interface LineMaterialProps {
|
|
|
4
4
|
/** Base color. Defaults to white, which is what a per-instance tint multiplies against. */
|
|
5
5
|
color?: ColorRepresentation;
|
|
6
6
|
/**
|
|
7
|
-
* Width every member without one of its own draws at, in screen-space pixels — `
|
|
7
|
+
* Width every member without one of its own draws at, in screen-space pixels — `BatchedLinesImpl`
|
|
8
8
|
* resolves an unset per-member width to this. Defaults to 1.
|
|
9
9
|
*/
|
|
10
10
|
width?: number;
|
|
@@ -32,7 +32,7 @@ export declare function useDimPatch(): DimPatch;
|
|
|
32
32
|
* is the exception: troika calls the base material's handler first and then rebuilds `main` around
|
|
33
33
|
* it — renaming the original `troikaOrigMain` and calling it from a new one — so a patch installed
|
|
34
34
|
* there would land in a scope the prologue's local never reaches. With this guard that early call
|
|
35
|
-
* simply does nothing, and `
|
|
35
|
+
* simply does nothing, and `BatchedTextImpl` runs the same patch again once its prologue is in.
|
|
36
36
|
* @param parameters - The shader being compiled.
|
|
37
37
|
* @param uniform - The layer's dim amount.
|
|
38
38
|
* @returns Whether the shader was patched.
|
|
@@ -42,7 +42,7 @@ export function useDimPatch() {
|
|
|
42
42
|
* is the exception: troika calls the base material's handler first and then rebuilds `main` around
|
|
43
43
|
* it — renaming the original `troikaOrigMain` and calling it from a new one — so a patch installed
|
|
44
44
|
* there would land in a scope the prologue's local never reaches. With this guard that early call
|
|
45
|
-
* simply does nothing, and `
|
|
45
|
+
* simply does nothing, and `BatchedTextImpl` runs the same patch again once its prologue is in.
|
|
46
46
|
* @param parameters - The shader being compiled.
|
|
47
47
|
* @param uniform - The layer's dim amount.
|
|
48
48
|
* @returns Whether the shader was patched.
|
|
@@ -136,7 +136,7 @@ function ModelPartMesh(props) {
|
|
|
136
136
|
// Only the instances are staged; the container is sized and ordered from every member.
|
|
137
137
|
const mounted = props.mounted ?? defs.length;
|
|
138
138
|
// Ordering is a no-op for models — their container declares it so, and the mesh depth-sorts itself
|
|
139
|
-
// instead — but the hit resolution is not: `
|
|
139
|
+
// instead — but the hit resolution is not: `InstancedMeshImpl.raycast` walks the live slots,
|
|
140
140
|
// skipping deleted and hidden ones, and raycasts the real merged geometry, so a hit names the
|
|
141
141
|
// model's actual triangles and the slot that drew them.
|
|
142
142
|
const container = useContainer(() => new ModelContainer(asset.extents, defs.length, kind), defs);
|
|
@@ -150,7 +150,7 @@ function ModelPartMesh(props) {
|
|
|
150
150
|
}, [container, onKindMismatch]);
|
|
151
151
|
// The geometry belongs to the module-level cache and may be drawing in another layer, so it is
|
|
152
152
|
// mounted as a `primitive` with `dispose={null}` — R3F must not free it on unmount. Sharing it is
|
|
153
|
-
// safe because `
|
|
153
|
+
// safe because `InstancedMeshImpl` never writes to the geometry it is handed: its draw list lives in
|
|
154
154
|
// a texture of its own, addressed by `gl_InstanceID`. The material cannot be shared the same way —
|
|
155
155
|
// the mesh wraps it in a closure over its own textures — so `ModelMaterial` clones it per mesh.
|
|
156
156
|
//
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Rect } from '@expofp/geometry';
|
|
2
2
|
import { type Box3, Matrix4 } from 'three';
|
|
3
|
-
import { type
|
|
3
|
+
import { type InstancedMeshImpl, type InstancedMeshImplParams } from '../../core/instanced/InstancedMesh';
|
|
4
4
|
import { type ModelDef } from '../../types/defs';
|
|
5
5
|
import { SlotContainer } from '../containers';
|
|
6
6
|
/**
|
|
@@ -10,7 +10,7 @@ import { SlotContainer } from '../containers';
|
|
|
10
10
|
*/
|
|
11
11
|
export declare const OPACITY_UNIFORM = "instanceOpacity";
|
|
12
12
|
/** The constructor tuple R3F builds one model mesh from. Frozen, so R3F never rebuilds the mesh. */
|
|
13
|
-
export type ModelMeshArgs = [params:
|
|
13
|
+
export type ModelMeshArgs = [params: InstancedMeshImplParams];
|
|
14
14
|
/**
|
|
15
15
|
* Every kind of model batch, **in the order they draw within a layer** — which is what `Models`
|
|
16
16
|
* numbers them by.
|
|
@@ -34,11 +34,11 @@ export declare function modelKindOf(def: ModelDef): ModelKind;
|
|
|
34
34
|
* twenty copies of a chair are one draw call rather than twenty.
|
|
35
35
|
*
|
|
36
36
|
* Much simpler than a shape container. The geometry is the part's — shared, never per instance — so
|
|
37
|
-
* there is no geometry cache and no capacity pre-scan, and `
|
|
37
|
+
* there is no geometry cache and no capacity pre-scan, and `InstancedMeshImpl` grows its own buffers,
|
|
38
38
|
* so nothing here has to size anything. What is left is a slot per def and the transform each one
|
|
39
39
|
* draws with.
|
|
40
40
|
*/
|
|
41
|
-
export declare class ModelContainer extends SlotContainer<null,
|
|
41
|
+
export declare class ModelContainer extends SlotContainer<null, InstancedMeshImpl, ModelDef> {
|
|
42
42
|
/** The constructor args R3F builds the mesh from; a frozen snapshot, never mutated. */
|
|
43
43
|
readonly args: ModelMeshArgs;
|
|
44
44
|
/** Which kind of member this container holds, and so which render list its mesh draws from. */
|
|
@@ -50,7 +50,6 @@ export declare class ModelContainer extends SlotContainer<null, InstancedMeshExt
|
|
|
50
50
|
readonly meshMatrix: Matrix4;
|
|
51
51
|
/** The model's bounds in plan units; every instance is fitted against them. */
|
|
52
52
|
private readonly extents;
|
|
53
|
-
private kindMismatchHandler;
|
|
54
53
|
/**
|
|
55
54
|
* Builds the bookkeeping for one model part.
|
|
56
55
|
* @param extents - The model's own bounds, y-up, as `bakeGltf` left them.
|
|
@@ -74,21 +73,6 @@ export declare class ModelContainer extends SlotContainer<null, InstancedMeshExt
|
|
|
74
73
|
* quietly appear to order this one.
|
|
75
74
|
*/
|
|
76
75
|
setPaintOrder(): void;
|
|
77
|
-
/**
|
|
78
|
-
* Registers what to do when a member turns out to be the wrong kind. `Models` supplies a re-split;
|
|
79
|
-
* `undefined` clears it.
|
|
80
|
-
*
|
|
81
|
-
* A method rather than an assignable field because the container is held in `useState`, and the
|
|
82
|
-
* React Compiler rejects writing to a property of a state value.
|
|
83
|
-
* @param handler - The re-split to run, or `undefined` to clear it.
|
|
84
|
-
*/
|
|
85
|
-
setKindMismatchHandler(handler: (() => void) | undefined): void;
|
|
86
|
-
/**
|
|
87
|
-
* Reports that a member no longer matches {@link kind} — its `opacity` crossed 1 — so it is
|
|
88
|
-
* drawing from a mesh whose material describes the wrong render list. Runs the registered handler,
|
|
89
|
-
* if any; a container mounted outside `Models` has none and the report is simply dropped.
|
|
90
|
-
*/
|
|
91
|
-
reportKindMismatch(): void;
|
|
92
76
|
/**
|
|
93
77
|
* Writes a def's placement into its slot: the model's extents fitted into `bounds`.
|
|
94
78
|
*
|
|
@@ -30,7 +30,7 @@ export function modelKindOf(def) {
|
|
|
30
30
|
* twenty copies of a chair are one draw call rather than twenty.
|
|
31
31
|
*
|
|
32
32
|
* Much simpler than a shape container. The geometry is the part's — shared, never per instance — so
|
|
33
|
-
* there is no geometry cache and no capacity pre-scan, and `
|
|
33
|
+
* there is no geometry cache and no capacity pre-scan, and `InstancedMeshImpl` grows its own buffers,
|
|
34
34
|
* so nothing here has to size anything. What is left is a slot per def and the transform each one
|
|
35
35
|
* draws with.
|
|
36
36
|
*/
|
|
@@ -46,7 +46,6 @@ export class ModelContainer extends SlotContainer {
|
|
|
46
46
|
meshMatrix = PLAN_FROM_GLTF;
|
|
47
47
|
/** The model's bounds in plan units; every instance is fitted against them. */
|
|
48
48
|
extents;
|
|
49
|
-
kindMismatchHandler;
|
|
50
49
|
/**
|
|
51
50
|
* Builds the bookkeeping for one model part.
|
|
52
51
|
* @param extents - The model's own bounds, y-up, as `bakeGltf` left them.
|
|
@@ -78,25 +77,6 @@ export class ModelContainer extends SlotContainer {
|
|
|
78
77
|
setPaintOrder() {
|
|
79
78
|
// Nothing: the depth buffer orders models, and a layer's parts are separate meshes regardless.
|
|
80
79
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Registers what to do when a member turns out to be the wrong kind. `Models` supplies a re-split;
|
|
83
|
-
* `undefined` clears it.
|
|
84
|
-
*
|
|
85
|
-
* A method rather than an assignable field because the container is held in `useState`, and the
|
|
86
|
-
* React Compiler rejects writing to a property of a state value.
|
|
87
|
-
* @param handler - The re-split to run, or `undefined` to clear it.
|
|
88
|
-
*/
|
|
89
|
-
setKindMismatchHandler(handler) {
|
|
90
|
-
this.kindMismatchHandler = handler;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Reports that a member no longer matches {@link kind} — its `opacity` crossed 1 — so it is
|
|
94
|
-
* drawing from a mesh whose material describes the wrong render list. Runs the registered handler,
|
|
95
|
-
* if any; a container mounted outside `Models` has none and the report is simply dropped.
|
|
96
|
-
*/
|
|
97
|
-
reportKindMismatch() {
|
|
98
|
-
this.kindMismatchHandler?.();
|
|
99
|
-
}
|
|
100
80
|
/**
|
|
101
81
|
* Writes a def's placement into its slot: the model's extents fitted into `bounds`.
|
|
102
82
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Shape } from '@expofp/geometry';
|
|
2
2
|
import { type BufferGeometry, type Intersection } from 'three';
|
|
3
|
-
import { type
|
|
3
|
+
import { type BatchedMeshImpl } from '../../core/batch/BatchedMesh';
|
|
4
4
|
import { type RenderableDef, type ShapeDef } from '../../types/defs';
|
|
5
5
|
import { SlotContainer } from '../containers';
|
|
6
6
|
/**
|
|
@@ -21,7 +21,7 @@ export declare const SHAPE_KINDS: readonly ['planar', 'solid', 'translucent'];
|
|
|
21
21
|
* One value rather than the `solid`/`translucent` pair it replaces. The pair could express a
|
|
22
22
|
* translucent-but-flat batch, which nothing partitions for and no material describes, and it split
|
|
23
23
|
* one fact across a field each reader needed and a field none did. This is also the "kind" that
|
|
24
|
-
* {@link
|
|
24
|
+
* {@link SlotContainer.reportKindMismatch} and its handler have always named.
|
|
25
25
|
*
|
|
26
26
|
* Derived from {@link SHAPE_KINDS} rather than listed again, so the two cannot drift.
|
|
27
27
|
*/
|
|
@@ -67,7 +67,7 @@ export declare function shapeKindOf(def: ShapeDef): ShapeKind;
|
|
|
67
67
|
* which of its geometry ids each template was given. Building the templates is not its work either;
|
|
68
68
|
* they come from {@link shapeGeometry}, which caches them across every container.
|
|
69
69
|
*/
|
|
70
|
-
export declare class ShapeContainer extends SlotContainer<BufferGeometry,
|
|
70
|
+
export declare class ShapeContainer extends SlotContainer<BufferGeometry, BatchedMeshImpl, ShapeDef> {
|
|
71
71
|
/**
|
|
72
72
|
* The mesh's constructor args, sized to hold the defs the container was created with exactly.
|
|
73
73
|
* Passed as `<batchedMesh args={container.capacity}>`; R3F diffs `args` element-wise and a change
|
|
@@ -96,7 +96,6 @@ export declare class ShapeContainer extends SlotContainer<BufferGeometry, Batche
|
|
|
96
96
|
* going to do anyway.
|
|
97
97
|
*/
|
|
98
98
|
private readonly target;
|
|
99
|
-
private kindMismatchHandler;
|
|
100
99
|
/**
|
|
101
100
|
* Builds a shape layer's container, sized to hold `defs` exactly so a layer that mounts full never
|
|
102
101
|
* reallocates. The mesh itself is R3F's: the component renders `<batchedMesh>` from
|
|
@@ -130,22 +129,6 @@ export declare class ShapeContainer extends SlotContainer<BufferGeometry, Batche
|
|
|
130
129
|
* @param defs - The shapes this container is about to hold.
|
|
131
130
|
*/
|
|
132
131
|
reserve(defs: readonly ShapeDef[]): void;
|
|
133
|
-
/**
|
|
134
|
-
* Registers what to do when a member turns out to be the wrong kind. `Shapes` supplies a re-split;
|
|
135
|
-
* `undefined` clears it.
|
|
136
|
-
*
|
|
137
|
-
* A method rather than an assignable field because the container is held in `useState`, and the
|
|
138
|
-
* React Compiler rejects writing to a property of a state value ("This value cannot be modified").
|
|
139
|
-
* Calling a method is fine, which is how {@link reserve} already mutates.
|
|
140
|
-
* @param handler - The re-split to run, or `undefined` to clear it.
|
|
141
|
-
*/
|
|
142
|
-
setKindMismatchHandler(handler: (() => void) | undefined): void;
|
|
143
|
-
/**
|
|
144
|
-
* Reports that a member no longer matches {@link kind} — its color crossed alpha 1, or its shape
|
|
145
|
-
* was replaced with one of another kind — so it is drawing from the wrong batch. Runs the registered handler, if any;
|
|
146
|
-
* a container mounted outside `Shapes` has none and the report is simply dropped.
|
|
147
|
-
*/
|
|
148
|
-
reportKindMismatch(): void;
|
|
149
132
|
/**
|
|
150
133
|
* A batched mesh reports the instance it hit as `batchId`, which is the slot this container
|
|
151
134
|
* allocated.
|
|
@@ -84,7 +84,6 @@ export class ShapeContainer extends SlotContainer {
|
|
|
84
84
|
* going to do anyway.
|
|
85
85
|
*/
|
|
86
86
|
target;
|
|
87
|
-
kindMismatchHandler;
|
|
88
87
|
/**
|
|
89
88
|
* Builds a shape layer's container, sized to hold `defs` exactly so a layer that mounts full never
|
|
90
89
|
* reallocates. The mesh itself is R3F's: the component renders `<batchedMesh>` from
|
|
@@ -152,26 +151,6 @@ export class ShapeContainer extends SlotContainer {
|
|
|
152
151
|
this.target.vertices = vertices;
|
|
153
152
|
this.target.indices = indices;
|
|
154
153
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Registers what to do when a member turns out to be the wrong kind. `Shapes` supplies a re-split;
|
|
157
|
-
* `undefined` clears it.
|
|
158
|
-
*
|
|
159
|
-
* A method rather than an assignable field because the container is held in `useState`, and the
|
|
160
|
-
* React Compiler rejects writing to a property of a state value ("This value cannot be modified").
|
|
161
|
-
* Calling a method is fine, which is how {@link reserve} already mutates.
|
|
162
|
-
* @param handler - The re-split to run, or `undefined` to clear it.
|
|
163
|
-
*/
|
|
164
|
-
setKindMismatchHandler(handler) {
|
|
165
|
-
this.kindMismatchHandler = handler;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Reports that a member no longer matches {@link kind} — its color crossed alpha 1, or its shape
|
|
169
|
-
* was replaced with one of another kind — so it is drawing from the wrong batch. Runs the registered handler, if any;
|
|
170
|
-
* a container mounted outside `Shapes` has none and the report is simply dropped.
|
|
171
|
-
*/
|
|
172
|
-
reportKindMismatch() {
|
|
173
|
-
this.kindMismatchHandler?.();
|
|
174
|
-
}
|
|
175
154
|
/**
|
|
176
155
|
* A batched mesh reports the instance it hit as `batchId`, which is the slot this container
|
|
177
156
|
* allocated.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type Intersection } from 'three';
|
|
2
|
-
import { type
|
|
3
|
-
import {
|
|
2
|
+
import { type BatchedTextImpl } from '../../core/text/BatchedText';
|
|
3
|
+
import { TextImpl } from '../../core/text/Text';
|
|
4
4
|
import { type RenderableDef, type TextDef } from '../../types/defs';
|
|
5
5
|
import { SlotContainer } from '../containers';
|
|
6
|
-
/** One def's members: a `
|
|
6
|
+
/** One def's members: a `TextImpl` per line, and the batch slot each of them occupies. */
|
|
7
7
|
export interface LineGroup {
|
|
8
8
|
/** The members, in the def's line order. */
|
|
9
|
-
readonly texts: readonly
|
|
9
|
+
readonly texts: readonly TextImpl[];
|
|
10
10
|
/** Each member's batch slot, index-parallel to {@link texts}. */
|
|
11
11
|
readonly slots: readonly number[];
|
|
12
12
|
}
|
|
@@ -14,7 +14,7 @@ export interface LineGroup {
|
|
|
14
14
|
* One text layer's bookkeeping: a group of members per def, and the paint order across them.
|
|
15
15
|
*
|
|
16
16
|
* The slot a def claims here is a **group**, not a batch member — a `TextDef` holds an array of
|
|
17
|
-
* lines and each line is its own `
|
|
17
|
+
* lines and each line is its own `TextImpl`. That is the one place this differs from the shape and
|
|
18
18
|
* image containers, and it falls out of the def type rather than being a choice: the lines of one
|
|
19
19
|
* def are laid out together (a centered block needs every line's height before it can place the
|
|
20
20
|
* first), so they cannot be independent instances.
|
|
@@ -27,7 +27,7 @@ export interface LineGroup {
|
|
|
27
27
|
* draw list, so {@link applyOrder} hands the batch a rebuilt member list instead of labeling slots,
|
|
28
28
|
* and the inherited `customSort` goes unused.
|
|
29
29
|
*/
|
|
30
|
-
export declare class TextContainer extends SlotContainer<number,
|
|
30
|
+
export declare class TextContainer extends SlotContainer<number, BatchedTextImpl, TextDef> {
|
|
31
31
|
/** Groups by slot, with holes for released ones. */
|
|
32
32
|
private readonly groups;
|
|
33
33
|
private readonly freeGroups;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TextImpl } from '../../core/text/Text';
|
|
2
2
|
import { sameSequence } from '../../utils/arrays';
|
|
3
3
|
import { SlotContainer } from '../containers';
|
|
4
4
|
import { dimOrdered, isDimmed } from '../materials/effects/color-dim';
|
|
@@ -7,7 +7,7 @@ import { LAYOUT_FONT_SIZE, LINE_HEIGHT } from './text-layout';
|
|
|
7
7
|
* One text layer's bookkeeping: a group of members per def, and the paint order across them.
|
|
8
8
|
*
|
|
9
9
|
* The slot a def claims here is a **group**, not a batch member — a `TextDef` holds an array of
|
|
10
|
-
* lines and each line is its own `
|
|
10
|
+
* lines and each line is its own `TextImpl`. That is the one place this differs from the shape and
|
|
11
11
|
* image containers, and it falls out of the def type rather than being a choice: the lines of one
|
|
12
12
|
* def are laid out together (a centered block needs every line's height before it can place the
|
|
13
13
|
* first), so they cannot be independent instances.
|
|
@@ -194,7 +194,7 @@ export class TextContainer extends SlotContainer {
|
|
|
194
194
|
* @returns The member.
|
|
195
195
|
*/
|
|
196
196
|
function makeMember() {
|
|
197
|
-
const text = new
|
|
197
|
+
const text = new TextImpl();
|
|
198
198
|
text.fontSize = LAYOUT_FONT_SIZE;
|
|
199
199
|
text.lineHeight = LINE_HEIGHT;
|
|
200
200
|
// Wrapping is the floorplan's job: it measures and breaks lines itself, then hands over the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Rect } from '@expofp/geometry';
|
|
2
|
-
import { type
|
|
2
|
+
import { type TextImpl } from '../../core/text/Text';
|
|
3
3
|
import { type TextDef, type TextLineDef } from '../../types/defs';
|
|
4
4
|
/**
|
|
5
5
|
* The em size every member lays out at, fixed for its lifetime.
|
|
@@ -70,7 +70,7 @@ export declare function layoutText(def: TextDef): LaidOutLine[];
|
|
|
70
70
|
* @param line - The line's local placement.
|
|
71
71
|
* @param bounds - The def's bounds, supplying the rotation, center and elevation.
|
|
72
72
|
*/
|
|
73
|
-
export declare function applyPlacement(text:
|
|
73
|
+
export declare function applyPlacement(text: TextImpl, line: LaidOutLine, bounds: Rect): void;
|
|
74
74
|
/**
|
|
75
75
|
* The height one line's box occupies.
|
|
76
76
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expofp/renderer",
|
|
3
|
-
"version": "3.35.
|
|
3
|
+
"version": "3.35.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/expofp/efp-app.git",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"troika-three-text": "^0.52.5",
|
|
43
43
|
"tslib": "^2.3.0",
|
|
44
44
|
"webgl-memory": "^1.1.3",
|
|
45
|
-
"@expofp/geometry": "3.35.
|
|
45
|
+
"@expofp/geometry": "3.35.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@react-three/test-renderer": "^9.1.0",
|