@thatopen/components 3.4.7 → 3.4.9

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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import CameraControls from 'camera-controls';
2
1
  import { DataMap as DataMap_2 } from '@thatopen/fragments';
3
2
  import { DataSet as DataSet_2 } from '@thatopen/fragments';
3
+ import { default as default_2 } from 'camera-controls';
4
4
  import * as FRAGS from '@thatopen/fragments';
5
5
  import * as THREE from 'three';
6
6
  import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';
@@ -345,7 +345,7 @@ export declare abstract class BaseCamera extends BaseWorldItem {
345
345
  * Optional CameraControls instance for controlling the camera.
346
346
  * This property is only available if the camera is controllable.
347
347
  */
348
- abstract controls?: CameraControls;
348
+ abstract controls?: default_2;
349
349
  /**
350
350
  * Checks whether the instance is {@link CameraControllable}.
351
351
  *
@@ -1170,7 +1170,7 @@ export declare interface CameraControllable {
1170
1170
  * An instance of CameraControls that provides camera control functionalities.
1171
1171
  * This instance is used to manipulate the camera.
1172
1172
  */
1173
- controls: CameraControls;
1173
+ controls: default_2;
1174
1174
  }
1175
1175
 
1176
1176
  /**
@@ -1464,6 +1464,8 @@ export declare class Clipper extends Component implements Createable, Disposable
1464
1464
  * A list of all the clipping planes created by this component.
1465
1465
  */
1466
1466
  readonly list: FRAGS.DataMap<string, SimplePlane>;
1467
+ /** Planes between the list's before-delete and item-deleted events. */
1468
+ private _deleting;
1467
1469
  /** {@link Configurable.config} */
1468
1470
  config: ClipperConfigManager;
1469
1471
  protected _defaultConfig: ClipperConfig;
@@ -2785,10 +2787,23 @@ export declare class EdgeProjector extends Component implements Disposable_2 {
2785
2787
  */
2786
2788
  readonly generator: any;
2787
2789
  /**
2788
- * Resolution of the visibility culler in pixels per meter.
2789
- * Higher values = more accurate occlusion but slower culling.
2790
+ * Size of one visibility-culling pixel, in meters (despite the name, the
2791
+ * value is meters per pixel). LOWER values mean finer culling — fewer small
2792
+ * meshes are discarded — at the cost of a larger render target, more tiles
2793
+ * and more readback time. Higher values are coarser and faster. Default is
2794
+ * 0.05 (one culling pixel covers 5 cm).
2795
+ *
2796
+ * Note: meshes without a single visible pixel are removed from BOTH the
2797
+ * visible and the hidden line sets, so this value bounds how much small
2798
+ * geometry a projection loses.
2790
2799
  */
2791
2800
  cullerPixelsPerMeter: number;
2801
+ /**
2802
+ * Alias of {@link EdgeProjector.cullerPixelsPerMeter} under a name that
2803
+ * matches what the value actually is. Reads and writes the same setting.
2804
+ */
2805
+ get cullerMetersPerPixel(): number;
2806
+ set cullerMetersPerPixel(value: number);
2792
2807
  /**
2793
2808
  * The direction the projector looks along. Meshes are projected onto the plane
2794
2809
  * perpendicular to this direction. Default is top-down (plan view).
@@ -2821,10 +2836,14 @@ export declare class EdgeProjector extends Component implements Disposable_2 {
2821
2836
  * @param world - The world whose renderer will be used for visibility culling.
2822
2837
  * @param config - Optional configuration.
2823
2838
  * @param config.onProgress - Optional progress callback receiving (message, progress?, collector?).
2839
+ * @param config.signal - Optional AbortSignal. The generator pumps itself on
2840
+ * requestAnimationFrame and checks it on every frame, so aborting rejects the
2841
+ * returned promise and stops the pump instead of draining the whole task.
2824
2842
  * @returns Visible/hidden geometries with a `group` vertex attribute, and a groups mapping.
2825
2843
  */
2826
2844
  get(modelIdMap: ModelIdMap, world: World, config?: {
2827
2845
  onProgress?: (message: string, progress?: number) => void;
2846
+ signal?: AbortSignal;
2828
2847
  }): Promise<EdgeProjectionResult>;
2829
2848
  dispose(): void;
2830
2849
  }
