@lingbi/studio 0.8.3 → 0.9.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/Application.d.ts +3 -0
- package/ImportProgressCompositor.d.ts +13 -0
- package/StudioToolbarState.d.ts +2 -0
- package/StudioWorkspace.d.ts +5 -0
- package/archive/ArchiveImportWorkerClient.d.ts +3 -1
- package/archive/ArchiveImportWorkerMessage.d.ts +7 -1
- package/archive/ArchiveImportWorkerMessageParser.d.ts +2 -0
- package/archive/ArchiveImportWorkerRuntime.d.ts +3 -0
- package/assets/{ArchiveImportWorkerEntry-Dh4RZo22.js → ArchiveImportWorkerEntry-wkxjE56k.js} +36 -0
- package/index.js +512 -41
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -29202,7 +29202,8 @@ const MINIMUM_FRUSTUM_HEIGHT = 1e-4;
|
|
|
29202
29202
|
const MINIMUM_NEAR = 0.01;
|
|
29203
29203
|
const MINIMUM_ZOOM = 0.01;
|
|
29204
29204
|
const MAXIMUM_ZOOM = 100;
|
|
29205
|
-
const CLIP_MARGIN_RATIO = 0.
|
|
29205
|
+
const CLIP_MARGIN_RATIO = 0.5;
|
|
29206
|
+
const VIEW_MARGIN_RATIO = 1.3;
|
|
29206
29207
|
const WHEEL_ZOOM_SPEED = 15e-4;
|
|
29207
29208
|
var CameraNavigationMode = /* @__PURE__ */ ((CameraNavigationMode2) => {
|
|
29208
29209
|
CameraNavigationMode2[CameraNavigationMode2["Rotate"] = 0] = "Rotate";
|
|
@@ -29716,7 +29717,7 @@ class CameraController {
|
|
|
29716
29717
|
);
|
|
29717
29718
|
const frustumHeight = this.getFullFrustumHeight(safeFrustumHeight);
|
|
29718
29719
|
const depthRange = maximumForward - minimumForward;
|
|
29719
|
-
const clipMargin =
|
|
29720
|
+
const clipMargin = this.createClipMargin(depthRange, frustumHeight);
|
|
29720
29721
|
const distance = Math.max(
|
|
29721
29722
|
this.initialCameraDistance,
|
|
29722
29723
|
-minimumForward + clipMargin * 2,
|
|
@@ -29921,7 +29922,10 @@ class CameraController {
|
|
|
29921
29922
|
maximumDepth = Math.max(maximumDepth, depth);
|
|
29922
29923
|
}
|
|
29923
29924
|
const depthRange = maximumDepth - minimumDepth;
|
|
29924
|
-
const clipMargin =
|
|
29925
|
+
const clipMargin = this.createClipMargin(
|
|
29926
|
+
depthRange,
|
|
29927
|
+
(this.camera.top - this.camera.bottom) / this.camera.zoom
|
|
29928
|
+
);
|
|
29925
29929
|
const minimumVisibleDepth = MINIMUM_NEAR + clipMargin;
|
|
29926
29930
|
if (minimumDepth >= minimumVisibleDepth) {
|
|
29927
29931
|
return;
|
|
@@ -29944,7 +29948,10 @@ class CameraController {
|
|
|
29944
29948
|
maximumDepth = Math.max(maximumDepth, depth);
|
|
29945
29949
|
}
|
|
29946
29950
|
const depthRange = maximumDepth - minimumDepth;
|
|
29947
|
-
const clipMargin =
|
|
29951
|
+
const clipMargin = this.createClipMargin(
|
|
29952
|
+
depthRange,
|
|
29953
|
+
(this.camera.top - this.camera.bottom) / this.camera.zoom
|
|
29954
|
+
);
|
|
29948
29955
|
this.camera.near = Math.max(MINIMUM_NEAR, minimumDepth - clipMargin);
|
|
29949
29956
|
this.camera.far = Math.max(
|
|
29950
29957
|
this.camera.near + MINIMUM_CLIP_RANGE,
|
|
@@ -29984,6 +29991,19 @@ class CameraController {
|
|
|
29984
29991
|
getSafeAspect() {
|
|
29985
29992
|
return this.viewportWidth / this.getSafeViewportHeight();
|
|
29986
29993
|
}
|
|
29994
|
+
/**
|
|
29995
|
+
* Orthographic depth is linear, so generous margins cost nothing. The
|
|
29996
|
+
* model ratio covers scene depth, and the viewport ratio keeps the ground
|
|
29997
|
+
* grid inside the clip window as the camera zooms out.
|
|
29998
|
+
*/
|
|
29999
|
+
createClipMargin(depthRange, frustumHeight) {
|
|
30000
|
+
const aspect2 = this.getSafeAspect();
|
|
30001
|
+
const halfDiagonal = frustumHeight / 2 * Math.sqrt(1 + aspect2 * aspect2);
|
|
30002
|
+
return Math.max(
|
|
30003
|
+
MINIMUM_CLIP_MARGIN,
|
|
30004
|
+
Math.max(depthRange * CLIP_MARGIN_RATIO, halfDiagonal * VIEW_MARGIN_RATIO)
|
|
30005
|
+
);
|
|
30006
|
+
}
|
|
29987
30007
|
getSafeViewportHeight() {
|
|
29988
30008
|
const maximumInset = Math.max(0, this.viewportHeight - 1);
|
|
29989
30009
|
const effectiveInset = Math.min(this.viewportBottomInset, maximumInset);
|
|
@@ -30545,6 +30565,148 @@ class CanvasController {
|
|
|
30545
30565
|
}
|
|
30546
30566
|
}
|
|
30547
30567
|
}
|
|
30568
|
+
const CENTER_LINE_COLOR = 10132122;
|
|
30569
|
+
const CENTER_LINE_EXTRA_WIDTH = "2.0";
|
|
30570
|
+
const FADE_END_RATIO = 1.4;
|
|
30571
|
+
const FADE_START_RATIO = 0.8;
|
|
30572
|
+
const GRID_DIVISIONS = 24;
|
|
30573
|
+
const GRID_LINE_COLOR = 9474192;
|
|
30574
|
+
const GRID_LINE_OPACITY = 1;
|
|
30575
|
+
const GRID_LINE_WIDTH_PIXELS = 2;
|
|
30576
|
+
const GRID_SEPARATION_RATIO = 2e-3;
|
|
30577
|
+
const MINIMUM_ALPHA = "0.01";
|
|
30578
|
+
const QUAD_COVERAGE = 2.1;
|
|
30579
|
+
const VIEW_RATIO = 0.6;
|
|
30580
|
+
const VERTEX_SHADER = (
|
|
30581
|
+
/* glsl */
|
|
30582
|
+
`
|
|
30583
|
+
varying vec2 vUv;
|
|
30584
|
+
|
|
30585
|
+
void main() {
|
|
30586
|
+
vUv = uv;
|
|
30587
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
30588
|
+
}
|
|
30589
|
+
`
|
|
30590
|
+
);
|
|
30591
|
+
const FRAGMENT_SHADER = (
|
|
30592
|
+
/* glsl */
|
|
30593
|
+
`
|
|
30594
|
+
uniform vec3 uCenterColor;
|
|
30595
|
+
uniform float uDivisionCount;
|
|
30596
|
+
uniform float uFadeEnd;
|
|
30597
|
+
uniform float uFadeStart;
|
|
30598
|
+
uniform vec3 uGridColor;
|
|
30599
|
+
uniform float uGridSize;
|
|
30600
|
+
uniform float uLineOpacity;
|
|
30601
|
+
uniform float uLineWidth;
|
|
30602
|
+
varying vec2 vUv;
|
|
30603
|
+
|
|
30604
|
+
void main() {
|
|
30605
|
+
vec2 coord = (vUv - 0.5) * uGridSize;
|
|
30606
|
+
float cellSize = uGridSize / uDivisionCount;
|
|
30607
|
+
vec2 cellCoord = coord / cellSize;
|
|
30608
|
+
vec2 gridDistance = abs(fract(cellCoord - 0.5) - 0.5) / (fwidth(cellCoord) * uLineWidth);
|
|
30609
|
+
float gridLine = 1.0 - min(min(gridDistance.x, gridDistance.y), 1.0);
|
|
30610
|
+
vec2 centerDistance = abs(coord) / (fwidth(coord) * uLineWidth * ${CENTER_LINE_EXTRA_WIDTH});
|
|
30611
|
+
float centerLine = 1.0 - min(min(centerDistance.x, centerDistance.y), 1.0);
|
|
30612
|
+
float lineStrength = max(gridLine, centerLine);
|
|
30613
|
+
vec3 lineColor = mix(uGridColor, uCenterColor, centerLine);
|
|
30614
|
+
float radial = length(coord);
|
|
30615
|
+
float alpha = lineStrength * (1.0 - smoothstep(uFadeStart, uFadeEnd, radial)) * uLineOpacity;
|
|
30616
|
+
|
|
30617
|
+
if (alpha < ${MINIMUM_ALPHA}) {
|
|
30618
|
+
discard;
|
|
30619
|
+
}
|
|
30620
|
+
|
|
30621
|
+
gl_FragColor = vec4(lineColor, alpha);
|
|
30622
|
+
}
|
|
30623
|
+
`
|
|
30624
|
+
);
|
|
30625
|
+
class GroundGrid {
|
|
30626
|
+
material;
|
|
30627
|
+
mesh;
|
|
30628
|
+
anchorCenterX = 0;
|
|
30629
|
+
anchorCenterY = 0;
|
|
30630
|
+
anchorMinZ = 0;
|
|
30631
|
+
anchorSpan = 1;
|
|
30632
|
+
gridUniforms = {
|
|
30633
|
+
uCenterColor: { value: new Color(CENTER_LINE_COLOR) },
|
|
30634
|
+
uDivisionCount: { value: GRID_DIVISIONS },
|
|
30635
|
+
uFadeEnd: { value: FADE_END_RATIO },
|
|
30636
|
+
uFadeStart: { value: FADE_START_RATIO },
|
|
30637
|
+
uGridColor: { value: new Color(GRID_LINE_COLOR) },
|
|
30638
|
+
uGridSize: { value: 1 },
|
|
30639
|
+
uLineOpacity: { value: GRID_LINE_OPACITY },
|
|
30640
|
+
uLineWidth: { value: 1 / GRID_LINE_WIDTH_PIXELS }
|
|
30641
|
+
};
|
|
30642
|
+
constructor() {
|
|
30643
|
+
this.material = new ShaderMaterial({
|
|
30644
|
+
depthWrite: false,
|
|
30645
|
+
fragmentShader: FRAGMENT_SHADER,
|
|
30646
|
+
side: DoubleSide,
|
|
30647
|
+
transparent: true,
|
|
30648
|
+
uniforms: this.gridUniforms,
|
|
30649
|
+
vertexShader: VERTEX_SHADER
|
|
30650
|
+
});
|
|
30651
|
+
this.mesh = new Mesh(new PlaneGeometry(1, 1), this.material);
|
|
30652
|
+
this.mesh.visible = false;
|
|
30653
|
+
}
|
|
30654
|
+
getHelper() {
|
|
30655
|
+
return this.mesh;
|
|
30656
|
+
}
|
|
30657
|
+
attach(scene) {
|
|
30658
|
+
scene.add(this.mesh);
|
|
30659
|
+
}
|
|
30660
|
+
updateFromBounds(bounds) {
|
|
30661
|
+
this.anchorCenterX = (bounds.min.x + bounds.max.x) / 2;
|
|
30662
|
+
this.anchorCenterY = (bounds.min.y + bounds.max.y) / 2;
|
|
30663
|
+
this.anchorMinZ = bounds.min.z;
|
|
30664
|
+
this.anchorSpan = Math.max(bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y);
|
|
30665
|
+
this.applyLayout(this.anchorSpan * FADE_END_RATIO);
|
|
30666
|
+
this.mesh.visible = true;
|
|
30667
|
+
}
|
|
30668
|
+
/**
|
|
30669
|
+
* Grows the grid when the viewport zooms out beyond the model-anchored
|
|
30670
|
+
* radius, so the ground keeps covering most of the visible area instead
|
|
30671
|
+
* of shrinking into a patch around the model.
|
|
30672
|
+
*/
|
|
30673
|
+
updateForViewport(halfDiagonal) {
|
|
30674
|
+
if (!this.mesh.visible) {
|
|
30675
|
+
return;
|
|
30676
|
+
}
|
|
30677
|
+
const viewportRadius = halfDiagonal * VIEW_RATIO;
|
|
30678
|
+
const fadeRadius = Math.max(this.anchorSpan * FADE_END_RATIO, viewportRadius);
|
|
30679
|
+
this.applyLayout(fadeRadius);
|
|
30680
|
+
}
|
|
30681
|
+
applyLayout(fadeRadius) {
|
|
30682
|
+
const size = fadeRadius * QUAD_COVERAGE;
|
|
30683
|
+
this.gridUniforms.uGridSize.value = size;
|
|
30684
|
+
this.gridUniforms.uFadeStart.value = fadeRadius * (FADE_START_RATIO / FADE_END_RATIO);
|
|
30685
|
+
this.gridUniforms.uFadeEnd.value = fadeRadius;
|
|
30686
|
+
this.mesh.scale.set(size, size, 1);
|
|
30687
|
+
this.mesh.position.set(
|
|
30688
|
+
this.anchorCenterX,
|
|
30689
|
+
this.anchorCenterY,
|
|
30690
|
+
this.anchorMinZ - this.anchorSpan * GRID_SEPARATION_RATIO
|
|
30691
|
+
);
|
|
30692
|
+
}
|
|
30693
|
+
/**
|
|
30694
|
+
* Keeps the drawn line width at the intended CSS pixel size on high-DPI
|
|
30695
|
+
* outputs: fwidth-based lines live in framebuffer pixels, so the inverse
|
|
30696
|
+
* width must scale with the device pixel ratio.
|
|
30697
|
+
*/
|
|
30698
|
+
setPixelRatio(pixelRatio) {
|
|
30699
|
+
this.gridUniforms.uLineWidth.value = 1 / (GRID_LINE_WIDTH_PIXELS * pixelRatio);
|
|
30700
|
+
}
|
|
30701
|
+
hide() {
|
|
30702
|
+
this.mesh.visible = false;
|
|
30703
|
+
}
|
|
30704
|
+
dispose() {
|
|
30705
|
+
this.mesh.removeFromParent();
|
|
30706
|
+
this.mesh.geometry.dispose();
|
|
30707
|
+
this.material.dispose();
|
|
30708
|
+
}
|
|
30709
|
+
}
|
|
30548
30710
|
class ConsoleImportPerformanceLogSink {
|
|
30549
30711
|
categoryByStageName = {
|
|
30550
30712
|
"boolean-source-snapshot": "scene",
|
|
@@ -30840,6 +31002,51 @@ class ImportPerformanceTracer {
|
|
|
30840
31002
|
return trace;
|
|
30841
31003
|
}
|
|
30842
31004
|
}
|
|
31005
|
+
const COMMITTED_PERCENT = 100;
|
|
31006
|
+
const ROLE_SPAN_TOTAL = 0.96;
|
|
31007
|
+
class ImportProgressTracker {
|
|
31008
|
+
listener;
|
|
31009
|
+
percent = 0;
|
|
31010
|
+
rolePositions = /* @__PURE__ */ new Map();
|
|
31011
|
+
roleSpans;
|
|
31012
|
+
constructor(roles, listener) {
|
|
31013
|
+
this.listener = listener;
|
|
31014
|
+
const roleSpans = /* @__PURE__ */ new Map();
|
|
31015
|
+
const spanPerRole = ROLE_SPAN_TOTAL / roles.length;
|
|
31016
|
+
for (const [roleIndex, role] of roles.entries()) {
|
|
31017
|
+
roleSpans.set(role, { span: spanPerRole, start: spanPerRole * roleIndex });
|
|
31018
|
+
}
|
|
31019
|
+
this.roleSpans = roleSpans;
|
|
31020
|
+
}
|
|
31021
|
+
completeRole(role) {
|
|
31022
|
+
this.setRolePosition(role, 1);
|
|
31023
|
+
}
|
|
31024
|
+
completeScene() {
|
|
31025
|
+
this.setPercent(COMMITTED_PERCENT);
|
|
31026
|
+
}
|
|
31027
|
+
getPercent() {
|
|
31028
|
+
return this.percent;
|
|
31029
|
+
}
|
|
31030
|
+
setRolePosition(role, position) {
|
|
31031
|
+
const roleSpan = this.roleSpans.get(role);
|
|
31032
|
+
if (roleSpan === void 0) {
|
|
31033
|
+
return;
|
|
31034
|
+
}
|
|
31035
|
+
const nextPosition = Math.max(this.rolePositions.get(role) ?? 0, Math.min(1, position));
|
|
31036
|
+
this.rolePositions.set(role, nextPosition);
|
|
31037
|
+
this.setPercent(
|
|
31038
|
+
Math.floor((roleSpan.start + roleSpan.span * nextPosition) * COMMITTED_PERCENT)
|
|
31039
|
+
);
|
|
31040
|
+
}
|
|
31041
|
+
setPercent(nextPercent) {
|
|
31042
|
+
const percent = Math.max(this.percent, Math.min(COMMITTED_PERCENT, nextPercent));
|
|
31043
|
+
if (percent === this.percent) {
|
|
31044
|
+
return;
|
|
31045
|
+
}
|
|
31046
|
+
this.percent = percent;
|
|
31047
|
+
this.listener?.(this);
|
|
31048
|
+
}
|
|
31049
|
+
}
|
|
30843
31050
|
const LOCAL_RESOURCE_BASE_URL = "https://renderer-local.invalid/";
|
|
30844
31051
|
class ObjResourceList {
|
|
30845
31052
|
mtlUrls;
|
|
@@ -32022,12 +32229,15 @@ class TextureLoadMonitor {
|
|
|
32022
32229
|
encounteredError = false;
|
|
32023
32230
|
finishedScheduling = false;
|
|
32024
32231
|
manager;
|
|
32232
|
+
onTextureSettled;
|
|
32025
32233
|
originalTextureLoader;
|
|
32026
32234
|
pendingRequests = 0;
|
|
32235
|
+
scheduledTextureCount = 0;
|
|
32027
32236
|
settled = false;
|
|
32028
32237
|
textures = /* @__PURE__ */ new Set();
|
|
32029
|
-
constructor(manager, creator) {
|
|
32238
|
+
constructor(manager, creator, onTextureSettled) {
|
|
32030
32239
|
this.manager = manager;
|
|
32240
|
+
this.onTextureSettled = onTextureSettled;
|
|
32031
32241
|
this.completionPromise = new Promise(
|
|
32032
32242
|
this.captureCompletionResolver.bind(this)
|
|
32033
32243
|
);
|
|
@@ -32038,6 +32248,9 @@ class TextureLoadMonitor {
|
|
|
32038
32248
|
this.finishedScheduling = true;
|
|
32039
32249
|
this.resolveIfSettled();
|
|
32040
32250
|
}
|
|
32251
|
+
getScheduledTextureCount() {
|
|
32252
|
+
return this.scheduledTextureCount;
|
|
32253
|
+
}
|
|
32041
32254
|
getTextures() {
|
|
32042
32255
|
return [...this.textures];
|
|
32043
32256
|
}
|
|
@@ -32065,14 +32278,17 @@ class TextureLoadMonitor {
|
|
|
32065
32278
|
handleTextureError() {
|
|
32066
32279
|
this.encounteredError = true;
|
|
32067
32280
|
this.pendingRequests -= 1;
|
|
32281
|
+
this.onTextureSettled?.();
|
|
32068
32282
|
this.resolveIfSettled();
|
|
32069
32283
|
}
|
|
32070
32284
|
handleTextureLoad() {
|
|
32071
32285
|
this.pendingRequests -= 1;
|
|
32286
|
+
this.onTextureSettled?.();
|
|
32072
32287
|
this.resolveIfSettled();
|
|
32073
32288
|
}
|
|
32074
32289
|
loadTexture(url, mapping) {
|
|
32075
32290
|
this.pendingRequests += 1;
|
|
32291
|
+
this.scheduledTextureCount += 1;
|
|
32076
32292
|
try {
|
|
32077
32293
|
const texture = this.originalTextureLoader(
|
|
32078
32294
|
url,
|
|
@@ -32108,15 +32324,16 @@ class ObjLoader {
|
|
|
32108
32324
|
constructor(parser = new OBJLoader()) {
|
|
32109
32325
|
this.parser = parser;
|
|
32110
32326
|
}
|
|
32111
|
-
async loadResources(resources, signal, performanceTrace, role) {
|
|
32327
|
+
async loadResources(resources, signal, performanceTrace, role, progress) {
|
|
32112
32328
|
return this.loadInternal(
|
|
32113
32329
|
resources,
|
|
32114
32330
|
signal,
|
|
32115
32331
|
performanceTrace ?? ImportPerformanceTrace.createDisabled(),
|
|
32116
|
-
role ?? "stone"
|
|
32332
|
+
role ?? "stone",
|
|
32333
|
+
progress
|
|
32117
32334
|
);
|
|
32118
32335
|
}
|
|
32119
|
-
async loadInternal(resources, signal, performanceTrace, role) {
|
|
32336
|
+
async loadInternal(resources, signal, performanceTrace, role, progress) {
|
|
32120
32337
|
if (this.hasEmptyRequiredUrl(resources)) {
|
|
32121
32338
|
return {
|
|
32122
32339
|
code: ObjImportFailureCode$1.EmptySource,
|
|
@@ -32130,6 +32347,7 @@ class ObjLoader {
|
|
|
32130
32347
|
const objFetchStage = performanceTrace.startStage("obj-fetch", role);
|
|
32131
32348
|
const objSource = await this.loadText(resources.objUrl, signal);
|
|
32132
32349
|
performanceTrace.endStage(objFetchStage, "success");
|
|
32350
|
+
progress?.markModelFetched();
|
|
32133
32351
|
this.assertNotCancelled(signal);
|
|
32134
32352
|
const materialScanStage = performanceTrace.startStage("obj-material-scan", role);
|
|
32135
32353
|
const materialReferences = this.getMaterialLibraryReferences(objSource);
|
|
@@ -32149,9 +32367,11 @@ class ObjLoader {
|
|
|
32149
32367
|
materialContext = await this.loadMaterialContext(
|
|
32150
32368
|
materialUrls,
|
|
32151
32369
|
resources,
|
|
32152
|
-
signal
|
|
32370
|
+
signal,
|
|
32371
|
+
progress
|
|
32153
32372
|
);
|
|
32154
32373
|
performanceTrace.endStage(materialLoadStage, "success");
|
|
32374
|
+
progress?.markMaterialsResolved(this.getScheduledTextureCount(materialContext));
|
|
32155
32375
|
} catch {
|
|
32156
32376
|
performanceTrace.endStage(
|
|
32157
32377
|
materialLoadStage,
|
|
@@ -32175,6 +32395,7 @@ class ObjLoader {
|
|
|
32175
32395
|
resources.upAxis
|
|
32176
32396
|
);
|
|
32177
32397
|
performanceTrace.endStage(modelCreateStage, "success");
|
|
32398
|
+
progress?.markModelParsed();
|
|
32178
32399
|
if (!this.hasRenderablePrimitive(group) || !model.hasFiniteBounds()) {
|
|
32179
32400
|
model.dispose();
|
|
32180
32401
|
return {
|
|
@@ -32335,6 +32556,13 @@ class ObjLoader {
|
|
|
32335
32556
|
}
|
|
32336
32557
|
return [...textures];
|
|
32337
32558
|
}
|
|
32559
|
+
getScheduledTextureCount(context) {
|
|
32560
|
+
let scheduledTextureCount = 0;
|
|
32561
|
+
for (const monitor of context.monitors) {
|
|
32562
|
+
scheduledTextureCount += monitor.getScheduledTextureCount();
|
|
32563
|
+
}
|
|
32564
|
+
return scheduledTextureCount;
|
|
32565
|
+
}
|
|
32338
32566
|
getObjectTree(root) {
|
|
32339
32567
|
const objectTree = [root];
|
|
32340
32568
|
for (const object of objectTree) {
|
|
@@ -32451,11 +32679,11 @@ class ObjLoader {
|
|
|
32451
32679
|
isPoints(object) {
|
|
32452
32680
|
return object instanceof Points;
|
|
32453
32681
|
}
|
|
32454
|
-
async loadMaterialContext(mtlUrls, resources, signal) {
|
|
32682
|
+
async loadMaterialContext(mtlUrls, resources, signal, progress) {
|
|
32455
32683
|
const libraries = [];
|
|
32456
32684
|
try {
|
|
32457
32685
|
for (const mtlUrl of mtlUrls) {
|
|
32458
|
-
libraries.push(await this.loadMaterialLibrary(mtlUrl, resources, signal));
|
|
32686
|
+
libraries.push(await this.loadMaterialLibrary(mtlUrl, resources, signal, progress));
|
|
32459
32687
|
}
|
|
32460
32688
|
return this.createMaterialContext(libraries);
|
|
32461
32689
|
} catch (error2) {
|
|
@@ -32463,7 +32691,7 @@ class ObjLoader {
|
|
|
32463
32691
|
throw error2;
|
|
32464
32692
|
}
|
|
32465
32693
|
}
|
|
32466
|
-
async loadMaterialLibrary(mtlUrl, resources, signal) {
|
|
32694
|
+
async loadMaterialLibrary(mtlUrl, resources, signal, progress) {
|
|
32467
32695
|
const materialSource = await this.loadText(mtlUrl, signal);
|
|
32468
32696
|
this.assertNotCancelled(signal);
|
|
32469
32697
|
const materialBaseUrl = this.getResourceDirectoryUrl(resources, mtlUrl);
|
|
@@ -32474,7 +32702,11 @@ class ObjLoader {
|
|
|
32474
32702
|
side: DoubleSide
|
|
32475
32703
|
});
|
|
32476
32704
|
const creator = materialLoader.parse(materialSource, materialBaseUrl);
|
|
32477
|
-
const monitor = new TextureLoadMonitor(
|
|
32705
|
+
const monitor = new TextureLoadMonitor(
|
|
32706
|
+
manager,
|
|
32707
|
+
creator,
|
|
32708
|
+
progress === void 0 ? void 0 : progress.markTextureSettled.bind(progress)
|
|
32709
|
+
);
|
|
32478
32710
|
try {
|
|
32479
32711
|
const pbrMaterialReferences = this.parsePbrMaterialReferences(materialSource);
|
|
32480
32712
|
this.assertMaterialTextures(resources, materialSource, materialBaseUrl, creator);
|
|
@@ -33450,7 +33682,7 @@ class PlyLoader {
|
|
|
33450
33682
|
this.parser = parser;
|
|
33451
33683
|
this.textureLoader = textureLoader;
|
|
33452
33684
|
}
|
|
33453
|
-
async load(resources, signal) {
|
|
33685
|
+
async load(resources, signal, progress) {
|
|
33454
33686
|
if (signal.aborted) {
|
|
33455
33687
|
return {
|
|
33456
33688
|
code: ObjImportFailureCode$1.Cancelled,
|
|
@@ -33461,6 +33693,7 @@ class PlyLoader {
|
|
|
33461
33693
|
if (!(source instanceof ArrayBuffer)) {
|
|
33462
33694
|
return source;
|
|
33463
33695
|
}
|
|
33696
|
+
progress?.markModelFetched();
|
|
33464
33697
|
let geometry;
|
|
33465
33698
|
let metadata;
|
|
33466
33699
|
try {
|
|
@@ -33486,7 +33719,14 @@ class PlyLoader {
|
|
|
33486
33719
|
success: false
|
|
33487
33720
|
};
|
|
33488
33721
|
}
|
|
33489
|
-
|
|
33722
|
+
progress?.markModelParsed();
|
|
33723
|
+
const modelResult = metadata.hasFaces ? await this.createMeshModel(
|
|
33724
|
+
geometry,
|
|
33725
|
+
metadata.textureReference,
|
|
33726
|
+
resources,
|
|
33727
|
+
signal,
|
|
33728
|
+
progress
|
|
33729
|
+
) : this.createPointsModel(geometry, resources);
|
|
33490
33730
|
if ("success" in modelResult) {
|
|
33491
33731
|
return modelResult;
|
|
33492
33732
|
}
|
|
@@ -33514,13 +33754,14 @@ class PlyLoader {
|
|
|
33514
33754
|
vertexColors: geometry.hasAttribute("color")
|
|
33515
33755
|
});
|
|
33516
33756
|
}
|
|
33517
|
-
async createMeshModel(geometry, textureReference, resources, signal) {
|
|
33757
|
+
async createMeshModel(geometry, textureReference, resources, signal, progress) {
|
|
33518
33758
|
if (!geometry.hasAttribute("normal")) {
|
|
33519
33759
|
geometry.computeVertexNormals();
|
|
33520
33760
|
}
|
|
33521
33761
|
const warnings = [];
|
|
33522
33762
|
let texture;
|
|
33523
33763
|
if (textureReference !== void 0 && geometry.hasAttribute("uv")) {
|
|
33764
|
+
progress?.markMaterialsResolved(1);
|
|
33524
33765
|
const textureResult = await this.textureLoader.load(
|
|
33525
33766
|
resources.resolveTextureUrl(textureReference),
|
|
33526
33767
|
signal
|
|
@@ -33532,6 +33773,7 @@ class PlyLoader {
|
|
|
33532
33773
|
success: false
|
|
33533
33774
|
};
|
|
33534
33775
|
}
|
|
33776
|
+
progress?.markTextureSettled();
|
|
33535
33777
|
if (textureResult.outcome === "succeeded") {
|
|
33536
33778
|
texture = textureResult.texture;
|
|
33537
33779
|
} else {
|
|
@@ -33617,6 +33859,57 @@ class PlyLoader {
|
|
|
33617
33859
|
return value;
|
|
33618
33860
|
}
|
|
33619
33861
|
}
|
|
33862
|
+
const OBJ_MODEL_LOAD_PROGRESS_PROFILE = {
|
|
33863
|
+
fetchedPosition: 0.2,
|
|
33864
|
+
materialsPosition: 0.3,
|
|
33865
|
+
parsedPosition: 0.95,
|
|
33866
|
+
textureCeiling: 0.99
|
|
33867
|
+
};
|
|
33868
|
+
const PLY_MODEL_LOAD_PROGRESS_PROFILE = {
|
|
33869
|
+
fetchedPosition: 0.4,
|
|
33870
|
+
materialsPosition: 0.85,
|
|
33871
|
+
parsedPosition: 0.85,
|
|
33872
|
+
textureCeiling: 0.99
|
|
33873
|
+
};
|
|
33874
|
+
class RoleImportProgressReporter {
|
|
33875
|
+
profile;
|
|
33876
|
+
role;
|
|
33877
|
+
textureSettled = 0;
|
|
33878
|
+
textureTotal;
|
|
33879
|
+
tracker;
|
|
33880
|
+
constructor(tracker, role, profile) {
|
|
33881
|
+
this.profile = profile;
|
|
33882
|
+
this.role = role;
|
|
33883
|
+
this.tracker = tracker;
|
|
33884
|
+
}
|
|
33885
|
+
markMaterialsResolved(textureTotal) {
|
|
33886
|
+
this.textureTotal = textureTotal;
|
|
33887
|
+
this.tracker.setRolePosition(this.role, this.profile.materialsPosition);
|
|
33888
|
+
this.reportTexturePosition();
|
|
33889
|
+
}
|
|
33890
|
+
markModelFetched() {
|
|
33891
|
+
this.tracker.setRolePosition(this.role, this.profile.fetchedPosition);
|
|
33892
|
+
}
|
|
33893
|
+
markModelParsed() {
|
|
33894
|
+
this.tracker.setRolePosition(this.role, this.profile.parsedPosition);
|
|
33895
|
+
}
|
|
33896
|
+
markTextureSettled() {
|
|
33897
|
+
this.textureSettled += 1;
|
|
33898
|
+
this.reportTexturePosition();
|
|
33899
|
+
}
|
|
33900
|
+
reportTexturePosition() {
|
|
33901
|
+
const textureTotal = this.textureTotal;
|
|
33902
|
+
if (textureTotal === void 0 || textureTotal <= 0 || this.textureSettled === 0) {
|
|
33903
|
+
return;
|
|
33904
|
+
}
|
|
33905
|
+
const textureSpan = this.profile.textureCeiling - this.profile.parsedPosition;
|
|
33906
|
+
const settledShare = Math.min(this.textureSettled, textureTotal) / textureTotal;
|
|
33907
|
+
this.tracker.setRolePosition(
|
|
33908
|
+
this.role,
|
|
33909
|
+
this.profile.parsedPosition + textureSpan * settledShare
|
|
33910
|
+
);
|
|
33911
|
+
}
|
|
33912
|
+
}
|
|
33620
33913
|
class SimulationSnapshotFactory {
|
|
33621
33914
|
constructor(scheduler) {
|
|
33622
33915
|
this.scheduler = scheduler;
|
|
@@ -35922,6 +36215,7 @@ class Renderer {
|
|
|
35922
36215
|
fillLight;
|
|
35923
36216
|
frameHandle;
|
|
35924
36217
|
gizmoController;
|
|
36218
|
+
groundGrid;
|
|
35925
36219
|
hemisphereLight;
|
|
35926
36220
|
pendingFirstFramePerformance;
|
|
35927
36221
|
importPerformanceTracer = new ImportPerformanceTracer();
|
|
@@ -35959,6 +36253,7 @@ class Renderer {
|
|
|
35959
36253
|
let contextRestoreListenerAttached = false;
|
|
35960
36254
|
let controller;
|
|
35961
36255
|
let gizmoController;
|
|
36256
|
+
let groundGrid;
|
|
35962
36257
|
let resizeObserver;
|
|
35963
36258
|
let viewCube;
|
|
35964
36259
|
this.canvas = canvas;
|
|
@@ -35991,6 +36286,9 @@ class Renderer {
|
|
|
35991
36286
|
);
|
|
35992
36287
|
this.gizmoController = gizmoController;
|
|
35993
36288
|
this.scene.add(gizmoController.getHelper());
|
|
36289
|
+
groundGrid = new GroundGrid();
|
|
36290
|
+
this.groundGrid = groundGrid;
|
|
36291
|
+
groundGrid.attach(this.scene);
|
|
35994
36292
|
canvasController = new CanvasController(
|
|
35995
36293
|
canvas,
|
|
35996
36294
|
viewCube,
|
|
@@ -36044,9 +36342,13 @@ class Renderer {
|
|
|
36044
36342
|
viewCube?.dispose();
|
|
36045
36343
|
} finally {
|
|
36046
36344
|
try {
|
|
36047
|
-
|
|
36345
|
+
groundGrid?.dispose();
|
|
36048
36346
|
} finally {
|
|
36049
|
-
|
|
36347
|
+
try {
|
|
36348
|
+
controller?.dispose();
|
|
36349
|
+
} finally {
|
|
36350
|
+
renderer.dispose();
|
|
36351
|
+
}
|
|
36050
36352
|
}
|
|
36051
36353
|
}
|
|
36052
36354
|
}
|
|
@@ -36093,25 +36395,29 @@ class Renderer {
|
|
|
36093
36395
|
this.viewCube.dispose();
|
|
36094
36396
|
} finally {
|
|
36095
36397
|
try {
|
|
36096
|
-
this.
|
|
36398
|
+
this.groundGrid.dispose();
|
|
36097
36399
|
} finally {
|
|
36098
36400
|
try {
|
|
36099
|
-
this.
|
|
36401
|
+
this.releaseActiveModels();
|
|
36100
36402
|
} finally {
|
|
36101
36403
|
try {
|
|
36102
|
-
this.
|
|
36103
|
-
"webglcontextrestored",
|
|
36104
|
-
this.contextRestoreListener
|
|
36105
|
-
);
|
|
36404
|
+
this.resizeObserver.disconnect();
|
|
36106
36405
|
} finally {
|
|
36107
36406
|
try {
|
|
36108
36407
|
this.canvas.removeEventListener(
|
|
36109
|
-
"
|
|
36110
|
-
this.
|
|
36408
|
+
"webglcontextrestored",
|
|
36409
|
+
this.contextRestoreListener
|
|
36111
36410
|
);
|
|
36112
36411
|
} finally {
|
|
36113
|
-
|
|
36114
|
-
|
|
36412
|
+
try {
|
|
36413
|
+
this.canvas.removeEventListener(
|
|
36414
|
+
"webglcontextlost",
|
|
36415
|
+
this.contextLossListener
|
|
36416
|
+
);
|
|
36417
|
+
} finally {
|
|
36418
|
+
this.renderer.forceContextLoss();
|
|
36419
|
+
this.renderer.dispose();
|
|
36420
|
+
}
|
|
36115
36421
|
}
|
|
36116
36422
|
}
|
|
36117
36423
|
}
|
|
@@ -36149,7 +36455,10 @@ class Renderer {
|
|
|
36149
36455
|
stone: new ModelResourceList(source.stone.fileUrls, source.stone.upAxis)
|
|
36150
36456
|
};
|
|
36151
36457
|
return this.completeSceneImportFromResources(
|
|
36152
|
-
this.startImportSession(
|
|
36458
|
+
this.startImportSession(
|
|
36459
|
+
performanceTrace,
|
|
36460
|
+
this.createImportProgressTracker(resources)
|
|
36461
|
+
),
|
|
36153
36462
|
resources
|
|
36154
36463
|
);
|
|
36155
36464
|
} catch {
|
|
@@ -36191,7 +36500,10 @@ class Renderer {
|
|
|
36191
36500
|
stone: new ModelResourceList(source.stone.files, source.stone.upAxis)
|
|
36192
36501
|
};
|
|
36193
36502
|
return this.completeSceneImportFromResources(
|
|
36194
|
-
this.startImportSession(
|
|
36503
|
+
this.startImportSession(
|
|
36504
|
+
performanceTrace,
|
|
36505
|
+
this.createImportProgressTracker(resources)
|
|
36506
|
+
),
|
|
36195
36507
|
resources
|
|
36196
36508
|
);
|
|
36197
36509
|
} catch {
|
|
@@ -36238,6 +36550,7 @@ class Renderer {
|
|
|
36238
36550
|
available: this.activeStoneModel !== void 0,
|
|
36239
36551
|
contextLost: this.contextLost,
|
|
36240
36552
|
importInProgress: this.activeImport !== void 0,
|
|
36553
|
+
...this.activeImport === void 0 ? {} : { importProgress: this.activeImport.progressTracker.getPercent() },
|
|
36241
36554
|
interactionInProgress,
|
|
36242
36555
|
revision: this.sceneRevision,
|
|
36243
36556
|
resourceRevision: this.sceneResourceRevision
|
|
@@ -36700,12 +37013,22 @@ class Renderer {
|
|
|
36700
37013
|
let result;
|
|
36701
37014
|
try {
|
|
36702
37015
|
try {
|
|
37016
|
+
const progress = new RoleImportProgressReporter(
|
|
37017
|
+
session.progressTracker,
|
|
37018
|
+
role,
|
|
37019
|
+
source.resources instanceof ObjResourceList ? OBJ_MODEL_LOAD_PROGRESS_PROFILE : PLY_MODEL_LOAD_PROGRESS_PROFILE
|
|
37020
|
+
);
|
|
36703
37021
|
result = source.resources instanceof ObjResourceList ? await this.modelLoader.loadResources(
|
|
36704
37022
|
source.resources,
|
|
36705
37023
|
session.controller.signal,
|
|
36706
37024
|
session.performanceTrace,
|
|
36707
|
-
role
|
|
36708
|
-
|
|
37025
|
+
role,
|
|
37026
|
+
progress
|
|
37027
|
+
) : await this.plyLoader.load(
|
|
37028
|
+
source.resources,
|
|
37029
|
+
session.controller.signal,
|
|
37030
|
+
progress
|
|
37031
|
+
);
|
|
36709
37032
|
} catch {
|
|
36710
37033
|
return this.completeUnexpectedImportFailure(session);
|
|
36711
37034
|
}
|
|
@@ -36750,6 +37073,7 @@ class Renderer {
|
|
|
36750
37073
|
};
|
|
36751
37074
|
}
|
|
36752
37075
|
loadStatus = "success";
|
|
37076
|
+
session.progressTracker.completeRole(role);
|
|
36753
37077
|
return {
|
|
36754
37078
|
model: result.model,
|
|
36755
37079
|
warnings: result.warnings ?? []
|
|
@@ -36837,6 +37161,7 @@ class Renderer {
|
|
|
36837
37161
|
this.booleanEditSessionActive = false;
|
|
36838
37162
|
this.activeBooleanOperationSessionToken = void 0;
|
|
36839
37163
|
this.abortEditingState();
|
|
37164
|
+
this.refreshGroundGrid([stone, candidate]);
|
|
36840
37165
|
} catch {
|
|
36841
37166
|
this.activeBaseModel = previousBase;
|
|
36842
37167
|
(candidate.transformRoot ?? candidate.object).removeFromParent();
|
|
@@ -37153,6 +37478,7 @@ class Renderer {
|
|
|
37153
37478
|
...this.collectPresentModels(this.activeStoneModel, this.activeBaseModel)
|
|
37154
37479
|
];
|
|
37155
37480
|
this.gizmoController.setActiveScene({ base: void 0, stone: void 0 });
|
|
37481
|
+
this.groundGrid.hide();
|
|
37156
37482
|
this.transformedSceneBoundsDirty = false;
|
|
37157
37483
|
this.activeStoneModel = void 0;
|
|
37158
37484
|
this.activeBaseModel = void 0;
|
|
@@ -37201,6 +37527,18 @@ class Renderer {
|
|
|
37201
37527
|
this.gizmoController.setModelVisibility("stone", this.modelVisibility.stoneVisible);
|
|
37202
37528
|
this.gizmoController.setModelVisibility("base", this.modelVisibility.baseVisible);
|
|
37203
37529
|
}
|
|
37530
|
+
/**
|
|
37531
|
+
* Retargets the ground grid from the present models. The grid anchors to
|
|
37532
|
+
* models that are merely hidden as well, so toggling base visibility never
|
|
37533
|
+
* moves the ground plane; only a committed paired scene shows it.
|
|
37534
|
+
*/
|
|
37535
|
+
refreshGroundGrid(models) {
|
|
37536
|
+
if (models.length < 2) {
|
|
37537
|
+
this.groundGrid.hide();
|
|
37538
|
+
return;
|
|
37539
|
+
}
|
|
37540
|
+
this.groundGrid.updateFromBounds(this.mergeBounds(models));
|
|
37541
|
+
}
|
|
37204
37542
|
applyModelVisibility() {
|
|
37205
37543
|
const stoneRoot = this.activeStoneModel?.transformRoot ?? this.activeStoneModel?.object;
|
|
37206
37544
|
const baseRoot = this.activeBaseModel?.transformRoot ?? this.activeBaseModel?.object;
|
|
@@ -37249,6 +37587,7 @@ class Renderer {
|
|
|
37249
37587
|
}
|
|
37250
37588
|
renderScene(includeViewCube = true) {
|
|
37251
37589
|
this.syncTransformedSceneBounds();
|
|
37590
|
+
this.syncGroundGridForCamera();
|
|
37252
37591
|
this.gizmoController.updateForRender();
|
|
37253
37592
|
if (includeViewCube) {
|
|
37254
37593
|
this.viewCube.update(this.camera);
|
|
@@ -37258,6 +37597,17 @@ class Renderer {
|
|
|
37258
37597
|
this.renderViewCube();
|
|
37259
37598
|
}
|
|
37260
37599
|
}
|
|
37600
|
+
/**
|
|
37601
|
+
* Keeps the ground grid covering most of the visible area as the camera
|
|
37602
|
+
* zooms. Runs per rendered frame; updating only touches uniforms and the
|
|
37603
|
+
* mesh transform, so it stays allocation-free.
|
|
37604
|
+
*/
|
|
37605
|
+
syncGroundGridForCamera() {
|
|
37606
|
+
const frustumHeight = (this.camera.top - this.camera.bottom) / this.camera.zoom;
|
|
37607
|
+
const frustumWidth = (this.camera.right - this.camera.left) / (this.camera.top - this.camera.bottom) * frustumHeight;
|
|
37608
|
+
const halfDiagonal = Math.sqrt(frustumHeight * frustumHeight + frustumWidth * frustumWidth) / 2;
|
|
37609
|
+
this.groundGrid.updateForViewport(halfDiagonal);
|
|
37610
|
+
}
|
|
37261
37611
|
renderViewCube() {
|
|
37262
37612
|
const viewport = this.viewCube.getViewport();
|
|
37263
37613
|
const previousAutoClear = this.renderer.autoClear;
|
|
@@ -37296,6 +37646,9 @@ class Renderer {
|
|
|
37296
37646
|
}
|
|
37297
37647
|
}
|
|
37298
37648
|
this.controller.syncTransformedBounds(this.mergeBounds(models));
|
|
37649
|
+
this.refreshGroundGrid(
|
|
37650
|
+
this.collectPresentModels(this.activeStoneModel, this.activeBaseModel)
|
|
37651
|
+
);
|
|
37299
37652
|
}
|
|
37300
37653
|
/**
|
|
37301
37654
|
* Atomically replaces the committed active scene. New model references are
|
|
@@ -37370,6 +37723,7 @@ class Renderer {
|
|
|
37370
37723
|
};
|
|
37371
37724
|
this.gizmoController.setActiveScene(activeScene);
|
|
37372
37725
|
this.applyGizmoVisibility();
|
|
37726
|
+
this.refreshGroundGrid(candidateModels);
|
|
37373
37727
|
this.sceneRevision += 1;
|
|
37374
37728
|
this.sceneResourceRevision = this.sceneRevision;
|
|
37375
37729
|
this.pendingFirstFramePerformance = {
|
|
@@ -37379,6 +37733,7 @@ class Renderer {
|
|
|
37379
37733
|
};
|
|
37380
37734
|
session.performanceTrace.markStage("import-promise-resolved", "scene");
|
|
37381
37735
|
session.performanceTrace.endStage(sceneCommitStage, "success");
|
|
37736
|
+
session.progressTracker.completeScene();
|
|
37382
37737
|
this.finishImportSession(session);
|
|
37383
37738
|
this.releasePair(previousStone, previousBase);
|
|
37384
37739
|
this.requestRender();
|
|
@@ -37502,6 +37857,13 @@ class Renderer {
|
|
|
37502
37857
|
this.notifyWorkspaceState();
|
|
37503
37858
|
}
|
|
37504
37859
|
}
|
|
37860
|
+
handleImportProgressChanged(_source) {
|
|
37861
|
+
this.notifyWorkspaceState();
|
|
37862
|
+
}
|
|
37863
|
+
createImportProgressTracker(resources) {
|
|
37864
|
+
const roles = resources.base === void 0 ? ["stone"] : ["stone", "base"];
|
|
37865
|
+
return new ImportProgressTracker(roles, this.handleImportProgressChanged.bind(this));
|
|
37866
|
+
}
|
|
37505
37867
|
notifyWorkspaceState() {
|
|
37506
37868
|
this.workspaceStateListener?.(this.getWorkspaceState());
|
|
37507
37869
|
}
|
|
@@ -37550,6 +37912,7 @@ class Renderer {
|
|
|
37550
37912
|
this.renderer.setSize(width, height, false);
|
|
37551
37913
|
this.controller.resize(width, height);
|
|
37552
37914
|
this.viewCube.resize(width, height, pixelRatio);
|
|
37915
|
+
this.groundGrid.setPixelRatio(pixelRatio);
|
|
37553
37916
|
this.requestRender();
|
|
37554
37917
|
}
|
|
37555
37918
|
invalidateActiveImport(code) {
|
|
@@ -37595,7 +37958,7 @@ class Renderer {
|
|
|
37595
37958
|
this.notifyWorkspaceState();
|
|
37596
37959
|
}
|
|
37597
37960
|
}
|
|
37598
|
-
startImportSession(performanceTrace) {
|
|
37961
|
+
startImportSession(performanceTrace, progressTracker) {
|
|
37599
37962
|
this.cancelSimulation();
|
|
37600
37963
|
this.cancelBooleanOperation();
|
|
37601
37964
|
this.cancelPendingFirstFramePerformance("cancelled");
|
|
@@ -37608,7 +37971,8 @@ class Renderer {
|
|
|
37608
37971
|
const session = {
|
|
37609
37972
|
controller: new AbortController(),
|
|
37610
37973
|
invalidationCode: void 0,
|
|
37611
|
-
performanceTrace
|
|
37974
|
+
performanceTrace,
|
|
37975
|
+
progressTracker
|
|
37612
37976
|
};
|
|
37613
37977
|
performanceTrace.markStage("import-session-start", "scene");
|
|
37614
37978
|
this.activeImport = session;
|
|
@@ -37849,6 +38213,8 @@ class ArchiveImportWorkerMessageParser {
|
|
|
37849
38213
|
return this.parseEntryStart(record, taskId);
|
|
37850
38214
|
case "error":
|
|
37851
38215
|
return typeof record["message"] === "string" ? { message: record["message"], taskId, type: "error" } : void 0;
|
|
38216
|
+
case "progress":
|
|
38217
|
+
return this.parseProgress(record, taskId);
|
|
37852
38218
|
default:
|
|
37853
38219
|
return void 0;
|
|
37854
38220
|
}
|
|
@@ -37866,6 +38232,17 @@ class ArchiveImportWorkerMessageParser {
|
|
|
37866
38232
|
isPositiveSafeInteger(value) {
|
|
37867
38233
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
37868
38234
|
}
|
|
38235
|
+
isNonNegativeSafeInteger(value) {
|
|
38236
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
38237
|
+
}
|
|
38238
|
+
parseProgress(record, taskId) {
|
|
38239
|
+
const bytesLoaded = record["bytesLoaded"];
|
|
38240
|
+
const bytesTotal = record["bytesTotal"];
|
|
38241
|
+
if (!this.isNonNegativeSafeInteger(bytesLoaded) || !this.isNonNegativeSafeInteger(bytesTotal)) {
|
|
38242
|
+
return void 0;
|
|
38243
|
+
}
|
|
38244
|
+
return { bytesLoaded, bytesTotal, taskId, type: "progress" };
|
|
38245
|
+
}
|
|
37869
38246
|
isRecord(value) {
|
|
37870
38247
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37871
38248
|
}
|
|
@@ -37925,7 +38302,7 @@ class BrowserArchiveImportWorkerEndpoint {
|
|
|
37925
38302
|
constructor() {
|
|
37926
38303
|
this.worker = new Worker(new URL(
|
|
37927
38304
|
/* @vite-ignore */
|
|
37928
|
-
"" + new URL("assets/ArchiveImportWorkerEntry-
|
|
38305
|
+
"" + new URL("assets/ArchiveImportWorkerEntry-wkxjE56k.js", import.meta.url).href,
|
|
37929
38306
|
import.meta.url
|
|
37930
38307
|
), {
|
|
37931
38308
|
type: "module"
|
|
@@ -37965,9 +38342,11 @@ class ArchiveImportWorkerClient {
|
|
|
37965
38342
|
jobValidator = new ArchiveImportJobValidator();
|
|
37966
38343
|
lastStartedTaskId = 0;
|
|
37967
38344
|
messageParser = new ArchiveImportWorkerMessageParser();
|
|
38345
|
+
onProgress;
|
|
37968
38346
|
workerFactory;
|
|
37969
|
-
constructor(workerFactory = new BrowserArchiveImportWorkerFactory()) {
|
|
38347
|
+
constructor(workerFactory = new BrowserArchiveImportWorkerFactory(), onProgress) {
|
|
37970
38348
|
this.workerFactory = workerFactory;
|
|
38349
|
+
this.onProgress = onProgress;
|
|
37971
38350
|
}
|
|
37972
38351
|
cancel(taskId) {
|
|
37973
38352
|
const task = this.activeTask;
|
|
@@ -38042,6 +38421,10 @@ class ArchiveImportWorkerClient {
|
|
|
38042
38421
|
outbound.message
|
|
38043
38422
|
)
|
|
38044
38423
|
);
|
|
38424
|
+
return;
|
|
38425
|
+
case "progress":
|
|
38426
|
+
this.handleProgress(outbound);
|
|
38427
|
+
return;
|
|
38045
38428
|
}
|
|
38046
38429
|
} catch (error2) {
|
|
38047
38430
|
this.rejectTask(task, this.toError(error2));
|
|
@@ -38111,6 +38494,10 @@ class ArchiveImportWorkerClient {
|
|
|
38111
38494
|
type: "acknowledge-chunk"
|
|
38112
38495
|
});
|
|
38113
38496
|
}
|
|
38497
|
+
handleProgress(message) {
|
|
38498
|
+
const percent = message.bytesTotal <= 0 ? 0 : Math.min(100, Math.floor(message.bytesLoaded / message.bytesTotal * 100));
|
|
38499
|
+
this.onProgress?.(percent);
|
|
38500
|
+
}
|
|
38114
38501
|
rejectTask(task, error2) {
|
|
38115
38502
|
if (this.activeTask !== task) {
|
|
38116
38503
|
return;
|
|
@@ -38292,6 +38679,26 @@ var ImportPerformanceMode = /* @__PURE__ */ ((ImportPerformanceMode2) => {
|
|
|
38292
38679
|
ImportPerformanceMode2["Verbose"] = "verbose";
|
|
38293
38680
|
return ImportPerformanceMode2;
|
|
38294
38681
|
})(ImportPerformanceMode || {});
|
|
38682
|
+
const ARCHIVE_SEGMENT_PERCENT = 20;
|
|
38683
|
+
class ImportProgressCompositor {
|
|
38684
|
+
compose(input) {
|
|
38685
|
+
const archiveProgress = this.clampPercent(input.archiveProgress);
|
|
38686
|
+
const rendererProgress = this.clampPercent(input.rendererProgress);
|
|
38687
|
+
if (archiveProgress === void 0) {
|
|
38688
|
+
return rendererProgress;
|
|
38689
|
+
}
|
|
38690
|
+
if (rendererProgress === void 0) {
|
|
38691
|
+
return Math.floor(archiveProgress / 100 * ARCHIVE_SEGMENT_PERCENT);
|
|
38692
|
+
}
|
|
38693
|
+
return ARCHIVE_SEGMENT_PERCENT + Math.floor(rendererProgress / 100 * (100 - ARCHIVE_SEGMENT_PERCENT));
|
|
38694
|
+
}
|
|
38695
|
+
clampPercent(percent) {
|
|
38696
|
+
if (percent === void 0) {
|
|
38697
|
+
return void 0;
|
|
38698
|
+
}
|
|
38699
|
+
return Math.max(0, Math.min(100, percent));
|
|
38700
|
+
}
|
|
38701
|
+
}
|
|
38295
38702
|
class DownloadSaveSink {
|
|
38296
38703
|
aborted = false;
|
|
38297
38704
|
blobChunks = [];
|
|
@@ -40011,7 +40418,7 @@ var StoneBasePoseMode = /* @__PURE__ */ ((StoneBasePoseMode2) => {
|
|
|
40011
40418
|
StoneBasePoseMode2["PreservePose"] = "preserve-pose";
|
|
40012
40419
|
return StoneBasePoseMode2;
|
|
40013
40420
|
})(StoneBasePoseMode || {});
|
|
40014
|
-
const studioWorkspaceStyles = ".lingbi-studio-workspace {\n position: relative;\n display: block;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n.lingbi-studio-viewport {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n.lingbi-studio-viewport > canvas {\n display: block;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n background: #3d3f41;\n}\n\n.lingbi-studio-boolean-operation-overlay {\n position: absolute;\n z-index: 3;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n background: rgba(17, 17, 17, 0.32);\n color: #ffffff;\n cursor: wait;\n}\n\n.lingbi-studio-boolean-operation-overlay[hidden] {\n display: none;\n}\n\n.lingbi-studio-boolean-edit-confirmation {\n position: absolute;\n z-index: 4;\n top: 50%;\n left: 50%;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n width: min(420px, calc(100% - 32px));\n padding: 24px;\n border-radius: 8px;\n background: #ffffff;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.22);\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n}\n\n.lingbi-studio-boolean-edit-confirmation[hidden] {\n display: none;\n}\n\n.lingbi-studio-boolean-edit-confirmation-text {\n grid-column: 1 / -1;\n margin: 0 0 8px;\n color: #171717;\n font-size: 16px;\n font-weight: 500;\n line-height: 24px;\n text-align: center;\n}\n\n.lingbi-studio-boolean-edit-confirmation-cancel,\n.lingbi-studio-boolean-edit-confirmation-continue {\n height: 40px;\n border: 1px solid #d9d9d9;\n border-radius: 4px;\n font: inherit;\n font-size: 16px;\n font-weight: 500;\n line-height: 24px;\n cursor: pointer;\n}\n\n.lingbi-studio-boolean-edit-confirmation-cancel {\n background: #ffffff;\n color: #171717;\n}\n\n.lingbi-studio-boolean-edit-confirmation-continue {\n border-color: #f27c38;\n background: #f27c38;\n color: #ffffff;\n}\n\n.lingbi-studio-boolean-operation-spinner {\n width: 32px;\n height: 32px;\n border: 3px solid rgba(255, 105, 0, 0.28);\n border-top-color: #ff6900;\n border-radius: 50%;\n animation: lingbi-studio-boolean-operation-spin 0.8s linear infinite;\n box-sizing: border-box;\n}\n\n.lingbi-studio-boolean-operation-status {\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n letter-spacing: 0;\n}\n\n.lingbi-studio-bottom-toolbar {\n position: absolute;\n z-index: 1;\n bottom: 36px;\n left: 50%;\n display: grid;\n align-items: center;\n grid-template-columns: minmax(0, 1fr);\n width: min(120px, calc(100% - 32px));\n height: 64px;\n padding: 8px 12px;\n transform: translateX(-50%);\n box-sizing: border-box;\n border-radius: 8px;\n background: #f4f4f4;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.14);\n}\n\n.lingbi-studio-bottom-toolbar.has-edit-control {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n width: min(480px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-inventory-control {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n width: min(240px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-edit-control.has-inventory-control {\n grid-template-columns: repeat(5, minmax(0, 1fr));\n width: min(600px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-model-control.has-inventory-control {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n width: min(360px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-model-control.has-edit-control {\n grid-template-columns: repeat(5, minmax(0, 1fr));\n width: min(600px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-model-control.has-edit-control.has-inventory-control {\n grid-template-columns: repeat(6, minmax(0, 1fr));\n width: min(720px, calc(100% - 32px));\n}\n\n.lingbi-studio-model-visibility {\n position: absolute;\n z-index: 1;\n bottom: 108px;\n left: 50%;\n display: grid;\n gap: 8px;\n width: 144px;\n padding: 12px;\n border-radius: 8px;\n background: #f4f4f4;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.14);\n transform: translateX(-240px);\n box-sizing: border-box;\n}\n\n.lingbi-studio-model-visibility[hidden] {\n display: none;\n}\n\n.lingbi-studio-model-visibility-title {\n color: #171717;\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.lingbi-studio-model-visibility-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n color: #171717;\n font-size: 14px;\n line-height: 20px;\n}\n\n.lingbi-studio-model-visibility-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n appearance: none;\n width: 20px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n color: #171717;\n cursor: not-allowed;\n font: inherit;\n line-height: 0;\n outline: none;\n box-sizing: border-box;\n}\n\n.lingbi-studio-model-visibility-icon {\n display: block;\n width: 18px;\n height: 18px;\n flex: 0 0 auto;\n pointer-events: none;\n}\n\n.lingbi-studio-model-visibility-button:not(:disabled) {\n cursor: pointer;\n}\n\n.lingbi-studio-model-visibility-button:disabled {\n color: #8c8c8c;\n}\n\n.lingbi-studio-model-button.is-active,\n.lingbi-studio-model-button.is-active:disabled {\n color: #ff6900;\n font-weight: 600;\n}\n\n.lingbi-studio-boolean-button,\n.lingbi-studio-simulation-button,\n.lingbi-studio-download-button,\n.lingbi-studio-inventory-button,\n.lingbi-studio-edit-button,\n.lingbi-studio-model-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n min-width: 0;\n height: 48px;\n padding: 0 8px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: #171717;\n cursor: not-allowed;\n font: inherit;\n font-size: 18px;\n font-weight: 500;\n line-height: 24px;\n letter-spacing: 0;\n opacity: 1;\n box-sizing: border-box;\n white-space: nowrap;\n transition:\n background-color 140ms ease,\n color 140ms ease;\n}\n\n.lingbi-studio-operation-button-wrapper {\n display: block;\n width: 100%;\n min-width: 0;\n height: 48px;\n box-sizing: border-box;\n}\n\n.lingbi-studio-operation-button-wrapper > button:disabled {\n pointer-events: none;\n}\n\n.lingbi-studio-boolean-button[hidden],\n.lingbi-studio-simulation-button[hidden],\n.lingbi-studio-download-button[hidden],\n.lingbi-studio-inventory-button[hidden],\n.lingbi-studio-edit-button[hidden],\n.lingbi-studio-model-button[hidden] {\n display: none;\n}\n\n.lingbi-studio-boolean-button:not(:disabled),\n.lingbi-studio-simulation-button:not(:disabled),\n.lingbi-studio-download-button:not(:disabled),\n.lingbi-studio-inventory-button:not(:disabled),\n.lingbi-studio-edit-button:not(:disabled),\n.lingbi-studio-model-button:not(:disabled) {\n cursor: pointer;\n}\n\n.lingbi-studio-boolean-button:disabled,\n.lingbi-studio-simulation-button:disabled,\n.lingbi-studio-download-button:disabled,\n.lingbi-studio-inventory-button:disabled,\n.lingbi-studio-edit-button:disabled,\n.lingbi-studio-model-button:disabled,\n.lingbi-studio-model-visibility-button:disabled {\n background: transparent;\n color: #8c8c8c;\n opacity: 1;\n}\n\n.lingbi-studio-edit-button.is-active,\n.lingbi-studio-edit-button.is-active:disabled,\n.lingbi-studio-model-button.is-active,\n.lingbi-studio-model-button.is-active:disabled {\n color: #ff6900;\n font-weight: 600;\n}\n\n.lingbi-studio-download-status {\n position: absolute;\n z-index: 2;\n top: 24px;\n left: 50%;\n max-width: calc(100% - 24px);\n padding: 6px 10px;\n border: 1px solid #f4b5b0;\n border-radius: 4px;\n background: #fff1f0;\n color: #b42318;\n font-size: 13px;\n font-weight: 500;\n line-height: 20px;\n text-align: center;\n transform: translateX(-50%);\n box-sizing: border-box;\n}\n\n.lingbi-studio-download-status[hidden] {\n display: none;\n}\n\n.lingbi-studio-download-success {\n position: absolute;\n z-index: 2;\n top: 24px;\n left: 50%;\n max-width: calc(100% - 24px);\n padding: 8px 16px;\n border: 1px solid #86d39a;\n border-radius: 6px;\n background: #f0fff4;\n color: #176b32;\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n text-align: center;\n transform: translateX(-50%);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n box-sizing: border-box;\n}\n\n.lingbi-studio-download-success[hidden] {\n display: none;\n}\n\n.lingbi-studio-edit-status {\n position: absolute;\n z-index: 2;\n bottom: 112px;\n left: 50%;\n display: flex;\n align-items: center;\n gap: 12px;\n max-width: calc(100% - 24px);\n padding: 10px 14px;\n border: 0;\n border-radius: 8px;\n background: #e9e9e9;\n color: #171717;\n transform: translateX(-50%);\n box-sizing: border-box;\n}\n\n.lingbi-studio-edit-status[hidden] {\n display: none;\n}\n\n.lingbi-studio-edit-status-text {\n display: inline-block;\n min-width: 0;\n font-size: 20px;\n line-height: 28px;\n letter-spacing: 0;\n}\n\n.lingbi-studio-exit-button {\n display: inline-flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: center;\n height: 40px;\n padding: 0 18px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: #f27c38;\n color: #ffffff;\n cursor: pointer;\n font: inherit;\n font-size: 18px;\n font-weight: 600;\n line-height: 24px;\n letter-spacing: 0;\n transition:\n background-color 140ms ease,\n color 140ms ease;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .lingbi-studio-boolean-button:not(:disabled):hover,\n .lingbi-studio-simulation-button:not(:disabled):hover,\n .lingbi-studio-download-button:not(:disabled):hover,\n .lingbi-studio-inventory-button:not(:disabled):hover,\n .lingbi-studio-edit-button:not(:disabled):hover,\n .lingbi-studio-model-button:not(:disabled):hover {\n background: #e8e8e8;\n }\n\n .lingbi-studio-simulation-button:not(:disabled):hover,\n .lingbi-studio-download-button:not(:disabled):hover,\n .lingbi-studio-inventory-button:not(:disabled):hover,\n .lingbi-studio-edit-button:not(:disabled):hover,\n .lingbi-studio-model-button:not(:disabled):hover {\n color: #f06400;\n }\n\n .lingbi-studio-model-visibility-button:not(:disabled):hover {\n background: transparent;\n }\n\n .lingbi-studio-exit-button:hover {\n background: #ff8a1f;\n }\n\n .lingbi-studio-boolean-edit-confirmation-cancel:hover {\n background: #f5f5f5;\n }\n\n .lingbi-studio-boolean-edit-confirmation-continue:hover {\n background: #ff8a1f;\n }\n}\n\n.lingbi-studio-boolean-button:not(:disabled):active,\n.lingbi-studio-download-button:not(:disabled):active,\n.lingbi-studio-inventory-button:not(:disabled):active,\n.lingbi-studio-edit-button:not(:disabled):active,\n.lingbi-studio-model-button:not(:disabled):active,\n.lingbi-studio-model-visibility-button:not(:disabled):active {\n background: transparent;\n}\n\n.lingbi-studio-exit-button:active {\n background: #e66d00;\n}\n\n@keyframes lingbi-studio-boolean-operation-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .lingbi-studio-boolean-button,\n .lingbi-studio-simulation-button,\n .lingbi-studio-download-button,\n .lingbi-studio-inventory-button,\n .lingbi-studio-edit-button,\n .lingbi-studio-model-button,\n .lingbi-studio-exit-button {\n transition: none;\n }\n\n .lingbi-studio-boolean-operation-spinner {\n animation: none;\n }\n}\n\n@media (max-width: 420px) {\n .lingbi-studio-bottom-toolbar.has-edit-control {\n width: calc(100% - 16px);\n padding: 8px 4px;\n }\n\n .lingbi-studio-bottom-toolbar.has-model-control.has-edit-control {\n width: calc(100% - 16px);\n }\n\n .lingbi-studio-bottom-toolbar.has-model-control.has-edit-control.has-inventory-control {\n width: calc(100% - 16px);\n }\n\n .lingbi-studio-model-visibility {\n left: 8px;\n transform: none;\n }\n\n .lingbi-studio-boolean-button,\n .lingbi-studio-simulation-button,\n .lingbi-studio-download-button,\n .lingbi-studio-inventory-button,\n .lingbi-studio-edit-button,\n .lingbi-studio-model-button {\n padding: 0 2px;\n font-size: 16px;\n }\n\n .lingbi-studio-edit-status-text {\n font-size: 16px;\n line-height: 24px;\n }\n\n .lingbi-studio-exit-button {\n height: 36px;\n padding: 0 14px;\n font-size: 16px;\n }\n}\n\n.lingbi-studio-viewport > canvas:focus-visible,\n.lingbi-studio-boolean-button:focus-visible,\n.lingbi-studio-simulation-button:focus-visible,\n.lingbi-studio-download-button:focus-visible,\n.lingbi-studio-inventory-button:focus-visible,\n.lingbi-studio-edit-button:focus-visible,\n.lingbi-studio-model-button:focus-visible,\n.lingbi-studio-model-visibility-button:focus-visible,\n.lingbi-studio-exit-button:focus-visible,\n.lingbi-studio-boolean-edit-confirmation-cancel:focus-visible,\n.lingbi-studio-boolean-edit-confirmation-continue:focus-visible {\n outline: 2px solid #7cc0ff;\n outline-offset: 2px;\n}\n";
|
|
40421
|
+
const studioWorkspaceStyles = ".lingbi-studio-workspace {\n position: relative;\n display: block;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n.lingbi-studio-viewport {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n.lingbi-studio-viewport > canvas {\n display: block;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n background: #3d3f41;\n}\n\n.lingbi-studio-boolean-operation-overlay {\n position: absolute;\n z-index: 3;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n background: rgba(17, 17, 17, 0.32);\n color: #ffffff;\n cursor: wait;\n}\n\n.lingbi-studio-boolean-operation-overlay[hidden] {\n display: none;\n}\n\n.lingbi-studio-boolean-edit-confirmation {\n position: absolute;\n z-index: 4;\n top: 50%;\n left: 50%;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n width: min(420px, calc(100% - 32px));\n padding: 24px;\n border-radius: 8px;\n background: #ffffff;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.22);\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n}\n\n.lingbi-studio-boolean-edit-confirmation[hidden] {\n display: none;\n}\n\n.lingbi-studio-boolean-edit-confirmation-text {\n grid-column: 1 / -1;\n margin: 0 0 8px;\n color: #171717;\n font-size: 16px;\n font-weight: 500;\n line-height: 24px;\n text-align: center;\n}\n\n.lingbi-studio-boolean-edit-confirmation-cancel,\n.lingbi-studio-boolean-edit-confirmation-continue {\n height: 40px;\n border: 1px solid #d9d9d9;\n border-radius: 4px;\n font: inherit;\n font-size: 16px;\n font-weight: 500;\n line-height: 24px;\n cursor: pointer;\n}\n\n.lingbi-studio-boolean-edit-confirmation-cancel {\n background: #ffffff;\n color: #171717;\n}\n\n.lingbi-studio-boolean-edit-confirmation-continue {\n border-color: #f27c38;\n background: #f27c38;\n color: #ffffff;\n}\n\n.lingbi-studio-boolean-operation-spinner {\n width: 32px;\n height: 32px;\n border: 3px solid rgba(255, 105, 0, 0.28);\n border-top-color: #ff6900;\n border-radius: 50%;\n animation: lingbi-studio-boolean-operation-spin 0.8s linear infinite;\n box-sizing: border-box;\n}\n\n.lingbi-studio-boolean-operation-status {\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n letter-spacing: 0;\n}\n\n.lingbi-studio-import-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.lingbi-studio-import-row[hidden] {\n display: none;\n}\n\n.lingbi-studio-import-progress {\n display: block;\n width: 160px;\n height: 4px;\n overflow: hidden;\n border-radius: 999px;\n background: rgba(255, 105, 0, 0.28);\n box-sizing: border-box;\n}\n\n.lingbi-studio-import-progress[hidden] {\n display: none;\n}\n\n.lingbi-studio-import-progress-fill {\n width: 0;\n height: 100%;\n border-radius: 999px;\n background: #ff6900;\n}\n\n.lingbi-studio-import-percent {\n min-width: 36px;\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n text-align: left;\n}\n\n.lingbi-studio-bottom-toolbar {\n position: absolute;\n z-index: 1;\n bottom: 36px;\n left: 50%;\n display: grid;\n align-items: center;\n grid-template-columns: minmax(0, 1fr);\n width: min(120px, calc(100% - 32px));\n height: 64px;\n padding: 8px 12px;\n transform: translateX(-50%);\n box-sizing: border-box;\n border-radius: 8px;\n background: #f4f4f4;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.14);\n}\n\n.lingbi-studio-bottom-toolbar.has-edit-control {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n width: min(480px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-inventory-control {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n width: min(240px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-edit-control.has-inventory-control {\n grid-template-columns: repeat(5, minmax(0, 1fr));\n width: min(600px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-model-control.has-inventory-control {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n width: min(360px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-model-control.has-edit-control {\n grid-template-columns: repeat(5, minmax(0, 1fr));\n width: min(600px, calc(100% - 32px));\n}\n\n.lingbi-studio-bottom-toolbar.has-model-control.has-edit-control.has-inventory-control {\n grid-template-columns: repeat(6, minmax(0, 1fr));\n width: min(720px, calc(100% - 32px));\n}\n\n.lingbi-studio-model-visibility {\n position: absolute;\n z-index: 1;\n bottom: 108px;\n left: 50%;\n display: grid;\n gap: 8px;\n width: 144px;\n padding: 12px;\n border-radius: 8px;\n background: #f4f4f4;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.14);\n transform: translateX(-240px);\n box-sizing: border-box;\n}\n\n.lingbi-studio-model-visibility[hidden] {\n display: none;\n}\n\n.lingbi-studio-model-visibility-title {\n color: #171717;\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.lingbi-studio-model-visibility-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n color: #171717;\n font-size: 14px;\n line-height: 20px;\n}\n\n.lingbi-studio-model-visibility-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n appearance: none;\n width: 20px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n color: #171717;\n cursor: not-allowed;\n font: inherit;\n line-height: 0;\n outline: none;\n box-sizing: border-box;\n}\n\n.lingbi-studio-model-visibility-icon {\n display: block;\n width: 18px;\n height: 18px;\n flex: 0 0 auto;\n pointer-events: none;\n}\n\n.lingbi-studio-model-visibility-button:not(:disabled) {\n cursor: pointer;\n}\n\n.lingbi-studio-model-visibility-button:disabled {\n color: #8c8c8c;\n}\n\n.lingbi-studio-model-button.is-active,\n.lingbi-studio-model-button.is-active:disabled {\n color: #ff6900;\n font-weight: 600;\n}\n\n.lingbi-studio-boolean-button,\n.lingbi-studio-simulation-button,\n.lingbi-studio-download-button,\n.lingbi-studio-inventory-button,\n.lingbi-studio-edit-button,\n.lingbi-studio-model-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n min-width: 0;\n height: 48px;\n padding: 0 8px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: #171717;\n cursor: not-allowed;\n font: inherit;\n font-size: 18px;\n font-weight: 500;\n line-height: 24px;\n letter-spacing: 0;\n opacity: 1;\n box-sizing: border-box;\n white-space: nowrap;\n transition:\n background-color 140ms ease,\n color 140ms ease;\n}\n\n.lingbi-studio-operation-button-wrapper {\n display: block;\n width: 100%;\n min-width: 0;\n height: 48px;\n box-sizing: border-box;\n}\n\n.lingbi-studio-operation-button-wrapper > button:disabled {\n pointer-events: none;\n}\n\n.lingbi-studio-boolean-button[hidden],\n.lingbi-studio-simulation-button[hidden],\n.lingbi-studio-download-button[hidden],\n.lingbi-studio-inventory-button[hidden],\n.lingbi-studio-edit-button[hidden],\n.lingbi-studio-model-button[hidden] {\n display: none;\n}\n\n.lingbi-studio-boolean-button:not(:disabled),\n.lingbi-studio-simulation-button:not(:disabled),\n.lingbi-studio-download-button:not(:disabled),\n.lingbi-studio-inventory-button:not(:disabled),\n.lingbi-studio-edit-button:not(:disabled),\n.lingbi-studio-model-button:not(:disabled) {\n cursor: pointer;\n}\n\n.lingbi-studio-boolean-button:disabled,\n.lingbi-studio-simulation-button:disabled,\n.lingbi-studio-download-button:disabled,\n.lingbi-studio-inventory-button:disabled,\n.lingbi-studio-edit-button:disabled,\n.lingbi-studio-model-button:disabled,\n.lingbi-studio-model-visibility-button:disabled {\n background: transparent;\n color: #8c8c8c;\n opacity: 1;\n}\n\n.lingbi-studio-edit-button.is-active,\n.lingbi-studio-edit-button.is-active:disabled,\n.lingbi-studio-model-button.is-active,\n.lingbi-studio-model-button.is-active:disabled {\n color: #ff6900;\n font-weight: 600;\n}\n\n.lingbi-studio-download-status {\n position: absolute;\n z-index: 2;\n top: 24px;\n left: 50%;\n max-width: calc(100% - 24px);\n padding: 6px 10px;\n border: 1px solid #f4b5b0;\n border-radius: 4px;\n background: #fff1f0;\n color: #b42318;\n font-size: 13px;\n font-weight: 500;\n line-height: 20px;\n text-align: center;\n transform: translateX(-50%);\n box-sizing: border-box;\n}\n\n.lingbi-studio-download-status[hidden] {\n display: none;\n}\n\n.lingbi-studio-download-success {\n position: absolute;\n z-index: 2;\n top: 24px;\n left: 50%;\n max-width: calc(100% - 24px);\n padding: 8px 16px;\n border: 1px solid #86d39a;\n border-radius: 6px;\n background: #f0fff4;\n color: #176b32;\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n text-align: center;\n transform: translateX(-50%);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n box-sizing: border-box;\n}\n\n.lingbi-studio-download-success[hidden] {\n display: none;\n}\n\n.lingbi-studio-edit-status {\n position: absolute;\n z-index: 2;\n bottom: 112px;\n left: 50%;\n display: flex;\n align-items: center;\n gap: 12px;\n max-width: calc(100% - 24px);\n padding: 10px 14px;\n border: 0;\n border-radius: 8px;\n background: #e9e9e9;\n color: #171717;\n transform: translateX(-50%);\n box-sizing: border-box;\n}\n\n.lingbi-studio-edit-status[hidden] {\n display: none;\n}\n\n.lingbi-studio-edit-status-text {\n display: inline-block;\n min-width: 0;\n font-size: 20px;\n line-height: 28px;\n letter-spacing: 0;\n}\n\n.lingbi-studio-exit-button {\n display: inline-flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: center;\n height: 40px;\n padding: 0 18px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: #f27c38;\n color: #ffffff;\n cursor: pointer;\n font: inherit;\n font-size: 18px;\n font-weight: 600;\n line-height: 24px;\n letter-spacing: 0;\n transition:\n background-color 140ms ease,\n color 140ms ease;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .lingbi-studio-boolean-button:not(:disabled):hover,\n .lingbi-studio-simulation-button:not(:disabled):hover,\n .lingbi-studio-download-button:not(:disabled):hover,\n .lingbi-studio-inventory-button:not(:disabled):hover,\n .lingbi-studio-edit-button:not(:disabled):hover,\n .lingbi-studio-model-button:not(:disabled):hover {\n background: #e8e8e8;\n }\n\n .lingbi-studio-simulation-button:not(:disabled):hover,\n .lingbi-studio-download-button:not(:disabled):hover,\n .lingbi-studio-inventory-button:not(:disabled):hover,\n .lingbi-studio-edit-button:not(:disabled):hover,\n .lingbi-studio-model-button:not(:disabled):hover {\n color: #f06400;\n }\n\n .lingbi-studio-model-visibility-button:not(:disabled):hover {\n background: transparent;\n }\n\n .lingbi-studio-exit-button:hover {\n background: #ff8a1f;\n }\n\n .lingbi-studio-boolean-edit-confirmation-cancel:hover {\n background: #f5f5f5;\n }\n\n .lingbi-studio-boolean-edit-confirmation-continue:hover {\n background: #ff8a1f;\n }\n}\n\n.lingbi-studio-boolean-button:not(:disabled):active,\n.lingbi-studio-download-button:not(:disabled):active,\n.lingbi-studio-inventory-button:not(:disabled):active,\n.lingbi-studio-edit-button:not(:disabled):active,\n.lingbi-studio-model-button:not(:disabled):active,\n.lingbi-studio-model-visibility-button:not(:disabled):active {\n background: transparent;\n}\n\n.lingbi-studio-exit-button:active {\n background: #e66d00;\n}\n\n@keyframes lingbi-studio-boolean-operation-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .lingbi-studio-boolean-button,\n .lingbi-studio-simulation-button,\n .lingbi-studio-download-button,\n .lingbi-studio-inventory-button,\n .lingbi-studio-edit-button,\n .lingbi-studio-model-button,\n .lingbi-studio-exit-button {\n transition: none;\n }\n\n .lingbi-studio-boolean-operation-spinner {\n animation: none;\n }\n}\n\n@media (max-width: 420px) {\n .lingbi-studio-bottom-toolbar.has-edit-control {\n width: calc(100% - 16px);\n padding: 8px 4px;\n }\n\n .lingbi-studio-bottom-toolbar.has-model-control.has-edit-control {\n width: calc(100% - 16px);\n }\n\n .lingbi-studio-bottom-toolbar.has-model-control.has-edit-control.has-inventory-control {\n width: calc(100% - 16px);\n }\n\n .lingbi-studio-model-visibility {\n left: 8px;\n transform: none;\n }\n\n .lingbi-studio-boolean-button,\n .lingbi-studio-simulation-button,\n .lingbi-studio-download-button,\n .lingbi-studio-inventory-button,\n .lingbi-studio-edit-button,\n .lingbi-studio-model-button {\n padding: 0 2px;\n font-size: 16px;\n }\n\n .lingbi-studio-edit-status-text {\n font-size: 16px;\n line-height: 24px;\n }\n\n .lingbi-studio-exit-button {\n height: 36px;\n padding: 0 14px;\n font-size: 16px;\n }\n}\n\n.lingbi-studio-viewport > canvas:focus-visible,\n.lingbi-studio-boolean-button:focus-visible,\n.lingbi-studio-simulation-button:focus-visible,\n.lingbi-studio-download-button:focus-visible,\n.lingbi-studio-inventory-button:focus-visible,\n.lingbi-studio-edit-button:focus-visible,\n.lingbi-studio-model-button:focus-visible,\n.lingbi-studio-model-visibility-button:focus-visible,\n.lingbi-studio-exit-button:focus-visible,\n.lingbi-studio-boolean-edit-confirmation-cancel:focus-visible,\n.lingbi-studio-boolean-edit-confirmation-continue:focus-visible {\n outline: 2px solid #7cc0ff;\n outline-offset: 2px;\n}\n";
|
|
40015
40422
|
class StudioWorkspace {
|
|
40016
40423
|
canvas;
|
|
40017
40424
|
static SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
@@ -40022,7 +40429,12 @@ class StudioWorkspace {
|
|
|
40022
40429
|
booleanButtonElement;
|
|
40023
40430
|
simulationButtonElement;
|
|
40024
40431
|
booleanOperationOverlayElement;
|
|
40432
|
+
booleanOperationSpinnerElement;
|
|
40025
40433
|
booleanOperationStatusElement;
|
|
40434
|
+
importPercentElement;
|
|
40435
|
+
importProgressElement;
|
|
40436
|
+
importProgressFillElement;
|
|
40437
|
+
importProgressRowElement;
|
|
40026
40438
|
booleanEditConfirmationElement;
|
|
40027
40439
|
bottomToolbarElement;
|
|
40028
40440
|
downloadButtonElement;
|
|
@@ -40054,6 +40466,10 @@ class StudioWorkspace {
|
|
|
40054
40466
|
const booleanOperationOverlayElement = ownerDocument.createElement("div");
|
|
40055
40467
|
const booleanOperationSpinnerElement = ownerDocument.createElement("div");
|
|
40056
40468
|
const booleanOperationStatusElement = ownerDocument.createElement("div");
|
|
40469
|
+
const importPercentElement = ownerDocument.createElement("div");
|
|
40470
|
+
const importProgressElement = ownerDocument.createElement("div");
|
|
40471
|
+
const importProgressFillElement = ownerDocument.createElement("div");
|
|
40472
|
+
const importProgressRowElement = ownerDocument.createElement("div");
|
|
40057
40473
|
const booleanEditConfirmationElement = ownerDocument.createElement("div");
|
|
40058
40474
|
const booleanEditConfirmationTextElement = ownerDocument.createElement("p");
|
|
40059
40475
|
const booleanEditConfirmationCancelButtonElement = ownerDocument.createElement("button");
|
|
@@ -40103,10 +40519,24 @@ class StudioWorkspace {
|
|
|
40103
40519
|
booleanOperationOverlayElement.hidden = true;
|
|
40104
40520
|
booleanOperationSpinnerElement.className = "lingbi-studio-boolean-operation-spinner";
|
|
40105
40521
|
booleanOperationSpinnerElement.setAttribute("aria-hidden", "true");
|
|
40522
|
+
importProgressRowElement.className = "lingbi-studio-import-row";
|
|
40523
|
+
importProgressRowElement.hidden = true;
|
|
40524
|
+
importPercentElement.className = "lingbi-studio-import-percent";
|
|
40525
|
+
importPercentElement.textContent = "0%";
|
|
40526
|
+
importProgressElement.className = "lingbi-studio-import-progress";
|
|
40527
|
+
importProgressElement.setAttribute("aria-label", "模型加载进度");
|
|
40528
|
+
importProgressElement.setAttribute("aria-valuemax", "100");
|
|
40529
|
+
importProgressElement.setAttribute("aria-valuemin", "0");
|
|
40530
|
+
importProgressElement.setAttribute("aria-valuenow", "0");
|
|
40531
|
+
importProgressElement.setAttribute("role", "progressbar");
|
|
40532
|
+
importProgressFillElement.className = "lingbi-studio-import-progress-fill";
|
|
40533
|
+
importProgressElement.append(importProgressFillElement);
|
|
40534
|
+
importProgressRowElement.append(importProgressElement, importPercentElement);
|
|
40106
40535
|
booleanOperationStatusElement.className = "lingbi-studio-boolean-operation-status";
|
|
40107
40536
|
booleanOperationStatusElement.textContent = "布尔计算中";
|
|
40108
40537
|
booleanOperationOverlayElement.append(
|
|
40109
40538
|
booleanOperationSpinnerElement,
|
|
40539
|
+
importProgressRowElement,
|
|
40110
40540
|
booleanOperationStatusElement
|
|
40111
40541
|
);
|
|
40112
40542
|
booleanEditConfirmationElement.className = "lingbi-studio-boolean-edit-confirmation";
|
|
@@ -40234,7 +40664,12 @@ class StudioWorkspace {
|
|
|
40234
40664
|
this.booleanButtonElement = booleanButtonElement;
|
|
40235
40665
|
this.simulationButtonElement = simulationButtonElement;
|
|
40236
40666
|
this.booleanOperationOverlayElement = booleanOperationOverlayElement;
|
|
40667
|
+
this.booleanOperationSpinnerElement = booleanOperationSpinnerElement;
|
|
40237
40668
|
this.booleanOperationStatusElement = booleanOperationStatusElement;
|
|
40669
|
+
this.importPercentElement = importPercentElement;
|
|
40670
|
+
this.importProgressElement = importProgressElement;
|
|
40671
|
+
this.importProgressFillElement = importProgressFillElement;
|
|
40672
|
+
this.importProgressRowElement = importProgressRowElement;
|
|
40238
40673
|
this.booleanEditConfirmationElement = booleanEditConfirmationElement;
|
|
40239
40674
|
this.bottomToolbarElement = bottomToolbarElement;
|
|
40240
40675
|
this.downloadButtonElement = downloadButtonElement;
|
|
@@ -40357,11 +40792,14 @@ class StudioWorkspace {
|
|
|
40357
40792
|
}
|
|
40358
40793
|
/** Applies Application's combined renderer and download state. */
|
|
40359
40794
|
setToolbarState(state) {
|
|
40795
|
+
const importInProgress = state.importInProgress ?? false;
|
|
40796
|
+
const importProgress = Math.max(0, Math.min(100, Math.floor(state.importProgress ?? 0)));
|
|
40360
40797
|
const booleanOperationInProgress = state.booleanInProgress ?? false;
|
|
40361
40798
|
const downloadInProgress = state.downloadInProgress ?? false;
|
|
40362
40799
|
const inventoryInProgress = state.inventoryInProgress ?? false;
|
|
40363
40800
|
const simulationInProgress = state.simulationInProgress ?? false;
|
|
40364
|
-
const
|
|
40801
|
+
const otherOperationInProgress = booleanOperationInProgress || downloadInProgress || inventoryInProgress || simulationInProgress;
|
|
40802
|
+
const operationInProgress = importInProgress || otherOperationInProgress;
|
|
40365
40803
|
const confirmationVisible = state.booleanEditConfirmationVisible ?? false;
|
|
40366
40804
|
const modelVisibility = state.modelVisibility;
|
|
40367
40805
|
this.currentEditActive = state.editActive;
|
|
@@ -40385,7 +40823,15 @@ class StudioWorkspace {
|
|
|
40385
40823
|
this.booleanButtonElement.setAttribute("aria-busy", String(booleanOperationInProgress));
|
|
40386
40824
|
this.booleanOperationOverlayElement.hidden = !operationInProgress;
|
|
40387
40825
|
this.booleanOperationOverlayElement.setAttribute("aria-busy", String(operationInProgress));
|
|
40388
|
-
this.
|
|
40826
|
+
this.booleanOperationSpinnerElement.hidden = importInProgress;
|
|
40827
|
+
this.importProgressRowElement.hidden = !importInProgress;
|
|
40828
|
+
if (importInProgress) {
|
|
40829
|
+
const percentText = `${String(importProgress)}%`;
|
|
40830
|
+
this.importProgressElement.setAttribute("aria-valuenow", String(importProgress));
|
|
40831
|
+
this.importProgressFillElement.style.width = percentText;
|
|
40832
|
+
this.importPercentElement.textContent = percentText;
|
|
40833
|
+
}
|
|
40834
|
+
this.booleanOperationStatusElement.textContent = importInProgress ? "模型加载中" : simulationInProgress ? "仿真计算中" : booleanOperationInProgress ? "布尔计算中" : inventoryInProgress ? "入库处理中" : "下载处理中";
|
|
40389
40835
|
this.canvas.toggleAttribute("inert", operationInProgress || confirmationVisible);
|
|
40390
40836
|
this.bottomToolbarElement.toggleAttribute(
|
|
40391
40837
|
"inert",
|
|
@@ -40573,6 +41019,7 @@ class StudioWorkspace {
|
|
|
40573
41019
|
class Application {
|
|
40574
41020
|
archiveImportController;
|
|
40575
41021
|
archiveImporting = false;
|
|
41022
|
+
archiveImportProgress;
|
|
40576
41023
|
booleanEditConfirmationVisible = false;
|
|
40577
41024
|
disposed = false;
|
|
40578
41025
|
downloadController;
|
|
@@ -40585,6 +41032,7 @@ class Application {
|
|
|
40585
41032
|
editedArchiveResourceContext;
|
|
40586
41033
|
importGeneration = 0;
|
|
40587
41034
|
importPerformanceMode = ImportPerformanceMode.Off;
|
|
41035
|
+
importProgressCompositor = new ImportProgressCompositor();
|
|
40588
41036
|
inventoryConfirmationController;
|
|
40589
41037
|
inventoryConfirming = false;
|
|
40590
41038
|
inventoryError;
|
|
@@ -40642,7 +41090,10 @@ class Application {
|
|
|
40642
41090
|
this.handleInventorySuccess.bind(this),
|
|
40643
41091
|
this.handleInventoryStateChanged.bind(this)
|
|
40644
41092
|
);
|
|
40645
|
-
this.archiveImportController = new ArchiveImportWorkerClient(
|
|
41093
|
+
this.archiveImportController = new ArchiveImportWorkerClient(
|
|
41094
|
+
void 0,
|
|
41095
|
+
this.handleArchiveImportProgress.bind(this)
|
|
41096
|
+
);
|
|
40646
41097
|
this.handleRendererWorkspaceStateChanged(renderer.getWorkspaceState());
|
|
40647
41098
|
} catch (error2) {
|
|
40648
41099
|
this.workspace = void 0;
|
|
@@ -40728,12 +41179,14 @@ class Application {
|
|
|
40728
41179
|
}
|
|
40729
41180
|
this.nextArchiveTaskId += 1;
|
|
40730
41181
|
this.archiveImporting = true;
|
|
41182
|
+
this.archiveImportProgress = 0;
|
|
40731
41183
|
this.downloadError = void 0;
|
|
40732
41184
|
this.downloadSuccess = void 0;
|
|
40733
41185
|
this.publishWorkspaceState();
|
|
40734
41186
|
const controller = this.archiveImportController;
|
|
40735
41187
|
if (controller === void 0) {
|
|
40736
41188
|
this.archiveImporting = false;
|
|
41189
|
+
this.archiveImportProgress = void 0;
|
|
40737
41190
|
this.publishWorkspaceState();
|
|
40738
41191
|
return Promise.resolve({
|
|
40739
41192
|
code: ObjImportFailureCode.Unavailable,
|
|
@@ -40791,6 +41244,7 @@ class Application {
|
|
|
40791
41244
|
cancelArchiveImport() {
|
|
40792
41245
|
this.archiveImportController?.cancel();
|
|
40793
41246
|
this.archiveImporting = false;
|
|
41247
|
+
this.archiveImportProgress = void 0;
|
|
40794
41248
|
this.invalidateImportGeneration();
|
|
40795
41249
|
}
|
|
40796
41250
|
async completeModelResourceSceneImport(source, candidate, generation) {
|
|
@@ -40861,6 +41315,7 @@ class Application {
|
|
|
40861
41315
|
} finally {
|
|
40862
41316
|
if (this.isCurrentImportGeneration(generation)) {
|
|
40863
41317
|
this.archiveImporting = false;
|
|
41318
|
+
this.archiveImportProgress = void 0;
|
|
40864
41319
|
this.publishWorkspaceState();
|
|
40865
41320
|
}
|
|
40866
41321
|
}
|
|
@@ -40868,6 +41323,7 @@ class Application {
|
|
|
40868
41323
|
completeEditedArchiveImportFailure(generation, error2) {
|
|
40869
41324
|
if (this.isCurrentImportGeneration(generation)) {
|
|
40870
41325
|
this.archiveImporting = false;
|
|
41326
|
+
this.archiveImportProgress = void 0;
|
|
40871
41327
|
this.publishWorkspaceState();
|
|
40872
41328
|
}
|
|
40873
41329
|
return Promise.resolve(this.mapEditedArchiveError(error2));
|
|
@@ -41238,6 +41694,13 @@ class Application {
|
|
|
41238
41694
|
}
|
|
41239
41695
|
this.clearBooleanEditConfirmation();
|
|
41240
41696
|
}
|
|
41697
|
+
handleArchiveImportProgress(percent) {
|
|
41698
|
+
if (this.disposed || !this.archiveImporting) {
|
|
41699
|
+
return;
|
|
41700
|
+
}
|
|
41701
|
+
this.archiveImportProgress = percent;
|
|
41702
|
+
this.publishWorkspaceState();
|
|
41703
|
+
}
|
|
41241
41704
|
handleRendererWorkspaceStateChanged(state) {
|
|
41242
41705
|
if (this.disposed) {
|
|
41243
41706
|
return;
|
|
@@ -41355,6 +41818,10 @@ class Application {
|
|
|
41355
41818
|
if (workspace === void 0 || state === void 0) {
|
|
41356
41819
|
return;
|
|
41357
41820
|
}
|
|
41821
|
+
const importProgress = this.importProgressCompositor.compose({
|
|
41822
|
+
archiveProgress: this.archiveImportProgress,
|
|
41823
|
+
rendererProgress: state.scene.importProgress
|
|
41824
|
+
});
|
|
41358
41825
|
const toolbarState = {
|
|
41359
41826
|
simulationEnabled: state.simulation?.enabled === true && !this.downloading && !this.inventorying && !this.inventoryConfirming && !this.archiveImporting && !this.booleanEditConfirmationVisible,
|
|
41360
41827
|
simulationInProgress: state.simulation?.inProgress ?? false,
|
|
@@ -41372,6 +41839,8 @@ class Application {
|
|
|
41372
41839
|
editEnabled: state.edit.enabled && !this.downloading && !this.inventorying && !this.archiveImporting && !this.booleanEditConfirmationVisible,
|
|
41373
41840
|
editVisible: state.edit.visible,
|
|
41374
41841
|
...this.editStatusMessage === void 0 ? {} : { editStatusMessage: this.editStatusMessage },
|
|
41842
|
+
importInProgress: state.scene.importInProgress || this.archiveImporting,
|
|
41843
|
+
...importProgress === void 0 ? {} : { importProgress },
|
|
41375
41844
|
inventoryEnabled: this.canInventory(state),
|
|
41376
41845
|
...this.inventoryError === void 0 ? {} : { inventoryError: this.inventoryError },
|
|
41377
41846
|
inventoryInProgress: this.inventorying,
|
|
@@ -41417,9 +41886,11 @@ class Application {
|
|
|
41417
41886
|
state.scene.available,
|
|
41418
41887
|
state.scene.contextLost,
|
|
41419
41888
|
state.scene.importInProgress,
|
|
41889
|
+
state.scene.importProgress ?? null,
|
|
41420
41890
|
state.scene.revision,
|
|
41421
41891
|
state.scene.resourceRevision ?? null,
|
|
41422
41892
|
this.archiveImporting,
|
|
41893
|
+
this.archiveImportProgress ?? null,
|
|
41423
41894
|
this.downloading,
|
|
41424
41895
|
this.inventoryConfirming,
|
|
41425
41896
|
this.inventorying,
|
|
@@ -41432,7 +41903,7 @@ class Application {
|
|
|
41432
41903
|
]);
|
|
41433
41904
|
}
|
|
41434
41905
|
isSameToolbarState(state, previousState) {
|
|
41435
|
-
return previousState !== void 0 && state.simulationEnabled === previousState.simulationEnabled && state.simulationInProgress === previousState.simulationInProgress && state.simulationOutcome === previousState.simulationOutcome && state.booleanEnabled === previousState.booleanEnabled && state.booleanInProgress === previousState.booleanInProgress && state.booleanReediting === previousState.booleanReediting && state.booleanResultInvalidated === previousState.booleanResultInvalidated && state.booleanEditConfirmationVisible === previousState.booleanEditConfirmationVisible && state.downloadEnabled === previousState.downloadEnabled && state.downloadError === previousState.downloadError && state.downloadInProgress === previousState.downloadInProgress && state.downloadSuccess === previousState.downloadSuccess && state.editActive === previousState.editActive && state.editEnabled === previousState.editEnabled && state.editVisible === previousState.editVisible && state.editStatusMessage === previousState.editStatusMessage && state.inventoryEnabled === previousState.inventoryEnabled && state.inventoryError === previousState.inventoryError && state.inventoryInProgress === previousState.inventoryInProgress && state.inventoryVisible === previousState.inventoryVisible && this.isSameModelVisibility(state.modelVisibility, previousState.modelVisibility);
|
|
41906
|
+
return previousState !== void 0 && state.simulationEnabled === previousState.simulationEnabled && state.simulationInProgress === previousState.simulationInProgress && state.simulationOutcome === previousState.simulationOutcome && state.booleanEnabled === previousState.booleanEnabled && state.booleanInProgress === previousState.booleanInProgress && state.booleanReediting === previousState.booleanReediting && state.booleanResultInvalidated === previousState.booleanResultInvalidated && state.booleanEditConfirmationVisible === previousState.booleanEditConfirmationVisible && state.downloadEnabled === previousState.downloadEnabled && state.downloadError === previousState.downloadError && state.downloadInProgress === previousState.downloadInProgress && state.downloadSuccess === previousState.downloadSuccess && state.editActive === previousState.editActive && state.editEnabled === previousState.editEnabled && state.editVisible === previousState.editVisible && state.editStatusMessage === previousState.editStatusMessage && state.importInProgress === previousState.importInProgress && state.importProgress === previousState.importProgress && state.inventoryEnabled === previousState.inventoryEnabled && state.inventoryError === previousState.inventoryError && state.inventoryInProgress === previousState.inventoryInProgress && state.inventoryVisible === previousState.inventoryVisible && this.isSameModelVisibility(state.modelVisibility, previousState.modelVisibility);
|
|
41436
41907
|
}
|
|
41437
41908
|
isSameModelVisibility(state, previousState) {
|
|
41438
41909
|
return state?.baseVisible === previousState?.baseVisible && state?.enabled === previousState?.enabled && state?.stoneVisible === previousState?.stoneVisible;
|