@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.
@@ -185,7 +185,7 @@ class SessionEngine {
185
185
  return this._viewerSettings;
186
186
  }
187
187
  // #endregion Public Accessors (25)
188
- // #region Public Methods (25)
188
+ // #region Public Methods (27)
189
189
  applySettings(response, sections) {
190
190
  sections = sections || {};
191
191
  if (sections.session === undefined) {
@@ -232,7 +232,7 @@ class SessionEngine {
232
232
  if (sections.session.parameter.hidden)
233
233
  this.parameters[p].hidden = settings.session[p].hidden || false;
234
234
  }
235
- if (response.parameters && response.parameters[p]) {
235
+ if (response.parameters && response.parameters[p] && !((this.parameters[p] instanceof FileParameter_1.FileParameter) || this.parameters[p].type.startsWith('s'))) {
236
236
  if (sections.session.parameter.value)
237
237
  this.parameters[p].value = response.parameters[p].defval !== undefined ? response.parameters[p].defval : this.parameters[p].value;
238
238
  }
@@ -318,6 +318,14 @@ class SessionEngine {
318
318
  canGoForward() {
319
319
  return __classPrivateFieldGet(this, _SessionEngine_parameterHistoryForward, "f").length > 0;
320
320
  }
321
+ cancelCustomization() {
322
+ if (__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f")) {
323
+ for (const r in this._stateEngine.renderingEngines)
324
+ if (this._stateEngine.renderingEngines[r].busy.includes(__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f")))
325
+ this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f")), 1);
326
+ }
327
+ __classPrivateFieldSet(this, _SessionEngine_customizationProcess, undefined, "f");
328
+ }
321
329
  close(retry = false) {
322
330
  return __awaiter(this, void 0, void 0, function* () {
323
331
  this.checkAvailability('close');
@@ -370,45 +378,15 @@ class SessionEngine {
370
378
  if (this.parameters[parameterId] instanceof FileParameter_1.FileParameter) {
371
379
  fileParameterIds[parameterId] = yield this.parameters[parameterId].upload();
372
380
  // OPTION TO SKIP - PART 1a
373
- if (__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f") !== customizationId) {
374
- for (const r in this._stateEngine.renderingEngines)
375
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
376
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
377
- this._logger.debug(`Session(${this.id}).customize: Session customization was exceeded by other customization request.`);
378
- const eventCancel1a = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customization was exceeded by other customization request' };
379
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel1a);
380
- return new SessionTreeNode_1.SessionTreeNode();
381
- }
382
- else if (this._closed === true) {
383
- for (const r in this._stateEngine.renderingEngines)
384
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
385
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
386
- this._logger.debug(`Session(${this.id}).customize: Session was closed during customization request.`);
387
- const eventCancel1a = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session was closed during customization request' };
388
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel1a);
389
- return new SessionTreeNode_1.SessionTreeNode();
390
- }
381
+ const cancelResult = this.cancelProcess(customizationId, eventId, viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
382
+ if (cancelResult)
383
+ return cancelResult;
391
384
  }
392
385
  }
393
386
  // OPTION TO SKIP - PART 1b
394
- if (__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f") !== customizationId) {
395
- for (const r in this._stateEngine.renderingEngines)
396
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
397
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
398
- const eventCancel1b = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customization was exceeded by other customization request' };
399
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel1b);
400
- this._logger.debug(`Session(${this.id}).customize: Session customization was exceeded by other customization request.`);
401
- return new SessionTreeNode_1.SessionTreeNode();
402
- }
403
- else if (this._closed === true) {
404
- for (const r in this._stateEngine.renderingEngines)
405
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
406
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
407
- this._logger.debug(`Session(${this.id}).customize: Session was closed during customization request.`);
408
- const eventCancel1b = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session was closed during customization request' };
409
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel1b);
410
- return new SessionTreeNode_1.SessionTreeNode();
411
- }
387
+ const cancelResult = this.cancelProcess(customizationId, eventId, viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
388
+ if (cancelResult)
389
+ return cancelResult;
412
390
  // assign the uploaded parameters
413
391
  for (const parameterId in fileParameterIds)
414
392
  this.parameters[parameterId].value = fileParameterIds[parameterId];
@@ -426,6 +404,7 @@ class SessionEngine {
426
404
  this._logger.info(`Session(${this.id}).customize: Customizing session with parameters ${JSON.stringify(this.parameterValues)}.`);
427
405
  const eventRequest = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.1, data: { sessionId: this.id }, status: 'Sending customization request' };
428
406
  this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
407
+ const oldOutputVersions = this._outputLoader.getCurrentOutputVersions();
429
408
  const newNode = yield this.customizeInternal(() => __classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f") !== customizationId, {
430
409
  eventId,
431
410
  type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION,
@@ -435,26 +414,29 @@ class SessionEngine {
435
414
  },
436
415
  data: { sessionId: this.id }
437
416
  });
417
+ // OPTION TO SKIP - PART 2
418
+ const cancelResult2 = this.cancelProcess(customizationId, eventId, viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
419
+ if (cancelResult2)
420
+ return cancelResult2;
421
+ const newOutputVersions = this._outputLoader.getCurrentOutputVersions();
438
422
  const eventSceneUpdate = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.9, data: { sessionId: this.id }, status: 'Updating scene' };
439
423
  this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
440
- // OPTION TO SKIP - PART 2
441
- if (__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f") !== customizationId) {
442
- for (const r in this._stateEngine.renderingEngines)
443
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
444
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
445
- const eventCancel2 = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customization was exceeded by other customization request' };
446
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel2);
447
- this._logger.debug(`Session(${this.id}).customize: Session customization was exceeded by other customization request.`);
448
- return newNode;
449
- }
450
- else if (this._closed === true) { // I get a TS warning here that the type of _closed is "false", I think TS doesn't get that there is a promise inbetween
451
- for (const r in this._stateEngine.renderingEngines)
452
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
453
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
454
- this._logger.debug(`Session(${this.id}).customize: Session was closed during customization request.`);
455
- const eventCancel2 = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session was closed during customization request' };
456
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel2);
457
- return new SessionTreeNode_1.SessionTreeNode();
424
+ // call the update callbacks
425
+ if (waitForViewportUpdate === false) {
426
+ for (const outputId in this.outputs) {
427
+ if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
428
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
429
+ outputId: outputId,
430
+ outputVersion: newOutputVersions[outputId],
431
+ newNode: newNode.children.find(c => c.name === outputId),
432
+ oldNode: oldNode.children.find(c => c.name === outputId)
433
+ });
434
+ }
435
+ }
436
+ yield this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
437
+ const cancelResult = this.cancelProcess(customizationId, eventId, viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
438
+ if (cancelResult)
439
+ return cancelResult;
458
440
  }
459
441
  // if this is not a call by the goBack or goForward functions, add the parameter values to the history and delete the forward history
460
442
  if (!__classPrivateFieldGet(this, _SessionEngine_parameterHistoryCall, "f")) {
@@ -486,16 +468,33 @@ class SessionEngine {
486
468
  const eventEnd = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customized' };
487
469
  this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_END, eventEnd);
488
470
  // update the viewports
489
- if (waitForViewportUpdate)
471
+ if (waitForViewportUpdate) {
490
472
  for (const r in this._stateEngine.renderingEngines)
491
473
  if (!this.excludeViewports.includes(this._stateEngine.renderingEngines[r].id))
492
474
  this._stateEngine.renderingEngines[r].update(`SessionEngine(${this.id}).customize`);
493
- // call the update callback function on the session
494
- if (this._updateCallback)
495
- this._updateCallback(newNode, oldNode);
496
- // call the update callback functions on the outputs
497
- for (const outputId in this.outputs)
498
- this.outputs[outputId].triggerUpdateCallback(newNode.children.find(c => c.name === outputId), oldNode.children.find(c => c.name === outputId));
475
+ for (const outputId in this.outputs) {
476
+ if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
477
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
478
+ outputId: outputId,
479
+ outputVersion: newOutputVersions[outputId],
480
+ newNode: newNode.children.find(c => c.name === outputId),
481
+ oldNode: oldNode.children.find(c => c.name === outputId)
482
+ });
483
+ }
484
+ }
485
+ // call the update callbacks
486
+ yield this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
487
+ const cancelResult = this.cancelProcess(customizationId, eventId, viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
488
+ if (cancelResult)
489
+ return cancelResult;
490
+ }
491
+ if (!waitForViewportUpdate) {
492
+ setTimeout(() => {
493
+ for (const r in this._stateEngine.renderingEngines)
494
+ if (!this.excludeViewports.includes(this._stateEngine.renderingEngines[r].id))
495
+ this._stateEngine.renderingEngines[r].update(`SessionEngine(${this.id}).customize`);
496
+ }, 0);
497
+ }
499
498
  return this.node;
500
499
  }
501
500
  catch (e) {
@@ -508,7 +507,7 @@ class SessionEngine {
508
507
  }
509
508
  });
