three-cad-viewer 5.1.0 → 5.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/viewer.d.ts +29 -3
- package/dist/scene/animation.d.ts +10 -0
- package/dist/three-cad-viewer.esm.js +76 -17
- package/dist/three-cad-viewer.esm.js.map +1 -1
- package/dist/three-cad-viewer.esm.min.js +3 -3
- package/dist/three-cad-viewer.js +76 -17
- package/dist/three-cad-viewer.min.js +3 -3
- package/package.json +1 -1
package/dist/core/viewer.d.ts
CHANGED
|
@@ -27,6 +27,11 @@ import { ViewerState } from "./viewer-state.js";
|
|
|
27
27
|
import type { Display } from "../ui/display.js";
|
|
28
28
|
import type { Vector3Tuple, QuaternionTuple } from "three";
|
|
29
29
|
import { CollapseState, type ZebraColorScheme, type ZebraMappingMode, type StudioToneMapping, type StudioTextureMapping, type StudioBackground, type NotificationCallback, type RenderOptions, type ViewerOptions, type Shapes, type VisibilityState, type ActiveTab, type Axis, type ClipIndex, type ThemeInput, type BoundingBoxFlat, type Keymap } from "./types.js";
|
|
30
|
+
/**
|
|
31
|
+
* Why the viewer renders continuously (see {@link Viewer.setLoopReason}): an
|
|
32
|
+
* animation is playing, a measure/select tool is active, or a screenshot is taken.
|
|
33
|
+
*/
|
|
34
|
+
export type LoopReason = "animation" | "tool" | "capture";
|
|
30
35
|
/**
|
|
31
36
|
* Material settings for the viewer.
|
|
32
37
|
*/
|
|
@@ -187,6 +192,8 @@ declare class Viewer {
|
|
|
187
192
|
hasAnimationLoop: boolean;
|
|
188
193
|
mixer: THREE.AnimationMixer | null;
|
|
189
194
|
continueAnimation: boolean;
|
|
195
|
+
/** Reasons for continuous rendering; the render loop runs while any is set. */
|
|
196
|
+
private _loopReasons;
|
|
190
197
|
clipAction: THREE.AnimationAction | null;
|
|
191
198
|
shapeRenderer: ShapeRenderer | null;
|
|
192
199
|
camera_distance: number;
|
|
@@ -219,7 +226,7 @@ declare class Viewer {
|
|
|
219
226
|
/** True while the Studio (presentation) tab owns the render. PickHost member. */
|
|
220
227
|
get studioActive(): boolean;
|
|
221
228
|
zScale: number;
|
|
222
|
-
/** Whether the attached animation has moved parts (Play
|
|
229
|
+
/** Whether the attached animation has moved parts (Play or time slider, not stopped since). */
|
|
223
230
|
private _animationStarted;
|
|
224
231
|
clipNormal0: Vector3Tuple | null;
|
|
225
232
|
clipNormal1: Vector3Tuple | null;
|
|
@@ -346,6 +353,24 @@ declare class Viewer {
|
|
|
346
353
|
* Start the animation loop
|
|
347
354
|
*/
|
|
348
355
|
animate: () => void;
|
|
356
|
+
/**
|
|
357
|
+
* Add or remove a reason for continuous rendering. The render loop runs while at
|
|
358
|
+
* least one reason is set; otherwise the viewer renders on demand (camera changes
|
|
359
|
+
* and explicit updates), so an idle viewer costs no CPU/GPU time.
|
|
360
|
+
* @param reason - why continuous rendering is needed.
|
|
361
|
+
* @param flag - whether the reason applies.
|
|
362
|
+
*/
|
|
363
|
+
setLoopReason(reason: LoopReason, flag: boolean): void;
|
|
364
|
+
/**
|
|
365
|
+
* Run the render loop only while the animation plays. When it stops (pause,
|
|
366
|
+
* stop, slider), render once so the final pose is shown.
|
|
367
|
+
*/
|
|
368
|
+
private _setAnimationPlaying;
|
|
369
|
+
/**
|
|
370
|
+
* Start or stop the render loop directly. Prefer {@link setLoopReason}, which keeps
|
|
371
|
+
* the loop running while any other reason still needs it.
|
|
372
|
+
* @param flag - whether the render loop should run.
|
|
373
|
+
*/
|
|
349
374
|
toggleAnimationLoop(flag: boolean): void;
|
|
350
375
|
/**
|
|
351
376
|
* Draw the outline of the clip caps over the frame (Clip tab active only). Skipped
|
|
@@ -567,8 +592,9 @@ declare class Viewer {
|
|
|
567
592
|
* Copy the world-space point under the cursor as `"x, y, z"` to the clipboard and
|
|
568
593
|
* send it to the host as a `copiedPoint` notification (for hosts that block the
|
|
569
594
|
* browser clipboard). Does nothing while parts may be displaced from their model
|
|
570
|
-
* positions — explode mode, an animation
|
|
571
|
-
* z-scale other than 1 — or when no
|
|
595
|
+
* positions — explode mode, an animation that was played or scrubbed and not
|
|
596
|
+
* stopped since (Stop puts the parts back), a z-scale other than 1 — or when no
|
|
597
|
+
* visible component is under the cursor.
|
|
572
598
|
* @returns true when a point was copied (the caller then consumes the key event).
|
|
573
599
|
*/
|
|
574
600
|
copyPointUnderCursor(): boolean;
|
|
@@ -116,6 +116,16 @@ declare class Animation {
|
|
|
116
116
|
* Dispose of animation resources.
|
|
117
117
|
*/
|
|
118
118
|
dispose(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Apply the current animation time to the objects without advancing it, so a
|
|
121
|
+
* single on-demand render shows the pose (e.g. after {@link setRelativeTime}).
|
|
122
|
+
*/
|
|
123
|
+
apply(): void;
|
|
124
|
+
/**
|
|
125
|
+
* Restart the frame-time measurement, so resuming playback after a pause does
|
|
126
|
+
* not advance the animation by the whole pause.
|
|
127
|
+
*/
|
|
128
|
+
resetClock(): void;
|
|
119
129
|
/**
|
|
120
130
|
* Update the animation mixer (call each frame when animating).
|
|
121
131
|
*/
|
|
@@ -92263,6 +92263,20 @@ class Animation {
|
|
|
92263
92263
|
this.tracks = [];
|
|
92264
92264
|
this.root = null;
|
|
92265
92265
|
}
|
|
92266
|
+
/**
|
|
92267
|
+
* Apply the current animation time to the objects without advancing it, so a
|
|
92268
|
+
* single on-demand render shows the pose (e.g. after {@link setRelativeTime}).
|
|
92269
|
+
*/
|
|
92270
|
+
apply() {
|
|
92271
|
+
this.mixer?.update(0);
|
|
92272
|
+
}
|
|
92273
|
+
/**
|
|
92274
|
+
* Restart the frame-time measurement, so resuming playback after a pause does
|
|
92275
|
+
* not advance the animation by the whole pause.
|
|
92276
|
+
*/
|
|
92277
|
+
resetClock() {
|
|
92278
|
+
this.clock.reset();
|
|
92279
|
+
}
|
|
92266
92280
|
/**
|
|
92267
92281
|
* Update the animation mixer (call each frame when animating).
|
|
92268
92282
|
*/
|
|
@@ -97834,7 +97848,7 @@ class Tools {
|
|
|
97834
97848
|
}
|
|
97835
97849
|
}
|
|
97836
97850
|
|
|
97837
|
-
const version = "5.1.
|
|
97851
|
+
const version = "5.1.2";
|
|
97838
97852
|
|
|
97839
97853
|
/**
|
|
97840
97854
|
* `PickedComponent` over a GPU id-pick result. Drives the shader
|
|
@@ -109429,6 +109443,8 @@ class Viewer {
|
|
|
109429
109443
|
* @param updateMarker - enforce to redraw orientation marker after every ui activity
|
|
109430
109444
|
*/
|
|
109431
109445
|
constructor(display, options, notifyCallback, pinAsPngCallback = null, updateMarker = true) {
|
|
109446
|
+
/** Reasons for continuous rendering; the render loop runs while any is set. */
|
|
109447
|
+
this._loopReasons = new Set();
|
|
109432
109448
|
// Hide-undo stack: each meta-double-click hide pushes the leaf id + its pre-hide
|
|
109433
109449
|
// state; meta-double-click on empty space pops and restores the last one. Lets a
|
|
109434
109450
|
// hidden object be brought back without the tree (e.g. in Studio, where it's hidden).
|
|
@@ -109455,7 +109471,7 @@ class Viewer {
|
|
|
109455
109471
|
this._capOutlineCamera = [];
|
|
109456
109472
|
/** Pending redraw that adds the outline once the camera has settled. */
|
|
109457
109473
|
this._capOutlineSettle = null;
|
|
109458
|
-
/** Whether the attached animation has moved parts (Play
|
|
109474
|
+
/** Whether the attached animation has moved parts (Play or time slider, not stopped since). */
|
|
109459
109475
|
this._animationStarted = false;
|
|
109460
109476
|
// ---------------------------------------------------------------------------
|
|
109461
109477
|
// Render Loop & Scene Updates
|
|
@@ -109864,12 +109880,19 @@ class Viewer {
|
|
|
109864
109880
|
this.clipAction.paused = false;
|
|
109865
109881
|
}
|
|
109866
109882
|
this.clipAction.play();
|
|
109883
|
+
this._setAnimationPlaying(true);
|
|
109867
109884
|
break;
|
|
109868
109885
|
case "pause":
|
|
109869
109886
|
this.clipAction.paused = !this.clipAction.paused;
|
|
109887
|
+
this._setAnimationPlaying(!this.clipAction.paused && this.clipAction.isRunning());
|
|
109870
109888
|
break;
|
|
109871
109889
|
case "stop":
|
|
109872
109890
|
this.clipAction.stop();
|
|
109891
|
+
// stop() restores the parts' original transforms (three.js
|
|
109892
|
+
// AnimationMixer._deactivateAction -> restoreOriginalState), so they are
|
|
109893
|
+
// at their model positions again and points can be copied.
|
|
109894
|
+
this._animationStarted = false;
|
|
109895
|
+
this._setAnimationPlaying(false);
|
|
109873
109896
|
break;
|
|
109874
109897
|
}
|
|
109875
109898
|
};
|
|
@@ -110759,10 +110782,7 @@ class Viewer {
|
|
|
110759
110782
|
return Promise.resolve({ task: taskId, dataUrl: null });
|
|
110760
110783
|
}
|
|
110761
110784
|
// canvas.toBlob can be very slow when animation loop is off!
|
|
110762
|
-
|
|
110763
|
-
if (!animationLoop) {
|
|
110764
|
-
this.toggleAnimationLoop(true);
|
|
110765
|
-
}
|
|
110785
|
+
this.setLoopReason("capture", true);
|
|
110766
110786
|
this.rendered.orientationMarker.setVisible(false);
|
|
110767
110787
|
this.update(true);
|
|
110768
110788
|
return this.display.captureCanvas({
|
|
@@ -110780,10 +110800,8 @@ class Viewer {
|
|
|
110780
110800
|
}
|
|
110781
110801
|
},
|
|
110782
110802
|
onComplete: () => {
|
|
110783
|
-
// Restore
|
|
110784
|
-
|
|
110785
|
-
this.toggleAnimationLoop(false);
|
|
110786
|
-
}
|
|
110803
|
+
// Restore the loop to what the other reasons need
|
|
110804
|
+
this.setLoopReason("capture", false);
|
|
110787
110805
|
this.rendered.orientationMarker.setVisible(true);
|
|
110788
110806
|
this.update(true);
|
|
110789
110807
|
},
|
|
@@ -111181,14 +111199,13 @@ class Viewer {
|
|
|
111181
111199
|
return;
|
|
111182
111200
|
}
|
|
111183
111201
|
logger.debug("Animation initialized");
|
|
111184
|
-
if (!this.hasAnimationLoop) {
|
|
111185
|
-
this.toggleAnimationLoop(true);
|
|
111186
|
-
}
|
|
111187
111202
|
this.state.set("animationMode", label === "E" ? "explode" : "animation");
|
|
111188
111203
|
this._animationStarted = false;
|
|
111189
111204
|
this.clipAction = this.animation.animate(this.rendered.nestedGroup.rootGroup, duration, speed, repeat);
|
|
111190
111205
|
// Reset animation slider to start
|
|
111191
111206
|
this.state.set("animationSliderValue", 0);
|
|
111207
|
+
// Not playing yet: render on demand only (the loop starts with Play).
|
|
111208
|
+
this._setAnimationPlaying(false);
|
|
111192
111209
|
}
|
|
111193
111210
|
/**
|
|
111194
111211
|
* Check whether animation object exists
|
|
@@ -111205,7 +111222,7 @@ class Viewer {
|
|
|
111205
111222
|
}
|
|
111206
111223
|
this.state.set("animationMode", "none");
|
|
111207
111224
|
this._animationStarted = false;
|
|
111208
|
-
this.
|
|
111225
|
+
this.setLoopReason("animation", false);
|
|
111209
111226
|
}
|
|
111210
111227
|
/**
|
|
111211
111228
|
* Set the animation to a specific relative time (0-1).
|
|
@@ -111217,6 +111234,8 @@ class Viewer {
|
|
|
111217
111234
|
this._animationStarted = true;
|
|
111218
111235
|
this.animation.setRelativeTime(fraction);
|
|
111219
111236
|
this.state.set("animationSliderValue", fraction * 1000);
|
|
111237
|
+
// Setting a time pauses the animation: stop the loop and show the new pose.
|
|
111238
|
+
this._setAnimationPlaying(false);
|
|
111220
111239
|
}
|
|
111221
111240
|
/**
|
|
111222
111241
|
* Get the current relative animation time (0-1).
|
|
@@ -111225,6 +111244,44 @@ class Viewer {
|
|
|
111225
111244
|
getRelativeTime() {
|
|
111226
111245
|
return this.animation.getRelativeTime();
|
|
111227
111246
|
}
|
|
111247
|
+
/**
|
|
111248
|
+
* Add or remove a reason for continuous rendering. The render loop runs while at
|
|
111249
|
+
* least one reason is set; otherwise the viewer renders on demand (camera changes
|
|
111250
|
+
* and explicit updates), so an idle viewer costs no CPU/GPU time.
|
|
111251
|
+
* @param reason - why continuous rendering is needed.
|
|
111252
|
+
* @param flag - whether the reason applies.
|
|
111253
|
+
*/
|
|
111254
|
+
setLoopReason(reason, flag) {
|
|
111255
|
+
if (flag) {
|
|
111256
|
+
this._loopReasons.add(reason);
|
|
111257
|
+
}
|
|
111258
|
+
else {
|
|
111259
|
+
this._loopReasons.delete(reason);
|
|
111260
|
+
}
|
|
111261
|
+
const run = this._loopReasons.size > 0;
|
|
111262
|
+
if (run !== this.hasAnimationLoop)
|
|
111263
|
+
this.toggleAnimationLoop(run);
|
|
111264
|
+
}
|
|
111265
|
+
/**
|
|
111266
|
+
* Run the render loop only while the animation plays. When it stops (pause,
|
|
111267
|
+
* stop, slider), render once so the final pose is shown.
|
|
111268
|
+
*/
|
|
111269
|
+
_setAnimationPlaying(playing) {
|
|
111270
|
+
if (playing) {
|
|
111271
|
+
// Resume without jumping ahead by the time spent paused.
|
|
111272
|
+
this.animation.resetClock();
|
|
111273
|
+
}
|
|
111274
|
+
this.setLoopReason("animation", playing);
|
|
111275
|
+
if (!playing && this._rendered !== null) {
|
|
111276
|
+
this.animation.apply();
|
|
111277
|
+
this.update(true, false);
|
|
111278
|
+
}
|
|
111279
|
+
}
|
|
111280
|
+
/**
|
|
111281
|
+
* Start or stop the render loop directly. Prefer {@link setLoopReason}, which keeps
|
|
111282
|
+
* the loop running while any other reason still needs it.
|
|
111283
|
+
* @param flag - whether the render loop should run.
|
|
111284
|
+
*/
|
|
111228
111285
|
toggleAnimationLoop(flag) {
|
|
111229
111286
|
if (flag) {
|
|
111230
111287
|
this.continueAnimation = true;
|
|
@@ -111375,6 +111432,7 @@ class Viewer {
|
|
|
111375
111432
|
// Hide the topo filter (+ detach its shortcuts) for a clean cleared canvas.
|
|
111376
111433
|
this.display.shapeFilterDropDownMenu.show(false);
|
|
111377
111434
|
// stop animation
|
|
111435
|
+
this._loopReasons.clear();
|
|
111378
111436
|
this.hasAnimationLoop = false;
|
|
111379
111437
|
this.continueAnimation = false;
|
|
111380
111438
|
// remove change listener if exists
|
|
@@ -111957,8 +112015,9 @@ class Viewer {
|
|
|
111957
112015
|
* Copy the world-space point under the cursor as `"x, y, z"` to the clipboard and
|
|
111958
112016
|
* send it to the host as a `copiedPoint` notification (for hosts that block the
|
|
111959
112017
|
* browser clipboard). Does nothing while parts may be displaced from their model
|
|
111960
|
-
* positions — explode mode, an animation
|
|
111961
|
-
* z-scale other than 1 — or when no
|
|
112018
|
+
* positions — explode mode, an animation that was played or scrubbed and not
|
|
112019
|
+
* stopped since (Stop puts the parts back), a z-scale other than 1 — or when no
|
|
112020
|
+
* visible component is under the cursor.
|
|
111962
112021
|
* @returns true when a point was copied (the caller then consumes the key event).
|
|
111963
112022
|
*/
|
|
111964
112023
|
copyPointUnderCursor() {
|
|
@@ -114069,7 +114128,7 @@ class Display {
|
|
|
114069
114128
|
if (flag && this.viewer.isStudioActive) {
|
|
114070
114129
|
return;
|
|
114071
114130
|
}
|
|
114072
|
-
this.viewer.
|
|
114131
|
+
this.viewer.setLoopReason("tool", flag);
|
|
114073
114132
|
if (flag) {
|
|
114074
114133
|
// Delegate state mutations to Viewer
|
|
114075
114134
|
this.viewer.activateTool(name, true);
|