@geometra/renderer-three 0.1.2 → 0.2.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 +34 -4
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/split-host.d.ts +15 -13
- package/dist/split-host.d.ts.map +1 -1
- package/dist/split-host.js +53 -29
- package/dist/split-host.js.map +1 -1
- package/dist/stacked-host.d.ts +59 -0
- package/dist/stacked-host.d.ts.map +1 -0
- package/dist/stacked-host.js +182 -0
- package/dist/stacked-host.js.map +1 -0
- package/dist/three-scene-basics.d.ts +27 -0
- package/dist/three-scene-basics.d.ts.map +1 -0
- package/dist/three-scene-basics.js +18 -0
- package/dist/three-scene-basics.js.map +1 -0
- package/dist/utils.d.ts +9 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +15 -0
- package/dist/utils.js.map +1 -1
- package/package.json +7 -10
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
**Three.js helpers alongside Geometra** — not a replacement for `@geometra/renderer-canvas`. Geometra’s WebSocket geometry protocol still drives the 2D canvas; Three.js owns WebGL for meshes, scenes, and cameras.
|
|
4
4
|
|
|
5
|
-
This package ships the **split-view host** pattern (Three.js pane + Geometra pane) as
|
|
5
|
+
This package ships the **split-view host** pattern (Three.js pane + Geometra pane) and a **stacked HUD** host (full-viewport WebGL + corner Geometra overlay) as bootstrap helpers, plus small WebGL sizing utilities.
|
|
6
|
+
|
|
7
|
+
For the long-term goal — Three.js and Geometra in one **native**, protocol-first, DOM-free space — see [docs/GEOMETRA_NATIVE_SPACE.md](docs/GEOMETRA_NATIVE_SPACE.md). To drive the Cursor Agent CLI in a loop (like the main Geometra repo), use [`scripts/cursor-agent-loop.sh`](scripts/cursor-agent-loop.sh) after installing the [`agent` CLI](https://cursor.com/install); each iteration should pass `npm run release:gate`.
|
|
6
8
|
|
|
7
9
|
## Install
|
|
8
10
|
|
|
@@ -39,17 +41,45 @@ const host = createThreeGeometraSplitHost({
|
|
|
39
41
|
host.destroy()
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
### Stacked HUD (WebGL + overlay)
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import * as THREE from 'three'
|
|
48
|
+
import { createThreeGeometraStackedHost } from '@geometra/renderer-three'
|
|
49
|
+
|
|
50
|
+
const stacked = createThreeGeometraStackedHost({
|
|
51
|
+
container: document.getElementById('app')!,
|
|
52
|
+
geometraHudWidth: 400,
|
|
53
|
+
geometraHudHeight: 280,
|
|
54
|
+
geometraHudPlacement: 'bottom-right',
|
|
55
|
+
geometraHudMargin: 16,
|
|
56
|
+
url: 'ws://localhost:8080/geometra-ws',
|
|
57
|
+
binaryFraming: true,
|
|
58
|
+
onThreeReady: ({ scene, camera }) => {
|
|
59
|
+
scene.add(new THREE.AmbientLight(0xffffff, 0.55))
|
|
60
|
+
camera.position.set(0, 1.5, 6)
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
stacked.destroy()
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Use `geometraHudPointerEvents` (CSS `pointer-events`, default `'auto'`) when you want the HUD to ignore input — for example `'none'` so pointer events reach the full-viewport Three.js canvas underneath.
|
|
67
|
+
|
|
68
|
+
`createThreeGeometraSplitHost` and `createThreeGeometraStackedHost` each forward all [`createBrowserCanvasClient`](https://github.com/razroo/geometra/tree/main/packages/renderer-canvas) options except `canvas` (the host creates the Geometra canvas for you).
|
|
43
69
|
|
|
44
70
|
### Geometra resize
|
|
45
71
|
|
|
46
72
|
The Geometra thin client listens to `window` resize by default. When only the Geometra column changes size, this host dispatches a synthetic `window` `resize` after layout so server layout width/height stay in sync.
|
|
47
73
|
|
|
74
|
+
### Shared scene / camera defaults (headless-friendly)
|
|
75
|
+
|
|
76
|
+
`createGeometraThreeSceneBasics` builds a `Scene`, `PerspectiveCamera`, and `Clock` with the same defaults as the split and stacked hosts. Pair it with your own `WebGLRenderer` (or a headless GL context) and `resizeGeometraThreePerspectiveView` so buffer size and camera aspect match those hosts, or use `setWebGLDrawingBufferSize` alone when you already manage aspect and `setPixelRatio` yourself.
|
|
77
|
+
|
|
48
78
|
## Roadmap (not in v0)
|
|
49
79
|
|
|
50
80
|
- Optional **scene-graph extension** to the GEOM protocol (headless + WebGL from the same JSON).
|
|
51
|
-
- **Stacked** overlay
|
|
52
|
-
- **Node / headless Three** helpers for parity with “AI talks the same protocol” stories.
|
|
81
|
+
- **Stacked** overlay: v0 ships a corner HUD layout; richer stacking (custom regions, explicit `pointer-events` policies) may follow.
|
|
82
|
+
- **Node / headless Three** helpers for parity with “AI talks the same protocol” stories (`createGeometraThreeSceneBasics` is a small shared baseline; richer helpers may follow).
|
|
53
83
|
|
|
54
84
|
## Releasing (GitHub + npm)
|
|
55
85
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export { createThreeGeometraSplitHost, type ThreeGeometraSplitHostHandle, type ThreeGeometraSplitHostOptions, type ThreeFrameContext, type ThreeRuntimeContext, } from './split-host.js';
|
|
2
|
-
export {
|
|
2
|
+
export { createThreeGeometraStackedHost, type GeometraHudPlacement, type ThreeGeometraStackedHostHandle, type ThreeGeometraStackedHostOptions, } from './stacked-host.js';
|
|
3
|
+
export { resizeGeometraThreePerspectiveView, setWebGLDrawingBufferSize } from './utils.js';
|
|
4
|
+
export { createGeometraThreeSceneBasics, type GeometraThreeSceneBasicsOptions, } from './three-scene-basics.js';
|
|
5
|
+
/** Re-export for hybrid apps using {@link createThreeGeometraSplitHost} with `onData`. */
|
|
6
|
+
export { GEOM_DATA_CHANNEL_TRACKER_SNAPSHOT } from '@geometra/client';
|
|
3
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,8BAA8B,EAC9B,KAAK,oBAAoB,EACzB,KAAK,8BAA8B,EACnC,KAAK,+BAA+B,GACrC,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,kCAAkC,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAC1F,OAAO,EACL,8BAA8B,EAC9B,KAAK,+BAA+B,GACrC,MAAM,yBAAyB,CAAA;AAEhC,0FAA0F;AAC1F,OAAO,EAAE,kCAAkC,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export { createThreeGeometraSplitHost, } from './split-host.js';
|
|
2
|
-
export {
|
|
2
|
+
export { createThreeGeometraStackedHost, } from './stacked-host.js';
|
|
3
|
+
export { resizeGeometraThreePerspectiveView, setWebGLDrawingBufferSize } from './utils.js';
|
|
4
|
+
export { createGeometraThreeSceneBasics, } from './three-scene-basics.js';
|
|
5
|
+
/** Re-export for hybrid apps using {@link createThreeGeometraSplitHost} with `onData`. */
|
|
6
|
+
export { GEOM_DATA_CHANNEL_TRACKER_SNAPSHOT } from '@geometra/client';
|
|
3
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,GAK7B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,GAK7B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,8BAA8B,GAI/B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,kCAAkC,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAC1F,OAAO,EACL,8BAA8B,GAE/B,MAAM,yBAAyB,CAAA;AAEhC,0FAA0F;AAC1F,OAAO,EAAE,kCAAkC,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/split-host.d.ts
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { type BrowserCanvasClientHandle, type BrowserCanvasClientOptions } from '@geometra/renderer-canvas';
|
|
3
|
-
|
|
3
|
+
import { type GeometraThreeSceneBasicsOptions } from './three-scene-basics.js';
|
|
4
|
+
export interface ThreeGeometraSplitHostOptions extends Omit<BrowserCanvasClientOptions, 'canvas'>, GeometraThreeSceneBasicsOptions {
|
|
4
5
|
/** Host element; a flex row is appended as a child (existing children are left untouched). */
|
|
5
6
|
container: HTMLElement;
|
|
6
7
|
/** Geometra column width in CSS pixels. Default: 420. */
|
|
7
8
|
geometraWidth?: number;
|
|
8
9
|
/** When true, Geometra panel is on the left. Default: false (Three.js left, Geometra right). */
|
|
9
10
|
geometraOnLeft?: boolean;
|
|
10
|
-
/** Clear color for the Three.js scene. Default: `0x000000`. */
|
|
11
|
-
threeBackground?: THREE.ColorRepresentation;
|
|
12
|
-
/** Perspective camera FOV in degrees. Default: 50. */
|
|
13
|
-
cameraFov?: number;
|
|
14
|
-
/** Near plane. Default: 0.1. */
|
|
15
|
-
cameraNear?: number;
|
|
16
|
-
/** Far plane. Default: 2000. */
|
|
17
|
-
cameraFar?: number;
|
|
18
|
-
/** Initial camera position. Default: `(0, 0, 5)`. */
|
|
19
|
-
cameraPosition?: THREE.Vector3Tuple;
|
|
20
11
|
/**
|
|
21
12
|
* Called once after scene, camera, and renderer are created.
|
|
22
|
-
* Add meshes, lights, controls, etc.
|
|
13
|
+
* Add meshes, lights, controls, etc. Call `ctx.destroy()` to tear down immediately; the render loop
|
|
14
|
+
* will not start if the host is already destroyed.
|
|
23
15
|
*/
|
|
24
16
|
onThreeReady?: (ctx: ThreeRuntimeContext) => void;
|
|
25
17
|
/**
|
|
@@ -33,6 +25,8 @@ export interface ThreeRuntimeContext {
|
|
|
33
25
|
scene: THREE.Scene;
|
|
34
26
|
camera: THREE.PerspectiveCamera;
|
|
35
27
|
threeCanvas: HTMLCanvasElement;
|
|
28
|
+
/** Same as `ThreeGeometraSplitHostHandle.destroy` — idempotent full teardown. */
|
|
29
|
+
destroy(): void;
|
|
36
30
|
}
|
|
37
31
|
export interface ThreeFrameContext extends ThreeRuntimeContext {
|
|
38
32
|
clock: THREE.Clock;
|
|
@@ -58,7 +52,15 @@ export interface ThreeGeometraSplitHostHandle {
|
|
|
58
52
|
*
|
|
59
53
|
* This is the recommended **hybrid** layout: 3D stays in Three; chrome and data panes stay in Geometra’s protocol.
|
|
60
54
|
* Geometra’s client still uses `resizeTarget: window` by default; when only the Geometra column changes size,
|
|
61
|
-
* a `ResizeObserver` dispatches a synthetic `resize` on `window` so layout width/height track the panel
|
|
55
|
+
* a `ResizeObserver` dispatches a synthetic `resize` on `window` so layout width/height track the panel
|
|
56
|
+
* (coalesced to at most once per animation frame when both panes notify in the same frame).
|
|
57
|
+
*
|
|
58
|
+
* The Three.js pane listens to `window` `resize` as well so `devicePixelRatio` updates (zoom / display changes)
|
|
59
|
+
* refresh the WebGL drawing buffer without relying on panel `ResizeObserver` alone.
|
|
60
|
+
*
|
|
61
|
+
* Pass through {@link BrowserCanvasClientOptions} from `@geometra/renderer-canvas` / `@geometra/client`
|
|
62
|
+
* (for example `binaryFraming`, `onError`, `onFrameMetrics`, `onData` for JSON side-channels on the same
|
|
63
|
+
* socket as layout; channel names are defined by your app and the Geometra server).
|
|
62
64
|
*/
|
|
63
65
|
export declare function createThreeGeometraSplitHost(options: ThreeGeometraSplitHostOptions): ThreeGeometraSplitHostHandle;
|
|
64
66
|
//# sourceMappingURL=split-host.d.ts.map
|
package/dist/split-host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-host.d.ts","sourceRoot":"","sources":["../src/split-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAChC,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"split-host.d.ts","sourceRoot":"","sources":["../src/split-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAChC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAkC,KAAK,+BAA+B,EAAE,MAAM,yBAAyB,CAAA;AAG9G,MAAM,WAAW,6BACf,SAAQ,IAAI,CAAC,0BAA0B,EAAE,QAAQ,CAAC,EAChD,+BAA+B;IACjC,8FAA8F;IAC9F,SAAS,EAAE,WAAW,CAAA;IACtB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gGAAgG;IAChG,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,CAAA;IACjD;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAA;CAChD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAA;IAC7B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAA;IAC/B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,iFAAiF;IACjF,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,cAAc,CAAA;IACpB,UAAU,EAAE,cAAc,CAAA;IAC1B,aAAa,EAAE,cAAc,CAAA;IAC7B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,cAAc,EAAE,iBAAiB,CAAA;IACjC,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAA;IAC7B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAA;IAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,QAAQ,EAAE,yBAAyB,CAAA;IACnC,wGAAwG;IACxG,OAAO,IAAI,IAAI,CAAA;CAChB;AAgBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,4BAA4B,CAkK9B"}
|
package/dist/split-host.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { createBrowserCanvasClient, } from '@geometra/renderer-canvas';
|
|
3
|
+
import { createGeometraThreeSceneBasics } from './three-scene-basics.js';
|
|
4
|
+
import { resizeGeometraThreePerspectiveView } from './utils.js';
|
|
3
5
|
function panelStyle(el, flex) {
|
|
4
6
|
el.style.flex = flex;
|
|
5
7
|
el.style.minWidth = '0';
|
|
@@ -17,7 +19,15 @@ function fullSizeCanvas(canvas) {
|
|
|
17
19
|
*
|
|
18
20
|
* This is the recommended **hybrid** layout: 3D stays in Three; chrome and data panes stay in Geometra’s protocol.
|
|
19
21
|
* Geometra’s client still uses `resizeTarget: window` by default; when only the Geometra column changes size,
|
|
20
|
-
* a `ResizeObserver` dispatches a synthetic `resize` on `window` so layout width/height track the panel
|
|
22
|
+
* a `ResizeObserver` dispatches a synthetic `resize` on `window` so layout width/height track the panel
|
|
23
|
+
* (coalesced to at most once per animation frame when both panes notify in the same frame).
|
|
24
|
+
*
|
|
25
|
+
* The Three.js pane listens to `window` `resize` as well so `devicePixelRatio` updates (zoom / display changes)
|
|
26
|
+
* refresh the WebGL drawing buffer without relying on panel `ResizeObserver` alone.
|
|
27
|
+
*
|
|
28
|
+
* Pass through {@link BrowserCanvasClientOptions} from `@geometra/renderer-canvas` / `@geometra/client`
|
|
29
|
+
* (for example `binaryFraming`, `onError`, `onFrameMetrics`, `onData` for JSON side-channels on the same
|
|
30
|
+
* socket as layout; channel names are defined by your app and the Geometra server).
|
|
21
31
|
*/
|
|
22
32
|
export function createThreeGeometraSplitHost(options) {
|
|
23
33
|
const { container, geometraWidth = 420, geometraOnLeft = false, threeBackground = 0x000000, cameraFov = 50, cameraNear = 0.1, cameraFar = 2000, cameraPosition = [0, 0, 5], onThreeReady, onThreeFrame, window: providedWindow, ...browserOptions } = options;
|
|
@@ -57,27 +67,32 @@ export function createThreeGeometraSplitHost(options) {
|
|
|
57
67
|
antialias: true,
|
|
58
68
|
alpha: false,
|
|
59
69
|
});
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
const { scene, camera, clock } = createGeometraThreeSceneBasics({
|
|
71
|
+
threeBackground,
|
|
72
|
+
cameraFov,
|
|
73
|
+
cameraNear,
|
|
74
|
+
cameraFar,
|
|
75
|
+
cameraPosition,
|
|
76
|
+
});
|
|
66
77
|
const resizeThree = () => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
glRenderer.setSize(w, h, false);
|
|
78
|
+
resizeGeometraThreePerspectiveView(glRenderer, camera, threePanel.clientWidth, threePanel.clientHeight, win.devicePixelRatio || 1);
|
|
79
|
+
};
|
|
80
|
+
const onWindowResize = () => {
|
|
81
|
+
resizeThree();
|
|
72
82
|
};
|
|
83
|
+
win.addEventListener('resize', onWindowResize, { passive: true });
|
|
73
84
|
resizeThree();
|
|
74
85
|
const geometraHandle = createBrowserCanvasClient({
|
|
75
86
|
...browserOptions,
|
|
76
87
|
canvas: geometraCanvas,
|
|
77
88
|
window: win,
|
|
78
89
|
});
|
|
90
|
+
let geometraResizeRafId;
|
|
79
91
|
const triggerGeometraResize = () => {
|
|
80
|
-
|
|
92
|
+
if (geometraResizeRafId !== undefined)
|
|
93
|
+
return;
|
|
94
|
+
geometraResizeRafId = win.requestAnimationFrame(() => {
|
|
95
|
+
geometraResizeRafId = undefined;
|
|
81
96
|
win.dispatchEvent(new Event('resize'));
|
|
82
97
|
});
|
|
83
98
|
};
|
|
@@ -87,37 +102,46 @@ export function createThreeGeometraSplitHost(options) {
|
|
|
87
102
|
});
|
|
88
103
|
roContainer.observe(threePanel);
|
|
89
104
|
roContainer.observe(geometraPanel);
|
|
105
|
+
let rafId;
|
|
106
|
+
let destroyed = false;
|
|
107
|
+
const destroy = () => {
|
|
108
|
+
if (destroyed)
|
|
109
|
+
return;
|
|
110
|
+
destroyed = true;
|
|
111
|
+
if (rafId !== undefined) {
|
|
112
|
+
win.cancelAnimationFrame(rafId);
|
|
113
|
+
rafId = undefined;
|
|
114
|
+
}
|
|
115
|
+
if (geometraResizeRafId !== undefined) {
|
|
116
|
+
win.cancelAnimationFrame(geometraResizeRafId);
|
|
117
|
+
geometraResizeRafId = undefined;
|
|
118
|
+
}
|
|
119
|
+
win.removeEventListener('resize', onWindowResize);
|
|
120
|
+
roContainer.disconnect();
|
|
121
|
+
geometraHandle.destroy();
|
|
122
|
+
glRenderer.dispose();
|
|
123
|
+
root.remove();
|
|
124
|
+
};
|
|
90
125
|
const ctxBase = {
|
|
91
126
|
renderer: glRenderer,
|
|
92
127
|
scene,
|
|
93
128
|
camera,
|
|
94
129
|
threeCanvas,
|
|
130
|
+
destroy,
|
|
95
131
|
};
|
|
96
132
|
onThreeReady?.(ctxBase);
|
|
97
|
-
let raf = 0;
|
|
98
|
-
let destroyed = false;
|
|
99
133
|
const loop = () => {
|
|
100
134
|
if (destroyed)
|
|
101
135
|
return;
|
|
102
|
-
|
|
136
|
+
rafId = win.requestAnimationFrame(loop);
|
|
103
137
|
const delta = clock.getDelta();
|
|
104
138
|
const elapsed = clock.elapsedTime;
|
|
105
139
|
onThreeFrame?.({ ...ctxBase, clock, delta, elapsed });
|
|
106
140
|
glRenderer.render(scene, camera);
|
|
107
141
|
};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return;
|
|
112
|
-
destroyed = true;
|
|
113
|
-
win.cancelAnimationFrame(raf);
|
|
114
|
-
roContainer.disconnect();
|
|
115
|
-
geometraHandle.destroy();
|
|
116
|
-
glRenderer.dispose();
|
|
117
|
-
if (root.parentNode === container) {
|
|
118
|
-
container.removeChild(root);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
142
|
+
if (!destroyed) {
|
|
143
|
+
rafId = win.requestAnimationFrame(loop);
|
|
144
|
+
}
|
|
121
145
|
return {
|
|
122
146
|
root,
|
|
123
147
|
threePanel,
|
package/dist/split-host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-host.js","sourceRoot":"","sources":["../src/split-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EACL,yBAAyB,GAG1B,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"split-host.js","sourceRoot":"","sources":["../src/split-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { type BrowserCanvasClientHandle, type BrowserCanvasClientOptions } from '@geometra/renderer-canvas';
|
|
3
|
+
import type { ThreeFrameContext, ThreeRuntimeContext } from './split-host.js';
|
|
4
|
+
import { type GeometraThreeSceneBasicsOptions } from './three-scene-basics.js';
|
|
5
|
+
/** Corner anchor for the Geometra HUD overlay (CSS `position: absolute` on the host). */
|
|
6
|
+
export type GeometraHudPlacement = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
7
|
+
export interface ThreeGeometraStackedHostOptions extends Omit<BrowserCanvasClientOptions, 'canvas'>, GeometraThreeSceneBasicsOptions {
|
|
8
|
+
/** Host element; a full-size stacking context is appended (existing children are left untouched). */
|
|
9
|
+
container: HTMLElement;
|
|
10
|
+
/** HUD width in CSS pixels. Default: 420. */
|
|
11
|
+
geometraHudWidth?: number;
|
|
12
|
+
/** HUD height in CSS pixels. Default: 320. */
|
|
13
|
+
geometraHudHeight?: number;
|
|
14
|
+
/** HUD corner. Default: `bottom-right`. */
|
|
15
|
+
geometraHudPlacement?: GeometraHudPlacement;
|
|
16
|
+
/** Inset from the chosen corner in CSS pixels. Default: 12. */
|
|
17
|
+
geometraHudMargin?: number;
|
|
18
|
+
/**
|
|
19
|
+
* CSS `pointer-events` on the HUD wrapper (e.g. `'none'` so input falls through to the WebGL canvas).
|
|
20
|
+
* Default: `'auto'`.
|
|
21
|
+
*/
|
|
22
|
+
geometraHudPointerEvents?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Called once after scene, camera, and renderer are created.
|
|
25
|
+
* Call `ctx.destroy()` to tear down immediately; the render loop will not start if the host is already destroyed.
|
|
26
|
+
*/
|
|
27
|
+
onThreeReady?: (ctx: ThreeRuntimeContext) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Called every frame before `renderer.render`.
|
|
30
|
+
*/
|
|
31
|
+
onThreeFrame?: (ctx: ThreeFrameContext) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface ThreeGeometraStackedHostHandle {
|
|
34
|
+
root: HTMLDivElement;
|
|
35
|
+
/** Absolutely positioned wrapper around the Geometra canvas (stacked HUD). */
|
|
36
|
+
geometraHud: HTMLDivElement;
|
|
37
|
+
threeCanvas: HTMLCanvasElement;
|
|
38
|
+
geometraCanvas: HTMLCanvasElement;
|
|
39
|
+
renderer: THREE.WebGLRenderer;
|
|
40
|
+
scene: THREE.Scene;
|
|
41
|
+
camera: THREE.PerspectiveCamera;
|
|
42
|
+
clock: THREE.Clock;
|
|
43
|
+
geometra: BrowserCanvasClientHandle;
|
|
44
|
+
destroy(): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Stacked host: full-viewport Three.js `WebGLRenderer` with a positioned Geometra canvas **HUD** on top.
|
|
48
|
+
*
|
|
49
|
+
* Pointer routing follows normal hit-testing: events hit the Geometra canvas where it overlaps the WebGL layer
|
|
50
|
+
* (`z-index` above the Three canvas); elsewhere, the Three canvas receives input. Override with
|
|
51
|
+
* {@link ThreeGeometraStackedHostOptions.geometraHudPointerEvents} (e.g. `'none'` for a click-through HUD).
|
|
52
|
+
*
|
|
53
|
+
* Geometra’s client still uses `resizeTarget: window` by default; when only the HUD box changes size,
|
|
54
|
+
* a coalesced synthetic `resize` is dispatched on `window` (same pattern as {@link createThreeGeometraSplitHost}).
|
|
55
|
+
* The Three.js layer listens to `window` `resize` for `devicePixelRatio` changes and uses the host `root` size
|
|
56
|
+
* for the drawing buffer.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createThreeGeometraStackedHost(options: ThreeGeometraStackedHostOptions): ThreeGeometraStackedHostHandle;
|
|
59
|
+
//# sourceMappingURL=stacked-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stacked-host.d.ts","sourceRoot":"","sources":["../src/stacked-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAChC,MAAM,2BAA2B,CAAA;AAClC,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC7E,OAAO,EAAkC,KAAK,+BAA+B,EAAE,MAAM,yBAAyB,CAAA;AAG9G,yFAAyF;AACzF,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAA;AAE5F,MAAM,WAAW,+BACf,SAAQ,IAAI,CAAC,0BAA0B,EAAE,QAAQ,CAAC,EAChD,+BAA+B;IACjC,qGAAqG;IACrG,SAAS,EAAE,WAAW,CAAA;IACtB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,2CAA2C;IAC3C,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,CAAA;IACjD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAA;CAChD;AAED,MAAM,WAAW,8BAA8B;IAC7C,IAAI,EAAE,cAAc,CAAA;IACpB,8EAA8E;IAC9E,WAAW,EAAE,cAAc,CAAA;IAC3B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,cAAc,EAAE,iBAAiB,CAAA;IACjC,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAA;IAC7B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAA;IAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,QAAQ,EAAE,yBAAyB,CAAA;IACnC,OAAO,IAAI,IAAI,CAAA;CAChB;AAsCD;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,+BAA+B,GACvC,8BAA8B,CA6KhC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { createBrowserCanvasClient, } from '@geometra/renderer-canvas';
|
|
3
|
+
import { createGeometraThreeSceneBasics } from './three-scene-basics.js';
|
|
4
|
+
import { resizeGeometraThreePerspectiveView } from './utils.js';
|
|
5
|
+
function fullSizeCanvas(canvas) {
|
|
6
|
+
canvas.style.display = 'block';
|
|
7
|
+
canvas.style.width = '100%';
|
|
8
|
+
canvas.style.height = '100%';
|
|
9
|
+
}
|
|
10
|
+
function applyHudPlacement(wrap, placement, marginPx) {
|
|
11
|
+
const m = `${marginPx}px`;
|
|
12
|
+
wrap.style.left = '';
|
|
13
|
+
wrap.style.right = '';
|
|
14
|
+
wrap.style.top = '';
|
|
15
|
+
wrap.style.bottom = '';
|
|
16
|
+
switch (placement) {
|
|
17
|
+
case 'bottom-right':
|
|
18
|
+
wrap.style.right = m;
|
|
19
|
+
wrap.style.bottom = m;
|
|
20
|
+
break;
|
|
21
|
+
case 'bottom-left':
|
|
22
|
+
wrap.style.left = m;
|
|
23
|
+
wrap.style.bottom = m;
|
|
24
|
+
break;
|
|
25
|
+
case 'top-right':
|
|
26
|
+
wrap.style.right = m;
|
|
27
|
+
wrap.style.top = m;
|
|
28
|
+
break;
|
|
29
|
+
case 'top-left':
|
|
30
|
+
wrap.style.left = m;
|
|
31
|
+
wrap.style.top = m;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Stacked host: full-viewport Three.js `WebGLRenderer` with a positioned Geometra canvas **HUD** on top.
|
|
37
|
+
*
|
|
38
|
+
* Pointer routing follows normal hit-testing: events hit the Geometra canvas where it overlaps the WebGL layer
|
|
39
|
+
* (`z-index` above the Three canvas); elsewhere, the Three canvas receives input. Override with
|
|
40
|
+
* {@link ThreeGeometraStackedHostOptions.geometraHudPointerEvents} (e.g. `'none'` for a click-through HUD).
|
|
41
|
+
*
|
|
42
|
+
* Geometra’s client still uses `resizeTarget: window` by default; when only the HUD box changes size,
|
|
43
|
+
* a coalesced synthetic `resize` is dispatched on `window` (same pattern as {@link createThreeGeometraSplitHost}).
|
|
44
|
+
* The Three.js layer listens to `window` `resize` for `devicePixelRatio` changes and uses the host `root` size
|
|
45
|
+
* for the drawing buffer.
|
|
46
|
+
*/
|
|
47
|
+
export function createThreeGeometraStackedHost(options) {
|
|
48
|
+
const { container, geometraHudWidth = 420, geometraHudHeight = 320, geometraHudPlacement = 'bottom-right', geometraHudMargin = 12, geometraHudPointerEvents = 'auto', threeBackground = 0x000000, cameraFov = 50, cameraNear = 0.1, cameraFar = 2000, cameraPosition = [0, 0, 5], onThreeReady, onThreeFrame, window: providedWindow, ...browserOptions } = options;
|
|
49
|
+
const doc = container.ownerDocument;
|
|
50
|
+
const win = providedWindow ?? doc.defaultView;
|
|
51
|
+
if (!win) {
|
|
52
|
+
throw new Error('createThreeGeometraStackedHost requires a browser window');
|
|
53
|
+
}
|
|
54
|
+
const root = doc.createElement('div');
|
|
55
|
+
root.style.position = 'relative';
|
|
56
|
+
root.style.width = '100%';
|
|
57
|
+
root.style.height = '100%';
|
|
58
|
+
root.style.minHeight = '0';
|
|
59
|
+
root.style.minWidth = '0';
|
|
60
|
+
root.style.overflow = 'hidden';
|
|
61
|
+
container.appendChild(root);
|
|
62
|
+
const threeCanvas = doc.createElement('canvas');
|
|
63
|
+
fullSizeCanvas(threeCanvas);
|
|
64
|
+
threeCanvas.style.position = 'absolute';
|
|
65
|
+
threeCanvas.style.left = '0';
|
|
66
|
+
threeCanvas.style.top = '0';
|
|
67
|
+
threeCanvas.style.width = '100%';
|
|
68
|
+
threeCanvas.style.height = '100%';
|
|
69
|
+
threeCanvas.style.zIndex = '0';
|
|
70
|
+
root.appendChild(threeCanvas);
|
|
71
|
+
const geometraHud = doc.createElement('div');
|
|
72
|
+
geometraHud.style.position = 'absolute';
|
|
73
|
+
geometraHud.style.zIndex = '1';
|
|
74
|
+
geometraHud.style.width = `${geometraHudWidth}px`;
|
|
75
|
+
geometraHud.style.height = `${geometraHudHeight}px`;
|
|
76
|
+
geometraHud.style.minWidth = '0';
|
|
77
|
+
geometraHud.style.minHeight = '0';
|
|
78
|
+
geometraHud.style.overflow = 'hidden';
|
|
79
|
+
geometraHud.style.pointerEvents = geometraHudPointerEvents;
|
|
80
|
+
applyHudPlacement(geometraHud, geometraHudPlacement, geometraHudMargin);
|
|
81
|
+
root.appendChild(geometraHud);
|
|
82
|
+
const geometraCanvas = doc.createElement('canvas');
|
|
83
|
+
fullSizeCanvas(geometraCanvas);
|
|
84
|
+
geometraHud.appendChild(geometraCanvas);
|
|
85
|
+
const glRenderer = new THREE.WebGLRenderer({
|
|
86
|
+
canvas: threeCanvas,
|
|
87
|
+
antialias: true,
|
|
88
|
+
alpha: false,
|
|
89
|
+
});
|
|
90
|
+
const { scene, camera, clock } = createGeometraThreeSceneBasics({
|
|
91
|
+
threeBackground,
|
|
92
|
+
cameraFov,
|
|
93
|
+
cameraNear,
|
|
94
|
+
cameraFar,
|
|
95
|
+
cameraPosition,
|
|
96
|
+
});
|
|
97
|
+
const resizeThree = () => {
|
|
98
|
+
resizeGeometraThreePerspectiveView(glRenderer, camera, root.clientWidth, root.clientHeight, win.devicePixelRatio || 1);
|
|
99
|
+
};
|
|
100
|
+
const onWindowResize = () => {
|
|
101
|
+
resizeThree();
|
|
102
|
+
};
|
|
103
|
+
win.addEventListener('resize', onWindowResize, { passive: true });
|
|
104
|
+
resizeThree();
|
|
105
|
+
const geometraHandle = createBrowserCanvasClient({
|
|
106
|
+
...browserOptions,
|
|
107
|
+
canvas: geometraCanvas,
|
|
108
|
+
window: win,
|
|
109
|
+
});
|
|
110
|
+
let geometraResizeRafId;
|
|
111
|
+
const triggerGeometraResize = () => {
|
|
112
|
+
if (geometraResizeRafId !== undefined)
|
|
113
|
+
return;
|
|
114
|
+
geometraResizeRafId = win.requestAnimationFrame(() => {
|
|
115
|
+
geometraResizeRafId = undefined;
|
|
116
|
+
win.dispatchEvent(new Event('resize'));
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
const roRoot = new ResizeObserver(() => {
|
|
120
|
+
resizeThree();
|
|
121
|
+
triggerGeometraResize();
|
|
122
|
+
});
|
|
123
|
+
roRoot.observe(root);
|
|
124
|
+
const roHud = new ResizeObserver(() => {
|
|
125
|
+
triggerGeometraResize();
|
|
126
|
+
});
|
|
127
|
+
roHud.observe(geometraHud);
|
|
128
|
+
let rafId;
|
|
129
|
+
let destroyed = false;
|
|
130
|
+
const destroy = () => {
|
|
131
|
+
if (destroyed)
|
|
132
|
+
return;
|
|
133
|
+
destroyed = true;
|
|
134
|
+
if (rafId !== undefined) {
|
|
135
|
+
win.cancelAnimationFrame(rafId);
|
|
136
|
+
rafId = undefined;
|
|
137
|
+
}
|
|
138
|
+
if (geometraResizeRafId !== undefined) {
|
|
139
|
+
win.cancelAnimationFrame(geometraResizeRafId);
|
|
140
|
+
geometraResizeRafId = undefined;
|
|
141
|
+
}
|
|
142
|
+
win.removeEventListener('resize', onWindowResize);
|
|
143
|
+
roRoot.disconnect();
|
|
144
|
+
roHud.disconnect();
|
|
145
|
+
geometraHandle.destroy();
|
|
146
|
+
glRenderer.dispose();
|
|
147
|
+
root.remove();
|
|
148
|
+
};
|
|
149
|
+
const ctxBase = {
|
|
150
|
+
renderer: glRenderer,
|
|
151
|
+
scene,
|
|
152
|
+
camera,
|
|
153
|
+
threeCanvas,
|
|
154
|
+
destroy,
|
|
155
|
+
};
|
|
156
|
+
onThreeReady?.(ctxBase);
|
|
157
|
+
const loop = () => {
|
|
158
|
+
if (destroyed)
|
|
159
|
+
return;
|
|
160
|
+
rafId = win.requestAnimationFrame(loop);
|
|
161
|
+
const delta = clock.getDelta();
|
|
162
|
+
const elapsed = clock.elapsedTime;
|
|
163
|
+
onThreeFrame?.({ ...ctxBase, clock, delta, elapsed });
|
|
164
|
+
glRenderer.render(scene, camera);
|
|
165
|
+
};
|
|
166
|
+
if (!destroyed) {
|
|
167
|
+
rafId = win.requestAnimationFrame(loop);
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
root,
|
|
171
|
+
geometraHud,
|
|
172
|
+
threeCanvas,
|
|
173
|
+
geometraCanvas,
|
|
174
|
+
renderer: glRenderer,
|
|
175
|
+
scene,
|
|
176
|
+
camera,
|
|
177
|
+
clock,
|
|
178
|
+
geometra: geometraHandle,
|
|
179
|
+
destroy,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=stacked-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stacked-host.js","sourceRoot":"","sources":["../src/stacked-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EACL,yBAAyB,GAG1B,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,8BAA8B,EAAwC,MAAM,yBAAyB,CAAA;AAC9G,OAAO,EAAE,kCAAkC,EAAE,MAAM,YAAY,CAAA;AAgD/D,SAAS,cAAc,CAAC,MAAyB;IAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAA;IAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAA;IAC3B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;AAC9B,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAoB,EACpB,SAA+B,EAC/B,QAAgB;IAEhB,MAAM,CAAC,GAAG,GAAG,QAAQ,IAAI,CAAA;IACzB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAA;IACpB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAA;IACrB,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAA;IACnB,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,CAAA;IACtB,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,cAAc;YACjB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAA;YACpB,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;YACrB,MAAK;QACP,KAAK,aAAa;YAChB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAA;YACnB,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;YACrB,MAAK;QACP,KAAK,WAAW;YACd,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAA;YACpB,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAA;YAClB,MAAK;QACP,KAAK,UAAU;YACb,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAA;YACnB,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAA;YAClB,MAAK;IACT,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,8BAA8B,CAC5C,OAAwC;IAExC,MAAM,EACJ,SAAS,EACT,gBAAgB,GAAG,GAAG,EACtB,iBAAiB,GAAG,GAAG,EACvB,oBAAoB,GAAG,cAAc,EACrC,iBAAiB,GAAG,EAAE,EACtB,wBAAwB,GAAG,MAAM,EACjC,eAAe,GAAG,QAAQ,EAC1B,SAAS,GAAG,EAAE,EACd,UAAU,GAAG,GAAG,EAChB,SAAS,GAAG,IAAI,EAChB,cAAc,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,YAAY,EACZ,YAAY,EACZ,MAAM,EAAE,cAAc,EACtB,GAAG,cAAc,EAClB,GAAG,OAAO,CAAA;IAEX,MAAM,GAAG,GAAG,SAAS,CAAC,aAAa,CAAA;IACnC,MAAM,GAAG,GAAG,cAAc,IAAI,GAAG,CAAC,WAAW,CAAA;IAC7C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IACrC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAA;IAChC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAA;IACzB,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;IAC1B,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAA;IAC1B,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAA;IACzB,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC9B,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAE3B,MAAM,WAAW,GAAG,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;IAC/C,cAAc,CAAC,WAAW,CAAC,CAAA;IAC3B,WAAW,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAA;IACvC,WAAW,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAA;IAC5B,WAAW,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAA;IAC3B,WAAW,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAA;IAChC,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;IACjC,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAA;IAC9B,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;IAE7B,MAAM,WAAW,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC5C,WAAW,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAA;IACvC,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAA;IAC9B,WAAW,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,gBAAgB,IAAI,CAAA;IACjD,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,iBAAiB,IAAI,CAAA;IACnD,WAAW,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAA;IAChC,WAAW,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAA;IACjC,WAAW,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAA;IACrC,WAAW,CAAC,KAAK,CAAC,aAAa,GAAG,wBAAwB,CAAA;IAC1D,iBAAiB,CAAC,WAAW,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,CAAA;IACvE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;IAE7B,MAAM,cAAc,GAAG,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;IAClD,cAAc,CAAC,cAAc,CAAC,CAAA;IAC9B,WAAW,CAAC,WAAW,CAAC,cAAc,CAAC,CAAA;IAEvC,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC;QACzC,MAAM,EAAE,WAAW;QACnB,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,KAAK;KACb,CAAC,CAAA;IACF,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,8BAA8B,CAAC;QAC9D,eAAe;QACf,SAAS;QACT,UAAU;QACV,SAAS;QACT,cAAc;KACf,CAAC,CAAA;IAEF,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,kCAAkC,CAChC,UAAU,EACV,MAAM,EACN,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,YAAY,EACjB,GAAG,CAAC,gBAAgB,IAAI,CAAC,CAC1B,CAAA;IACH,CAAC,CAAA;IAED,MAAM,cAAc,GAAG,GAAG,EAAE;QAC1B,WAAW,EAAE,CAAA;IACf,CAAC,CAAA;IACD,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IAEjE,WAAW,EAAE,CAAA;IAEb,MAAM,cAAc,GAAG,yBAAyB,CAAC;QAC/C,GAAG,cAAc;QACjB,MAAM,EAAE,cAAc;QACtB,MAAM,EAAE,GAAG;KACZ,CAAC,CAAA;IAEF,IAAI,mBAAuC,CAAA;IAC3C,MAAM,qBAAqB,GAAG,GAAG,EAAE;QACjC,IAAI,mBAAmB,KAAK,SAAS;YAAE,OAAM;QAC7C,mBAAmB,GAAG,GAAG,CAAC,qBAAqB,CAAC,GAAG,EAAE;YACnD,mBAAmB,GAAG,SAAS,CAAA;YAC/B,GAAG,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;QACrC,WAAW,EAAE,CAAA;QACb,qBAAqB,EAAE,CAAA;IACzB,CAAC,CAAC,CAAA;IACF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpB,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;QACpC,qBAAqB,EAAE,CAAA;IACzB,CAAC,CAAC,CAAA;IACF,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAE1B,IAAI,KAAyB,CAAA;IAC7B,IAAI,SAAS,GAAG,KAAK,CAAA;IAErB,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,SAAS;YAAE,OAAM;QACrB,SAAS,GAAG,IAAI,CAAA;QAChB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,GAAG,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;YAC/B,KAAK,GAAG,SAAS,CAAA;QACnB,CAAC;QACD,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;YACtC,GAAG,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAA;YAC7C,mBAAmB,GAAG,SAAS,CAAA;QACjC,CAAC;QACD,GAAG,CAAC,mBAAmB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QACjD,MAAM,CAAC,UAAU,EAAE,CAAA;QACnB,KAAK,CAAC,UAAU,EAAE,CAAA;QAClB,cAAc,CAAC,OAAO,EAAE,CAAA;QACxB,UAAU,CAAC,OAAO,EAAE,CAAA;QACpB,IAAI,CAAC,MAAM,EAAE,CAAA;IACf,CAAC,CAAA;IAED,MAAM,OAAO,GAAwB;QACnC,QAAQ,EAAE,UAAU;QACpB,KAAK;QACL,MAAM;QACN,WAAW;QACX,OAAO;KACR,CAAA;IAED,YAAY,EAAE,CAAC,OAAO,CAAC,CAAA;IAEvB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,SAAS;YAAE,OAAM;QACrB,KAAK,GAAG,GAAG,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;QACvC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAA;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,CAAA;QACjC,YAAY,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;QACrD,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAClC,CAAC,CAAA;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,KAAK,GAAG,GAAG,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;IACzC,CAAC;IAED,OAAO;QACL,IAAI;QACJ,WAAW;QACX,WAAW;QACX,cAAc;QACd,QAAQ,EAAE,UAAU;QACpB,KAAK;QACL,MAAM;QACN,KAAK;QACL,QAAQ,EAAE,cAAc;QACxB,OAAO;KACR,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
/** Options shared by split/stacked hosts and {@link createGeometraThreeSceneBasics}. */
|
|
3
|
+
export interface GeometraThreeSceneBasicsOptions {
|
|
4
|
+
/** Clear color for the Three.js scene. Default: `0x000000`. */
|
|
5
|
+
threeBackground?: THREE.ColorRepresentation;
|
|
6
|
+
/** Perspective camera FOV in degrees. Default: 50. */
|
|
7
|
+
cameraFov?: number;
|
|
8
|
+
/** Near plane. Default: 0.1. */
|
|
9
|
+
cameraNear?: number;
|
|
10
|
+
/** Far plane. Default: 2000. */
|
|
11
|
+
cameraFar?: number;
|
|
12
|
+
/** Initial camera position. Default: `(0, 0, 5)`. */
|
|
13
|
+
cameraPosition?: THREE.Vector3Tuple;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a scene, perspective camera, and clock with the same defaults as
|
|
17
|
+
* {@link createThreeGeometraSplitHost} and {@link createThreeGeometraStackedHost}.
|
|
18
|
+
*
|
|
19
|
+
* Use this when you want Three.js state aligned with those hosts but manage your own
|
|
20
|
+
* `WebGLRenderer` (for example headless GL, offscreen canvas, or custom render targets).
|
|
21
|
+
*/
|
|
22
|
+
export declare function createGeometraThreeSceneBasics(options?: GeometraThreeSceneBasicsOptions): {
|
|
23
|
+
scene: THREE.Scene;
|
|
24
|
+
camera: THREE.PerspectiveCamera;
|
|
25
|
+
clock: THREE.Clock;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=three-scene-basics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"three-scene-basics.d.ts","sourceRoot":"","sources":["../src/three-scene-basics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,wFAAwF;AACxF,MAAM,WAAW,+BAA+B;IAC9C,+DAA+D;IAC/D,eAAe,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAA;IAC3C,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qDAAqD;IACrD,cAAc,CAAC,EAAE,KAAK,CAAC,YAAY,CAAA;CACpC;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,GAAE,+BAAoC,GAC5C;IACD,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAA;IAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;CACnB,CAkBA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* Create a scene, perspective camera, and clock with the same defaults as
|
|
4
|
+
* {@link createThreeGeometraSplitHost} and {@link createThreeGeometraStackedHost}.
|
|
5
|
+
*
|
|
6
|
+
* Use this when you want Three.js state aligned with those hosts but manage your own
|
|
7
|
+
* `WebGLRenderer` (for example headless GL, offscreen canvas, or custom render targets).
|
|
8
|
+
*/
|
|
9
|
+
export function createGeometraThreeSceneBasics(options = {}) {
|
|
10
|
+
const { threeBackground = 0x000000, cameraFov = 50, cameraNear = 0.1, cameraFar = 2000, cameraPosition = [0, 0, 5], } = options;
|
|
11
|
+
const scene = new THREE.Scene();
|
|
12
|
+
scene.background = new THREE.Color(threeBackground);
|
|
13
|
+
const camera = new THREE.PerspectiveCamera(cameraFov, 1, cameraNear, cameraFar);
|
|
14
|
+
camera.position.set(cameraPosition[0], cameraPosition[1], cameraPosition[2]);
|
|
15
|
+
const clock = new THREE.Clock();
|
|
16
|
+
return { scene, camera, clock };
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=three-scene-basics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"three-scene-basics.js","sourceRoot":"","sources":["../src/three-scene-basics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAgB9B;;;;;;GAMG;AACH,MAAM,UAAU,8BAA8B,CAC5C,UAA2C,EAAE;IAM7C,MAAM,EACJ,eAAe,GAAG,QAAQ,EAC1B,SAAS,GAAG,EAAE,EACd,UAAU,GAAG,GAAG,EAChB,SAAS,GAAG,IAAI,EAChB,cAAc,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC3B,GAAG,OAAO,CAAA;IAEX,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAA;IAC/B,KAAK,CAAC,UAAU,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IAEnD,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,CAAA;IAC/E,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAE,EAAE,cAAc,CAAC,CAAC,CAAE,EAAE,cAAc,CAAC,CAAC,CAAE,CAAC,CAAA;IAE/E,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAA;IAE/B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;AACjC,CAAC"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import type { WebGLRenderer } from 'three';
|
|
1
|
+
import type { PerspectiveCamera, WebGLRenderer } from 'three';
|
|
2
2
|
/**
|
|
3
3
|
* Resize drawing buffer to match CSS pixel size × device pixel ratio.
|
|
4
4
|
* Use when you manage your own canvas layout (no `renderer.setSize`).
|
|
5
5
|
*/
|
|
6
6
|
export declare function setWebGLDrawingBufferSize(renderer: WebGLRenderer, cssWidth: number, cssHeight: number, pixelRatio?: number): void;
|
|
7
|
+
/**
|
|
8
|
+
* Apply the same CSS-size → aspect ratio → WebGL buffer sizing path as
|
|
9
|
+
* {@link createThreeGeometraSplitHost} and {@link createThreeGeometraStackedHost}.
|
|
10
|
+
*
|
|
11
|
+
* Use with {@link createGeometraThreeSceneBasics} when you own the `WebGLRenderer` (headless GL,
|
|
12
|
+
* offscreen canvas, tests) but want buffer dimensions and projection to stay aligned with those hosts.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resizeGeometraThreePerspectiveView(renderer: WebGLRenderer, camera: PerspectiveCamera, cssWidth: number, cssHeight: number, pixelRatio: number): void;
|
|
7
15
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAE7D;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CAKN;AAED;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,IAAI,CAON"}
|
package/dist/utils.js
CHANGED
|
@@ -8,4 +8,19 @@ export function setWebGLDrawingBufferSize(renderer, cssWidth, cssHeight, pixelRa
|
|
|
8
8
|
const h = Math.max(1, Math.floor(cssHeight * pr));
|
|
9
9
|
renderer.setDrawingBufferSize(w, h, pr);
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Apply the same CSS-size → aspect ratio → WebGL buffer sizing path as
|
|
13
|
+
* {@link createThreeGeometraSplitHost} and {@link createThreeGeometraStackedHost}.
|
|
14
|
+
*
|
|
15
|
+
* Use with {@link createGeometraThreeSceneBasics} when you own the `WebGLRenderer` (headless GL,
|
|
16
|
+
* offscreen canvas, tests) but want buffer dimensions and projection to stay aligned with those hosts.
|
|
17
|
+
*/
|
|
18
|
+
export function resizeGeometraThreePerspectiveView(renderer, camera, cssWidth, cssHeight, pixelRatio) {
|
|
19
|
+
renderer.setPixelRatio(pixelRatio);
|
|
20
|
+
const w = Math.max(1, Math.floor(cssWidth));
|
|
21
|
+
const h = Math.max(1, Math.floor(cssHeight));
|
|
22
|
+
camera.aspect = w / h;
|
|
23
|
+
camera.updateProjectionMatrix();
|
|
24
|
+
renderer.setSize(w, h, false);
|
|
25
|
+
}
|
|
11
26
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAAuB,EACvB,QAAgB,EAChB,SAAiB,EACjB,UAAmB;IAEnB,MAAM,EAAE,GAAG,UAAU,IAAI,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3F,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAA;IAChD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;AACzC,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAAuB,EACvB,QAAgB,EAChB,SAAiB,EACjB,UAAmB;IAEnB,MAAM,EAAE,GAAG,UAAU,IAAI,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3F,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAA;IAChD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kCAAkC,CAChD,QAAuB,EACvB,MAAyB,EACzB,QAAgB,EAChB,SAAiB,EACjB,UAAkB;IAElB,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;IAClC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAA;IAC5C,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAA;IACrB,MAAM,CAAC,sBAAsB,EAAE,CAAA;IAC/B,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;AAC/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geometra/renderer-three",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Three.js render target helpers for Geometra — stack WebGL with the geometry-streamed canvas client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -33,24 +33,21 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
35
35
|
"check": "tsc --noEmit -p tsconfig.json",
|
|
36
|
-
"
|
|
36
|
+
"verify:exports": "node scripts/verify-exports.mjs",
|
|
37
|
+
"verify:utils": "node scripts/verify-utils.mjs",
|
|
38
|
+
"release:gate": "npm run check && npm run build && npm run verify:exports && npm run verify:utils",
|
|
37
39
|
"prepare": "npm run build",
|
|
38
40
|
"prepublishOnly": "npm run build"
|
|
39
41
|
},
|
|
40
42
|
"peerDependencies": {
|
|
41
|
-
"@geometra/renderer-canvas": "^1.2.
|
|
43
|
+
"@geometra/renderer-canvas": "^1.2.2",
|
|
42
44
|
"three": ">=0.160.0 <0.180.0"
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
45
|
-
"@geometra/client": "^1.2.
|
|
46
|
-
"@geometra/renderer-canvas": "^1.2.
|
|
47
|
+
"@geometra/client": "^1.2.2",
|
|
48
|
+
"@geometra/renderer-canvas": "^1.2.2",
|
|
47
49
|
"@types/three": "^0.170.0",
|
|
48
50
|
"three": "^0.170.0",
|
|
49
51
|
"typescript": "^6.0.2"
|
|
50
|
-
},
|
|
51
|
-
"overrides": {
|
|
52
|
-
"@geometra/renderer-canvas": {
|
|
53
|
-
"@geometra/client": "^1.2.1"
|
|
54
|
-
}
|
|
55
52
|
}
|
|
56
53
|
}
|