@expofp/renderer 3.2.5 → 3.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -0
- package/dist/Renderer.d.ts +88 -0
- package/dist/Renderer.js +53 -0
- package/dist/controls/CameraControls.d.ts +102 -0
- package/dist/controls/CameraControls.js +239 -0
- package/dist/controls/camera-api.d.ts +206 -0
- package/dist/controls/camera-api.js +181 -0
- package/dist/controls/camera-move.d.ts +13 -0
- package/dist/controls/camera-move.js +18 -0
- package/dist/controls/camera-state.d.ts +40 -0
- package/dist/controls/camera-state.js +65 -0
- package/dist/controls/gestures.d.ts +70 -0
- package/dist/controls/gestures.js +84 -0
- package/dist/controls/handlers/Inertia.d.ts +111 -0
- package/dist/controls/handlers/Inertia.js +215 -0
- package/dist/controls/handlers/Pan.d.ts +23 -0
- package/dist/controls/handlers/Pan.js +32 -0
- package/dist/controls/handlers/Pitch.d.ts +94 -0
- package/dist/controls/handlers/Pitch.js +191 -0
- package/dist/controls/handlers/Roll.d.ts +103 -0
- package/dist/controls/handlers/Roll.js +182 -0
- package/dist/controls/handlers/Zoom.d.ts +15 -0
- package/dist/controls/handlers/Zoom.js +26 -0
- package/dist/controls/index.d.ts +56 -0
- package/dist/controls/index.js +58 -0
- package/dist/controls/zoom-to.d.ts +89 -0
- package/dist/controls/zoom-to.js +91 -0
- package/dist/core/InstanceUniforms.d.ts +93 -0
- package/dist/core/InstanceUniforms.js +266 -0
- package/dist/core/SquareDataTexture.d.ts +277 -0
- package/dist/core/SquareDataTexture.js +476 -0
- package/dist/core/batch/BatchedMesh.d.ts +74 -0
- package/dist/core/batch/BatchedMesh.js +149 -0
- package/dist/core/instanced/FrustumCulling.d.ts +141 -0
- package/dist/core/instanced/FrustumCulling.js +246 -0
- package/dist/core/instanced/InstancedMesh.d.ts +302 -0
- package/dist/core/instanced/InstancedMesh.js +497 -0
- package/dist/core/instanced/Instances.d.ts +119 -0
- package/dist/core/instanced/Instances.js +230 -0
- package/dist/core/instanced/Raycasting.d.ts +118 -0
- package/dist/core/instanced/Raycasting.js +134 -0
- package/dist/core/instanced/instanced-material.d.ts +77 -0
- package/dist/core/instanced/instanced-material.js +224 -0
- package/dist/core/lines/BatchedLines.d.ts +135 -0
- package/dist/core/lines/BatchedLines.js +213 -0
- package/dist/core/lines/FrustumCulling.d.ts +43 -0
- package/dist/core/lines/FrustumCulling.js +85 -0
- package/dist/core/lines/Raycasting.d.ts +44 -0
- package/dist/core/lines/Raycasting.js +91 -0
- package/dist/core/lines/lines-material.d.ts +47 -0
- package/dist/core/lines/lines-material.js +115 -0
- package/dist/core/shader-source.d.ts +50 -0
- package/dist/core/shader-source.js +84 -0
- package/dist/core/text/BatchedText.d.ts +227 -0
- package/dist/core/text/BatchedText.js +467 -0
- package/dist/core/text/MemberTexture.d.ts +90 -0
- package/dist/core/text/MemberTexture.js +194 -0
- package/dist/core/text/Text.d.ts +73 -0
- package/dist/core/text/Text.js +215 -0
- package/dist/core/text/batched-text-material.d.ts +56 -0
- package/dist/core/text/batched-text-material.js +121 -0
- package/dist/core/text/glyph-packing.d.ts +17 -0
- package/dist/core/text/glyph-packing.js +61 -0
- package/dist/core/typed-array.d.ts +16 -0
- package/dist/core/typed-array.js +20 -0
- package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
- package/dist/debug/components/DebugPanelProvider.js +38 -0
- package/dist/debug/components/DebugTools.d.ts +22 -0
- package/dist/debug/components/DebugTools.js +28 -0
- package/dist/debug/components/Gui.d.ts +20 -0
- package/dist/debug/components/Gui.js +32 -0
- package/dist/debug/components/MemoryInfo.d.ts +22 -0
- package/dist/debug/components/MemoryInfo.js +42 -0
- package/dist/debug/components/Panel.d.ts +31 -0
- package/dist/debug/components/Panel.js +98 -0
- package/dist/debug/components/Stats.d.ts +9 -0
- package/dist/debug/components/Stats.js +24 -0
- package/dist/debug/debug-context.d.ts +41 -0
- package/dist/debug/debug-context.js +59 -0
- package/dist/debug/index.d.ts +51 -0
- package/dist/debug/index.js +64 -0
- package/dist/events/LayoutDriver.d.ts +31 -0
- package/dist/events/LayoutDriver.js +88 -0
- package/dist/events/PointerMissed.d.ts +23 -0
- package/dist/events/PointerMissed.js +58 -0
- package/dist/events/def-culling.d.ts +46 -0
- package/dist/events/def-culling.js +69 -0
- package/dist/events/layout-targets.d.ts +104 -0
- package/dist/events/layout-targets.js +245 -0
- package/dist/events/pointer.d.ts +118 -0
- package/dist/events/pointer.js +168 -0
- package/dist/external/ExternalCanvas.d.ts +56 -0
- package/dist/external/ExternalCanvas.js +178 -0
- package/dist/external/external-camera.d.ts +17 -0
- package/dist/external/external-camera.js +82 -0
- package/dist/external/external-events.d.ts +14 -0
- package/dist/external/external-events.js +33 -0
- package/dist/index.d.ts +11 -783
- package/dist/index.js +12 -8031
- package/dist/objects/Background.d.ts +31 -0
- package/dist/objects/Background.js +37 -0
- package/dist/objects/Lighting.d.ts +20 -0
- package/dist/objects/Lighting.js +85 -0
- package/dist/objects/containers/SlotContainer.d.ts +266 -0
- package/dist/objects/containers/SlotContainer.js +251 -0
- package/dist/objects/containers/hooks.d.ts +46 -0
- package/dist/objects/containers/hooks.js +118 -0
- package/dist/objects/containers/index.d.ts +6 -0
- package/dist/objects/containers/index.js +4 -0
- package/dist/objects/containers/keys.d.ts +10 -0
- package/dist/objects/containers/keys.js +18 -0
- package/dist/objects/containers/mesh-writes.d.ts +106 -0
- package/dist/objects/containers/mesh-writes.js +97 -0
- package/dist/objects/containers/props.d.ts +23 -0
- package/dist/objects/containers/props.js +1 -0
- package/dist/objects/images/ImageInstance.d.ts +29 -0
- package/dist/objects/images/ImageInstance.js +83 -0
- package/dist/objects/images/Images.d.ts +37 -0
- package/dist/objects/images/Images.js +204 -0
- package/dist/objects/images/atlas-packer.d.ts +128 -0
- package/dist/objects/images/atlas-packer.js +315 -0
- package/dist/objects/images/image-container.d.ts +51 -0
- package/dist/objects/images/image-container.js +70 -0
- package/dist/objects/images/index.d.ts +2 -0
- package/dist/objects/images/index.js +1 -0
- package/dist/objects/images/texture-budget.d.ts +120 -0
- package/dist/objects/images/texture-budget.js +215 -0
- package/dist/objects/layer/Layer.d.ts +27 -0
- package/dist/objects/layer/Layer.js +114 -0
- package/dist/objects/layer/index.d.ts +2 -0
- package/dist/objects/layer/index.js +1 -0
- package/dist/objects/layer/mount-scheduler.d.ts +102 -0
- package/dist/objects/layer/mount-scheduler.js +145 -0
- package/dist/objects/layer/visibility-gui.d.ts +19 -0
- package/dist/objects/layer/visibility-gui.js +93 -0
- package/dist/objects/lines/LineInstance.d.ts +21 -0
- package/dist/objects/lines/LineInstance.js +73 -0
- package/dist/objects/lines/Lines.d.ts +17 -0
- package/dist/objects/lines/Lines.js +29 -0
- package/dist/objects/lines/index.d.ts +2 -0
- package/dist/objects/lines/index.js +1 -0
- package/dist/objects/lines/line-container.d.ts +35 -0
- package/dist/objects/lines/line-container.js +40 -0
- package/dist/objects/materials/ColorMaterial.d.ts +85 -0
- package/dist/objects/materials/ColorMaterial.js +89 -0
- package/dist/objects/materials/LineMaterial.d.ts +44 -0
- package/dist/objects/materials/LineMaterial.js +72 -0
- package/dist/objects/materials/ModelMaterial.d.ts +41 -0
- package/dist/objects/materials/ModelMaterial.js +84 -0
- package/dist/objects/materials/TextureMaterial.d.ts +30 -0
- package/dist/objects/materials/TextureMaterial.js +29 -0
- package/dist/objects/materials/dim.d.ts +123 -0
- package/dist/objects/materials/dim.js +213 -0
- package/dist/objects/materials/shared.d.ts +6 -0
- package/dist/objects/materials/shared.js +51 -0
- package/dist/objects/models/ModelInstance.d.ts +22 -0
- package/dist/objects/models/ModelInstance.js +33 -0
- package/dist/objects/models/Models.d.ts +22 -0
- package/dist/objects/models/Models.js +177 -0
- package/dist/objects/models/gltf-cache.d.ts +17 -0
- package/dist/objects/models/gltf-cache.js +50 -0
- package/dist/objects/models/index.d.ts +2 -0
- package/dist/objects/models/index.js +1 -0
- package/dist/objects/models/model-asset.d.ts +48 -0
- package/dist/objects/models/model-asset.js +77 -0
- package/dist/objects/models/model-container.d.ts +139 -0
- package/dist/objects/models/model-container.js +227 -0
- package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
- package/dist/objects/shapes/ShapeInstance.js +40 -0
- package/dist/objects/shapes/Shapes.d.ts +21 -0
- package/dist/objects/shapes/Shapes.js +120 -0
- package/dist/objects/shapes/index.d.ts +2 -0
- package/dist/objects/shapes/index.js +1 -0
- package/dist/objects/shapes/shape-container.d.ts +165 -0
- package/dist/objects/shapes/shape-container.js +272 -0
- package/dist/objects/shapes/shape-geometry.d.ts +27 -0
- package/dist/objects/shapes/shape-geometry.js +94 -0
- package/dist/objects/text/TextInstance.d.ts +22 -0
- package/dist/objects/text/TextInstance.js +95 -0
- package/dist/objects/text/Texts.d.ts +30 -0
- package/dist/objects/text/Texts.js +41 -0
- package/dist/objects/text/index.d.ts +2 -0
- package/dist/objects/text/index.js +1 -0
- package/dist/objects/text/text-container.d.ts +105 -0
- package/dist/objects/text/text-container.js +206 -0
- package/dist/objects/text/text-layout.d.ts +83 -0
- package/dist/objects/text/text-layout.js +154 -0
- package/dist/space/Camera.d.ts +103 -0
- package/dist/space/Camera.js +321 -0
- package/dist/space/Scene.d.ts +44 -0
- package/dist/space/Scene.js +112 -0
- package/dist/space/Space.d.ts +288 -0
- package/dist/space/Space.js +329 -0
- package/dist/space/VisibleRect.d.ts +72 -0
- package/dist/space/VisibleRect.js +129 -0
- package/dist/space/camera-handle.d.ts +67 -0
- package/dist/space/camera-handle.js +63 -0
- package/dist/space/camera-kind.d.ts +26 -0
- package/dist/space/camera-kind.js +30 -0
- package/dist/space/canvas-size.d.ts +24 -0
- package/dist/space/canvas-size.js +20 -0
- package/dist/space/clipping.d.ts +55 -0
- package/dist/space/clipping.js +108 -0
- package/dist/space/layout-measure.d.ts +65 -0
- package/dist/space/layout-measure.js +173 -0
- package/dist/space/viewport.d.ts +112 -0
- package/dist/space/viewport.js +67 -0
- package/dist/types/defs.d.ts +169 -0
- package/dist/types/defs.js +1 -0
- package/dist/types/events.d.ts +183 -0
- package/dist/types/events.js +1 -0
- package/dist/types/guards.d.ts +14 -0
- package/dist/types/guards.js +42 -0
- package/dist/update/index.d.ts +3 -0
- package/dist/update/index.js +2 -0
- package/dist/update/slot-writers.d.ts +30 -0
- package/dist/update/slot-writers.js +72 -0
- package/dist/update/store.d.ts +41 -0
- package/dist/update/store.js +98 -0
- package/dist/utils/arrays.d.ts +13 -0
- package/dist/utils/arrays.js +20 -0
- package/dist/utils/colors.d.ts +19 -0
- package/dist/utils/colors.js +27 -0
- package/dist/utils/logging.d.ts +26 -0
- package/dist/utils/logging.js +47 -0
- package/dist/utils/math.d.ts +24 -0
- package/dist/utils/math.js +27 -0
- package/package.json +67 -19
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type Camera } from 'three';
|
|
2
|
+
import { type CameraControlsImpl } from '../controls/CameraControls';
|
|
3
|
+
import { type Space } from './Space';
|
|
4
|
+
/**
|
|
5
|
+
* How much of the plan one device pixel spans, in plan units — what everything sized in pixels is
|
|
6
|
+
* authored against, and what the imperative renderer published as `ptScale`.
|
|
7
|
+
*
|
|
8
|
+
* **One number for a view that has many.** Perspective foreshortens a pitched plan, so no single
|
|
9
|
+
* factor is true across the whole screen. The one the plan is laid out against is the value where
|
|
10
|
+
* the camera is aimed ({@link aimedAt}), which is why the reading does not move with pitch — only
|
|
11
|
+
* with dolly.
|
|
12
|
+
*
|
|
13
|
+
* **Derived where the controls can say, measured where they cannot.** They hold the distance to
|
|
14
|
+
* that point, and the projection says how much world a screen spans at it: the imperative
|
|
15
|
+
* renderer's own arithmetic, for free. Without them — external mode, a bare scene — the screen row
|
|
16
|
+
* through the aim is taken onto the plan and divided by the buffer's width, which asks nothing of
|
|
17
|
+
* the camera but its matrices. That row is an iso-depth line wherever the screen's x axis lies
|
|
18
|
+
* parallel to the plan, true for this renderer's camera and a map host's alike, so the average
|
|
19
|
+
* along it is exact rather than approximate.
|
|
20
|
+
*
|
|
21
|
+
* Neither path knows a `visibleRect` exists: its framing rides in `projectionMatrix`, which one
|
|
22
|
+
* reads `m00` out of and the other projects through.
|
|
23
|
+
*
|
|
24
|
+
* **Device pixels, not css pixels** — a plan at dpr 2 reports half the pixel size of the same plan
|
|
25
|
+
* at dpr 1, as the imperative renderer did measuring `canvas.height`.
|
|
26
|
+
* @param camera - The camera in use.
|
|
27
|
+
* @param space - The scene's space.
|
|
28
|
+
* @param bufferWidth - The drawing buffer's width in device pixels.
|
|
29
|
+
* @param controls - The camera controls, when mounted; they own the distance to the target.
|
|
30
|
+
* @returns Plan units per device pixel, or `undefined` while the camera misses the plan or the
|
|
31
|
+
* buffer has no width.
|
|
32
|
+
*/
|
|
33
|
+
export declare function measurePixelSize(camera: Camera, space: Space, bufferWidth: number, controls?: CameraControlsImpl): number | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Which way the plan is turned, in radians clockwise from north — {@link measurePixelSize}'s
|
|
36
|
+
* counterpart on the roll axis, split the same way.
|
|
37
|
+
*
|
|
38
|
+
* The controls hold an azimuth, so where they exist that is the whole answer. Without them it is
|
|
39
|
+
* the screen direction of the plan's own x axis at {@link aimedAt}, read off the matrix that takes
|
|
40
|
+
* the plan to clip space: the plan's x axis is that matrix's first column, and a screen direction is
|
|
41
|
+
* what its clip image becomes once the perspective divide is differentiated through. Under an
|
|
42
|
+
* external host this composes the host's bearing with the static transform's own rotation, which is
|
|
43
|
+
* the venue-relative angle the imperative path fed its roll handlers by hand.
|
|
44
|
+
*
|
|
45
|
+
* A direction rather than the angle between two projected points is what removes the probe the
|
|
46
|
+
* imperative renderer used, and with it the question of how far apart to place it.
|
|
47
|
+
* @param camera - The camera in use.
|
|
48
|
+
* @param space - The scene's space.
|
|
49
|
+
* @param bufferWidth - The drawing buffer's width in device pixels.
|
|
50
|
+
* @param bufferHeight - Its height, which weights the two NDC axes back into pixels.
|
|
51
|
+
* @param controls - The camera controls, when mounted; they hold the angle outright.
|
|
52
|
+
* @returns The roll in `[0, 2π)`, or `undefined` while the camera misses the plan.
|
|
53
|
+
*/
|
|
54
|
+
export declare function measureRoll(camera: Camera, space: Space, bufferWidth: number, bufferHeight: number, controls?: CameraControlsImpl): number | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Whether a new pixel size differs enough from the last one to re-lay out on.
|
|
57
|
+
*
|
|
58
|
+
* Absolute rather than relative, and the same `1e-4` the imperative renderer compared with, so the
|
|
59
|
+
* handlers ported onto this API keep firing at the zoom steps they were tuned against.
|
|
60
|
+
* @param pixelSize - The new value.
|
|
61
|
+
* @param previous - The value last laid out at.
|
|
62
|
+
* @returns Whether the change is worth acting on.
|
|
63
|
+
*/
|
|
64
|
+
export declare function pixelSizeMoved(pixelSize: number, previous: number): boolean;
|
|
65
|
+
//# sourceMappingURL=layout-measure.d.ts.map
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { Point } from '@expofp/geometry';
|
|
2
|
+
import { Matrix4, Ray, Vector2, Vector4 } from 'three';
|
|
3
|
+
import { bearing } from '../controls/CameraControls';
|
|
4
|
+
import { euclideanModulo } from '../utils/math';
|
|
5
|
+
import { isOrthographic, isPerspective } from './camera-kind';
|
|
6
|
+
/**
|
|
7
|
+
* How much of the plan one device pixel spans, in plan units — what everything sized in pixels is
|
|
8
|
+
* authored against, and what the imperative renderer published as `ptScale`.
|
|
9
|
+
*
|
|
10
|
+
* **One number for a view that has many.** Perspective foreshortens a pitched plan, so no single
|
|
11
|
+
* factor is true across the whole screen. The one the plan is laid out against is the value where
|
|
12
|
+
* the camera is aimed ({@link aimedAt}), which is why the reading does not move with pitch — only
|
|
13
|
+
* with dolly.
|
|
14
|
+
*
|
|
15
|
+
* **Derived where the controls can say, measured where they cannot.** They hold the distance to
|
|
16
|
+
* that point, and the projection says how much world a screen spans at it: the imperative
|
|
17
|
+
* renderer's own arithmetic, for free. Without them — external mode, a bare scene — the screen row
|
|
18
|
+
* through the aim is taken onto the plan and divided by the buffer's width, which asks nothing of
|
|
19
|
+
* the camera but its matrices. That row is an iso-depth line wherever the screen's x axis lies
|
|
20
|
+
* parallel to the plan, true for this renderer's camera and a map host's alike, so the average
|
|
21
|
+
* along it is exact rather than approximate.
|
|
22
|
+
*
|
|
23
|
+
* Neither path knows a `visibleRect` exists: its framing rides in `projectionMatrix`, which one
|
|
24
|
+
* reads `m00` out of and the other projects through.
|
|
25
|
+
*
|
|
26
|
+
* **Device pixels, not css pixels** — a plan at dpr 2 reports half the pixel size of the same plan
|
|
27
|
+
* at dpr 1, as the imperative renderer did measuring `canvas.height`.
|
|
28
|
+
* @param camera - The camera in use.
|
|
29
|
+
* @param space - The scene's space.
|
|
30
|
+
* @param bufferWidth - The drawing buffer's width in device pixels.
|
|
31
|
+
* @param controls - The camera controls, when mounted; they own the distance to the target.
|
|
32
|
+
* @returns Plan units per device pixel, or `undefined` while the camera misses the plan or the
|
|
33
|
+
* buffer has no width.
|
|
34
|
+
*/
|
|
35
|
+
export function measurePixelSize(camera, space, bufferWidth, controls) {
|
|
36
|
+
if (!(bufferWidth > 0) || !(space.scale > 0))
|
|
37
|
+
return undefined;
|
|
38
|
+
if (controls) {
|
|
39
|
+
const worldWidth = visibleWorldWidth(camera, controls.distance);
|
|
40
|
+
if (!(worldWidth > 0))
|
|
41
|
+
return undefined;
|
|
42
|
+
// The camera measures the world, and only the fit says how much plan that world is.
|
|
43
|
+
return worldWidth / bufferWidth / space.scale;
|
|
44
|
+
}
|
|
45
|
+
const aim = aimedAt(camera, space);
|
|
46
|
+
if (!aim)
|
|
47
|
+
return undefined;
|
|
48
|
+
// Only the row's height is wanted, so `_ndc` is free to be re-aimed along it below.
|
|
49
|
+
const rowY = space.planToNdc(aim, camera, _ndc)?.y;
|
|
50
|
+
if (rowY === undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
const left = space.ndcToPlan(_ndc.set(-1, rowY), camera, _left);
|
|
53
|
+
const right = space.ndcToPlan(_ndc.set(1, rowY), camera, _right);
|
|
54
|
+
if (!left || !right)
|
|
55
|
+
return undefined;
|
|
56
|
+
const planLength = Math.hypot(right.x - left.x, right.y - left.y);
|
|
57
|
+
if (!(planLength > 0))
|
|
58
|
+
return undefined;
|
|
59
|
+
return planLength / bufferWidth;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Which way the plan is turned, in radians clockwise from north — {@link measurePixelSize}'s
|
|
63
|
+
* counterpart on the roll axis, split the same way.
|
|
64
|
+
*
|
|
65
|
+
* The controls hold an azimuth, so where they exist that is the whole answer. Without them it is
|
|
66
|
+
* the screen direction of the plan's own x axis at {@link aimedAt}, read off the matrix that takes
|
|
67
|
+
* the plan to clip space: the plan's x axis is that matrix's first column, and a screen direction is
|
|
68
|
+
* what its clip image becomes once the perspective divide is differentiated through. Under an
|
|
69
|
+
* external host this composes the host's bearing with the static transform's own rotation, which is
|
|
70
|
+
* the venue-relative angle the imperative path fed its roll handlers by hand.
|
|
71
|
+
*
|
|
72
|
+
* A direction rather than the angle between two projected points is what removes the probe the
|
|
73
|
+
* imperative renderer used, and with it the question of how far apart to place it.
|
|
74
|
+
* @param camera - The camera in use.
|
|
75
|
+
* @param space - The scene's space.
|
|
76
|
+
* @param bufferWidth - The drawing buffer's width in device pixels.
|
|
77
|
+
* @param bufferHeight - Its height, which weights the two NDC axes back into pixels.
|
|
78
|
+
* @param controls - The camera controls, when mounted; they hold the angle outright.
|
|
79
|
+
* @returns The roll in `[0, 2π)`, or `undefined` while the camera misses the plan.
|
|
80
|
+
*/
|
|
81
|
+
export function measureRoll(camera, space, bufferWidth, bufferHeight, controls) {
|
|
82
|
+
if (controls)
|
|
83
|
+
return bearing(controls);
|
|
84
|
+
const aim = aimedAt(camera, space);
|
|
85
|
+
if (!aim)
|
|
86
|
+
return undefined;
|
|
87
|
+
_planToClip
|
|
88
|
+
.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
|
|
89
|
+
.multiply(space.matrix);
|
|
90
|
+
// Column-major, so elements 0 to 3 are the first column: the plan's x axis as a clip direction.
|
|
91
|
+
const column = _planToClip.elements;
|
|
92
|
+
const clip = _clip.set(aim.x, aim.y, 0, 1).applyMatrix4(_planToClip);
|
|
93
|
+
// d(ndc)/dx by the quotient rule, less its `1/w²` — positive, so it moves no direction. NDC is
|
|
94
|
+
// aspect-distorted, so each axis is weighted back into pixels; canvas y grows downward where NDC
|
|
95
|
+
// y grows up.
|
|
96
|
+
const dx = (column[0] * clip.w - clip.x * column[3]) * bufferWidth;
|
|
97
|
+
const dy = -(column[1] * clip.w - clip.y * column[3]) * bufferHeight;
|
|
98
|
+
if (dx === 0 && dy === 0)
|
|
99
|
+
return undefined;
|
|
100
|
+
// The plan turned clockwise by θ shows its east axis at screen angle -θ.
|
|
101
|
+
return euclideanModulo(-Math.atan2(dy, dx), 2 * Math.PI);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Whether a new pixel size differs enough from the last one to re-lay out on.
|
|
105
|
+
*
|
|
106
|
+
* Absolute rather than relative, and the same `1e-4` the imperative renderer compared with, so the
|
|
107
|
+
* handlers ported onto this API keep firing at the zoom steps they were tuned against.
|
|
108
|
+
* @param pixelSize - The new value.
|
|
109
|
+
* @param previous - The value last laid out at.
|
|
110
|
+
* @returns Whether the change is worth acting on.
|
|
111
|
+
*/
|
|
112
|
+
export function pixelSizeMoved(pixelSize, previous) {
|
|
113
|
+
return Math.abs(pixelSize - previous) >= PIXEL_SIZE_EPSILON;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Where the camera is aimed on the plan: the point its own axis crosses, which is what the controls
|
|
117
|
+
* would call their target and what the derived path's distance is measured to.
|
|
118
|
+
*
|
|
119
|
+
* Read off the camera's world matrix rather than asked of anything that might not be there —
|
|
120
|
+
* external mode's camera carries a rigid one recovered from the host's folded matrix, so its eye
|
|
121
|
+
* and direction are as true as a camera three placed itself.
|
|
122
|
+
* @param camera - The camera in use.
|
|
123
|
+
* @param space - The scene's space.
|
|
124
|
+
* @returns The plan point, or `undefined` when the camera looks along the plan and never meets it.
|
|
125
|
+
*/
|
|
126
|
+
function aimedAt(camera, space) {
|
|
127
|
+
_axis.origin.setFromMatrixPosition(camera.matrixWorld);
|
|
128
|
+
camera.getWorldDirection(_axis.direction);
|
|
129
|
+
return space.rayToPlan(_axis, _aim);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The world-space width one screen covers at a distance.
|
|
133
|
+
*
|
|
134
|
+
* Read off the projection matrix rather than rebuilt from `fov` and `zoom`: `m00` is `2·near /
|
|
135
|
+
* (right − left)` under perspective and `2 / (right − left)` under orthographic, so it holds for a
|
|
136
|
+
* projection nobody derived from a symmetric frustum — the off-centre, expanded one a `visibleRect`
|
|
137
|
+
* installs, which leaves `fov` untouched.
|
|
138
|
+
*
|
|
139
|
+
* Width where the imperative renderer took height, so both of {@link measurePixelSize}'s paths
|
|
140
|
+
* divide by the one buffer dimension they are given; for a projection whose aspect is the buffer's
|
|
141
|
+
* the two agree exactly.
|
|
142
|
+
* @param camera - The camera in use.
|
|
143
|
+
* @param distance - Distance from the camera to the point it is aimed at, in world units.
|
|
144
|
+
* @returns The width in world units, or `NaN` for a camera that projects neither way.
|
|
145
|
+
*/
|
|
146
|
+
function visibleWorldWidth(camera, distance) {
|
|
147
|
+
// Column-major: element 0 is row 0 of column 0.
|
|
148
|
+
const m00 = camera.projectionMatrix.elements[0];
|
|
149
|
+
if (!(m00 > 0))
|
|
150
|
+
return NaN;
|
|
151
|
+
// A perspective frustum widens with distance; an orthographic one covers the same width wherever
|
|
152
|
+
// it sits, which is the whole difference between the two.
|
|
153
|
+
if (isPerspective(camera))
|
|
154
|
+
return (2 * distance) / m00;
|
|
155
|
+
if (isOrthographic(camera))
|
|
156
|
+
return 2 / m00;
|
|
157
|
+
return NaN;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The change in {@link measurePixelSize} below which nothing is re-laid out. Not configurable: it
|
|
161
|
+
* is the granularity every handler's thresholds are expressed against, so a scene tuning it would
|
|
162
|
+
* be tuning every handler at once.
|
|
163
|
+
*/
|
|
164
|
+
const PIXEL_SIZE_EPSILON = 1e-4;
|
|
165
|
+
// Scratch, each filled and consumed within one call — and the two readings never overlap, so the
|
|
166
|
+
// aim they share is one point rather than two.
|
|
167
|
+
const _axis = new Ray();
|
|
168
|
+
const _aim = new Point();
|
|
169
|
+
const _left = new Point();
|
|
170
|
+
const _right = new Point();
|
|
171
|
+
const _ndc = new Vector2();
|
|
172
|
+
const _planToClip = new Matrix4();
|
|
173
|
+
const _clip = new Vector4();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { type Camera as ThreeCamera } from 'three';
|
|
2
|
+
import { type CanvasPoint, type CanvasPointLike, type PlanPoint, type PlanPointLike, type Space } from './Space';
|
|
3
|
+
/**
|
|
4
|
+
* Where things are: the two directions between the plan's own coordinates and the canvas the user
|
|
5
|
+
* points at, and the one question that rides on them.
|
|
6
|
+
*
|
|
7
|
+
* The counterpart to `CameraAPI`, and the division is the obvious one — that moves the camera, this
|
|
8
|
+
* reads where the camera has left things. Nothing here changes anything, so nothing here returns a
|
|
9
|
+
* promise: every method answers for the plan as it stands at the moment of asking.
|
|
10
|
+
*
|
|
11
|
+
* Both conversions can fail, and both failures are real rather than defensive: a tilted camera looks
|
|
12
|
+
* past the plan entirely above the horizon, and a plan point can sit behind the camera. `undefined`
|
|
13
|
+
* says so in each direction, rather than a number that would read as a position.
|
|
14
|
+
*
|
|
15
|
+
* This is the surface that replaces the imperative renderer's `viewport`, whose `canvasToSvg`
|
|
16
|
+
* covered only the first of these — and returned one point per loaded scene, leaving every caller
|
|
17
|
+
* to pick the default one out of an array.
|
|
18
|
+
*/
|
|
19
|
+
export interface ViewportAPI {
|
|
20
|
+
/**
|
|
21
|
+
* Where a point on the canvas lands on the plan.
|
|
22
|
+
*
|
|
23
|
+
* **The plan plane, not the geometry drawn on it.** A click on the roof of a raised model reports
|
|
24
|
+
* the ground point the ray carries on to, which is the floor coordinate this answers for; what the
|
|
25
|
+
* ray actually struck is a pointer event's business, and `PointerEventData.point` reports that.
|
|
26
|
+
* @param point - The canvas position, in css pixels from the canvas's top-left corner.
|
|
27
|
+
* @param out - A point to write into, for a caller converting enough of them to care. Omit it and
|
|
28
|
+
* each call allocates, which is what makes the result safe to keep.
|
|
29
|
+
* @returns The plan position, or `undefined` when the camera never meets the plan there.
|
|
30
|
+
*/
|
|
31
|
+
canvasToPlan(point: CanvasPointLike, out?: PlanPoint): PlanPoint | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Where a point on the plan lands on the canvas.
|
|
34
|
+
*
|
|
35
|
+
* **Unclamped:** a point off the side of the plan reports the position it really has, outside the
|
|
36
|
+
* canvas, which is what makes it usable for placing something that may scroll into view.
|
|
37
|
+
* @param point - The plan position; a missing `z` is read as `0`, so an elevated point projects
|
|
38
|
+
* from the height it is drawn at.
|
|
39
|
+
* @param out - A point to write into, for a caller converting enough of them to care. Omit it and
|
|
40
|
+
* each call allocates, which is what makes the result safe to keep.
|
|
41
|
+
* @returns The canvas position in css pixels, or `undefined` when the point is behind the camera.
|
|
42
|
+
*/
|
|
43
|
+
planToCanvas(point: PlanPointLike, out?: CanvasPoint): CanvasPoint | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Whether a point on the plan is on screen.
|
|
46
|
+
*
|
|
47
|
+
* **The whole canvas counts**, including any part of it a host's own UI covers: a `visibleRect`
|
|
48
|
+
* expands the frustum rather than cropping it, so the plan really is drawn edge to edge and a
|
|
49
|
+
* point behind a bottom sheet is drawn as much as one beside it. A caller asking the narrower
|
|
50
|
+
* question — can the *user* see it — tests {@link planToCanvas} against its own region.
|
|
51
|
+
* @param point - The plan position; a missing `z` is read as `0`.
|
|
52
|
+
* @returns Whether it is drawn on the canvas.
|
|
53
|
+
*/
|
|
54
|
+
isVisible(point: PlanPointLike): boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* What {@link Viewport} needs from the scene it reads.
|
|
58
|
+
*
|
|
59
|
+
* Handed over whole rather than reached for, as `CameraContext` is, and the store getter is here for
|
|
60
|
+
* the same reason: R3F may swap the camera out from under a held reference, and every conversion
|
|
61
|
+
* below has to run through the one the canvas is currently drawn with.
|
|
62
|
+
*/
|
|
63
|
+
interface ViewportContext {
|
|
64
|
+
/** Reads the canvas state, which is where the camera in use is found. */
|
|
65
|
+
get: () => {
|
|
66
|
+
camera: ThreeCamera;
|
|
67
|
+
};
|
|
68
|
+
/** The scene's space, which owns the mapping every conversion here composes. */
|
|
69
|
+
space: Space;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The scene's coordinate conversions.
|
|
73
|
+
*
|
|
74
|
+
* A hook for the same reason `useCameraAPI` is one: it resolves only inside a component mounted
|
|
75
|
+
* under `<Renderer>`, so "the plan cannot be measured before the scene exists" is enforced by where
|
|
76
|
+
* the code can live rather than by a null check every caller has to remember. A host that needs to
|
|
77
|
+
* convert coordinates from outside React publishes this object from an effect.
|
|
78
|
+
*
|
|
79
|
+
* **Nothing here subscribes to the canvas size**, and it does not need to: `Space` is refitted in
|
|
80
|
+
* place on every resize, so the object below reads the current fit through the same reference for as
|
|
81
|
+
* long as the scene lives, and the camera is read at the moment of asking. That is the reading
|
|
82
|
+
* discipline `Space` documents — and the reason it is safe here is that no render output is derived
|
|
83
|
+
* from these answers.
|
|
84
|
+
*
|
|
85
|
+
* **The returned object is new on every render, deliberately**, as `useCameraAPI`'s is: this module
|
|
86
|
+
* memoizes nothing, so a consumer that cannot re-subscribe cheaply holds it in a ref and pays that
|
|
87
|
+
* cost where the cost is understood.
|
|
88
|
+
* @returns The conversions.
|
|
89
|
+
*/
|
|
90
|
+
export declare function useViewport(): ViewportAPI;
|
|
91
|
+
/**
|
|
92
|
+
* The coordinate conversions, over whatever the scene currently holds.
|
|
93
|
+
*
|
|
94
|
+
* A class rather than an object literal because it is the renderer's published surface, and built
|
|
95
|
+
* fresh rather than mutated so that nothing here is state — every answer is composed from the space
|
|
96
|
+
* and the camera as they stand when the method is called.
|
|
97
|
+
*/
|
|
98
|
+
export declare class Viewport implements ViewportAPI {
|
|
99
|
+
private readonly context;
|
|
100
|
+
/**
|
|
101
|
+
* @param context - What the scene holds; the instance is rebuilt whenever it moves.
|
|
102
|
+
*/
|
|
103
|
+
constructor(context: ViewportContext);
|
|
104
|
+
/** @inheritdoc */
|
|
105
|
+
canvasToPlan(point: CanvasPointLike, out?: PlanPoint): PlanPoint | undefined;
|
|
106
|
+
/** @inheritdoc */
|
|
107
|
+
planToCanvas(point: PlanPointLike, out?: CanvasPoint): CanvasPoint | undefined;
|
|
108
|
+
/** @inheritdoc */
|
|
109
|
+
isVisible(point: PlanPointLike): boolean;
|
|
110
|
+
}
|
|
111
|
+
export {};
|
|
112
|
+
//# sourceMappingURL=viewport.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useThree } from '@react-three/fiber';
|
|
2
|
+
import { Vector2 } from 'three';
|
|
3
|
+
import { useSpace, } from './Space';
|
|
4
|
+
/**
|
|
5
|
+
* The scene's coordinate conversions.
|
|
6
|
+
*
|
|
7
|
+
* A hook for the same reason `useCameraAPI` is one: it resolves only inside a component mounted
|
|
8
|
+
* under `<Renderer>`, so "the plan cannot be measured before the scene exists" is enforced by where
|
|
9
|
+
* the code can live rather than by a null check every caller has to remember. A host that needs to
|
|
10
|
+
* convert coordinates from outside React publishes this object from an effect.
|
|
11
|
+
*
|
|
12
|
+
* **Nothing here subscribes to the canvas size**, and it does not need to: `Space` is refitted in
|
|
13
|
+
* place on every resize, so the object below reads the current fit through the same reference for as
|
|
14
|
+
* long as the scene lives, and the camera is read at the moment of asking. That is the reading
|
|
15
|
+
* discipline `Space` documents — and the reason it is safe here is that no render output is derived
|
|
16
|
+
* from these answers.
|
|
17
|
+
*
|
|
18
|
+
* **The returned object is new on every render, deliberately**, as `useCameraAPI`'s is: this module
|
|
19
|
+
* memoizes nothing, so a consumer that cannot re-subscribe cheaply holds it in a ref and pays that
|
|
20
|
+
* cost where the cost is understood.
|
|
21
|
+
* @returns The conversions.
|
|
22
|
+
*/
|
|
23
|
+
export function useViewport() {
|
|
24
|
+
const get = useThree((state) => state.get);
|
|
25
|
+
const space = useSpace();
|
|
26
|
+
return new Viewport({ get, space });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The coordinate conversions, over whatever the scene currently holds.
|
|
30
|
+
*
|
|
31
|
+
* A class rather than an object literal because it is the renderer's published surface, and built
|
|
32
|
+
* fresh rather than mutated so that nothing here is state — every answer is composed from the space
|
|
33
|
+
* and the camera as they stand when the method is called.
|
|
34
|
+
*/
|
|
35
|
+
export class Viewport {
|
|
36
|
+
context;
|
|
37
|
+
/**
|
|
38
|
+
* @param context - What the scene holds; the instance is rebuilt whenever it moves.
|
|
39
|
+
*/
|
|
40
|
+
constructor(context) {
|
|
41
|
+
this.context = context;
|
|
42
|
+
}
|
|
43
|
+
/** @inheritdoc */
|
|
44
|
+
canvasToPlan(point, out) {
|
|
45
|
+
const { space, get } = this.context;
|
|
46
|
+
return space.canvasToPlan(point, get().camera, out);
|
|
47
|
+
}
|
|
48
|
+
/** @inheritdoc */
|
|
49
|
+
planToCanvas(point, out) {
|
|
50
|
+
const { space, get } = this.context;
|
|
51
|
+
// Never a shared scratch when the caller named none: this is public, and a caller that kept the
|
|
52
|
+
// point it was handed must never find it moved under them. An `out` they passed is theirs, and
|
|
53
|
+
// the aliasing is then a choice they made rather than one made for them.
|
|
54
|
+
return space.planToCanvas(point, get().camera, out);
|
|
55
|
+
}
|
|
56
|
+
/** @inheritdoc */
|
|
57
|
+
isVisible(point) {
|
|
58
|
+
const { space, get } = this.context;
|
|
59
|
+
// Tested in normalized device coordinates rather than in canvas pixels, which is the same test
|
|
60
|
+
// — `ndcToCanvas` maps `[-1, 1]` onto the canvas and nothing else — arrived at without the
|
|
61
|
+
// canvas size, and so with nothing to disagree with when a resize is halfway through.
|
|
62
|
+
const ndc = space.planToNdc(point, get().camera, _ndc);
|
|
63
|
+
return !!ndc && Math.abs(ndc.x) <= 1 && Math.abs(ndc.y) <= 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Where {@link Viewport.isVisible} projects to; it never escapes the method. */
|
|
67
|
+
const _ndc = new Vector2();
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { type Box, type LineLike, type Rect, type Shape } from '@expofp/geometry';
|
|
2
|
+
import { type LayoutHandlers, type PointerHandlers } from './events';
|
|
3
|
+
/** A color as a css string or a packed numeric value. */
|
|
4
|
+
export type ColorInput = string | number;
|
|
5
|
+
/** Any image-like source that can be uploaded as a texture. */
|
|
6
|
+
export type ImageSource = HTMLImageElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas;
|
|
7
|
+
/** Scene definition */
|
|
8
|
+
export interface SceneDef {
|
|
9
|
+
/** Root layer of the scene tree */
|
|
10
|
+
rootLayer: LayerDef;
|
|
11
|
+
/** Background color in css format */
|
|
12
|
+
background?: ColorInput;
|
|
13
|
+
/** SVG viewbox */
|
|
14
|
+
viewbox: Box;
|
|
15
|
+
/** Static transform matrix */
|
|
16
|
+
staticTransform?: number[];
|
|
17
|
+
}
|
|
18
|
+
/** Shared properties for all renderable defs */
|
|
19
|
+
export interface SharedDef extends LayoutHandlers {
|
|
20
|
+
/** Whether the def is hidden */
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* How strongly the def is dimmed — desaturated toward gray and darkened — from `0` (undimmed) to
|
|
24
|
+
* `1` (fully dimmed), interpolating in between.
|
|
25
|
+
*
|
|
26
|
+
* `undefined` inherits from the nearest ancestor that sets one, and only `undefined` inherits: a
|
|
27
|
+
* def's own `0` un-dims it inside a dimmed layer, and its own `1` dims it inside an undimmed one.
|
|
28
|
+
* A layer and a single def carry the same field with the same meaning, so dimming a whole floor
|
|
29
|
+
* and un-dimming one booth on it are the same operation at two levels. The root defaults to `0`.
|
|
30
|
+
*
|
|
31
|
+
* Values outside `[0, 1]` are clamped. Being a number rather than a flag is what lets a dim be
|
|
32
|
+
* animated — easing a layer's value from `0` to `1` costs one uniform per layer per frame,
|
|
33
|
+
* whatever the layer holds.
|
|
34
|
+
*/
|
|
35
|
+
dim?: number;
|
|
36
|
+
}
|
|
37
|
+
/** Any def that can be rendered into a scene. */
|
|
38
|
+
export type RenderableDef = LayerDef | ShapeDef | ImageDef | TextDef | LineDef | ModelDef;
|
|
39
|
+
/**
|
|
40
|
+
* An array of a single {@link RenderableDef} kind (never a mixed union). The conditional
|
|
41
|
+
* distributes over {@link RenderableDef}, so even the default is a union of single-kind arrays —
|
|
42
|
+
* a mixed array is unrepresentable, which is what lets a first-element guard speak for the whole
|
|
43
|
+
* collection. `Readonly<RenderableDefCollection<T>>` distributes the same way, into readonly
|
|
44
|
+
* single-kind arrays.
|
|
45
|
+
*/
|
|
46
|
+
export type RenderableDefCollection<T = RenderableDef> = T extends RenderableDef ? T[] : never;
|
|
47
|
+
/**
|
|
48
|
+
* Layer definition.
|
|
49
|
+
*
|
|
50
|
+
* A layer is also where interaction lives: the handlers it inherits from {@link PointerHandlers} are
|
|
51
|
+
* what make its subtree pickable, and each event names the def it hit. Layout is the other way round
|
|
52
|
+
* — a layer carries its own {@link LayoutHandlers} through {@link SharedDef}, like any other def, and
|
|
53
|
+
* that is how a layer whose contents depend on the camera re-derives them.
|
|
54
|
+
*/
|
|
55
|
+
export interface LayerDef<T extends RenderableDef = RenderableDef> extends SharedDef, PointerHandlers<T> {
|
|
56
|
+
/** Layer's name */
|
|
57
|
+
readonly name: string;
|
|
58
|
+
/** Collection of layer's children. Mixing different types of children is not supported. */
|
|
59
|
+
children: RenderableDefCollection<T>;
|
|
60
|
+
}
|
|
61
|
+
/** Shape definition. */
|
|
62
|
+
export interface ShapeDef extends SharedDef {
|
|
63
|
+
/**
|
|
64
|
+
* Shape to render. To change it, **replace** this with a new `Shape` and call `update(def)`: the
|
|
65
|
+
* new object re-claims the instance against fresh geometry, so even the shape *type* may change
|
|
66
|
+
* (rect ↔ polygon). Mutating the existing shape in place is more limited — a rect's or box's
|
|
67
|
+
* transform (center, size, rotation) is re-read every update, but a polygon's vertices and indices
|
|
68
|
+
* are cached by shape identity and will not rebuild in place.
|
|
69
|
+
*/
|
|
70
|
+
shape: Shape;
|
|
71
|
+
/** Shape's color in css format */
|
|
72
|
+
color: ColorInput;
|
|
73
|
+
}
|
|
74
|
+
/** Image definition */
|
|
75
|
+
export interface ImageDef extends SharedDef {
|
|
76
|
+
/**
|
|
77
|
+
* Image source. Write-once — a def's pixels are fixed for its lifetime: the atlas packs and
|
|
78
|
+
* uploads them at claim time and never re-reads the source, so a new image is a new def, not a
|
|
79
|
+
* reassignment. `readonly` makes that the type's guarantee (see {@link SceneDef.memoryLimit},
|
|
80
|
+
* which relies on a pack's byte totals staying stable until a repack).
|
|
81
|
+
*/
|
|
82
|
+
readonly source: ImageSource;
|
|
83
|
+
/** Image's bounds */
|
|
84
|
+
bounds: Rect;
|
|
85
|
+
/**
|
|
86
|
+
* Image's anchor point. Defines the point on the image that is used as an origin point for transformations.
|
|
87
|
+
* [0, 0] is the top-left corner, [0.5, 0.5] is the center (default), [1, 1] is the bottom-right corner.
|
|
88
|
+
*/
|
|
89
|
+
origin?: [number, number];
|
|
90
|
+
}
|
|
91
|
+
/** Text definition */
|
|
92
|
+
export interface TextDef extends SharedDef {
|
|
93
|
+
/**
|
|
94
|
+
* Array of text lines, drawn as a block stacked inside {@link bounds}.
|
|
95
|
+
*
|
|
96
|
+
* Updatable in both directions: a line's own fields are re-read on every `update(def)`, and
|
|
97
|
+
* changing the array's *length* re-claims the def's batch members against the new count. (The
|
|
98
|
+
* imperative renderer allocated members once and so required this to be fixed; React reconciles
|
|
99
|
+
* it instead.) A line whose `fontSize` is `0` is not drawn.
|
|
100
|
+
*/
|
|
101
|
+
lines: TextLineDef[];
|
|
102
|
+
/** Text's bounds */
|
|
103
|
+
bounds: Rect;
|
|
104
|
+
/** Text's padding [horizontal, vertical] */
|
|
105
|
+
padding: [number, number];
|
|
106
|
+
/** {@link TextAlignment} object describing text's alignment */
|
|
107
|
+
alignment: TextAlignment;
|
|
108
|
+
}
|
|
109
|
+
/** Single text line definition */
|
|
110
|
+
export interface TextLineDef {
|
|
111
|
+
/** Line's text */
|
|
112
|
+
text: string;
|
|
113
|
+
/** Line's color in css format */
|
|
114
|
+
color: ColorInput;
|
|
115
|
+
/** Line's font URL. Not updatable. Supported formats: .ttf, .otf, .woff (.woff2 is not supported). */
|
|
116
|
+
fontUrl: string;
|
|
117
|
+
/**
|
|
118
|
+
* Line's font size: its em height in plan units, the same units as the def's `bounds` and
|
|
119
|
+
* `padding`.
|
|
120
|
+
*
|
|
121
|
+
* Nothing here converts from pixels. A plan sizing a line to hold an on-screen size does that
|
|
122
|
+
* itself, against the pixel size the renderer publishes — as it does for every other
|
|
123
|
+
* pixel-authored thing it draws. `0` means the line is not drawn.
|
|
124
|
+
*/
|
|
125
|
+
fontSize: number;
|
|
126
|
+
/** Line's stroke color & width, the width in the same units as {@link fontSize}. Optional. */
|
|
127
|
+
stroke?: {
|
|
128
|
+
color: ColorInput;
|
|
129
|
+
width: number;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Text alignment */
|
|
133
|
+
export interface TextAlignment {
|
|
134
|
+
/** Horizontal alignment */
|
|
135
|
+
horizontal: 'left' | 'center' | 'right';
|
|
136
|
+
/** Vertical alignment */
|
|
137
|
+
vertical: 'top' | 'center' | 'bottom';
|
|
138
|
+
/** Text alignment within the line. Optional. */
|
|
139
|
+
text?: 'left' | 'center' | 'right';
|
|
140
|
+
}
|
|
141
|
+
/** Line definition */
|
|
142
|
+
export interface LineDef extends SharedDef {
|
|
143
|
+
/**
|
|
144
|
+
* The segment's endpoints, with an optional `elevation` placing it on its layer's plane.
|
|
145
|
+
*
|
|
146
|
+
* Updatable: both ends are re-read on every `update(def)` and written only when they moved,
|
|
147
|
+
* so a line can be animated in place rather than replaced. A `LineLike` exposes readonly coordinates,
|
|
148
|
+
* so an update means replacing this with a new one — or moving the `Line` behind it,
|
|
149
|
+
* whose own setters do the same job.
|
|
150
|
+
*/
|
|
151
|
+
points: LineLike;
|
|
152
|
+
/** Line's color in css format */
|
|
153
|
+
color: ColorInput;
|
|
154
|
+
/**
|
|
155
|
+
* Line's width in screen-space units (pixels), so it holds its thickness as the plan zooms.
|
|
156
|
+
* `0` draws nothing.
|
|
157
|
+
*/
|
|
158
|
+
width: number;
|
|
159
|
+
}
|
|
160
|
+
/** External 3D model definition */
|
|
161
|
+
export interface ModelDef extends SharedDef {
|
|
162
|
+
/** Model's URL. Not updatable. */
|
|
163
|
+
url: string;
|
|
164
|
+
/** Model's bounds */
|
|
165
|
+
bounds: Rect;
|
|
166
|
+
/** Model's opacity. Optional. */
|
|
167
|
+
opacity?: number;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=defs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|