@sienci/gviewer 0.1.29 → 0.1.32
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 +29 -2
- package/dist/{GCodeSVGRenderer-BezIPixY.js → GCodeSVGRenderer-D4QGoHWJ.js} +2686 -2491
- package/dist/{GCodeSVGRenderer-cfCcKFfP.cjs → GCodeSVGRenderer-i9duYU8q.cjs} +3 -3
- package/dist/gviewer.cjs +1 -1
- package/dist/gviewer.js +412 -407
- package/dist/react.cjs +1 -1
- package/dist/react.js +40 -34
- package/dist/types/geometry.d.ts +23 -5
- package/dist/types/types.d.ts +23 -0
- package/dist/types/viewer/GCodeViewer.d.ts +61 -7
- package/dist/types/viewer/camera/camera.d.ts +59 -1
- package/dist/types/viewer/index.d.ts +1 -1
- package/dist/types/viewer/toolpath/streams.d.ts +4 -0
- package/dist/types/viewer/types.d.ts +10 -0
- package/dist/viewcube.css +50 -0
- package/dist/viewer.cjs +1 -1
- package/dist/viewer.js +1 -1
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const F=require("react"),C=require("./GCodeSVGRenderer-i9duYU8q.cjs");function V(l){const d=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(l){for(const s in l)if(s!=="default"){const i=Object.getOwnPropertyDescriptor(l,s);Object.defineProperty(d,s,i.get?i:{enumerable:!0,get:()=>l[s]})}}return d.default=l,Object.freeze(d)}const o=V(F),g=o.forwardRef(function(d,s){const{id:i,options:a,callbacks:u,className:p,style:f}=d,c=o.useRef(null),r=o.useRef(null);return o.useEffect(()=>{const e=c.current;if(!e)return;const m=new C.GCodeViewer({id:i,container:e,options:a,callbacks:u});return r.current=m,()=>{r.current=null,m.dispose()}},[i]),o.useEffect(()=>{var e;(e=r.current)==null||e.setOptions(a??{})},[a]),o.useEffect(()=>{var e;(e=r.current)==null||e.setCallbacks(u??{})},[u]),o.useImperativeHandle(s,()=>{const e=()=>{const t=r.current;if(!t)throw new Error("GCodeViewer is not ready.");return t};return{get id(){return i},setCallbacks(t){e().setCallbacks(t)},snapCameraToView(t,n){e().snapCameraToView(t,n)},setCameraProjection(t){e().setCameraProjection(t)},getCameraProjection(){return e().getCameraProjection()},setRotateEnabled(t){e().setRotateEnabled(t)},setCameraFollowEnabled(t){e().setCameraFollowEnabled(t)},screenToWorld(t,n,w){return e().screenToWorld(t,n,w)},worldToScreen(t,n,w){return e().worldToScreen(t,n,w)},setBitPosition(t,n){e().setBitPosition(t,n)},setBitVisible(t){e().setBitVisible(t)},setBitSpinning(t){e().setBitSpinning(t)},setToolpathRotationA(t){e().setToolpathRotationA(t)},hideUntilLine(t,n){e().hideUntilLine(t,n)},seekToLine(t,n){e().seekToLine(t,n)},showAll(){e().showAll()},resetColors(){e().resetColors()},loadFromUrl(t,n){return e().loadFromUrl(t,n)},loadFromFile(t){return e().loadFromFile(t)},loadFromText(t){return e().loadFromText(t)},loadFromLines(t){return e().loadFromLines(t)},loadFromWorkerData(t){return e().loadFromWorkerData(t)},unload(){e().unload()},setOptions(t){e().setOptions(t)},getOptions(){return e().getOptions()},resize(){e().resize()},focusToModel(){e().focusToModel()},resetCamera(){e().resetCamera()},getBounds(){return e().getBounds()},dispose(){e().dispose()}}},[i]),o.createElement("div",{ref:c,className:p,style:f})}),G=o.forwardRef(function(d,s){const{id:i,options:a,className:u,style:p}=d,f=o.useRef(null),c=o.useRef(null);return o.useEffect(()=>{const r=f.current;if(!r)return;const e=new C.GCodeSVGRenderer(r,a);return c.current=e,()=>{c.current=null,e.dispose()}},[]),o.useEffect(()=>{var r;a&&((r=c.current)==null||r.setOptions(a))},[a]),o.useImperativeHandle(s,()=>{const r=()=>{const e=c.current;if(!e)throw new Error("GCodeSVGRenderer is not ready.");return e};return{loadFromLines:e=>r().loadFromLines(e),loadFromFile:e=>r().loadFromFile(e),loadFromText:e=>r().loadFromText(e),loadFromWorkerData:e=>r().loadFromWorkerData(e),loadFromPrecomputedGroups:(e,m)=>r().loadFromPrecomputedGroups(e,m),clear:()=>r().clear(),resetView:()=>r().resetView(),setOptions:e=>r().setOptions(e),setProjectionMode:e=>r().setProjectionMode(e),setBitPosition:e=>r().setBitPosition(e),setBitVisible:e=>r().setBitVisible(e),getSVGElement:()=>r().getSVGElement(),dispose:()=>r().dispose()}},[]),o.createElement("div",{ref:f,className:u,style:{width:"100%",height:"100%",...p}})});exports.GCodeSVGVisualizer=G;exports.GCodeVisualizer=g;
|
package/dist/react.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import * as o from "react";
|
|
2
|
-
import { a as w, G as
|
|
2
|
+
import { a as w, G as C } from "./GCodeSVGRenderer-D4QGoHWJ.js";
|
|
3
3
|
const G = o.forwardRef(
|
|
4
|
-
function(
|
|
5
|
-
const { id:
|
|
4
|
+
function(u, m) {
|
|
5
|
+
const { id: a, options: s, callbacks: l, className: f, style: c } = u, i = o.useRef(null), t = o.useRef(null);
|
|
6
6
|
return o.useEffect(() => {
|
|
7
7
|
const e = i.current;
|
|
8
8
|
if (!e)
|
|
9
9
|
return;
|
|
10
|
-
const d = new w({ id:
|
|
10
|
+
const d = new w({ id: a, container: e, options: s, callbacks: l });
|
|
11
11
|
return t.current = d, () => {
|
|
12
12
|
t.current = null, d.dispose();
|
|
13
13
|
};
|
|
14
|
-
}, [
|
|
14
|
+
}, [a]), o.useEffect(() => {
|
|
15
15
|
var e;
|
|
16
|
-
(e = t.current) == null || e.setOptions(
|
|
17
|
-
}, [
|
|
16
|
+
(e = t.current) == null || e.setOptions(s ?? {});
|
|
17
|
+
}, [s]), o.useEffect(() => {
|
|
18
18
|
var e;
|
|
19
|
-
(e = t.current) == null || e.setCallbacks(
|
|
20
|
-
}, [
|
|
19
|
+
(e = t.current) == null || e.setCallbacks(l ?? {});
|
|
20
|
+
}, [l]), o.useImperativeHandle(
|
|
21
21
|
m,
|
|
22
22
|
() => {
|
|
23
23
|
const e = () => {
|
|
@@ -28,13 +28,19 @@ const G = o.forwardRef(
|
|
|
28
28
|
};
|
|
29
29
|
return {
|
|
30
30
|
get id() {
|
|
31
|
-
return
|
|
31
|
+
return a;
|
|
32
32
|
},
|
|
33
33
|
setCallbacks(r) {
|
|
34
34
|
e().setCallbacks(r);
|
|
35
35
|
},
|
|
36
|
-
snapCameraToView(r,
|
|
37
|
-
e().snapCameraToView(r,
|
|
36
|
+
snapCameraToView(r, n) {
|
|
37
|
+
e().snapCameraToView(r, n);
|
|
38
|
+
},
|
|
39
|
+
setCameraProjection(r) {
|
|
40
|
+
e().setCameraProjection(r);
|
|
41
|
+
},
|
|
42
|
+
getCameraProjection() {
|
|
43
|
+
return e().getCameraProjection();
|
|
38
44
|
},
|
|
39
45
|
setRotateEnabled(r) {
|
|
40
46
|
e().setRotateEnabled(r);
|
|
@@ -42,14 +48,14 @@ const G = o.forwardRef(
|
|
|
42
48
|
setCameraFollowEnabled(r) {
|
|
43
49
|
e().setCameraFollowEnabled(r);
|
|
44
50
|
},
|
|
45
|
-
screenToWorld(r,
|
|
46
|
-
return e().screenToWorld(r,
|
|
51
|
+
screenToWorld(r, n, p) {
|
|
52
|
+
return e().screenToWorld(r, n, p);
|
|
47
53
|
},
|
|
48
|
-
worldToScreen(r,
|
|
49
|
-
return e().worldToScreen(r,
|
|
54
|
+
worldToScreen(r, n, p) {
|
|
55
|
+
return e().worldToScreen(r, n, p);
|
|
50
56
|
},
|
|
51
|
-
setBitPosition(r,
|
|
52
|
-
e().setBitPosition(r,
|
|
57
|
+
setBitPosition(r, n) {
|
|
58
|
+
e().setBitPosition(r, n);
|
|
53
59
|
},
|
|
54
60
|
setBitVisible(r) {
|
|
55
61
|
e().setBitVisible(r);
|
|
@@ -60,11 +66,11 @@ const G = o.forwardRef(
|
|
|
60
66
|
setToolpathRotationA(r) {
|
|
61
67
|
e().setToolpathRotationA(r);
|
|
62
68
|
},
|
|
63
|
-
hideUntilLine(r,
|
|
64
|
-
e().hideUntilLine(r,
|
|
69
|
+
hideUntilLine(r, n) {
|
|
70
|
+
e().hideUntilLine(r, n);
|
|
65
71
|
},
|
|
66
|
-
seekToLine(r,
|
|
67
|
-
e().seekToLine(r,
|
|
72
|
+
seekToLine(r, n) {
|
|
73
|
+
e().seekToLine(r, n);
|
|
68
74
|
},
|
|
69
75
|
showAll() {
|
|
70
76
|
e().showAll();
|
|
@@ -72,8 +78,8 @@ const G = o.forwardRef(
|
|
|
72
78
|
resetColors() {
|
|
73
79
|
e().resetColors();
|
|
74
80
|
},
|
|
75
|
-
loadFromUrl(r,
|
|
76
|
-
return e().loadFromUrl(r,
|
|
81
|
+
loadFromUrl(r, n) {
|
|
82
|
+
return e().loadFromUrl(r, n);
|
|
77
83
|
},
|
|
78
84
|
loadFromFile(r) {
|
|
79
85
|
return e().loadFromFile(r);
|
|
@@ -113,23 +119,23 @@ const G = o.forwardRef(
|
|
|
113
119
|
}
|
|
114
120
|
};
|
|
115
121
|
},
|
|
116
|
-
[
|
|
117
|
-
), o.createElement("div", { ref: i, className: f, style:
|
|
122
|
+
[a]
|
|
123
|
+
), o.createElement("div", { ref: i, className: f, style: c });
|
|
118
124
|
}
|
|
119
125
|
), R = o.forwardRef(
|
|
120
|
-
function(
|
|
121
|
-
const { id:
|
|
126
|
+
function(u, m) {
|
|
127
|
+
const { id: a, options: s, className: l, style: f } = u, c = o.useRef(null), i = o.useRef(null);
|
|
122
128
|
return o.useEffect(() => {
|
|
123
|
-
const t =
|
|
129
|
+
const t = c.current;
|
|
124
130
|
if (!t) return;
|
|
125
|
-
const e = new
|
|
131
|
+
const e = new C(t, s);
|
|
126
132
|
return i.current = e, () => {
|
|
127
133
|
i.current = null, e.dispose();
|
|
128
134
|
};
|
|
129
135
|
}, []), o.useEffect(() => {
|
|
130
136
|
var t;
|
|
131
|
-
|
|
132
|
-
}, [
|
|
137
|
+
s && ((t = i.current) == null || t.setOptions(s));
|
|
138
|
+
}, [s]), o.useImperativeHandle(m, () => {
|
|
133
139
|
const t = () => {
|
|
134
140
|
const e = i.current;
|
|
135
141
|
if (!e) throw new Error("GCodeSVGRenderer is not ready.");
|
|
@@ -151,8 +157,8 @@ const G = o.forwardRef(
|
|
|
151
157
|
dispose: () => t().dispose()
|
|
152
158
|
};
|
|
153
159
|
}, []), o.createElement("div", {
|
|
154
|
-
ref:
|
|
155
|
-
className:
|
|
160
|
+
ref: c,
|
|
161
|
+
className: l,
|
|
156
162
|
style: { width: "100%", height: "100%", ...f }
|
|
157
163
|
});
|
|
158
164
|
}
|
package/dist/types/geometry.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArcMoveCallback, LinearMoveCallback, Position, WorkerGeometryData } from "./types";
|
|
1
|
+
import { ArcMoveCallback, LinearMoveCallback, Position, WorkerGeometryData, LoadWorkerDataOptions } from "./types";
|
|
2
2
|
export type VertexCollector = {
|
|
3
3
|
onLinearMove?: (args: Parameters<LinearMoveCallback>[0], vertices: number[]) => void;
|
|
4
4
|
onArcMove?: (args: Parameters<ArcMoveCallback>[0], vertices: number[]) => void;
|
|
@@ -101,13 +101,18 @@ export type WorkerToolpathStream = {
|
|
|
101
101
|
positions: Float32Array;
|
|
102
102
|
colors: Float32Array;
|
|
103
103
|
prefixEndVertex: Int32Array;
|
|
104
|
+
/**
|
|
105
|
+
* Index into the `lineGroups` this stream was built for, or null for the
|
|
106
|
+
* catch-all stream holding lines that fell in no group.
|
|
107
|
+
*/
|
|
108
|
+
lineGroupIndex: number | null;
|
|
104
109
|
};
|
|
105
110
|
export type WorkerToolpathStreams = {
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
rapids: WorkerToolpathStream[];
|
|
112
|
+
cuts: WorkerToolpathStream[];
|
|
108
113
|
};
|
|
109
114
|
/**
|
|
110
|
-
* Builds
|
|
115
|
+
* Builds line-ordered toolpath streams (rapid + cut) from worker geometry,
|
|
111
116
|
* preserving per-vertex colours and producing per-stream `prefixEndVertex`
|
|
112
117
|
* arrays (indexed by source line) so `hideUntilLine`/progress greying works on
|
|
113
118
|
* the worker-data path.
|
|
@@ -115,5 +120,18 @@ export type WorkerToolpathStreams = {
|
|
|
115
120
|
* Unlike `buildWorkerSegmentGroups`, segments are appended in source-line order
|
|
116
121
|
* (driven by `frames`) rather than grouped by colour, which is what the
|
|
117
122
|
* cumulative `prefixEndVertex` cursor requires.
|
|
123
|
+
*
|
|
124
|
+
* With no `lineGroups`, the result is exactly one rapid stream and one cut
|
|
125
|
+
* stream, both with a null `lineGroupIndex`. Passing `lineGroups` splits both by
|
|
126
|
+
* source-line range instead - one rapid and one cut stream per group, plus a
|
|
127
|
+
* trailing pair for the lines in no group - so a host can hide an interior span
|
|
128
|
+
* by flipping those streams' visibility, which a single contiguous draw range
|
|
129
|
+
* (all `hideUntilLine` can offer) cannot express. Each group keeps its own
|
|
130
|
+
* carry-forward `prefixEndVertex`, so progress greying stays correct within
|
|
131
|
+
* every stream.
|
|
132
|
+
*
|
|
133
|
+
* Grouping costs an `Int32Array(framesLen)` per stream, so memory grows with
|
|
134
|
+
* lines x groups. It is meant for interactive review of a file already held in
|
|
135
|
+
* memory, not for the live job path.
|
|
118
136
|
*/
|
|
119
|
-
export declare function buildWorkerToolpathStreams(data: WorkerGeometryData): WorkerToolpathStreams;
|
|
137
|
+
export declare function buildWorkerToolpathStreams(data: WorkerGeometryData, options?: LoadWorkerDataOptions): WorkerToolpathStreams;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -81,3 +81,26 @@ export type WorkerGeometryData = {
|
|
|
81
81
|
isLaser?: boolean;
|
|
82
82
|
toolchangeCount?: number;
|
|
83
83
|
};
|
|
84
|
+
/**
|
|
85
|
+
* An inclusive range of source lines the host wants to show or hide as a unit,
|
|
86
|
+
* e.g. everything cut with one tool.
|
|
87
|
+
*
|
|
88
|
+
* Indices are 0-based and match `hideUntilLine`/`seekToLine` — the same source
|
|
89
|
+
* line indexing used by `prefixEndVertex` — not 1-based editor line numbers.
|
|
90
|
+
*/
|
|
91
|
+
export type LineRangeGroup = {
|
|
92
|
+
start: number;
|
|
93
|
+
end: number;
|
|
94
|
+
};
|
|
95
|
+
export type LoadWorkerDataOptions = {
|
|
96
|
+
/**
|
|
97
|
+
* Split the toolpath into separately hideable streams by source-line range,
|
|
98
|
+
* so `setLineGroupVisible` can hide an interior span. Without this the
|
|
99
|
+
* toolpath is one rapid stream plus one cut stream, and only a *prefix* can
|
|
100
|
+
* be hidden (via `hideUntilLine`, which sets a single contiguous draw range).
|
|
101
|
+
*
|
|
102
|
+
* Groups are matched in order, so where ranges overlap the first one wins.
|
|
103
|
+
* Lines in no group land in an always-visible stream.
|
|
104
|
+
*/
|
|
105
|
+
lineGroups?: readonly LineRangeGroup[];
|
|
106
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { WorkerGeometryData } from "../types";
|
|
2
|
-
import { GCodeViewerCameraView, GCodeViewerBounds, GCodeViewerCallbacks, GCodeViewerCreateArgs, GCodeViewerHandle, GCodeViewerBitPosition, GCodeViewerOptions } from "./types";
|
|
1
|
+
import type { LoadWorkerDataOptions, WorkerGeometryData } from "../types";
|
|
2
|
+
import { GCodeViewerCameraProjection, GCodeViewerCameraView, GCodeViewerBounds, GCodeViewerCallbacks, GCodeViewerCreateArgs, GCodeViewerHandle, GCodeViewerBitPosition, GCodeViewerOptions } from "./types";
|
|
3
3
|
export declare class GCodeViewer implements GCodeViewerHandle {
|
|
4
4
|
readonly id: string;
|
|
5
5
|
private readonly container;
|
|
@@ -7,7 +7,10 @@ export declare class GCodeViewer implements GCodeViewerHandle {
|
|
|
7
7
|
private readonly renderer;
|
|
8
8
|
private readonly scene;
|
|
9
9
|
private readonly toolpathRoot;
|
|
10
|
-
private readonly
|
|
10
|
+
private readonly perspectiveCamera;
|
|
11
|
+
private readonly orthographicCamera;
|
|
12
|
+
private camera;
|
|
13
|
+
private readonly orthoViewHeight;
|
|
11
14
|
private readonly controls;
|
|
12
15
|
private viewCube;
|
|
13
16
|
private readonly viewCubeCorrection;
|
|
@@ -56,7 +59,35 @@ export declare class GCodeViewer implements GCodeViewerHandle {
|
|
|
56
59
|
hideUntilLine(lineIndex: number, mode?: "hide" | "grey"): void;
|
|
57
60
|
seekToLine(lineIndex: number, mode?: "hide" | "grey"): void;
|
|
58
61
|
showAll(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Show or hide one of the `lineGroups` the toolpath was loaded with.
|
|
64
|
+
*
|
|
65
|
+
* This is deliberately independent of `showAll()`, `hideUntilLine()` and
|
|
66
|
+
* `resetColors()`, which are all about *progress*: they move draw ranges and
|
|
67
|
+
* colors, while this flips object visibility. So the two compose in either
|
|
68
|
+
* order - but note a hidden group therefore stays hidden across a `showAll()`,
|
|
69
|
+
* which looks surprising if you expect "show all" to mean everything. Call
|
|
70
|
+
* `showAllLineGroups()` for that.
|
|
71
|
+
*
|
|
72
|
+
* A no-op when the load passed no `lineGroups`, or for the catch-all stream of
|
|
73
|
+
* lines outside every group, which has no index and is always visible.
|
|
74
|
+
*/
|
|
75
|
+
setLineGroupVisible(groupIndex: number, visible: boolean): void;
|
|
76
|
+
showAllLineGroups(): void;
|
|
59
77
|
resetColors(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Swap the projection the viewer renders through, preserving the current
|
|
80
|
+
* framing and view direction. Delegates through setOptions so getOptions()
|
|
81
|
+
* stays the single source of truth for the active projection.
|
|
82
|
+
*/
|
|
83
|
+
setCameraProjection(projection: GCodeViewerCameraProjection): void;
|
|
84
|
+
getCameraProjection(): GCodeViewerCameraProjection;
|
|
85
|
+
/**
|
|
86
|
+
* `options.distance` is the camera standoff, which only affects framing under
|
|
87
|
+
* a perspective camera; an orthographic camera frames by frustum height, so
|
|
88
|
+
* the value moves the camera without changing how much of the model is
|
|
89
|
+
* visible. Use focusToModel() to reframe in either projection.
|
|
90
|
+
*/
|
|
60
91
|
snapCameraToView(view: GCodeViewerCameraView, options?: {
|
|
61
92
|
durationMs?: number;
|
|
62
93
|
distance?: number;
|
|
@@ -100,14 +131,31 @@ export declare class GCodeViewer implements GCodeViewerHandle {
|
|
|
100
131
|
* and mapped back onto the laid-out canvas rect, so overlays drawn in fixed
|
|
101
132
|
* (viewport) coordinates line up with picked scene points and track pan/zoom.
|
|
102
133
|
*
|
|
103
|
-
* `z` is the point's height in scene space (default 0)
|
|
104
|
-
* projected pixel under the perspective camera
|
|
105
|
-
*
|
|
134
|
+
* `z` is the point's height in scene space (default 0). It changes the
|
|
135
|
+
* projected pixel under the perspective camera (though not under an
|
|
136
|
+
* orthographic one, which has no divide-by-z), so callers placing markers off
|
|
137
|
+
* the Z=0 plane should pass it. Returns null when the canvas has no layout.
|
|
106
138
|
*/
|
|
107
139
|
worldToScreen(x: number, y: number, z?: number): {
|
|
108
140
|
x: number;
|
|
109
141
|
y: number;
|
|
110
142
|
} | null;
|
|
143
|
+
private isPerspectiveActive;
|
|
144
|
+
private viewportAspect;
|
|
145
|
+
/** Ortho zoom that frames `height` world units vertically. */
|
|
146
|
+
private orthoZoomForHeight;
|
|
147
|
+
/** World units the ortho camera currently frames vertically. */
|
|
148
|
+
private orthoFramedHeight;
|
|
149
|
+
private applyCameraDepthRange;
|
|
150
|
+
/**
|
|
151
|
+
* Swap the active camera, preserving view direction and apparent framing.
|
|
152
|
+
*
|
|
153
|
+
* The two projections are bridged by the vertical extent visible at the orbit
|
|
154
|
+
* target: an ortho frustum of that height shows the same content the
|
|
155
|
+
* perspective camera showed at that standoff. Going back the other way, the
|
|
156
|
+
* framed height determines the standoff to restore.
|
|
157
|
+
*/
|
|
158
|
+
private setActiveProjection;
|
|
111
159
|
private startSnapToView;
|
|
112
160
|
private startCameraLerp;
|
|
113
161
|
loadFromUrl(url: string, args?: {
|
|
@@ -116,7 +164,13 @@ export declare class GCodeViewer implements GCodeViewerHandle {
|
|
|
116
164
|
loadFromFile(file: File): Promise<void>;
|
|
117
165
|
loadFromText(gcode: string): Promise<void>;
|
|
118
166
|
loadFromLines(lines: readonly string[]): Promise<void>;
|
|
119
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Pass `options.lineGroups` to split the toolpath into separately hideable
|
|
169
|
+
* streams by source-line range; `setLineGroupVisible` then shows or hides a
|
|
170
|
+
* group. Without it the toolpath is one rapid + one cut stream, exactly as
|
|
171
|
+
* before, and only a prefix can be hidden (`hideUntilLine`).
|
|
172
|
+
*/
|
|
173
|
+
loadFromWorkerData(data: WorkerGeometryData, options?: LoadWorkerDataOptions): Promise<void>;
|
|
120
174
|
unload(): void;
|
|
121
175
|
setOptions(next: Partial<GCodeViewerOptions>): void;
|
|
122
176
|
getOptions(): Readonly<GCodeViewerOptions>;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import * as THREE from "three";
|
|
2
|
+
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
2
3
|
import type { GCodeViewerCameraView } from "../types";
|
|
4
|
+
/** Either projection the viewer can render through. */
|
|
5
|
+
export type GCodeViewerCameraLike = THREE.PerspectiveCamera | THREE.OrthographicCamera;
|
|
6
|
+
export declare class VerticalInvertOrbitControls extends OrbitControls {
|
|
7
|
+
_rotateUp(angle: number): void;
|
|
8
|
+
}
|
|
3
9
|
export declare function ensureContainerOverlayLayout(container: HTMLElement): void;
|
|
4
10
|
export declare function easeInOutCubic(t: number): number;
|
|
5
11
|
export declare function viewDirection(view: GCodeViewerCameraView): THREE.Vector3;
|
|
@@ -13,9 +19,61 @@ export declare function dominantCameraFace(cameraPosition: {
|
|
|
13
19
|
z: number;
|
|
14
20
|
}): "front" | "back" | "left" | "right" | "top" | "bottom";
|
|
15
21
|
export declare function orbitCameraByPixels(args: {
|
|
16
|
-
camera:
|
|
22
|
+
camera: GCodeViewerCameraLike;
|
|
17
23
|
target: THREE.Vector3;
|
|
18
24
|
deltaX: number;
|
|
19
25
|
deltaY: number;
|
|
20
26
|
speed?: number;
|
|
21
27
|
}): void;
|
|
28
|
+
/**
|
|
29
|
+
* Vertical world-space extent visible at `distance` under a perspective camera
|
|
30
|
+
* of vertical field of view `fovDeg`. The bridge between the two projections:
|
|
31
|
+
* an orthographic frustum of this height frames the same content as the
|
|
32
|
+
* perspective camera does at that distance.
|
|
33
|
+
*/
|
|
34
|
+
export declare function frustumHeightAtDistance(distance: number, fovDeg: number): number;
|
|
35
|
+
/** Inverse of frustumHeightAtDistance: the standoff that frames `height`. */
|
|
36
|
+
export declare function distanceForFrustumHeight(height: number, fovDeg: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* How far back to sit to frame a model of the given size. `size.z` is added
|
|
39
|
+
* rather than folded into the fit because the camera generally looks down at
|
|
40
|
+
* the model from above, so the model's height eats into the standoff.
|
|
41
|
+
*/
|
|
42
|
+
export declare function fitDistanceForBounds(size: {
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
z: number;
|
|
46
|
+
}, fovDeg: number, margin?: number): number;
|
|
47
|
+
/** Symmetric orthographic frustum framing `height` world units vertically. */
|
|
48
|
+
export declare function orthoFrustumFor(height: number, aspect: number): {
|
|
49
|
+
left: number;
|
|
50
|
+
right: number;
|
|
51
|
+
top: number;
|
|
52
|
+
bottom: number;
|
|
53
|
+
};
|
|
54
|
+
/** Perspective near/far for a model of extent `maxDim`. */
|
|
55
|
+
export declare function perspectiveDepthRange(maxDim: number): {
|
|
56
|
+
near: number;
|
|
57
|
+
far: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Orthographic near/far. Ortho depth is linear — there's no divide-by-z eating
|
|
61
|
+
* precision near the camera — so a negative near costs nothing and guarantees
|
|
62
|
+
* geometry behind the camera plane still draws, which matters because an ortho
|
|
63
|
+
* camera is routinely positioned inside or below the model it is framing.
|
|
64
|
+
*/
|
|
65
|
+
export declare function orthoDepthRange(distance: number, maxDim: number): {
|
|
66
|
+
near: number;
|
|
67
|
+
far: number;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Intersect a ray with the horizontal plane at `planeZ`.
|
|
71
|
+
*
|
|
72
|
+
* THREE.Ray.intersectPlane rejects hits behind the ray origin. Under a
|
|
73
|
+
* perspective camera that origin is the eye, and a backward hit really is a
|
|
74
|
+
* miss. Under ortho the origin sits on the camera plane, but the negative near
|
|
75
|
+
* from orthoDepthRange means geometry *behind* that plane is still on screen —
|
|
76
|
+
* so a pick plane above a camera dollied down into the model is a legitimate
|
|
77
|
+
* hit that intersectPlane would silently drop. Hence `allowBehind`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function intersectRayWithZPlane(origin: THREE.Vector3, direction: THREE.Vector3, planeZ: number, allowBehind: boolean): THREE.Vector3 | null;
|
|
@@ -5,4 +5,4 @@ export type { GCodeViewerThemePresetName } from "./themes";
|
|
|
5
5
|
export * from "./types";
|
|
6
6
|
export { GCodeSVGRenderer } from "./svg/GCodeSVGRenderer";
|
|
7
7
|
export type { GCodeSVGOptions } from "./svg/types";
|
|
8
|
-
export type { WorkerGeometryData } from "../types";
|
|
8
|
+
export type { LineRangeGroup, LoadWorkerDataOptions, WorkerGeometryData } from "../types";
|
|
@@ -10,6 +10,9 @@ export type ToolpathStreamState = {
|
|
|
10
10
|
greyCursorVertex: number;
|
|
11
11
|
kind: ToolpathStreamKind;
|
|
12
12
|
cutBucketIndex: number | null;
|
|
13
|
+
/** Which of the load's `lineGroups` this stream holds, or null for the always-visible
|
|
14
|
+
* catch-all and for ungrouped loads. Drives setLineGroupVisible. */
|
|
15
|
+
lineGroupIndex: number | null;
|
|
13
16
|
/** Set when colors came from the worker's pre-baked colorArrayBuffer (e.g. toolchange palette).
|
|
14
17
|
* refreshToolpathStreamColors skips these streams so theme changes don't flatten per-tool colors. */
|
|
15
18
|
workerColors?: Float32Array;
|
|
@@ -17,6 +20,7 @@ export type ToolpathStreamState = {
|
|
|
17
20
|
export type ToolpathStreamSpec = {
|
|
18
21
|
kind: ToolpathStreamKind;
|
|
19
22
|
cutBucketIndex: number | null;
|
|
23
|
+
lineGroupIndex?: number | null;
|
|
20
24
|
positions: Float32Array;
|
|
21
25
|
prefixEndVertex: Int32Array;
|
|
22
26
|
opacity: number;
|
|
@@ -109,6 +109,13 @@ export type GCodeViewerOptions = {
|
|
|
109
109
|
theme: GCodeViewerTheme;
|
|
110
110
|
};
|
|
111
111
|
camera: {
|
|
112
|
+
/**
|
|
113
|
+
* Perspective is the default. Orthographic removes the divide-by-z, so
|
|
114
|
+
* toolpath segments sharing X/Y but differing in Z land on the same pixel
|
|
115
|
+
* in an axis-aligned view instead of splaying apart away from the centre.
|
|
116
|
+
*/
|
|
117
|
+
projection: GCodeViewerCameraProjection;
|
|
118
|
+
/** Perspective vertical FOV. Also seeds ortho framing when projections swap. */
|
|
112
119
|
fov: number;
|
|
113
120
|
focusDurationMs: number;
|
|
114
121
|
orbit: {
|
|
@@ -174,6 +181,8 @@ export type GCodeViewerHandle = {
|
|
|
174
181
|
durationMs?: number;
|
|
175
182
|
distance?: number;
|
|
176
183
|
}): void;
|
|
184
|
+
setCameraProjection(projection: GCodeViewerCameraProjection): void;
|
|
185
|
+
getCameraProjection(): GCodeViewerCameraProjection;
|
|
177
186
|
setRotateEnabled(enabled: boolean): void;
|
|
178
187
|
setCameraFollowEnabled(enabled: boolean): void;
|
|
179
188
|
screenToWorld(clientX: number, clientY: number, options?: {
|
|
@@ -219,4 +228,5 @@ export type GCodeViewerCreateArgs = {
|
|
|
219
228
|
options?: Partial<GCodeViewerOptions>;
|
|
220
229
|
callbacks?: GCodeViewerCallbacks;
|
|
221
230
|
};
|
|
231
|
+
export type GCodeViewerCameraProjection = "perspective" | "orthographic";
|
|
222
232
|
export type GCodeViewerCameraView = "front" | "back" | "left" | "right" | "top" | "bottom" | "front-top-left" | "front-top-right" | "front-bottom-left" | "front-bottom-right" | "back-top-left" | "back-top-right" | "back-bottom-left" | "back-bottom-right";
|
package/dist/viewcube.css
CHANGED
|
@@ -53,6 +53,40 @@
|
|
|
53
53
|
.gViewer-viewcube__face--top{ transform: rotateX(-90deg) translateZ(42px); }
|
|
54
54
|
.gViewer-viewcube__face--bottom{ transform: rotateX(90deg) translateZ(42px); }
|
|
55
55
|
|
|
56
|
+
.gViewer-viewcube__corner{
|
|
57
|
+
position:absolute;
|
|
58
|
+
width:20px;
|
|
59
|
+
height:20px;
|
|
60
|
+
top:32px;
|
|
61
|
+
left:32px;
|
|
62
|
+
border-radius:50%;
|
|
63
|
+
background:rgba(12,16,20,0.45);
|
|
64
|
+
border:1px solid rgba(120,140,160,0.30);
|
|
65
|
+
cursor:pointer;
|
|
66
|
+
padding:0;
|
|
67
|
+
user-select:none;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.gViewer-viewcube__corner:hover{
|
|
71
|
+
background:rgba(12,16,20,0.75);
|
|
72
|
+
border-color:rgba(160,190,220,0.65);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.gViewer-viewcube__corner.is-active{
|
|
76
|
+
border-color: rgba(96,165,250,0.95);
|
|
77
|
+
box-shadow: 0 0 0 1px rgba(96,165,250,0.35);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.gViewer-viewcube__corner--front-top-right{ transform: rotateY(45deg) rotateX(-35.264deg) translateZ(72.746px); }
|
|
81
|
+
/* front-top-left is the restored gSender iso view; 35.264deg = atan(1/sqrt2), the tilt that points a face-oriented marker straight through a cube vertex */
|
|
82
|
+
.gViewer-viewcube__corner--front-top-left{ transform: rotateY(-45deg) rotateX(-35.264deg) translateZ(72.746px); }
|
|
83
|
+
.gViewer-viewcube__corner--front-bottom-right{ transform: rotateY(45deg) rotateX(35.264deg) translateZ(72.746px); }
|
|
84
|
+
.gViewer-viewcube__corner--front-bottom-left{ transform: rotateY(-45deg) rotateX(35.264deg) translateZ(72.746px); }
|
|
85
|
+
.gViewer-viewcube__corner--back-top-right{ transform: rotateY(135deg) rotateX(-35.264deg) translateZ(72.746px); }
|
|
86
|
+
.gViewer-viewcube__corner--back-top-left{ transform: rotateY(-135deg) rotateX(-35.264deg) translateZ(72.746px); }
|
|
87
|
+
.gViewer-viewcube__corner--back-bottom-right{ transform: rotateY(135deg) rotateX(35.264deg) translateZ(72.746px); }
|
|
88
|
+
.gViewer-viewcube__corner--back-bottom-left{ transform: rotateY(-135deg) rotateX(35.264deg) translateZ(72.746px); }
|
|
89
|
+
|
|
56
90
|
@media (orientation: portrait){
|
|
57
91
|
.gViewer-viewcube{
|
|
58
92
|
left:60px;
|
|
@@ -72,4 +106,20 @@
|
|
|
72
106
|
.gViewer-viewcube__face--right{ transform: rotateY(90deg) translateZ(32px); }
|
|
73
107
|
.gViewer-viewcube__face--top{ transform: rotateX(-90deg) translateZ(32px); }
|
|
74
108
|
.gViewer-viewcube__face--bottom{ transform: rotateX(90deg) translateZ(32px); }
|
|
109
|
+
|
|
110
|
+
.gViewer-viewcube__corner{
|
|
111
|
+
width:15px;
|
|
112
|
+
height:15px;
|
|
113
|
+
top:24.5px;
|
|
114
|
+
left:24.5px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.gViewer-viewcube__corner--front-top-right{ transform: rotateY(45deg) rotateX(-35.264deg) translateZ(55.426px); }
|
|
118
|
+
.gViewer-viewcube__corner--front-top-left{ transform: rotateY(-45deg) rotateX(-35.264deg) translateZ(55.426px); }
|
|
119
|
+
.gViewer-viewcube__corner--front-bottom-right{ transform: rotateY(45deg) rotateX(35.264deg) translateZ(55.426px); }
|
|
120
|
+
.gViewer-viewcube__corner--front-bottom-left{ transform: rotateY(-45deg) rotateX(35.264deg) translateZ(55.426px); }
|
|
121
|
+
.gViewer-viewcube__corner--back-top-right{ transform: rotateY(135deg) rotateX(-35.264deg) translateZ(55.426px); }
|
|
122
|
+
.gViewer-viewcube__corner--back-top-left{ transform: rotateY(-135deg) rotateX(-35.264deg) translateZ(55.426px); }
|
|
123
|
+
.gViewer-viewcube__corner--back-bottom-right{ transform: rotateY(135deg) rotateX(35.264deg) translateZ(55.426px); }
|
|
124
|
+
.gViewer-viewcube__corner--back-bottom-left{ transform: rotateY(-135deg) rotateX(35.264deg) translateZ(55.426px); }
|
|
75
125
|
}
|
package/dist/viewer.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./GCodeSVGRenderer-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./GCodeSVGRenderer-i9duYU8q.cjs"),a={dark:{background:"#111827",opacity:.9,rapidOpacity:.3,colors:{rapid:"#0ef6ae",cutting:"#3e85c7",laser:"#a855f7",processed:"#6b7280",boundingBox:"#e2e8f0",machineBed:"#f5a623",machineBedKeepout:"#df3b3b",grid:{major:"#77a9d7",minor:"#3e6e9e"},axes:{x:"#df3b3b",y:"#06b881",z:"#295d8d"}}},light:{background:"#e5e7eb",opacity:.9,rapidOpacity:.3,colors:{rapid:"#295d8d",cutting:"#111827",laser:"#FF0000",processed:"#9ca3af",boundingBox:"#4b5563",machineBed:"#b45309",machineBedKeepout:"#df3b3b",grid:{major:"#295d8d",minor:"#5191cc"},axes:{x:"#df3b3b",y:"#06b881",z:"#295d8d"}}},"flexoki-dark":{background:"#100f0f",opacity:.9,rapidOpacity:.3,colors:{rapid:"#DA702C",cutting:"#3AA99F",laser:"#8B7EC8",processed:"#6f6e69",boundingBox:"#cecdc3",machineBed:"#ffcc66",machineBedKeepout:"#d14d41",grid:{major:"#a89984",minor:"#6f6e69"},axes:{x:"#d14d41",y:"#879a39",z:"#4385be"}}},"tokyo-night":{background:"#1a1b26",opacity:.9,rapidOpacity:.3,colors:{rapid:"#ff9e64",cutting:"#7dcfff",laser:"#bb9af7",processed:"#565f89",boundingBox:"#c0caf5",machineBed:"#e0af68",machineBedKeepout:"#f7768e",grid:{major:"#7aa2f7",minor:"#414868"},axes:{x:"#f7768e",y:"#9ece6a",z:"#7aa2f7"}}},"gruvbox-light":{background:"#fbf1c7",opacity:.9,rapidOpacity:.3,colors:{rapid:"#d65d0e",cutting:"#3c3836",laser:"#b16286",processed:"#928374",boundingBox:"#7c6f64",machineBed:"#d79921",machineBedKeepout:"#cc241d",grid:{major:"#7c6f64",minor:"#a89984"},axes:{x:"#cc241d",y:"#98971a",z:"#458588"}}},"ayu-dark":{background:"#0b0e14",opacity:.9,rapidOpacity:.3,colors:{rapid:"#FFA659",cutting:"#73D0FF",laser:"#DFBFFF",processed:"#6E7C8F",boundingBox:"#CBCCC6",machineBed:"#FFD173",machineBedKeepout:"#F28779",grid:{major:"#77a9d7",minor:"#3e6590"},axes:{x:"#F28779",y:"#D5FF80",z:"#5CCFE6"}}},"ayu-light":{background:"#fafafa",opacity:.9,rapidOpacity:.3,colors:{rapid:"#FA8D3E",cutting:"#22A4E6",laser:"#A37ACC",processed:"#ADAEB1",boundingBox:"#5C6773",machineBed:"#F2AE49",machineBedKeepout:"#F07171",grid:{major:"#5c6773",minor:"#9aacba"},axes:{x:"#F07171",y:"#86B300",z:"#55B4D4"}}}};exports.GCodeSVGRenderer=e.GCodeSVGRenderer;exports.GCodeViewer=e.GCodeViewer;exports.ViewCube=e.ViewCube;exports.defaultGCodeViewerOptions=e.defaultGCodeViewerOptions;exports.defaultGCodeViewerTheme=e.defaultGCodeViewerTheme;exports.gCodeViewerThemePresets=a;
|
package/dist/viewer.js
CHANGED