510
509
  }
511
- customizeParallel(parameterValues) {
510
+ customizeParallel(parameterValues, loadOutputs = true) {
512
511
  return __awaiter(this, void 0, void 0, function* () {
513
512
  const eventId = this._uuidGenerator.create();
514
513
  const eventStart = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0, data: { sessionId: this.id }, status: 'Customizing session' };
@@ -517,7 +516,7 @@ class SessionEngine {
517
516
  // create a set of the current validated parameter values
518
517
  for (const parameterId in this.parameters)
519
518
  parameterSet[parameterId] = parameterValues[parameterId] !== undefined ? (' ' + parameterValues[parameterId]).slice(1) : this.parameters[parameterId].stringify();
520
- const newNode = yield this.customizeSession(parameterSet, () => false, {
519
+ const result = yield this.customizeSession(parameterSet, () => false, {
521
520
  eventId,
522
521
  type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION,
523
522
  progressRange: {
@@ -525,11 +524,12 @@ class SessionEngine {
525
524
  max: 1
526
525
  },
527
526
  data: { sessionId: this.id }
528
- }, true);
529
- newNode.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
527
+ }, true, loadOutputs);
528
+ if (result instanceof SessionTreeNode_1.SessionTreeNode)
529
+ result.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
530
530
  const eventEnd = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customized' };
531
531
  this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_END, eventEnd);
532
- return newNode;
532
+ return result;
533
533
  });
534
534
  }
535
535
  goBack() {
@@ -621,6 +621,55 @@ class SessionEngine {
621
621
  }
622
622
  });