@@ -2922,29 +2941,35 @@ export declare interface ExternalDocumentReference extends DocumentReference {
2922
2941
 
2923
2942
  /**
2924
2943
  * GPU-readback picker that identifies what's under a screen position
2925
- * without going through the worker raycast. Two granularities, same
2926
- * render pass:
2944
+ * without going through the worker raycast.
2927
2945
  *
2928
2946
  * - {@link getModelAt} returns the model id under the cursor.
2929
2947
  * - {@link getItemAt} returns the item itself (`modelId` + `localId`).
2948
+ * - {@link getPointAt} / {@link getNormalAt} return the surface point and normal.
2949
+ * - {@link getFullPick} returns all of the above from the same pick.
2930
2950
  *
2931
- * The fragments tile geometry already carries a per-vertex `id`
2932
- * attribute (the internal item id). We render the BIM scene to an
2933
- * offscreen target with a shader that packs `(modelByte, itemId)` into
2934
- * RGBA, then `readPixels` at the cursor and decode. One render plus
2935
- * one 4-byte readback per call. No worker round-trip for the model
2936
- * lookup; the first time we resolve a given `itemId` to a `localId`
2937
- * we ask the worker, and afterwards that lookup is cached.
2951
+ * Every query goes through {@link renderPick}: one render of the BIM scene
2952
+ * into a 1×1 multiple-render-target, through a camera whose frustum covers
2953
+ * only the pixel under the cursor. The pick shader writes the item id,
2954
+ * depth and normal of that pixel into one attachment each, so they always
2955
+ * describe the same fragment; each query reads back only the attachments
2956
+ * it needs.
2938
2957
  *
2939
- * Encoding (one pixel):
2958
+ * What can be picked is what is drawn. An item that fragments currently draws
2959
+ * at a reduced LOD — a line mesh carrying no `id` attribute — is not pickable,
2960
+ * and the pick resolves to whatever is behind it; the worker raycast tests the
2961
+ * authored geometry instead, so the two can disagree on small or distant
2962
+ * items, see {@link collectPickables}.
2963
+ *
2964
+ * Item id encoding (one pixel). The id is written as `itemId + 1` so that
2965
+ * an unwritten pixel (all zeroes) decodes as "no item" rather than item 0:
2940
2966
  * R = modelByte (1..254, 0 = void / unwritten)
2941
- * G = (itemId >> 16) & 0xff
2942
- * B = (itemId >> 8) & 0xff
2943
- * A = (itemId) & 0xff
2967
+ * G = ((itemId + 1) >> 16) & 0xff
2968
+ * B = ((itemId + 1) >> 8) & 0xff
2969
+ * A = (itemId + 1) & 0xff
2944
2970
  *
2945
- * `modelByte` is assigned per-pick from a `byteToModelId` map; the
2946
- * picker re-allocates bytes each call so the assignment is stable for
2947
- * the duration of the pick but doesn't grow over the session.
2971
+ * `modelByte` is assigned per-pick, so the assignment is stable for the
2972
+ * duration of the pick but doesn't grow over the session.
2948
2973
  */
2949
2974
  export declare class FastModelPicker implements Disposable_2 {
2950
2975
  /** {@link Component.enabled} */
@@ -2958,10 +2983,10 @@ export declare class FastModelPicker implements Disposable_2 {
2958
2983
  /** World this picker renders against. */
2959
2984
  world: World;
2960
2985
  /**
2961
- * When `true`, mirrors the id render to a debug canvas pinned in the
2962
- * top-right corner. Each model shows up as a near-uniform red band
2963
- * (the model byte) modulated by varying greens / blues from the
2964
- * per-item id encoding.
2986
+ * When `true`, mirrors the id output of the whole viewport to a debug
2987
+ * canvas pinned in the top-right corner. Each model shows up as a
2988
+ * near-uniform red band (the model byte) modulated by varying greens /
2989
+ * blues from the per-item id encoding.
2965
2990
  */
2966
2991
  debugMode: boolean;
2967
2992
  /**
@@ -2969,68 +2994,50 @@ export declare class FastModelPicker implements Disposable_2 {
2969
2994
  * by the 8-bit `modelByte`. In practice we never approach this.
2970
2995
  */
2971
2996
  static readonly MAX_MODELS = 254;
2972
- private _renderTarget?;
2973
- private _renderTargetSize;
2997
+ /** The 1×1 target every pick renders into. */
2998
+ private _pickTarget?;
2999
+ /** Viewport-sized target for the debug overlay, created on demand. */
3000
+ private _debugTarget?;
3001
+ private _pickBuffers;
2974
3002
  private _debugCanvas?;
2975
3003
  private _debugContainer?;
2976
3004
  /**
2977
- * Single shared shader for the id pass. The same program runs across
2978
- * every model; we flip the `modelByte` uniform between per-model
2979
- * render passes inside one pick to disambiguate which model owns a
2980
- * pixel.
2981
- */
2982
- private _idMaterial;
2983
- /**
2984
- * Depth-encoding shader used by {@link getPointAt}. Written via
2985
- * `scene.overrideMaterial` for one render of the BIM scene, packs
2986
- * `gl_FragCoord.z` into the four bytes of the color attachment using
2987
- * three's `packing` chunk. The packed value is robust to round-trip
2988
- * through an `UNSIGNED_BYTE` target.
2989
- */
2990
- private _depthMaterial;
2991
- /**
2992
- * World-space normal-encoding shader used by {@link getNormalAt}.
2993
- * Writes `(normal * 0.5 + 0.5)` into RGB, alpha = 1. Decode side maps
2994
- * `(rgb * 2 - 1)` and renormalizes. Naive packing wastes alpha and
2995
- * gives ~1° precision per axis, which is plenty for surface
2996
- * alignment, orbit-around-clicked-point, and snapping. Octahedral
2997
- * packing would buy us another bit per axis but isn't worth the
2998
- * complexity until a consumer actually needs sub-degree accuracy.
2999
- */
3000
- private _normalMaterial;
3001
- /**
3002
- * Cached original materials for the swap-render-restore pass.
3003
- * Populated in {@link applyIdMaterial}, drained in
3004
- * {@link restoreOriginalMaterials} after the render.
3005
- */
3006
- private _originalMaterials;
3007
- /**
3008
- * LOD line meshes don't carry the per-vertex `id` attribute and would
3009
- * write whatever color their normal shader produces into the id
3010
- * buffer, faking hits. Hidden for the duration of the id render and
3011
- * restored after.
3012
- */
3013
- private _hiddenLods;
3014
- /**
3015
- * The meshes each model owns, i.e. excluding those belonging to a
3016
- * model nested inside it. A delta model's object is parented under
3017
- * its parent model's object (see the fragments EditHelper), while
3018
- * both are listed as separate models, so subtree membership alone
3019
- * does not determine ownership.
3020
- *
3021
- * Populated in {@link applyIdMaterial}, consumed by
3022
- * {@link renderPickPass} to isolate one model per render without
3023
- * relying on root visibility. A nested model can't be isolated by
3024
- * its root, since hiding the parent's root culls the child too.
3025
- */
3026
- private _ownMeshes;
3005
+ * Writes every {@link PickOutput} on each draw. Set as the scene's
3006
+ * `overrideMaterial` for the pick render, so fragments' materials are
3007
+ * never swapped.
3008
+ */
3009
+ private _pickMaterial;
3010
+ /** Snapshot of the world camera with a narrowed projection. */
3011
+ private _pickCamera;
3012
+ private _pickMatrix;
3013
+ private _pickNdc;
3014
+ private _viewportSize;
3015
+ private _clearColor;
3016
+ /** The pick camera's world position, for measuring distance to a hit. */
3017
+ private _cameraPosition;
3018
+ /**
3019
+ * Per-pick state filled by {@link collectPickables}. `_meshBytes` is read
3020
+ * by the pick material while drawing; `_byteToModel` outlives the render
3021
+ * so the caller can decode the id output.
3022
+ */
3023
+ private _meshBytes;
3024
+ private _byteToModel;
3025
+ private _modelBytes;
3026
+ private _modelRoots;
3027
+ /** Undo log for {@link collectPickables}, drained by {@link restorePickables}. */
3028
+ private _hidden;
3029
+ private _forcedOverrides;
3030
+ private _walkNodes;
3031
+ private _walkOwners;
3032
+ /** The pick material's `clippingPlanes`, refilled by {@link collectLocalPlanes}. */
3033
+ private _localPlanes;
3027
3034
  constructor(components: Components, world: World);
3028
3035
  /**
3029
3036
  * Returns the model id under the given screen position, or `null` if
3030
3037
  * the cursor is over empty space.
3031
3038
  *
3032
3039
  * Cheaper than {@link getItemAt} because we don't resolve the
3033
- * `localId`; we just read the model byte from the same render.
3040
+ * `localId`; we just read the model byte.
3034
3041
  *
3035
3042
  * @param position - Normalized device coords. Defaults to the
3036
3043
  * picker's last known mouse position.
@@ -3040,10 +3047,12 @@ export declare class FastModelPicker implements Disposable_2 {
3040
3047
  * Returns `{ modelId, localId }` for the item under the given screen
3041
3048
  * position, or `null` if the cursor is over empty space.
3042
3049
  *
3043
- * Pure main-thread resolution: fragments now stores the user-facing
3044
- * `localId` directly in each tile's per-vertex `id` attribute, so
3045
- * the encoded RGBA pixel decodes straight to the localId. No worker
3046
- * round-trip, no cache.
3050
+ * The vertex `id` attribute encodes the internal **itemId** (the
3051
+ * FlatBuffer `sample.item()` index, key for `boxes.sampleOf`) rather
3052
+ * than the user-facing localId, which unblocks the snap path's O(1)
3053
+ * sample lookup. The trade-off: resolving `localId` takes one worker
3054
+ * round-trip. Internal consumers that only need itemId (e.g. snap) can
3055
+ * read it from the result directly.
3047
3056
  *
3048
3057
  * @param position - Normalized device coords. Defaults to the
3049
3058
  * picker's last known mouse position.
@@ -3057,16 +3066,9 @@ export declare class FastModelPicker implements Disposable_2 {
3057
3066
  * Returns the world-space point under the given screen position, or
3058
3067
  * `null` if the cursor is over empty space.
3059
3068
  *
3060
- * Renders the BIM scene with a depth-encoding override material that
3061
- * packs `gl_FragCoord.z` into the color buffer, reads four bytes at
3062
- * the cursor pixel, and unprojects through the camera matrices to a
3063
- * world point. One render pass, one 4-byte readback, no worker
3064
- * round-trip. Useful for things like "set camera orbit center to
3065
- * what the user just clicked on".
3066
- *
3067
- * Cheaper than {@link getItemAt} because we don't differentiate
3068
- * models — one render covers the whole BIM scene at once. We don't
3069
- * resolve any item id either.
3069
+ * Reads the packed `gl_FragCoord.z` of the picked pixel and unprojects
3070
+ * it through the pick camera. Useful for things like "set camera orbit
3071
+ * center to what the user just clicked on".
3070
3072
  *
3071
3073
  * @param position - Normalized device coords. Defaults to the
3072
3074
  * picker's last known mouse position.
@@ -3076,18 +3078,16 @@ export declare class FastModelPicker implements Disposable_2 {
3076
3078
  * Returns the world-space surface normal under the cursor, or `null`
3077
3079
  * if the cursor is over empty space.
3078
3080
  *
3079
- * Mirrors {@link getPointAt}'s structure: one `scene.overrideMaterial`
3080
- * render with the normal-encoding shader, one 4-byte readback,
3081
- * decode and renormalize.
3081
+ * @param position - Normalized device coords. Defaults to the
3082
+ * picker's last known mouse position.
3082
3083
  */
3083
3084
  getNormalAt(position?: THREE.Vector2): Promise<THREE.Vector3 | null>;
3084
3085
  /**
3085
3086
  * One-shot pick that produces the full result shape consumers need:
3086
- * `{ modelId, localId, point, normal, distance }`. Routes through the
3087
- * three GPU passes (id, depth, normal) and composes the output. No
3088
- * worker round-trip.
3087
+ * `{ modelId, localId, point, normal, distance }`, all from the same
3088
+ * render.
3089
3089
  *
3090
- * Returns `null` if the cursor is over empty space, the id pass
3090
+ * Returns `null` if the cursor is over empty space, the id output
3091
3091
  * decodes to the void sentinel, or the depth round-trip yields the
3092
3092
  * far plane.
3093
3093
  */
@@ -3106,142 +3106,126 @@ export declare class FastModelPicker implements Disposable_2 {
3106
3106
  distance: number;
3107
3107
  } | null>;
3108
3108
  /**
3109
- * Toggle the debug overlay. When enabled the picker mirrors its id
3110
- * render to a small canvas pinned in the top-right corner so you can
3111
- * see what the readback sees.
3109
+ * Toggle the debug overlay. When enabled the picker mirrors the id
3110
+ * output of the whole viewport to a small canvas pinned in the
3111
+ * top-right corner so you can see what the picks see.
3112
3112
  */
3113
3113
  setDebugMode(enabled: boolean): void;
3114
3114
  /** {@link Disposable.dispose} */
3115
3115
  dispose(): void;
3116
3116
  /**
3117
- * Runs the id renders and returns the raw decoded
3118
- * `(modelId, itemId)` for the cursor pixel. Two render passes:
3119
- *
3120
- * - Pass 1 (`_renderTarget`): writes the model byte into R via
3121
- * the `_idMaterial`. Used solely to disambiguate which model
3122
- * owns the picked pixel.
3123
- * - Pass 2 (`_localIdRenderTarget`): writes the full 32-bit
3124
- * localId across all four bytes via the same `_idMaterial`
3125
- * with `mode = 1`.
3126
- *
3127
- * Two single-attachment targets instead of MRT keeps the code
3128
- * portable and the diff small. Both passes use the same scene,
3129
- * camera and visibility toggling so depth tests resolve to the
3130
- * same front-most fragment per pixel.
3131
- *
3132
- * Both public entry points lean on this.
3133
- */
3134
- private runIdPass;
3135
- /**
3136
- * Walks every fragments model. For each shell mesh that carries the
3137
- * per-vertex `id` attribute, stashes the original material and swaps
3138
- * in the shared id-encoding shader. Hides LOD line meshes (which
3139
- * lack `id`) so they don't pollute the id buffer. Returns the
3140
- * temporary `byte → modelId` map the render pass uses to
3141
- * disambiguate models.
3142
- */
3143
- private applyIdMaterial;
3144
- /**
3145
- * The object roots of every loaded model.
3146
- */
3147
- private getModelRoots;
3148
- /**
3149
- * Like `Object3D.traverse`, but prunes the subtree of any nested model
3150
- * root, so each mesh is visited exactly once, by the model that owns
3151
- * it. A delta model's object hangs under its parent model's object
3152
- * while being a model in its own right; a plain `traverse` from the
3153
- * parent would walk into it.
3154
- */
3155
- private traverseOwn;
3156
- /**
3157
- * Renders the world scene to the id target one model at a time,
3158
- * flipping the `modelByte` uniform between renders. The depth buffer
3159
- * is shared across the per-model passes so the front-most item still
3160
- * wins each pixel regardless of which model it belongs to.
3161
- *
3162
- * Non-BIM meshes in the world scene (the user's own helpers, ground
3163
- * planes, hover proxies, anything else) are hidden for the duration
3164
- * of the render. Without this, their normal materials write whatever
3165
- * colour they happen to produce into the id target, which decodes as
3166
- * a bogus `(modelByte, itemId)` pair when the cursor lands on one.
3167
- */
3168
- /**
3169
- * Single id render. Iterates models in byte order, flipping the
3170
- * `modelByte` uniform between renders so each model's pixels carry
3171
- * its assigned byte in R while the lower 3 bytes of GBA carry
3172
- * `itemId + 1`. Depth buffer shared across the per-model passes so
3173
- * the front-most item still wins each pixel regardless of which
3174
- * model it belongs to.
3175
- */
3176
- private renderIdPass;
3177
- /**
3178
- * Renders the BIM scene model-by-model into `target` with `material`,
3179
- * scissor-clipped to a small box around the cursor. Iterates models
3180
- * in byte order so depth tests resolve to the same front-most
3181
- * fragment per pixel. Per-model loop sets `material.uniforms.modelByte`
3182
- * before each render so the picked pixel carries the model byte.
3183
- */
3184
- private renderPickPass;
3185
- /**
3186
- * Renders the picker's color target with the BIM tile shells using
3187
- * the given override-style material, swapped in **per-mesh** rather
3188
- * than via `scene.overrideMaterial`.
3189
- *
3190
- * Why per-mesh swap and not `scene.overrideMaterial`: fragments runs
3191
- * its own LOD/visibility logic on tile shells (`mesh.visible`
3192
- * toggled internally based on current LOD stage and frustum). At
3193
- * the moment we render, most tile shells are flagged invisible —
3194
- * `overrideMaterial` then renders nothing and we read back a
3195
- * cleared pixel. Per-mesh swap mirrors what {@link renderIdPass}
3196
- * does; we also force each shell visible for the duration of the
3197
- * render so fragments' culling decisions don't blank our output.
3198
- *
3199
- * Honours the renderer's clipping planes so picked depth/normal
3200
- * match what's actually rendered on screen.
3201
- */
3202
- private renderWithTileMaterial;
3203
- private renderDepthPass;
3204
- private renderNormalPass;
3205
- private restoreOriginalMaterials;
3206
- private readPixelAt;
3207
- /**
3208
- * Single id shader, single render pass. Reads:
3209
- * - `id`: per-vertex `vec4` — the four bytes of `itemId + 1`
3210
- * (big-endian) supplied as a non-normalised `Uint8Array`
3211
- * attribute by fragments. Each component is 0–255 as a float.
3212
- * - `modelByte` uniform — the byte assigned to the currently-
3213
- * rendered model.
3214
- *
3215
- * Output packs `(modelByte, idMid, idLo1, idLo0)` into one RGBA8
3216
- * pixel: model byte in R, the lower three bytes of `itemId + 1` in
3217
- * GBA. Capping the encoded id at 24 bits is fine because `itemId`
3218
- * is the FlatBuffer item index — bounded by item count per model
3219
- * (16M is plenty for any practical BIM model). The high byte of
3220
- * the vertex attribute (`vId.x`) is therefore always 0 and we
3221
- * discard it; that frees R for the model byte. One render → one
3222
- * readback per pick (the previous two-target layout cost two
3223
- * sync-stalling readPixels calls).
3224
- */
3225
- private buildIdMaterial;
3226
- /**
3227
- * Builds the depth-encoding override material used by
3228
- * {@link renderDepthPass}. Includes three's `packing` chunk to reuse
3229
- * the standard `packDepthToRGBA` helper, which is robust to the
3230
- * round-trip through an `UNSIGNED_BYTE` color attachment (the chunk
3231
- * pre-multiplies by `256/255` so `depth = 1.0` decodes back exactly
3232
- * to `1.0`). Decode side mirrors this with the same scaling factors;
3233
- * see {@link unpackDepthFromRGBA} below.
3234
- */
3235
- private buildDepthMaterial;
3236
- /**
3237
- * World-space normal in RGB. Handles backfaces by flipping the
3238
- * encoded normal so consumers always get the surface they're looking
3239
- * at. Decode side: `(rgb * 2 - 1)` → renormalize.
3240
- */
3241
- private buildNormalMaterial;
3242
- private setupRenderTarget;
3117
+ * Renders one pick and decodes the outputs named in `request` into values
3118
+ * the caller owns. Synchronous by design: everything that depends on the
3119
+ * picker's reused state is resolved here, so nothing an entry point does
3120
+ * afterwards can race the next pick.
3121
+ */
3122
+ private pick;
3123
+ /**
3124
+ * Renders every {@link PickOutput} for the region around `ndc` in a single
3125
+ * render, then reads the outputs named in `request` from the centre pixel of
3126
+ * `target` into `out`.
3127
+ *
3128
+ * `target` needs one attachment per output. Its size is the size of the
3129
+ * rendered region in viewport pixels: 1×1 for a pick, the whole viewport
3130
+ * centred on the origin for the debug overlay.
3131
+ *
3132
+ * The scene is left exactly as found, even if rendering throws.
3133
+ */
3134
+ private renderPick;
3135
+ /**
3136
+ * Copies the world camera into the pick camera and narrows its projection
3137
+ * to a `target`-sized region of the viewport centred on `ndc`, the
3138
+ * classic pick matrix: `P' = M · P`.
3139
+ *
3140
+ * - Frustum culling then skips every mesh whose bounds miss that region,
3141
+ * so only meshes under the cursor are drawn at all.
3142
+ * - `M` leaves the depth row alone, so depth decodes as usual.
3143
+ * - The centre of a 1×1 target is exactly `ndc`: no NDC → pixel rounding,
3144
+ * no scissor, no device pixel ratio to account for.
3145
+ * - The world camera is never modified, and custom projections work.
3146
+ */
3147
+ private snapshotCamera;
3148
+ /**
3149
+ * The planes the pick material clips by, so picks match what is on screen.
3150
+ *
3151
+ * - Global planes (`three.clippingPlanes`) are applied by three to every
3152
+ * material on its own. Listing them here too would clip by each twice.
3153
+ * - Local planes (`isLocal`, see `Clipper.localClippingPlanes`) stay out of
3154
+ * that list and reach only the tile materials, so the pick material has
3155
+ * to carry them itself.
3156
+ */
3157
+ private collectLocalPlanes;
3158
+ /**
3159
+ * Walks the scene once and decides what the pick render draws:
3160
+ *
3161
+ * - Shells owned by a model, i.e. meshes carrying the per-vertex `id`
3162
+ * attribute, are drawn and tagged with their model's byte. Ownership
3163
+ * is the nearest model root above the mesh: a delta model's object is
3164
+ * parented under its parent model's object (see the fragments
3165
+ * EditHelper) but keeps its own byte.
3166
+ * - Every other renderable is hidden:
3167
+ * - LOD line meshes, which fragments draws in place of small or distant
3168
+ * items, carry no `id`. Drawn, the missing attribute would read as
3169
+ * `(0, 0, 0, 1)` and write `itemId + 1 = 1`, i.e. a false hit on item 0,
3170
+ * while occluding the real shell behind it. Hidden, the item they stand
3171
+ * for simply isn't pickable, though the worker raycast still reports it.
3172
+ * - Non-BIM objects (helpers, grids, annotation lines, sprites) would
3173
+ * write their own colors into the pick outputs.
3174
+ *
3175
+ * Invisible subtrees are skipped: three won't draw them, and it leaves
3176
+ * fragments' own tile visibility (stale LOD stages, hidden items) as is.
3177
+ */
3178
+ private collectPickables;
3179
+ /**
3180
+ * The byte to draw `node` with, or 0 if it isn't a pickable shell of
3181
+ * `modelId`. Bytes are handed out on a model's first shell, so models with
3182
+ * nothing on screen don't use one up.
3183
+ */
3184
+ private pickableByte;
3185
+ /**
3186
+ * Three skips `scene.overrideMaterial` for materials with
3187
+ * `allowOverride === false`, which would draw a shell with its own shader
3188
+ * into the pick outputs.
3189
+ */
3190
+ private allowOverride;
3191
+ private restorePickables;
3192
+ /**
3193
+ * The pick shader. Writes one output per {@link PickOutput} attachment:
3194
+ *
3195
+ * - `id`: `(modelByte, idMid, idLo1, idLo0)`. The vertex `id` attribute
3196
+ * holds the four bytes of `itemId + 1` (big-endian, non-normalized
3197
+ * `Uint8Array`, so each component is 0–255 as a float). `itemId` is
3198
+ * bounded by the item count per model, so its high byte is always 0
3199
+ * and R is free for the model byte, set per draw from
3200
+ * {@link collectPickables}.
3201
+ * - `depth`: `gl_FragCoord.z` packed into four bytes, inverse of
3202
+ * {@link unpackDepthFromRGBA}:
3203
+ * r = fract(v * 256^3) (least significant)
3204
+ * g = fract(v * 256^2)
3205
+ * b = fract(v * 256)
3206
+ * a = v (most significant)
3207
+ * `r.yzw -= r.xyz / 256` shaves the residual from each higher component
3208
+ * so the encoded value is exact, and the final `* 256/255` upscale lands
3209
+ * `v = 1.0` at all-255 bytes rather than rolling over to 0. Packed by
3210
+ * hand: `ShaderMaterial` doesn't reliably resolve three's `packing`
3211
+ * chunk for custom shaders.
3212
+ * - `normal`: world-space normal as `normal * 0.5 + 0.5` in RGB, alpha 1.
3213
+ * Flipped on backfaces so consumers get the surface they're looking at.
3214
+ * ~1° precision per axis, plenty for surface alignment, orbiting and
3215
+ * snapping.
3216
+ *
3217
+ * Every output is written on every draw: rasterizing one pixel, the only
3218
+ * per-output cost worth saving is the readback, which
3219
+ * {@link renderPick} skips for outputs it wasn't asked for. Per-request
3220
+ * shader variants would each cost a program compile instead.
3221
+ */
3222
+ private buildPickMaterial;
3243
3223
  private setupDebugCanvas;
3244
3224
  private removeDebugCanvas;
3225
+ /**
3226
+ * Renders the pick for the whole viewport into {@link _debugTarget} and
3227
+ * mirrors its id output to the debug canvas.
3228
+ */
3245
3229
  private updateDebugCanvas;
3246
3230
  }
3247
3231
 
@@ -3367,7 +3351,7 @@ export declare class FirstPersonMode implements NavigationMode {
3367
3351
  readonly id = "FirstPerson";
3368
3352
  constructor(camera: OrthoPerspectiveCamera);
3369
3353
  /** {@link NavigationMode.set} */
3370
- set(active: boolean): void;
3354
+ set(active: boolean, options?: NavigationModeOptions): void;
3371
3355
  private setupFirstPersonCamera;
3372
3356
  }
3373
3357
 
@@ -3791,6 +3775,16 @@ export declare class IDSProperty extends IDSFacet {
3791
3775
  constructor(components: Components, propertySet: IDSFacetParameter, baseName: IDSFacetParameter);
3792
3776
  serialize(type: "applicability" | "requirement"): string;
3793
3777
  getEntities(modelIds: RegExp[], collector: ModelIdMap): Promise<void>;
3778
+ /**
3779
+ * Appends the elements that inherit one of `matchedSets` from their type,
3780
+ * as `test()` does through {@link getTypePsets} (issue #708), so a set that
3781
+ * only lives on a type selects the type's instances (issue #798).
3782
+ *
3783
+ * An element's own set of the same name overrides the inherited value of
3784
+ * any property it also defines: if it defines every matched property
3785
+ * itself, whether it applies was already decided from that set above.
3786
+ */
3787
+ private appendTypeInstances;
3794
3788
  test(items: ModelIdMap, collector: ModelIdDataMap<IDSItemCheckResult>, config?: {
3795
3789
  skipIfFails: boolean;
3796
3790
  }): Promise<void>;
@@ -4641,11 +4635,26 @@ export declare interface NavigationMode {
4641
4635
  * @param active - whether to enable or disable this mode.
4642
4636
  * @param options - any additional data required to enable or disable it.
4643
4637
  * */
4644
- set: (active: boolean, options?: any) => void;
4638
+ set: (active: boolean, options?: NavigationModeOptions) => void;
4645
4639
  /** Whether this navigation mode is active or not. */
4646
4640
  enabled: boolean;
4647
4641
  }
4648
4642
 
4643
+ /**
4644
+ * Optional data passed to {@link NavigationMode.set} when enabling or
4645
+ * disabling a navigation mode.
4646
+ */
4647
+ export declare interface NavigationModeOptions {
4648
+ /**
4649
+ * If `true`, the mode must not readjust the camera controls target when
4650
+ * it activates (i.e. it must skip any `moveTo` re-framing). Used by the
4651
+ * {@link OrthoPerspectiveCamera} on world assignment, where the initial
4652
+ * mode setup has already framed the camera and a second adjustment would
4653
+ * move the target again.
4654
+ */
4655
+ preventTargetAdjustment?: boolean;
4656
+ }
4657
+
4649
4658
  /**
4650
4659
  * The extensible list of supported navigation modes.
4651
4660
  */
@@ -4683,7 +4692,7 @@ export declare class OrbitMode implements NavigationMode {
4683
4692
  readonly id = "Orbit";
4684
4693
  constructor(camera: OrthoPerspectiveCamera);
4685
4694
  /** {@link NavigationMode.set} */
4686
- set(active: boolean): void;
4695
+ set(active: boolean, options?: NavigationModeOptions): void;
4687
4696
  private activateOrbitControls;
4688
4697
  }
4689
4698
 
@@ -4719,6 +4728,13 @@ export declare class OrthoPerspectiveCamera extends SimpleCamera {
4719
4728
  * @throws {Error} Throws an error if the mode is not found or the camera is not initialized.
4720
4729
  */
4721
4730
  get mode(): NavigationMode;
4731
+ /**
4732
+ * Whether the camera has a {@link NavigationMode} set. Navigation modes
4733
+ * are created when the camera is assigned to a world, so this is `false`
4734
+ * before that assignment (when {@link OrthoPerspectiveCamera.mode} would
4735
+ * throw). Useful to guard code that may run before initialization.
4736
+ */
4737
+ get hasMode(): boolean;
4722
4738
  constructor(components: Components);
4723
4739
  /** {@link Disposable.dispose} */
4724
4740
  dispose(): void;
@@ -4769,8 +4785,12 @@ export declare class PlanMode implements NavigationMode {
4769
4785
  private readonly defaultAzimuthSpeed;
4770
4786
  private readonly defaultPolarSpeed;
4771
4787
  constructor(camera: OrthoPerspectiveCamera);
4772
- /** {@link NavigationMode.set} */
4773
- set(active: boolean): void;
4788
+ /**
4789
+ * {@link NavigationMode.set}. This mode never adjusts the camera target,
4790
+ * so {@link NavigationModeOptions.preventTargetAdjustment} is trivially
4791
+ * honored: there is nothing to skip.
4792
+ */
4793
+ set(active: boolean, _options?: NavigationModeOptions): void;
4774
4794
  }
4775
4795
 
4776
4796
  /** Basic type to describe the progress of any kind of process. */
@@ -5033,6 +5053,27 @@ export declare interface SerializedQueryParameters {
5033
5053
  };
5034
5054
  }
5035
5055
 
5056
+ /**
5057
+ * Move the orbit point to an anchored surface without letting the camera
5058
+ * jump or the zoom decay.
5059
+ *
5060
+ * `CameraControls.setOrbitPoint` internally calls `dollyTo(distance)`, which
5061
+ * clamps the orbit radius to `[minDistance, maxDistance]`. If the anchored
5062
+ * surface sits closer than `minDistance`, that clamp would snap the camera
5063
+ * backwards, so the anchor has to be placed with a near-zero `minDistance`.
5064
+ *
5065
+ * But `minDistance` is also what stops the zoom from decaying: with
5066
+ * `dollyToCursor` + `infinityDolly` the wheel step is proportional to the
5067
+ * orbit radius, and the constant-speed "infinity" push only kicks in once the
5068
+ * radius reaches `minDistance`. Leaving `minDistance` near zero (as dynamic
5069
+ * anchoring used to, globally) let the radius shrink toward zero on every
5070
+ * zoom-in, so each notch moved exponentially less — the zoom felt like it was
5071
+ * grinding to a halt until a press re-anchored it. So we drop `minDistance`
5072
+ * only for the placement itself and restore it immediately, keeping the real
5073
+ * `minDistance` in force for the wheel.
5074
+ */
5075
+ export declare function setOrbitPoint(controls: default_2, point: THREE.Vector3): void;
5076
+
5036
5077
  /**
5037
5078
  * A scene that supports efficient cast shadows. 📕 [Tutorial](https://docs.thatopen.com/Tutorials/Components/Core/ShadowedScene). 📘 [API](https://docs.thatopen.com/api/@thatopen/components/classes/ShadowedScene).
5038
5079
  */
@@ -5117,7 +5158,7 @@ export declare class SimpleCamera extends BaseCamera implements Updateable, Disp
5117
5158
  * Transforming the camera directly will have no effect: you need to use this
5118
5159
  * object to move, rotate, look at objects, etc.
5119
5160
  */
5120
- get controls(): CameraControls;
5161
+ get controls(): default_2;
5121
5162
  /**
5122
5163
  * Getter for the enabled state of the camera controls.
5123
5164
  * If the current world is null, it returns false.