@shapediver/viewer.session-engine.session-engine 2.11.0 → 2.12.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/dist/implementation/OutputLoader.d.ts +4 -1
- package/dist/implementation/OutputLoader.d.ts.map +1 -1
- package/dist/implementation/OutputLoader.js +11 -4
- package/dist/implementation/OutputLoader.js.map +1 -1
- package/dist/implementation/SessionEngine.d.ts +9 -1
- package/dist/implementation/SessionEngine.d.ts.map +1 -1
- package/dist/implementation/SessionEngine.js +219 -107
- package/dist/implementation/SessionEngine.js.map +1 -1
- package/dist/implementation/dto/Output.d.ts +1 -1
- package/dist/implementation/dto/Output.d.ts.map +1 -1
- package/dist/implementation/dto/Output.js +4 -2
- package/dist/implementation/dto/Output.js.map +1 -1
- package/dist/interfaces/ISessionEngine.d.ts +7 -2
- package/dist/interfaces/ISessionEngine.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/implementation/OutputLoader.ts +16 -5
- package/src/implementation/SessionEngine.ts +244 -125
- package/src/implementation/dto/Output.ts +2 -2
- package/src/interfaces/ISessionEngine.ts +3 -2
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
latestVersion,
|
|
5
5
|
validate,
|
|
6
6
|
versions
|
|
7
|
-
|
|
7
|
+
} from '@shapediver/viewer.settings';
|
|
8
8
|
import {
|
|
9
9
|
create,
|
|
10
10
|
isGBResponseError,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
ShapeDiverResponseOutput,
|
|
22
22
|
ShapeDiverSdk,
|
|
23
23
|
ShapeDiverSdkConfigType
|
|
24
|
-
|
|
24
|
+
} from '@shapediver/sdk.geometry-api-sdk-v2';
|
|
25
25
|
import {
|
|
26
26
|
EventEngine,
|
|
27
27
|
EVENTTYPE,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
StateEngine,
|
|
37
37
|
SystemInfo,
|
|
38
38
|
UuidGenerator
|
|
39
|
-
|
|
39
|
+
} from '@shapediver/viewer.shared.services';
|
|
40
40
|
import { Export } from './dto/Export';
|
|
41
41
|
import { FileParameter } from './dto/FileParameter';
|
|
42
42
|
import { IExport } from '../interfaces/dto/IExport';
|
|
@@ -45,13 +45,13 @@ import { IOutput } from '../interfaces/dto/IOutput';
|
|
|
45
45
|
import { IParameter } from '../interfaces/dto/IParameter';
|
|
46
46
|
import { ISessionEngine, ISettingsSections, PARAMETER_TYPE } from '../interfaces/ISessionEngine';
|
|
47
47
|
import { ISessionTreeNode } from '../interfaces/ISessionTreeNode';
|
|
48
|
-
import { ITaskEvent, TASK_TYPE } from '@shapediver/viewer.shared.types';
|
|
48
|
+
import { IOutputEvent, ITaskEvent, TASK_TYPE } from '@shapediver/viewer.shared.types';
|
|
49
49
|
import {
|
|
50
50
|
ITree,
|
|
51
51
|
ITreeNode,
|
|
52
52
|
Tree,
|
|
53
53
|
TreeNode
|
|
54
|
-
|
|
54
|
+
} from '@shapediver/viewer.shared.node-tree';
|
|
55
55
|
import { Output } from './dto/Output';
|
|
56
56
|
import { OutputDelayException } from './OutputDelayException';
|
|
57
57
|
import { OutputLoader, OutputLoaderTaskEventInfo } from './OutputLoader';
|
|
@@ -84,7 +84,7 @@ export class SessionEngine implements ISessionEngine {
|
|
|
84
84
|
private readonly _ticket?: string;
|
|
85
85
|
private readonly _uuidGenerator = UuidGenerator.instance;
|
|
86
86
|
|
|
87
|
-
#customizationProcess
|
|
87
|
+
#customizationProcess?: string;
|
|
88
88
|
#parameterHistory: {
|
|
89
89
|
[key: string]: {
|
|
90
90
|
value: unknown,
|
|
@@ -267,7 +267,7 @@ export class SessionEngine implements ISessionEngine {
|
|
|
267
267
|
|
|
268
268
|
// #endregion Public Accessors (25)
|
|
269
269
|
|
|
270
|
-
// #region Public Methods (
|
|
270
|
+
// #region Public Methods (27)
|
|
271
271
|
|
|
272
272
|
public applySettings(response: ShapeDiverResponseDto, sections?: ISettingsSections) {
|
|
273
273
|
sections = sections || {};
|
|
@@ -317,7 +317,7 @@ export class SessionEngine implements ISessionEngine {
|
|
|
317
317
|
if (sections.session.parameter.hidden) this.parameters[p].hidden = settings.session[p].hidden || false;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
if (response.parameters && response.parameters[p]) {
|
|
320
|
+
if (response.parameters && response.parameters[p] && !((this.parameters[p] instanceof FileParameter) || this.parameters[p].type.startsWith('s'))) {
|
|
321
321
|
if (sections.session.parameter.value) this.parameters[p].value = response.parameters[p].defval !== undefined ? response.parameters[p].defval : this.parameters[p].value;
|
|
322
322
|
}
|
|
323
323
|
}
|
|
@@ -409,6 +409,15 @@ export class SessionEngine implements ISessionEngine {
|
|
|
409
409
|
return this.#parameterHistoryForward.length > 0;
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
+
public cancelCustomization() {
|
|
413
|
+
if(this.#customizationProcess) {
|
|
414
|
+
for (const r in this._stateEngine.renderingEngines)
|
|
415
|
+
if (this._stateEngine.renderingEngines[r].busy.includes(this.#customizationProcess))
|
|
416
|
+
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(this.#customizationProcess), 1);
|
|
417
|
+
}
|
|
418
|
+
this.#customizationProcess = undefined;
|
|
419
|
+
}
|
|
420
|
+
|
|
412
421
|
public async close(retry = false): Promise<void> {
|
|
413
422
|
this.checkAvailability('close');
|
|
414
423
|
|
|
@@ -466,51 +475,14 @@ export class SessionEngine implements ISessionEngine {
|
|
|
466
475
|
fileParameterIds[parameterId] = await (<IFileParameter>this.parameters[parameterId]).upload();
|
|
467
476
|
|
|
468
477
|
// OPTION TO SKIP - PART 1a
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
|
|
472
|
-
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
|
|
473
|
-
|
|
474
|
-
this._logger.debug(`Session(${this.id}).customize: Session customization was exceeded by other customization request.`);
|
|
475
|
-
|
|
476
|
-
const eventCancel1a: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customization was exceeded by other customization request' };
|
|
477
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel1a);
|
|
478
|
-
return new SessionTreeNode();
|
|
479
|
-
} else if (this._closed === true) {
|
|
480
|
-
for (const r in this._stateEngine.renderingEngines)
|
|
481
|
-
if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
|
|
482
|
-
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
|
|
483
|
-
|
|
484
|
-
this._logger.debug(`Session(${this.id}).customize: Session was closed during customization request.`);
|
|
485
|
-
|
|
486
|
-
const eventCancel1a: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session was closed during customization request' };
|
|
487
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel1a);
|
|
488
|
-
return new SessionTreeNode();
|
|
489
|
-
}
|
|
478
|
+
const cancelResult = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
479
|
+
if (cancelResult) return cancelResult;
|
|
490
480
|
}
|
|
491
481
|
}
|
|
492
482
|
|
|
493
483
|
// OPTION TO SKIP - PART 1b
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
|
|
497
|
-
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
|
|
498
|
-
|
|
499
|
-
const eventCancel1b: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customization was exceeded by other customization request' };
|
|
500
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel1b);
|
|
501
|
-
this._logger.debug(`Session(${this.id}).customize: Session customization was exceeded by other customization request.`);
|
|
502
|
-
return new SessionTreeNode();
|
|
503
|
-
} else if (this._closed === true) {
|
|
504
|
-
for (const r in this._stateEngine.renderingEngines)
|
|
505
|
-
if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
|
|
506
|
-
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
|
|
507
|
-
|
|
508
|
-
this._logger.debug(`Session(${this.id}).customize: Session was closed during customization request.`);
|
|
509
|
-
|
|
510
|
-
const eventCancel1b: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session was closed during customization request' };
|
|
511
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel1b);
|
|
512
|
-
return new SessionTreeNode();
|
|
513
|
-
}
|
|
484
|
+
const cancelResult = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
485
|
+
if (cancelResult) return cancelResult;
|
|
514
486
|
|
|
515
487
|
// assign the uploaded parameters
|
|
516
488
|
for (const parameterId in fileParameterIds)
|
|
@@ -539,6 +511,8 @@ export class SessionEngine implements ISessionEngine {
|
|
|
539
511
|
const eventRequest: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.1, data: { sessionId: this.id }, status: 'Sending customization request' };
|
|
540
512
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
|
|
541
513
|
|
|
514
|
+
const oldOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
515
|
+
|
|
542
516
|
const newNode = await this.customizeInternal(() => this.#customizationProcess !== customizationId, {
|
|
543
517
|
eventId,
|
|
544
518
|
type: TASK_TYPE.SESSION_CUSTOMIZATION,
|
|
@@ -549,29 +523,32 @@ export class SessionEngine implements ISessionEngine {
|
|
|
549
523
|
data: { sessionId: this.id }
|
|
550
524
|
});
|
|
551
525
|
|
|
526
|
+
// OPTION TO SKIP - PART 2
|
|
527
|
+
const cancelResult2 = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
528
|
+
if (cancelResult2) return cancelResult2;
|
|
529
|
+
|
|
530
|
+
const newOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
531
|
+
|
|
552
532
|
const eventSceneUpdate: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.9, data: { sessionId: this.id }, status: 'Updating scene' };
|
|
553
533
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
|
|
554
534
|
|
|
555
|
-
//
|
|
556
|
-
if (
|
|
557
|
-
for (const
|
|
558
|
-
if (
|
|
559
|
-
this.
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
|
|
568
|
-
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
|
|
535
|
+
// call the update callbacks
|
|
536
|
+
if (waitForViewportUpdate === false) {
|
|
537
|
+
for (const outputId in this.outputs) {
|
|
538
|
+
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
539
|
+
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, <IOutputEvent>{
|
|
540
|
+
outputId: outputId,
|
|
541
|
+
outputVersion: newOutputVersions[outputId],
|
|
542
|
+
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
543
|
+
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
}
|
|
569
547
|
|
|
570
|
-
this.
|
|
548
|
+
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
571
549
|
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
return new SessionTreeNode();
|
|
550
|
+
const cancelResult = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
551
|
+
if (cancelResult) return cancelResult;
|
|
575
552
|
}
|
|
576
553
|
|
|
577
554
|
// if this is not a call by the goBack or goForward functions, add the parameter values to the history and delete the forward history
|
|
@@ -617,20 +594,37 @@ export class SessionEngine implements ISessionEngine {
|
|
|
617
594
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
|
|
618
595
|
|
|
619
596
|
// update the viewports
|
|
620
|
-
if (waitForViewportUpdate)
|
|
597
|
+
if (waitForViewportUpdate) {
|
|
621
598
|
for (const r in this._stateEngine.renderingEngines)
|
|
622
599
|
if (!this.excludeViewports.includes(this._stateEngine.renderingEngines[r].id))
|
|
623
600
|
this._stateEngine.renderingEngines[r].update(`SessionEngine(${this.id}).customize`);
|
|
624
601
|
|
|
625
|
-
|
|
626
|
-
|
|
602
|
+
|
|
603
|
+
for (const outputId in this.outputs) {
|
|
604
|
+
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
605
|
+
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, <IOutputEvent>{
|
|
606
|
+
outputId: outputId,
|
|
607
|
+
outputVersion: newOutputVersions[outputId],
|
|
608
|
+
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
609
|
+
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
}
|
|
627
613
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
614
|
+
// call the update callbacks
|
|
615
|
+
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
616
|
+
|
|
617
|
+
const cancelResult = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
618
|
+
if (cancelResult) return cancelResult;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (!waitForViewportUpdate) {
|
|
622
|
+
setTimeout(() => {
|
|
623
|
+
for (const r in this._stateEngine.renderingEngines)
|
|
624
|
+
if (!this.excludeViewports.includes(this._stateEngine.renderingEngines[r].id))
|
|
625
|
+
this._stateEngine.renderingEngines[r].update(`SessionEngine(${this.id}).customize`);
|
|
626
|
+
}, 0);
|
|
627
|
+
}
|
|
634
628
|
|
|
635
629
|
return this.node;
|
|
636
630
|
} catch (e) {
|
|
@@ -645,7 +639,7 @@ export class SessionEngine implements ISessionEngine {
|
|
|
645
639
|
}
|
|
646
640
|
}
|
|
647
641
|
|
|
648
|
-
public async customizeParallel(parameterValues: { [key: string]: string }): Promise<
|
|
642
|
+
public async customizeParallel(parameterValues: { [key: string]: string }, loadOutputs = true): Promise<ISessionTreeNode | ShapeDiverResponseDto> {
|
|
649
643
|
const eventId = this._uuidGenerator.create();
|
|
650
644
|
|
|
651
645
|
const eventStart: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0, data: { sessionId: this.id }, status: 'Customizing session' };
|
|
@@ -659,7 +653,7 @@ export class SessionEngine implements ISessionEngine {
|
|
|
659
653
|
for (const parameterId in this.parameters)
|
|
660
654
|
parameterSet[parameterId] = parameterValues[parameterId] !== undefined ? (' ' + parameterValues[parameterId]).slice(1) : this.parameters[parameterId].stringify();
|
|
661
655
|
|
|
662
|
-
const
|
|
656
|
+
const result = await this.customizeSession(parameterSet, () => false, {
|
|
663
657
|
eventId,
|
|
664
658
|
type: TASK_TYPE.SESSION_CUSTOMIZATION,
|
|
665
659
|
progressRange: {
|
|
@@ -667,12 +661,14 @@ export class SessionEngine implements ISessionEngine {
|
|
|
667
661
|
max: 1
|
|
668
662
|
},
|
|
669
663
|
data: { sessionId: this.id }
|
|
670
|
-
}, true);
|
|
671
|
-
|
|
664
|
+
}, true, loadOutputs);
|
|
665
|
+
|
|
666
|
+
if (result instanceof SessionTreeNode)
|
|
667
|
+
result.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
|
|
672
668
|
|
|
673
669
|
const eventEnd: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customized' };
|
|
674
670
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
|
|
675
|
-
return
|
|
671
|
+
return result;
|
|
676
672
|
}
|
|
677
673
|
|
|
678
674
|
public async goBack(): Promise<ITreeNode> {
|
|
@@ -772,6 +768,63 @@ export class SessionEngine implements ISessionEngine {
|
|
|
772
768
|
}
|
|
773
769
|
}
|
|
774
770
|
|
|
771
|
+
public async loadCachedOutputsParallel(outputMapping: { [key: string]: string }, taskEventInfo?: OutputLoaderTaskEventInfo, retry = false): Promise<{ [key: string]: ITreeNode | undefined }> {
|
|
772
|
+
this.checkAvailability();
|
|
773
|
+
// if there is already task event info, use it
|
|
774
|
+
// this happens after a retry
|
|
775
|
+
const eventId = taskEventInfo ? taskEventInfo.eventId : this._uuidGenerator.create();
|
|
776
|
+
const eventType = taskEventInfo ? taskEventInfo.type : TASK_TYPE.SESSION_OUTPUTS_LOADING;
|
|
777
|
+
const eventData = taskEventInfo ? taskEventInfo.data : { sessionId: this.id };
|
|
778
|
+
|
|
779
|
+
taskEventInfo = taskEventInfo ? taskEventInfo : {
|
|
780
|
+
eventId,
|
|
781
|
+
type: eventType,
|
|
782
|
+
progressRange: {
|
|
783
|
+
min: 0,
|
|
784
|
+
max: 1
|
|
785
|
+
},
|
|
786
|
+
data: eventData
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
try {
|
|
790
|
+
// send start event if this function was called initially
|
|
791
|
+
if (!taskEventInfo) {
|
|
792
|
+
const eventStart: ITaskEvent = { type: eventType, id: eventId, progress: 0, data: eventData, status: 'Loading cached outputs' };
|
|
793
|
+
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
// get the cached outputs
|
|
797
|
+
const responseDto = await this._sdk.output.getCache(this._sessionId!, outputMapping);
|
|
798
|
+
|
|
799
|
+
// create atomic output api objects for them
|
|
800
|
+
const outputs: {
|
|
801
|
+
[key: string]: IOutput;
|
|
802
|
+
} = {};
|
|
803
|
+
for (const outputId in responseDto.outputs) {
|
|
804
|
+
responseDto.outputs[outputId].id = outputId;
|
|
805
|
+
outputs[outputId] = new Output(<ShapeDiverResponseOutput>responseDto.outputs[outputId], this);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// process the output data
|
|
809
|
+
const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', outputs, {}, taskEventInfo, false);
|
|
810
|
+
|
|
811
|
+
// send the end event once done
|
|
812
|
+
const eventEnd: ITaskEvent = { type: eventType, id: eventId, progress: 1, data: eventData, status: 'Loaded cached outputs' };
|
|
813
|
+
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
|
|
814
|
+
|
|
815
|
+
// create a mapping with a dictionary for the id of the outputs
|
|
816
|
+
const outputNodeMapping: { [key: string]: ITreeNode | undefined } = {};
|
|
817
|
+
for (const outputId in outputMapping)
|
|
818
|
+
outputNodeMapping[outputId] = node.children.find(n => n.name === outputId);
|
|
819
|
+
|
|
820
|
+
return outputNodeMapping;
|
|
821
|
+
}
|
|
822
|
+
catch (e) {
|
|
823
|
+
await this.handleError(e, retry);
|
|
824
|
+
return await this.loadCachedOutputsParallel(outputMapping, taskEventInfo, true);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
775
828
|
/**
|
|
776
829
|
* Load the outputs and return the scene graph node of the result.
|
|
777
830
|
* In case the outputs have a delay property, another customization request with the parameter set is sent.
|
|
@@ -788,15 +841,8 @@ export class SessionEngine implements ISessionEngine {
|
|
|
788
841
|
try {
|
|
789
842
|
const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', o, of, taskEventInfo);
|
|
790
843
|
node.data.push(new SessionData(this._responseDto!));
|
|
791
|
-
|
|
792
844
|
if (cancelRequest()) return node;
|
|
793
|
-
|
|
794
|
-
if (this._automaticSceneUpdate) this.removeFromSceneTree(this._node);
|
|
795
|
-
this._node = node;
|
|
796
|
-
if (this._automaticSceneUpdate && this._closed === false) this.addToSceneTree(this._node);
|
|
797
|
-
|
|
798
|
-
this.node.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
|
|
799
|
-
|
|
845
|
+
node.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
|
|
800
846
|
return node;
|
|
801
847
|
}
|
|
802
848
|
catch (e) {
|
|
@@ -1139,6 +1185,8 @@ export class SessionEngine implements ISessionEngine {
|
|
|
1139
1185
|
const eventRequest: ITaskEvent = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.1 + taskEventInfo.progressRange.min : 0.1, data: eventData, status: 'Loading outputs' };
|
|
1140
1186
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
|
|
1141
1187
|
|
|
1188
|
+
const oldOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
1189
|
+
|
|
1142
1190
|
const newNode = await this.loadOutputs(() => this.#customizationProcess !== customizationId, {
|
|
1143
1191
|
eventId,
|
|
1144
1192
|
type: eventType,
|
|
@@ -1149,29 +1197,33 @@ export class SessionEngine implements ISessionEngine {
|
|
|
1149
1197
|
data: eventData
|
|
1150
1198
|
});
|
|
1151
1199
|
|
|
1200
|
+
const newOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
1201
|
+
|
|
1152
1202
|
const eventSceneUpdate: ITaskEvent = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.9 + taskEventInfo.progressRange.min : 0.9, data: eventData, status: 'Updating scene' };
|
|
1153
1203
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
|
|
1154
1204
|
|
|
1155
1205
|
// OPTION TO SKIP - PART 1
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1206
|
+
const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
|
|
1207
|
+
if (cancelResult) return cancelResult;
|
|
1208
|
+
|
|
1209
|
+
// call the update callbacks
|
|
1210
|
+
if (waitForViewportUpdate === false) {
|
|
1211
|
+
for (const outputId in this.outputs) {
|
|
1212
|
+
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
1213
|
+
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
|
|
1214
|
+
outputId: outputId,
|
|
1215
|
+
outputVersion: newOutputVersions[outputId],
|
|
1216
|
+
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
1217
|
+
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
1171
1223
|
|
|
1172
|
-
|
|
1173
|
-
this.
|
|
1174
|
-
|
|
1224
|
+
// OPTION TO SKIP - PART 2
|
|
1225
|
+
const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
|
|
1226
|
+
if (cancelResult) return cancelResult;
|
|
1175
1227
|
}
|
|
1176
1228
|
|
|
1177
1229
|
if (this.automaticSceneUpdate) this.removeFromSceneTree(this.node);
|
|
@@ -1207,20 +1259,28 @@ export class SessionEngine implements ISessionEngine {
|
|
|
1207
1259
|
}
|
|
1208
1260
|
|
|
1209
1261
|
// update the viewports
|
|
1210
|
-
if (waitForViewportUpdate)
|
|
1262
|
+
if (waitForViewportUpdate) {
|
|
1211
1263
|
for (const r in this._stateEngine.renderingEngines)
|
|
1212
1264
|
if (!this.excludeViewports.includes(this._stateEngine.renderingEngines[r].id))
|
|
1213
1265
|
this._stateEngine.renderingEngines[r].update(`SessionEngine(${this.id}).updateOutputs`);
|
|
1214
1266
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1267
|
+
for (const outputId in this.outputs) {
|
|
1268
|
+
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
1269
|
+
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
|
|
1270
|
+
outputId: outputId,
|
|
1271
|
+
outputVersion: newOutputVersions[outputId],
|
|
1272
|
+
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
1273
|
+
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1217
1277
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1278
|
+
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
1279
|
+
|
|
1280
|
+
// OPTION TO SKIP - PART 3
|
|
1281
|
+
const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
|
|
1282
|
+
if (cancelResult) return cancelResult;
|
|
1283
|
+
}
|
|
1224
1284
|
|
|
1225
1285
|
return this.node;
|
|
1226
1286
|
}
|
|
@@ -1258,9 +1318,9 @@ export class SessionEngine implements ISessionEngine {
|
|
|
1258
1318
|
}
|
|
1259
1319
|
}
|
|
1260
1320
|
|
|
1261
|
-
// #endregion Public Methods (
|
|
1321
|
+
// #endregion Public Methods (27)
|
|
1262
1322
|
|
|
1263
|
-
// #region Private Methods (
|
|
1323
|
+
// #region Private Methods (13)
|
|
1264
1324
|
|
|
1265
1325
|
private _saveSessionSettings() {
|
|
1266
1326
|
const parameters = this.parameters;
|
|
@@ -1337,6 +1397,35 @@ export class SessionEngine implements ISessionEngine {
|
|
|
1337
1397
|
this._sceneTree.root.updateVersion();
|
|
1338
1398
|
}
|
|
1339
1399
|
|
|
1400
|
+
private cancelProcess(customizationId: string, eventId: string, eventType: TASK_TYPE, eventProgress: number, eventData: unknown, newNode: ITreeNode = new SessionTreeNode()): ITreeNode | undefined {
|
|
1401
|
+
if (this.#customizationProcess !== customizationId) {
|
|
1402
|
+
for (const r in this._stateEngine.renderingEngines)
|
|
1403
|
+
if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
|
|
1404
|
+
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
|
|
1405
|
+
|
|
1406
|
+
const eventCancel: ITaskEvent = {
|
|
1407
|
+
type: eventType,
|
|
1408
|
+
id: eventId,
|
|
1409
|
+
progress: eventProgress,
|
|
1410
|
+
data: eventData,
|
|
1411
|
+
status: 'The request was exceeded by another customization request'
|
|
1412
|
+
};
|
|
1413
|
+
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel);
|
|
1414
|
+
this._logger.debug(`Session(${this.id}).cancelProcess: The request was was exceeded by another request.`);
|
|
1415
|
+
return newNode;
|
|
1416
|
+
} else if ((this._closed as boolean) === true) {
|
|
1417
|
+
for (const r in this._stateEngine.renderingEngines)
|
|
1418
|
+
if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
|
|
1419
|
+
this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
|
|
1420
|
+
|
|
1421
|
+
this._logger.debug(`Session(${this.id}).cancelProcess: The session was closed during the request.`);
|
|
1422
|
+
|
|
1423
|
+
const eventCancel: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'The session was closed during the request.' };
|
|
1424
|
+
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel);
|
|
1425
|
+
return new SessionTreeNode();
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1340
1429
|
private checkAvailability(action?: string, checkForModelId = false) {
|
|
1341
1430
|
if (!this._responseDto)
|
|
1342
1431
|
throw new ShapeDiverViewerSessionError('Session.checkAvailability: responseDto not available.');
|
|
@@ -1385,22 +1474,33 @@ export class SessionEngine implements ISessionEngine {
|
|
|
1385
1474
|
}
|
|
1386
1475
|
|
|
1387
1476
|
private async customizeInternal(cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo): Promise<ISessionTreeNode> {
|
|
1388
|
-
return this.customizeSession(this._parameterValues, cancelRequest, taskEventInfo)
|
|
1477
|
+
return this.customizeSession(this._parameterValues, cancelRequest, taskEventInfo) as Promise<ISessionTreeNode>;
|
|
1389
1478
|
}
|
|
1390
1479
|
|
|
1391
|
-
private async customizeSession(parameters: { [key: string]: string }, cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo, parallel = false, retry = false): Promise<ISessionTreeNode> {
|
|
1480
|
+
private async customizeSession(parameters: { [key: string]: string }, cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo, parallel = false, loadOutputs = true, retry = false): Promise<ISessionTreeNode | ShapeDiverResponseDto> {
|
|
1392
1481
|
this.checkAvailability('customize');
|
|
1393
1482
|
try {
|
|
1394
1483
|
this._performanceEvaluator.startSection('sessionResponse');
|
|
1395
1484
|
const responseDto = await this._sdk.utils.submitAndWaitForCustomization(this._sdk, this._sessionId!, parameters);
|
|
1396
1485
|
this._performanceEvaluator.endSection('sessionResponse');
|
|
1397
|
-
if (
|
|
1398
|
-
|
|
1399
|
-
|
|
1486
|
+
if (loadOutputs === true) {
|
|
1487
|
+
if (cancelRequest()) return new SessionTreeNode();
|
|
1488
|
+
if (parallel === true) {
|
|
1489
|
+
// special case, we load the outputs put don't add them to the scene
|
|
1490
|
+
return this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo);
|
|
1491
|
+
} else {
|
|
1492
|
+
// default case, we load the outputs and return the nodes
|
|
1493
|
+
this.updateResponseDto(responseDto);
|
|
1494
|
+
return this.loadOutputs(cancelRequest, taskEventInfo);
|
|
1495
|
+
}
|
|
1496
|
+
} else {
|
|
1497
|
+
// special case, we don't load the outputs and only return the responseDto
|
|
1498
|
+
return responseDto;
|
|
1499
|
+
}
|
|
1400
1500
|
} catch (e) {
|
|
1401
1501
|
await this.handleError(e, retry);
|
|
1402
1502
|
if (cancelRequest()) return new SessionTreeNode();
|
|
1403
|
-
return await this.customizeSession(parameters, cancelRequest, taskEventInfo, parallel, true);
|
|
1503
|
+
return await this.customizeSession(parameters, cancelRequest, taskEventInfo, parallel, loadOutputs, true);
|
|
1404
1504
|
}
|
|
1405
1505
|
}
|
|
1406
1506
|
|
|
@@ -1585,5 +1685,24 @@ export class SessionEngine implements ISessionEngine {
|
|
|
1585
1685
|
}
|
|
1586
1686
|
}
|
|
1587
1687
|
|
|
1588
|
-
|
|
1688
|
+
private async waitForUpdateCallbacks(newOutputVersions: { [key: string]: string }, oldOutputVersions: { [key: string]: string }, newNode: ITreeNode, oldNode: ITreeNode) {
|
|
1689
|
+
// call the update callback function on the session
|
|
1690
|
+
if (this._updateCallback) await Promise.resolve(this._updateCallback(newNode, oldNode));
|
|
1691
|
+
|
|
1692
|
+
const promises = [];
|
|
1693
|
+
// call the update callback functions on the outputs
|
|
1694
|
+
for (const outputId in this.outputs) {
|
|
1695
|
+
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
1696
|
+
promises.push(
|
|
1697
|
+
this.outputs[outputId].triggerUpdateCallback(
|
|
1698
|
+
newNode.children.find(c => c.name === outputId)!,
|
|
1699
|
+
oldNode.children.find(c => c.name === outputId)!
|
|
1700
|
+
)
|
|
1701
|
+
);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
await Promise.all(promises);
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
// #endregion Private Methods (13)
|
|
1589
1708
|
}
|
|
@@ -173,8 +173,8 @@ export class Output implements IOutput {
|
|
|
173
173
|
|
|
174
174
|
// #region Public Methods (4)
|
|
175
175
|
|
|
176
|
-
public triggerUpdateCallback(newNode?: TreeNode, oldNode?: TreeNode) {
|
|
177
|
-
if (this.#updateCallback) this.#updateCallback(newNode, oldNode);
|
|
176
|
+
public async triggerUpdateCallback(newNode?: TreeNode, oldNode?: TreeNode) {
|
|
177
|
+
if (this.#updateCallback) await Promise.resolve(this.#updateCallback(newNode, oldNode));
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -130,11 +130,12 @@ export interface ISessionEngine {
|
|
|
130
130
|
canGoBack(): boolean;
|
|
131
131
|
canGoForward(): boolean;
|
|
132
132
|
close(): Promise<void>;
|
|
133
|
-
customize(force: boolean, waitForViewportUpdate?: boolean):
|
|
134
|
-
customizeParallel(parameterValues: { [key: string]: string }): Promise<ITreeNode>;
|
|
133
|
+
customize(force: boolean, waitForViewportUpdate?: boolean):Promise<ITreeNode | ShapeDiverResponseDto>;
|
|
134
|
+
customizeParallel(parameterValues: { [key: string]: string }, loadOutputs: boolean): Promise<ITreeNode | ShapeDiverResponseDto>;
|
|
135
135
|
goBack(): Promise<ITreeNode>;
|
|
136
136
|
goForward(): Promise<ITreeNode>;
|
|
137
137
|
init(parameterValues?: { [key: string]: string; }): Promise<void>;
|
|
138
|
+
loadCachedOutputsParallel(outputMapping: { [key: string]: string }, taskEventInfo?: OutputLoaderTaskEventInfo, retry?: boolean): Promise<{ [key: string]: ITreeNode | undefined }>;
|
|
138
139
|
loadOutputs(cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo): Promise<ITreeNode>;
|
|
139
140
|
loadOutputsParallel(responseDto: ShapeDiverResponseDto, cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo): Promise<ITreeNode>;
|
|
140
141
|
requestExport(exportId: string, parameters: ShapeDiverRequestCustomization, maxWaitTime: number): Promise<ShapeDiverResponseExport>;
|