623
623
  }
624
+ loadCachedOutputsParallel(outputMapping, taskEventInfo, retry = false) {
625
+ var _a;
626
+ return __awaiter(this, void 0, void 0, function* () {
627
+ this.checkAvailability();
628
+ // if there is already task event info, use it
629
+ // this happens after a retry
630
+ const eventId = taskEventInfo ? taskEventInfo.eventId : this._uuidGenerator.create();
631
+ const eventType = taskEventInfo ? taskEventInfo.type : viewer_shared_types_1.TASK_TYPE.SESSION_OUTPUTS_LOADING;
632
+ const eventData = taskEventInfo ? taskEventInfo.data : { sessionId: this.id };
633
+ taskEventInfo = taskEventInfo ? taskEventInfo : {
634
+ eventId,
635
+ type: eventType,
636
+ progressRange: {
637
+ min: 0,
638
+ max: 1
639
+ },
640
+ data: eventData
641
+ };
642
+ try {
643
+ // send start event if this function was called initially
644
+ if (!taskEventInfo) {
645
+ const eventStart = { type: eventType, id: eventId, progress: 0, data: eventData, status: 'Loading cached outputs' };
646
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_START, eventStart);
647
+ }
648
+ // get the cached outputs
649
+ const responseDto = yield this._sdk.output.getCache(this._sessionId, outputMapping);
650
+ // create atomic output api objects for them
651
+ const outputs = {};
652
+ for (const outputId in responseDto.outputs) {
653
+ responseDto.outputs[outputId].id = outputId;
654
+ outputs[outputId] = new Output_1.Output(responseDto.outputs[outputId], this);
655
+ }
656
+ // process the output data
657
+ const node = yield this._outputLoader.loadOutputs(((_a = this._responseDto.model) === null || _a === void 0 ? void 0 : _a.name) || 'model', outputs, {}, taskEventInfo, false);
658
+ // send the end event once done
659
+ const eventEnd = { type: eventType, id: eventId, progress: 1, data: eventData, status: 'Loaded cached outputs' };
660
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_END, eventEnd);
661
+ // create a mapping with a dictionary for the id of the outputs
662
+ const outputNodeMapping = {};
663
+ for (const outputId in outputMapping)
664
+ outputNodeMapping[outputId] = node.children.find(n => n.name === outputId);
665
+ return outputNodeMapping;
666
+ }
667
+ catch (e) {
668
+ yield this.handleError(e, retry);
669
+ return yield this.loadCachedOutputsParallel(outputMapping, taskEventInfo, true);
670
+ }
671
+ });
672
+ }
624
673
  /**
625
674
  * Load the outputs and return the scene graph node of the result.
626
675
  * In case the outputs have a delay property, another customization request with the parameter set is sent.
@@ -640,12 +689,7 @@ class SessionEngine {
640
689
  node.data.push(new SessionData_1.SessionData(this._responseDto));
641
690
  if (cancelRequest())
642
691
  return node;
643
- if (this._automaticSceneUpdate)
644
- this.removeFromSceneTree(this._node);
645
- this._node = node;
646
- if (this._automaticSceneUpdate && this._closed === false)
647
- this.addToSceneTree(this._node);
648
- this.node.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
692
+ node.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
649
693
  return node;
650
694
  }
651
695
  catch (e) {
@@ -968,6 +1012,7 @@ class SessionEngine {
968
1012
  this._stateEngine.renderingEngines[r].busy.push(customizationId);
969
1013
  const eventRequest = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.1 + taskEventInfo.progressRange.min : 0.1, data: eventData, status: 'Loading outputs' };
970
1014
  this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
1015
+ const oldOutputVersions = this._outputLoader.getCurrentOutputVersions();
971
1016
  const newNode = yield this.loadOutputs(() => __classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f") !== customizationId, {
972
1017
  eventId,
973
1018
  type: eventType,
@@ -977,26 +1022,30 @@ class SessionEngine {
977
1022
  },
978
1023
  data: eventData
979
1024
  });
1025
+ const newOutputVersions = this._outputLoader.getCurrentOutputVersions();
980
1026
  const eventSceneUpdate = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.9 + taskEventInfo.progressRange.min : 0.9, data: eventData, status: 'Updating scene' };
981
1027
  this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
982
1028
  // OPTION TO SKIP - PART 1
983
- if (__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f") !== customizationId) {
984
- for (const r in this._stateEngine.renderingEngines)
985
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
986
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
987
- const eventCancel1 = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, data: eventData, status: 'Output updating was exceeded by other customization request' };
988
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel1);
989
- this._logger.debug(`Session(${this.id}).updateOutputs: Output updating was exceeded by other request.`);
990
- return newNode;
991
- }
992
- else if (this._closed === true) {
993
- for (const r in this._stateEngine.renderingEngines)
994
- if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
995
- this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
996
- this._logger.debug(`Session(${this.id}).customize: Session was closed during customization request.`);
997
- const eventCancel1a = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session was closed during customization request' };
998
- this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel1a);
999
- return new SessionTreeNode_1.SessionTreeNode();
1029
+ const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
1030
+ if (cancelResult)
1031
+ return cancelResult;
1032
+ // call the update callbacks
1033
+ if (waitForViewportUpdate === false) {
1034
+ for (const outputId in this.outputs) {
1035
+ if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
1036
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
1037
+ outputId: outputId,
1038
+ outputVersion: newOutputVersions[outputId],
1039
+ newNode: newNode.children.find(c => c.name === outputId),
1040
+ oldNode: oldNode.children.find(c => c.name === outputId)
1041
+ });
1042
+ }
1043
+ }
1044
+ yield this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
1045
+ // OPTION TO SKIP - PART 2
1046
+ const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
1047
+ if (cancelResult)
1048
+ return cancelResult;
1000
1049
  }
1001
1050
  if (this.automaticSceneUpdate)
1002
1051
  this.removeFromSceneTree(this.node);
@@ -1022,16 +1071,26 @@ class SessionEngine {
1022
1071
  this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_END, eventEnd);
1023
1072
  }
1024
1073
  // update the viewports
1025
- if (waitForViewportUpdate)
1074
+ if (waitForViewportUpdate) {
1026
1075
  for (const r in this._stateEngine.renderingEngines)
1027
1076
  if (!this.excludeViewports.includes(this._stateEngine.renderingEngines[r].id))
1028
1077
  this._stateEngine.renderingEngines[r].update(`SessionEngine(${this.id}).updateOutputs`);
1029
- // call the update callback function on the session
1030
- if (this._updateCallback)
1031
- this._updateCallback(newNode, oldNode);
1032
- // call the update callback functions on the outputs
1033
- for (const outputId in this.outputs)
1034
- this.outputs[outputId].triggerUpdateCallback(newNode.children.find(c => c.name === outputId), oldNode.children.find(c => c.name === outputId));
1078
+ for (const outputId in this.outputs) {
1079
+ if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
1080
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
1081
+ outputId: outputId,
1082
+ outputVersion: newOutputVersions[outputId],
1083
+ newNode: newNode.children.find(c => c.name === outputId),
1084
+ oldNode: oldNode.children.find(c => c.name === outputId)
1085
+ });
1086
+ }
1087
+ }
1088
+ yield this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
1089
+ // OPTION TO SKIP - PART 3
1090
+ const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
1091
+ if (cancelResult)
1092
+ return cancelResult;
1093
+ }
1035
1094
  return this.node;
1036
1095
  });
1037
1096
  }
@@ -1072,8 +1131,8 @@ class SessionEngine {
1072
1131
  }
1073
1132
  });
1074
1133
  }
1075
- // #endregion Public Methods (25)
1076
- // #region Private Methods (11)
1134
+ // #endregion Public Methods (27)
1135
+ // #region Private Methods (13)
1077
1136
  _saveSessionSettings() {
1078
1137
  const parameters = this.parameters;
1079
1138
  const exports = this.exports;
@@ -1137,6 +1196,32 @@ class SessionEngine {
1137
1196
  this._sceneTree.addNode(node);
1138
1197
  this._sceneTree.root.updateVersion();
1139
1198
  }
1199
+ cancelProcess(customizationId, eventId, eventType, eventProgress, eventData, newNode = new SessionTreeNode_1.SessionTreeNode()) {
1200
+ if (__classPrivateFieldGet(this, _SessionEngine_customizationProcess, "f") !== customizationId) {
1201
+ for (const r in this._stateEngine.renderingEngines)
1202
+ if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
1203
+ this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
1204
+ const eventCancel = {
1205
+ type: eventType,
1206
+ id: eventId,
1207
+ progress: eventProgress,
1208
+ data: eventData,
1209
+ status: 'The request was exceeded by another customization request'
1210
+ };
1211
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel);
1212
+ this._logger.debug(`Session(${this.id}).cancelProcess: The request was was exceeded by another request.`);
1213
+ return newNode;
1214
+ }
1215
+ else if (this._closed === true) {
1216
+ for (const r in this._stateEngine.renderingEngines)
1217
+ if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
1218
+ this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
1219
+ this._logger.debug(`Session(${this.id}).cancelProcess: The session was closed during the request.`);
1220
+ const eventCancel = { type: viewer_shared_types_1.TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'The session was closed during the request.' };
1221
+ this._eventEngine.emitEvent(viewer_shared_services_1.EVENTTYPE.TASK.TASK_CANCEL, eventCancel);
1222
+ return new SessionTreeNode_1.SessionTreeNode();
1223
+ }
1224
+ }
1140
1225
  checkAvailability(action, checkForModelId = false) {
1141
1226
  var _a;
1142
1227
  if (!this._responseDto)
@@ -1180,24 +1265,36 @@ class SessionEngine {
1180
1265
  return this.customizeSession(this._parameterValues, cancelRequest, taskEventInfo);
1181
1266
  });
1182
1267
  }
1183
- customizeSession(parameters, cancelRequest, taskEventInfo, parallel = false, retry = false) {
1268
+ customizeSession(parameters, cancelRequest, taskEventInfo, parallel = false, loadOutputs = true, retry = false) {
1184
1269
  return __awaiter(this, void 0, void 0, function* () {
1185
1270
  this.checkAvailability('customize');
1186
1271
  try {
1187
1272
  this._performanceEvaluator.startSection('sessionResponse');
1188
1273
  const responseDto = yield this._sdk.utils.submitAndWaitForCustomization(this._sdk, this._sessionId, parameters);
1189
1274
  this._performanceEvaluator.endSection('sessionResponse');
1190
- if (cancelRequest())
1191
- return new SessionTreeNode_1.SessionTreeNode();
1192
- if (parallel === false)
1193
- this.updateResponseDto(responseDto);
1194
- return parallel === false ? this.loadOutputs(cancelRequest, taskEventInfo) : this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo);
1275
+ if (loadOutputs === true) {
1276
+ if (cancelRequest())
1277
+ return new SessionTreeNode_1.SessionTreeNode();
1278
+ if (parallel === true) {
1279
+ // special case, we load the outputs put don't add them to the scene
1280
+ return this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo);
1281
+ }
1282
+ else {
1283
+ // default case, we load the outputs and return the nodes
1284
+ this.updateResponseDto(responseDto);
1285
+ return this.loadOutputs(cancelRequest, taskEventInfo);
1286
+ }
1287
+ }
1288
+ else {
1289
+ // special case, we don't load the outputs and only return the responseDto
1290
+ return responseDto;
1291
+ }
1195
1292
  }
1196
1293
  catch (e) {
1197
1294
  yield this.handleError(e, retry);
1198
1295
  if (cancelRequest())
1199
1296
  return new SessionTreeNode_1.SessionTreeNode();
1200
- return yield this.customizeSession(parameters, cancelRequest, taskEventInfo, parallel, true);
1297
+ return yield this.customizeSession(parameters, cancelRequest, taskEventInfo, parallel, loadOutputs, true);
1201
1298
  }
1202
1299
  });
1203
1300
  }
@@ -1381,6 +1478,21 @@ class SessionEngine {
1381
1478
  }
1382
1479
  }
1383
1480
  }
1481
+ waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode) {
1482
+ return __awaiter(this, void 0, void 0, function* () {
1483
+ // call the update callback function on the session
1484
+ if (this._updateCallback)
1485
+ yield Promise.resolve(this._updateCallback(newNode, oldNode));
1486
+ const promises = [];
1487
+ // call the update callback functions on the outputs
1488
+ for (const outputId in this.outputs) {
1489
+ if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
1490
+ promises.push(this.outputs[outputId].triggerUpdateCallback(newNode.children.find(c => c.name === outputId), oldNode.children.find(c => c.name === outputId)));
1491
+ }
1492
+ }
1493
+ yield Promise.all(promises);
1494
+ });
1495
+ }
1384
1496
  }
1385
1497
  exports.SessionEngine = SessionEngine;
1386
1498
  _SessionEngine_customizationProcess = new WeakMap(), _SessionEngine_parameterHistory = new WeakMap(), _SessionEngine_parameterHistoryCall = new WeakMap(), _SessionEngine_parameterHistoryForward = new WeakMap();