@shapediver/viewer.session-engine.session-engine 3.3.3 → 3.3.6
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/SessionEngine.d.ts.map +1 -1
- package/dist/implementation/SessionEngine.js +18 -3
- package/dist/implementation/SessionEngine.js.map +1 -1
- package/dist/implementation/dto/DrawingParameter.d.ts +13 -0
- package/dist/implementation/dto/DrawingParameter.d.ts.map +1 -0
- package/dist/implementation/dto/DrawingParameter.js +43 -0
- package/dist/implementation/dto/DrawingParameter.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/dto/IDrawingParameter.d.ts +5 -0
- package/dist/interfaces/dto/IDrawingParameter.d.ts.map +1 -0
- package/dist/interfaces/dto/IDrawingParameter.js +3 -0
- package/dist/interfaces/dto/IDrawingParameter.js.map +1 -0
- package/dist/interfaces/dto/IDrawingToolsParameter.d.ts +5 -0
- package/dist/interfaces/dto/IDrawingToolsParameter.d.ts.map +1 -0
- package/dist/interfaces/dto/IDrawingToolsParameter.js +3 -0
- package/dist/interfaces/dto/IDrawingToolsParameter.js.map +1 -0
- package/package.json +10 -11
- package/src/implementation/OutputDelayException.ts +0 -22
- package/src/implementation/OutputLoader.ts +0 -378
- package/src/implementation/SessionData.ts +0 -44
- package/src/implementation/SessionEngine.ts +0 -2006
- package/src/implementation/SessionOutputData.ts +0 -44
- package/src/implementation/SessionTreeNode.ts +0 -44
- package/src/implementation/dto/Export.ts +0 -231
- package/src/implementation/dto/FileParameter.ts +0 -117
- package/src/implementation/dto/Output.ts +0 -223
- package/src/implementation/dto/Parameter.ts +0 -370
- package/src/implementation/dto/interaction/GumballParameter.ts +0 -78
- package/src/implementation/dto/interaction/SelectionParameter.ts +0 -66
- package/src/index.ts +0 -27
- package/src/interfaces/ISessionData.ts +0 -16
- package/src/interfaces/ISessionEngine.ts +0 -69
- package/src/interfaces/ISessionOutputData.ts +0 -16
- package/src/interfaces/ISessionTreeNode.ts +0 -9
- package/src/interfaces/dto/IExport.ts +0 -17
- package/src/interfaces/dto/IFileParameter.ts +0 -10
- package/src/interfaces/dto/IOutput.ts +0 -58
- package/src/interfaces/dto/IParameter.ts +0 -19
- package/src/interfaces/dto/interaction/IGumballParameter.ts +0 -5
- package/src/interfaces/dto/interaction/IInteractionParameter.ts +0 -10
- package/src/interfaces/dto/interaction/ISelectionParameter.ts +0 -5
- package/tsconfig.json +0 -17
|
@@ -1,2006 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
convert,
|
|
3
|
-
ISettings,
|
|
4
|
-
latestVersion,
|
|
5
|
-
validate,
|
|
6
|
-
versions
|
|
7
|
-
} from '@shapediver/viewer.settings';
|
|
8
|
-
import {
|
|
9
|
-
Converter,
|
|
10
|
-
EventEngine,
|
|
11
|
-
EVENTTYPE,
|
|
12
|
-
HttpClient,
|
|
13
|
-
HttpResponse,
|
|
14
|
-
Logger,
|
|
15
|
-
PerformanceEvaluator,
|
|
16
|
-
SettingsEngine,
|
|
17
|
-
ShapeDiverViewerError,
|
|
18
|
-
ShapeDiverViewerSessionError,
|
|
19
|
-
ShapeDiverViewerSettingsError,
|
|
20
|
-
StateEngine,
|
|
21
|
-
SystemInfo,
|
|
22
|
-
UuidGenerator
|
|
23
|
-
} from '@shapediver/viewer.shared.services';
|
|
24
|
-
import {
|
|
25
|
-
create,
|
|
26
|
-
isGBResponseError,
|
|
27
|
-
ShapeDiverError as ShapeDiverBackendError,
|
|
28
|
-
ShapeDiverRequestConfigure,
|
|
29
|
-
ShapeDiverRequestCustomization,
|
|
30
|
-
ShapeDiverRequestExport,
|
|
31
|
-
ShapeDiverRequestFileUploadPart,
|
|
32
|
-
ShapeDiverRequestGltfUploadQueryConversion,
|
|
33
|
-
ShapeDiverRequestModelState,
|
|
34
|
-
ShapeDiverResponseDto,
|
|
35
|
-
ShapeDiverResponseErrorType,
|
|
36
|
-
ShapeDiverResponseExport,
|
|
37
|
-
ShapeDiverResponseExportDefinitionType,
|
|
38
|
-
ShapeDiverResponseFileInfo,
|
|
39
|
-
ShapeDiverResponseModelComputationStatus,
|
|
40
|
-
ShapeDiverResponseModelState,
|
|
41
|
-
ShapeDiverResponseOutput,
|
|
42
|
-
ShapeDiverResponseParameter,
|
|
43
|
-
ShapeDiverSdk,
|
|
44
|
-
ShapeDiverSdkConfigType
|
|
45
|
-
} from '@shapediver/sdk.geometry-api-sdk-v2';
|
|
46
|
-
import { Export } from './dto/Export';
|
|
47
|
-
import { FileParameter } from './dto/FileParameter';
|
|
48
|
-
import { GumballParameter } from './dto/interaction/GumballParameter';
|
|
49
|
-
import { IExport } from '../interfaces/dto/IExport';
|
|
50
|
-
import { IFileParameter } from '../interfaces/dto/IFileParameter';
|
|
51
|
-
import {
|
|
52
|
-
IInteractionParameterSettings,
|
|
53
|
-
IOutputEvent,
|
|
54
|
-
ISettingsSections,
|
|
55
|
-
ITaskEvent,
|
|
56
|
-
PARAMETER_TYPE,
|
|
57
|
-
TASK_TYPE,
|
|
58
|
-
validateInteractionParameterSettings
|
|
59
|
-
} from '@shapediver/viewer.shared.types';
|
|
60
|
-
import { IOutput } from '../interfaces/dto/IOutput';
|
|
61
|
-
import { IParameter } from '../interfaces/dto/IParameter';
|
|
62
|
-
import { ISessionEngine } from '../interfaces/ISessionEngine';
|
|
63
|
-
import { ISessionTreeNode } from '../interfaces/ISessionTreeNode';
|
|
64
|
-
import {
|
|
65
|
-
ITree,
|
|
66
|
-
ITreeNode,
|
|
67
|
-
Tree,
|
|
68
|
-
TreeNode
|
|
69
|
-
} from '@shapediver/viewer.shared.node-tree';
|
|
70
|
-
import { Output } from './dto/Output';
|
|
71
|
-
import { OutputDelayException } from './OutputDelayException';
|
|
72
|
-
import { OutputLoader, OutputLoaderTaskEventInfo } from './OutputLoader';
|
|
73
|
-
import { Parameter } from './dto/Parameter';
|
|
74
|
-
import { SelectionParameter } from './dto/interaction/SelectionParameter';
|
|
75
|
-
import { SessionData } from './SessionData';
|
|
76
|
-
import { SessionTreeNode } from './SessionTreeNode';
|
|
77
|
-
import { vec3 } from 'gl-matrix';
|
|
78
|
-
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
79
|
-
|
|
80
|
-
export class SessionEngine implements ISessionEngine {
|
|
81
|
-
// #region Properties (50)
|
|
82
|
-
|
|
83
|
-
private readonly _converter = Converter.instance;
|
|
84
|
-
private readonly _eventEngine = EventEngine.instance;
|
|
85
|
-
private readonly _exports: { [key: string]: IExport; } = {};
|
|
86
|
-
private readonly _guid?: string;
|
|
87
|
-
private readonly _httpClient: HttpClient = HttpClient.instance;
|
|
88
|
-
private readonly _id: string;
|
|
89
|
-
private readonly _logger: Logger = Logger.instance;
|
|
90
|
-
private readonly _modelViewUrl: string;
|
|
91
|
-
private readonly _outputLoader: OutputLoader;
|
|
92
|
-
private readonly _outputs: { [key: string]: IOutput; } = {};
|
|
93
|
-
private readonly _outputsFreeze: { [key: string]: boolean; } = {};
|
|
94
|
-
private readonly _parameterValues: { [key: string]: string; } = {};
|
|
95
|
-
private readonly _parameters: { [key: string]: IParameter<unknown>; } = {};
|
|
96
|
-
private readonly _performanceEvaluator = PerformanceEvaluator.instance;
|
|
97
|
-
private readonly _sceneTree: ITree = Tree.instance;
|
|
98
|
-
private readonly _sessionEngineId = (UuidGenerator.instance).create();
|
|
99
|
-
private readonly _settingsEngine: SettingsEngine = new SettingsEngine();
|
|
100
|
-
private readonly _stateEngine: StateEngine = StateEngine.instance;
|
|
101
|
-
private readonly _ticket?: string;
|
|
102
|
-
private readonly _uuidGenerator = UuidGenerator.instance;
|
|
103
|
-
|
|
104
|
-
#customizationBusyModes: string[] = [];
|
|
105
|
-
#customizationProcess?: string;
|
|
106
|
-
#parameterHistory: {
|
|
107
|
-
[key: string]: {
|
|
108
|
-
value: unknown,
|
|
109
|
-
valueString: string
|
|
110
|
-
}
|
|
111
|
-
}[] = [];
|
|
112
|
-
#parameterHistoryCall = false;
|
|
113
|
-
#parameterHistoryForward: {
|
|
114
|
-
[key: string]: {
|
|
115
|
-
value: unknown,
|
|
116
|
-
valueString: string
|
|
117
|
-
}
|
|
118
|
-
}[] = [];
|
|
119
|
-
private _allowOutputLoading: boolean = true;
|
|
120
|
-
private _automaticSceneUpdate: boolean = true;
|
|
121
|
-
private _closeOnFailure: () => Promise<void> = async () => { };
|
|
122
|
-
private _closed: boolean = false;
|
|
123
|
-
private _customizeOnParameterChange: boolean = false;
|
|
124
|
-
private _dataCache: {
|
|
125
|
-
[key: string]: Promise<HttpResponse<unknown>>
|
|
126
|
-
} = {};
|
|
127
|
-
private _excludeViewports: string[] = [];
|
|
128
|
-
private _headers = {
|
|
129
|
-
'X-ShapeDiver-Origin': (SystemInfo.instance).origin,
|
|
130
|
-
'X-ShapeDiver-SessionEngineId': this._sessionEngineId,
|
|
131
|
-
'X-ShapeDiver-BuildVersion': '',
|
|
132
|
-
'X-ShapeDiver-BuildDate': ''
|
|
133
|
-
};
|
|
134
|
-
private _initialized: boolean = false;
|
|
135
|
-
private _jwtToken?: string;
|
|
136
|
-
private _loadSdtf: boolean = false;
|
|
137
|
-
private _modelId?: string;
|
|
138
|
-
private _modelState?: ShapeDiverResponseModelState;
|
|
139
|
-
private _modelStateId?: string;
|
|
140
|
-
private _modelStateValidationMode?: boolean;
|
|
141
|
-
private _node: ITreeNode;
|
|
142
|
-
private _refreshJwtToken?: () => Promise<string>;
|
|
143
|
-
private _responseDto?: ShapeDiverResponseDto;
|
|
144
|
-
private _retryCounter = 0;
|
|
145
|
-
private _sdk!: ShapeDiverSdk;
|
|
146
|
-
private _sessionId?: string;
|
|
147
|
-
private _updateCallback: ((newNode: ITreeNode, oldNode: ITreeNode) => void) | null = null;
|
|
148
|
-
private _viewerSettings?: object;
|
|
149
|
-
private _viewerSettingsVersion: string = latestVersion;
|
|
150
|
-
private _viewerSettingsVersionBackend: string = latestVersion;
|
|
151
|
-
|
|
152
|
-
// #endregion Properties (50)
|
|
153
|
-
|
|
154
|
-
// #region Constructors (1)
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Can be use to initialize a session with the ticket/guid and modelViewUrl and returns a scene graph node with the result.
|
|
158
|
-
* Can be use to customize the session with updated parameters to get the updated scene graph node.
|
|
159
|
-
*/
|
|
160
|
-
constructor(properties: { id: string, ticket?: string, guid?: string, modelViewUrl: string, buildVersion: string, buildDate: string, jwtToken?: string, excludeViewports?: string[], allowOutputLoading: boolean, loadSdtf: boolean, modelStateId?: string, modelStateValidationMode?: boolean }) {
|
|
161
|
-
this._id = properties.id;
|
|
162
|
-
this._node = new TreeNode(properties.id);
|
|
163
|
-
this._guid = properties.guid;
|
|
164
|
-
this._ticket = properties.ticket;
|
|
165
|
-
this._modelViewUrl = properties.modelViewUrl;
|
|
166
|
-
this._excludeViewports = properties.excludeViewports || [];
|
|
167
|
-
this._jwtToken = properties.jwtToken;
|
|
168
|
-
this._allowOutputLoading = properties.allowOutputLoading;
|
|
169
|
-
this._loadSdtf = properties.loadSdtf;
|
|
170
|
-
this._modelStateId = properties.modelStateId;
|
|
171
|
-
this._modelStateValidationMode = properties.modelStateValidationMode;
|
|
172
|
-
|
|
173
|
-
this._headers['X-ShapeDiver-BuildDate'] = properties.buildDate;
|
|
174
|
-
this._headers['X-ShapeDiver-BuildVersion'] = properties.buildVersion;
|
|
175
|
-
|
|
176
|
-
this._outputLoader = new OutputLoader(this);
|
|
177
|
-
|
|
178
|
-
try {
|
|
179
|
-
this._sdk = create(this._modelViewUrl, this._jwtToken);
|
|
180
|
-
this._sdk.setConfigurationValue(ShapeDiverSdkConfigType.REQUEST_HEADERS, this._headers);
|
|
181
|
-
} catch (e) {
|
|
182
|
-
throw this._httpClient.convertError(e);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// #endregion Constructors (1)
|
|
187
|
-
|
|
188
|
-
// #region Public Getters And Setters (28)
|
|
189
|
-
|
|
190
|
-
public get automaticSceneUpdate(): boolean {
|
|
191
|
-
return this._automaticSceneUpdate;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
public set automaticSceneUpdate(value: boolean) {
|
|
195
|
-
this._automaticSceneUpdate = value;
|
|
196
|
-
value && this._closed === false ? this.addToSceneTree(this._node) : this.removeFromSceneTree(this._node);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
public get canUploadGLTF(): boolean {
|
|
200
|
-
try {
|
|
201
|
-
this.checkAvailability('gltf-upload');
|
|
202
|
-
return true;
|
|
203
|
-
} catch (e) {
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
public get customizeOnParameterChange(): boolean {
|
|
209
|
-
return this._customizeOnParameterChange;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
public set customizeOnParameterChange(value: boolean) {
|
|
213
|
-
this._customizeOnParameterChange = value;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
public get excludeViewports(): string[] {
|
|
217
|
-
return this._excludeViewports;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
public set excludeViewports(value: string[]) {
|
|
221
|
-
this._excludeViewports = JSON.parse(JSON.stringify(value));
|
|
222
|
-
this._node.excludeViewports = JSON.parse(JSON.stringify(value));
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
public get exports(): { [key: string]: IExport; } {
|
|
226
|
-
return this._exports;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
public get guid(): string | undefined {
|
|
230
|
-
return this._guid;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
public get id(): string {
|
|
234
|
-
return this._id;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
public get initialized(): boolean {
|
|
238
|
-
return this._initialized;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
public get jwtToken(): string | undefined {
|
|
242
|
-
return this._jwtToken;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
public get loadSdtf(): boolean {
|
|
246
|
-
return this._loadSdtf;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
public set loadSdtf(value: boolean) {
|
|
250
|
-
this._loadSdtf = value;
|
|
251
|
-
if (this._initialized === true && this._loadSdtf === true) {
|
|
252
|
-
(async () => {
|
|
253
|
-
this._outputLoader.reloadSdtf = true;
|
|
254
|
-
await this.updateOutputs();
|
|
255
|
-
this._outputLoader.reloadSdtf = false;
|
|
256
|
-
this._eventEngine.emitEvent(EVENTTYPE.SESSION.SESSION_SDTF_DELAYED_LOADED, { sessionId: this.id });
|
|
257
|
-
})();
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
public get modelState(): ShapeDiverResponseModelState | undefined {
|
|
262
|
-
return this._modelState;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
public get modelViewUrl(): string {
|
|
266
|
-
return this._modelViewUrl;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
public get node(): ITreeNode {
|
|
270
|
-
return this._node;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
public get outputs(): { [key: string]: IOutput; } {
|
|
274
|
-
return this._outputs;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
public get outputsFreeze(): { [key: string]: boolean; } {
|
|
278
|
-
return this._outputsFreeze;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
public get parameterValues(): { [key: string]: string; } {
|
|
282
|
-
return this._parameterValues;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
public get parameters(): { [key: string]: IParameter<unknown>; } {
|
|
286
|
-
return this._parameters;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
public get refreshJwtToken(): (() => Promise<string>) | undefined {
|
|
290
|
-
return this._refreshJwtToken;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
public set refreshJwtToken(value: (() => Promise<string>) | undefined) {
|
|
294
|
-
this._refreshJwtToken = value;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
public get settingsEngine(): SettingsEngine {
|
|
298
|
-
return this._settingsEngine;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
public get ticket(): string | undefined {
|
|
302
|
-
return this._ticket;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
public get updateCallback(): ((newNode: ITreeNode, oldNode: ITreeNode) => void) | null {
|
|
306
|
-
return this._updateCallback;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
public set updateCallback(value: ((newNode: ITreeNode, oldNode: ITreeNode) => void) | null) {
|
|
310
|
-
this._updateCallback = value;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
public get viewerSettings(): object | undefined {
|
|
314
|
-
return this._viewerSettings;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// #endregion Public Getters And Setters (28)
|
|
318
|
-
|
|
319
|
-
// #region Public Methods (30)
|
|
320
|
-
|
|
321
|
-
public applySettings(response: ShapeDiverResponseDto, sections?: ISettingsSections) {
|
|
322
|
-
sections = sections || {};
|
|
323
|
-
if (sections.session === undefined) {
|
|
324
|
-
sections.session = {
|
|
325
|
-
parameter: { displayname: false, order: false, hidden: false },
|
|
326
|
-
export: { displayname: false, order: false, hidden: false }
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
if (sections.session.parameter === undefined)
|
|
330
|
-
sections.session.parameter = { displayname: false, order: false, hidden: false, value: false };
|
|
331
|
-
if (sections.session.export === undefined)
|
|
332
|
-
sections.session.export = { displayname: false, order: false, hidden: false };
|
|
333
|
-
if (sections.viewport === undefined)
|
|
334
|
-
sections.viewport = { ar: false, scene: false, camera: false, light: false, environment: false, general: false, postprocessing: false };
|
|
335
|
-
|
|
336
|
-
let config: object;
|
|
337
|
-
if ((<ShapeDiverResponseDto>response).viewer !== undefined) {
|
|
338
|
-
config = (<ShapeDiverResponseDto>response).viewer!.config;
|
|
339
|
-
} else {
|
|
340
|
-
throw new ShapeDiverViewerSettingsError('Session.applySettings: No config object available.');
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
try {
|
|
344
|
-
validate(config);
|
|
345
|
-
} catch (e) {
|
|
346
|
-
throw new ShapeDiverViewerSettingsError('Session.applySettings: Was not able to validate config object.');
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
const settings = <ISettings>convert(config, latestVersion);
|
|
350
|
-
|
|
351
|
-
const exportMappingUid: { [key: string]: string | undefined } = {};
|
|
352
|
-
if (sections.session.export.displayname || sections.session.export.order || sections.session.export.hidden)
|
|
353
|
-
if (response.exports)
|
|
354
|
-
for (const exportId in response.exports)
|
|
355
|
-
if (response.exports[exportId].uid !== undefined)
|
|
356
|
-
exportMappingUid[response.exports[exportId].uid!] = exportId;
|
|
357
|
-
|
|
358
|
-
const currentSettings = this._settingsEngine.settings;
|
|
359
|
-
|
|
360
|
-
// apply parameter settings
|
|
361
|
-
if (sections.session.parameter.displayname || sections.session.parameter.order || sections.session.parameter.hidden || sections.session.parameter.value) {
|
|
362
|
-
for (const p in this.parameters) {
|
|
363
|
-
if (settings.session[p]) {
|
|
364
|
-
if (sections.session.parameter.displayname) this.parameters[p].displayname = settings.session[p].displayname;
|
|
365
|
-
if (sections.session.parameter.order) this.parameters[p].order = settings.session[p].order;
|
|
366
|
-
if (sections.session.parameter.hidden) this.parameters[p].hidden = settings.session[p].hidden || false;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
if (response.parameters && response.parameters[p] && !((this.parameters[p] instanceof FileParameter) || this.parameters[p].type.startsWith('s'))) {
|
|
370
|
-
if (sections.session.parameter.value) this.parameters[p].value = response.parameters[p].defval !== undefined ? response.parameters[p].defval : this.parameters[p].value;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// apply export settings
|
|
376
|
-
if (sections.session.export.displayname || sections.session.export.order || sections.session.export.hidden) {
|
|
377
|
-
for (const p in this.exports) {
|
|
378
|
-
let idForSettings = '';
|
|
379
|
-
if (settings.session[p]) {
|
|
380
|
-
idForSettings = p;
|
|
381
|
-
} else {
|
|
382
|
-
const uid = this.exports[p].uid;
|
|
383
|
-
if (!uid) continue;
|
|
384
|
-
if (!exportMappingUid[uid]) continue;
|
|
385
|
-
idForSettings = exportMappingUid[uid]!;
|
|
386
|
-
}
|
|
387
|
-
if (settings.session[idForSettings]) {
|
|
388
|
-
if (sections.session.export.displayname) this.exports[p].displayname = settings.session[idForSettings].displayname;
|
|
389
|
-
if (sections.session.export.order) this.exports[p].order = settings.session[idForSettings].order;
|
|
390
|
-
if (sections.session.export.hidden) this.exports[p].hidden = settings.session[idForSettings].hidden || false;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// apply ar settings
|
|
396
|
-
if (sections.viewport.ar) {
|
|
397
|
-
currentSettings.ar = settings.ar;
|
|
398
|
-
currentSettings.general.transformation = settings.general.transformation;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// apply camera settings
|
|
402
|
-
if (sections.viewport.camera)
|
|
403
|
-
currentSettings.camera = settings.camera;
|
|
404
|
-
|
|
405
|
-
// apply light settings
|
|
406
|
-
if (sections.viewport.light)
|
|
407
|
-
currentSettings.light = settings.light;
|
|
408
|
-
|
|
409
|
-
// apply scene settings
|
|
410
|
-
if (sections.viewport.scene) {
|
|
411
|
-
currentSettings.environmentGeometry.gridColor = settings.environmentGeometry.gridColor;
|
|
412
|
-
currentSettings.environmentGeometry.gridVisibility = settings.environmentGeometry.gridVisibility;
|
|
413
|
-
currentSettings.environmentGeometry.groundPlaneColor = settings.environmentGeometry.groundPlaneColor;
|
|
414
|
-
currentSettings.environmentGeometry.groundPlaneVisibility = settings.environmentGeometry.groundPlaneVisibility;
|
|
415
|
-
currentSettings.environmentGeometry.groundPlaneShadowColor = settings.environmentGeometry.groundPlaneShadowColor;
|
|
416
|
-
currentSettings.environmentGeometry.groundPlaneShadowVisibility = settings.environmentGeometry.groundPlaneShadowVisibility;
|
|
417
|
-
|
|
418
|
-
currentSettings.rendering.shadows = settings.rendering.shadows;
|
|
419
|
-
currentSettings.rendering.softShadows = settings.rendering.softShadows;
|
|
420
|
-
|
|
421
|
-
currentSettings.rendering.automaticColorAdjustment = settings.rendering.automaticColorAdjustment;
|
|
422
|
-
currentSettings.rendering.textureEncoding = settings.rendering.textureEncoding;
|
|
423
|
-
currentSettings.rendering.outputEncoding = settings.rendering.outputEncoding;
|
|
424
|
-
currentSettings.rendering.physicallyCorrectLights = settings.rendering.physicallyCorrectLights;
|
|
425
|
-
currentSettings.rendering.toneMapping = settings.rendering.toneMapping;
|
|
426
|
-
currentSettings.rendering.toneMappingExposure = settings.rendering.toneMappingExposure;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (sections.viewport.general) {
|
|
430
|
-
currentSettings.general.defaultMaterialColor = settings.general.defaultMaterialColor;
|
|
431
|
-
currentSettings.general.commitParameters = settings.general.commitParameters;
|
|
432
|
-
currentSettings.general.pointSize = settings.general.pointSize;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// apply postprocessing settings
|
|
436
|
-
if (sections.viewport.postprocessing)
|
|
437
|
-
currentSettings.postprocessing = settings.postprocessing;
|
|
438
|
-
|
|
439
|
-
// apply environment settings
|
|
440
|
-
if (sections.viewport.environment) {
|
|
441
|
-
currentSettings.environment.clearAlpha = settings.environment.clearAlpha;
|
|
442
|
-
currentSettings.environment.clearColor = settings.environment.clearColor;
|
|
443
|
-
currentSettings.environment.map = settings.environment.map;
|
|
444
|
-
currentSettings.environment.mapAsBackground = settings.environment.mapAsBackground;
|
|
445
|
-
currentSettings.environment.rotation = settings.environment.rotation;
|
|
446
|
-
currentSettings.environment.blurriness = settings.environment.blurriness;
|
|
447
|
-
currentSettings.environment.intensity = settings.environment.intensity;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
public canGoBack(): boolean {
|
|
452
|
-
// the first entry is always the one from the init call
|
|
453
|
-
// all additional entries can be undone
|
|
454
|
-
return this.#parameterHistory.length > 1;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
public canGoForward(): boolean {
|
|
458
|
-
return this.#parameterHistoryForward.length > 0;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
public cancelCustomization() {
|
|
462
|
-
if (this.#customizationProcess)
|
|
463
|
-
this.removeBusyMode(this.#customizationProcess);
|
|
464
|
-
|
|
465
|
-
for (const busyId of this.#customizationBusyModes) {
|
|
466
|
-
for (const r in this._stateEngine.viewportEngines) {
|
|
467
|
-
if (this._stateEngine.viewportEngines[r] && this._stateEngine.viewportEngines[r]!.busy.includes(busyId))
|
|
468
|
-
this._stateEngine.viewportEngines[r]!.busy.splice(this._stateEngine.viewportEngines[r]!.busy.indexOf(busyId), 1);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
this.#customizationBusyModes = [];
|
|
473
|
-
this.#customizationProcess = undefined;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
public async close(retry = false): Promise<void> {
|
|
477
|
-
this.checkAvailability('close');
|
|
478
|
-
|
|
479
|
-
try {
|
|
480
|
-
this._httpClient.removeDataLoading(this._sessionId!);
|
|
481
|
-
await this._sdk.session.close(this._sessionId!);
|
|
482
|
-
if (this._automaticSceneUpdate) this.removeFromSceneTree(this._node);
|
|
483
|
-
|
|
484
|
-
this._closed = true;
|
|
485
|
-
} catch (e) {
|
|
486
|
-
await this.handleError(e, retry);
|
|
487
|
-
return await this.close(true);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
public async createModelState(
|
|
492
|
-
parameterValues: { [key: string]: unknown; } = {},
|
|
493
|
-
omitSessionParameterValues: boolean = false,
|
|
494
|
-
image?: (() => string) | string | Blob | File,
|
|
495
|
-
data?: Record<string, any>,
|
|
496
|
-
arScene?: (() => Promise<ArrayBuffer>) | ArrayBuffer | (() => Promise<Blob>) | Blob | File
|
|
497
|
-
): Promise < string > {
|
|
498
|
-
this.checkAvailability();
|
|
499
|
-
|
|
500
|
-
try {
|
|
501
|
-
const promises = [];
|
|
502
|
-
|
|
503
|
-
// process the parameters
|
|
504
|
-
const parameterSet: {
|
|
505
|
-
[key: string]: string
|
|
506
|
-
} = {};
|
|
507
|
-
promises.push(
|
|
508
|
-
this.uploadFileParameters(parameterValues).then(() => {
|
|
509
|
-
// create a set of the current validated parameter values
|
|
510
|
-
for (const parameterId in this.parameters) {
|
|
511
|
-
// if the parameter has not been set, we do not include it in the parameter set if the omitSessionParameterValues flag is set
|
|
512
|
-
if (!(omitSessionParameterValues === true && parameterValues[parameterId] === undefined)) {
|
|
513
|
-
parameterSet[parameterId] = (' ' + this.parameters[parameterId].stringify(parameterValues[parameterId])).slice(1);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
})
|
|
517
|
-
);
|
|
518
|
-
|
|
519
|
-
// process the image input
|
|
520
|
-
let imageData: ShapeDiverRequestFileUploadPart | undefined;
|
|
521
|
-
let imageArrayBuffer: ArrayBuffer | undefined;
|
|
522
|
-
if (image) {
|
|
523
|
-
promises.push(
|
|
524
|
-
this.processImageInput(image)
|
|
525
|
-
.then(result => {
|
|
526
|
-
imageData = result?.imageData;
|
|
527
|
-
imageArrayBuffer = result?.arrayBuffer;
|
|
528
|
-
})
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
// process the arScene input
|
|
533
|
-
let arSceneId: string | undefined;
|
|
534
|
-
if (arScene) {
|
|
535
|
-
promises.push(
|
|
536
|
-
this._converter.convertToArrayBuffer(arScene)
|
|
537
|
-
.then(arSceneArrayBuffer => this._sdk.gltf.upload(this._sessionId!, arSceneArrayBuffer, 'model/gltf-binary', ShapeDiverRequestGltfUploadQueryConversion.SCENE))
|
|
538
|
-
.then(arSceneResponseDto => {
|
|
539
|
-
arSceneId = arSceneResponseDto.gltf?.sceneId;
|
|
540
|
-
})
|
|
541
|
-
);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// wait for all promises to resolve
|
|
545
|
-
await Promise.all(promises);
|
|
546
|
-
|
|
547
|
-
// create the model state
|
|
548
|
-
const response = await this._sdk.modelState.create(this._sessionId!, {
|
|
549
|
-
parameters: parameterSet,
|
|
550
|
-
data: data,
|
|
551
|
-
image: imageData,
|
|
552
|
-
arSceneId: arSceneId
|
|
553
|
-
} as ShapeDiverRequestModelState);
|
|
554
|
-
|
|
555
|
-
if (imageData && imageArrayBuffer)
|
|
556
|
-
await this._sdk.utils.uploadAsset(response.asset!.modelState!.href, imageArrayBuffer, response.asset!.modelState!.headers);
|
|
557
|
-
|
|
558
|
-
return response.modelState!.id!;
|
|
559
|
-
} catch (e) {
|
|
560
|
-
throw this._httpClient.convertError(e);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
/**
|
|
565
|
-
* Customizes the session with updated parameters to get the updated scene graph node.
|
|
566
|
-
*
|
|
567
|
-
* @param parameters the parameter set to update the session
|
|
568
|
-
* @returns promise with a scene graph node
|
|
569
|
-
*/
|
|
570
|
-
public async customize(force: boolean = false, waitForViewportUpdate: boolean = false): Promise<ITreeNode> {
|
|
571
|
-
const eventId = this._uuidGenerator.create();
|
|
572
|
-
const customizationId = this._uuidGenerator.create();
|
|
573
|
-
try {
|
|
574
|
-
// we check if something changed
|
|
575
|
-
if (force === false) {
|
|
576
|
-
let changes = false;
|
|
577
|
-
for (const parameterId in this.parameters)
|
|
578
|
-
if (this.parameters[parameterId].sessionValue !== this.parameters[parameterId].value)
|
|
579
|
-
changes = true;
|
|
580
|
-
if (changes === false)
|
|
581
|
-
return this.node;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
const eventStart: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0, data: { sessionId: this.id }, status: 'Customizing session' };
|
|
585
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
|
|
586
|
-
|
|
587
|
-
const oldNode = this.node;
|
|
588
|
-
this.#customizationProcess = customizationId;
|
|
589
|
-
|
|
590
|
-
this._logger.debugLow(`Session(${this.id}).customize: Customizing session.`);
|
|
591
|
-
|
|
592
|
-
this.addBusyMode(customizationId);
|
|
593
|
-
|
|
594
|
-
const eventFileUpload: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.1, data: { sessionId: this.id }, status: 'Uploading file parameters' };
|
|
595
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventFileUpload);
|
|
596
|
-
|
|
597
|
-
// upload file parameters
|
|
598
|
-
await this.uploadFileParameters();
|
|
599
|
-
|
|
600
|
-
// OPTION TO SKIP - PART 1b
|
|
601
|
-
const cancelResult = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
602
|
-
if (cancelResult) return cancelResult;
|
|
603
|
-
|
|
604
|
-
const parameterSet: {
|
|
605
|
-
[key: string]: {
|
|
606
|
-
value: unknown,
|
|
607
|
-
valueString: string
|
|
608
|
-
}
|
|
609
|
-
} = {};
|
|
610
|
-
|
|
611
|
-
// create a set of the current validated parameter values
|
|
612
|
-
for (const parameterId in this.parameters) {
|
|
613
|
-
parameterSet[parameterId] = {
|
|
614
|
-
value: this.parameters[parameterId].value,
|
|
615
|
-
valueString: this.parameters[parameterId].stringify()
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// update the session engine parameter values if everything succeeded
|
|
620
|
-
for (const parameterId in this.parameters)
|
|
621
|
-
this.parameterValues[parameterId] = parameterSet[parameterId].valueString;
|
|
622
|
-
this._logger.info(`Session(${this.id}).customize: Customizing session with parameters ${JSON.stringify(this.parameterValues)}.`);
|
|
623
|
-
|
|
624
|
-
const eventRequest: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.1, data: { sessionId: this.id }, status: 'Sending customization request' };
|
|
625
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
|
|
626
|
-
|
|
627
|
-
const oldOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
628
|
-
|
|
629
|
-
const newNode = await this.customizeInternal(() => this.#customizationProcess !== customizationId, {
|
|
630
|
-
eventId,
|
|
631
|
-
type: TASK_TYPE.SESSION_CUSTOMIZATION,
|
|
632
|
-
progressRange: {
|
|
633
|
-
min: 0.1,
|
|
634
|
-
max: 0.9
|
|
635
|
-
},
|
|
636
|
-
data: { sessionId: this.id }
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
// OPTION TO SKIP - PART 2
|
|
640
|
-
const cancelResult2 = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
641
|
-
if (cancelResult2) return cancelResult2;
|
|
642
|
-
|
|
643
|
-
const newOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
644
|
-
|
|
645
|
-
const eventSceneUpdate: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.9, data: { sessionId: this.id }, status: 'Updating scene' };
|
|
646
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
|
|
647
|
-
|
|
648
|
-
// call the update callbacks
|
|
649
|
-
if (waitForViewportUpdate === false) {
|
|
650
|
-
for (const outputId in this.outputs) {
|
|
651
|
-
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
652
|
-
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, <IOutputEvent>{
|
|
653
|
-
outputId: outputId,
|
|
654
|
-
outputVersion: newOutputVersions[outputId],
|
|
655
|
-
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
656
|
-
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
657
|
-
});
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
662
|
-
|
|
663
|
-
const cancelResult = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
664
|
-
if (cancelResult) return cancelResult;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// if this is not a call by the goBack or goForward functions, add the parameter values to the history and delete the forward history
|
|
668
|
-
if (!this.#parameterHistoryCall) {
|
|
669
|
-
this.#parameterHistory.push(parameterSet);
|
|
670
|
-
this.#parameterHistoryForward = [];
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
if (this.automaticSceneUpdate) this.removeFromSceneTree(this.node);
|
|
674
|
-
this._node = newNode;
|
|
675
|
-
if (this.automaticSceneUpdate && this._closed === false) this.addToSceneTree(this.node);
|
|
676
|
-
|
|
677
|
-
this._logger.debug(`Session(${this.id}).customize: Customization request finished, updating geometry.`);
|
|
678
|
-
|
|
679
|
-
// set the session values to the current ones in all parameters
|
|
680
|
-
for (const parameterId in this.parameters)
|
|
681
|
-
(<unknown>this.parameters[parameterId].sessionValue) = parameterSet[parameterId].value;
|
|
682
|
-
|
|
683
|
-
// set the output content to what has been updated
|
|
684
|
-
for (const outputId in this.outputs)
|
|
685
|
-
this.outputs[outputId].updateOutput(
|
|
686
|
-
newNode.children.find(c => c.name === outputId)!,
|
|
687
|
-
oldNode.children.find(c => c.name === outputId)!
|
|
688
|
-
);
|
|
689
|
-
|
|
690
|
-
// set the export definitions
|
|
691
|
-
for (const exportId in this.exports)
|
|
692
|
-
this.exports[exportId].updateExport();
|
|
693
|
-
|
|
694
|
-
this._warningCreator();
|
|
695
|
-
|
|
696
|
-
this.node.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
|
|
697
|
-
|
|
698
|
-
this.removeBusyMode(customizationId);
|
|
699
|
-
|
|
700
|
-
this._logger.debug(`Session(${this.id}).customize: Session customized.`);
|
|
701
|
-
|
|
702
|
-
this._eventEngine.emitEvent(EVENTTYPE.SESSION.SESSION_CUSTOMIZED, { sessionId: this.id });
|
|
703
|
-
|
|
704
|
-
const eventEnd: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customized' };
|
|
705
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
|
|
706
|
-
|
|
707
|
-
// update the viewports
|
|
708
|
-
if (waitForViewportUpdate) {
|
|
709
|
-
for (const r in this._stateEngine.viewportEngines)
|
|
710
|
-
if (this._stateEngine.viewportEngines[r] && !this.excludeViewports.includes(this._stateEngine.viewportEngines[r]!.id))
|
|
711
|
-
this._stateEngine.viewportEngines[r]!.update(`SessionEngine(${this.id}).customize`);
|
|
712
|
-
|
|
713
|
-
for (const outputId in this.outputs) {
|
|
714
|
-
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
715
|
-
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, <IOutputEvent>{
|
|
716
|
-
outputId: outputId,
|
|
717
|
-
outputVersion: newOutputVersions[outputId],
|
|
718
|
-
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
719
|
-
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// call the update callbacks
|
|
725
|
-
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
726
|
-
|
|
727
|
-
const cancelResult = this.cancelProcess(customizationId, eventId, TASK_TYPE.SESSION_CUSTOMIZATION, 1, { sessionId: this.id });
|
|
728
|
-
if (cancelResult) return cancelResult;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
if (!waitForViewportUpdate) {
|
|
732
|
-
setTimeout(() => {
|
|
733
|
-
for (const r in this._stateEngine.viewportEngines)
|
|
734
|
-
if (this._stateEngine.viewportEngines[r] && !this.excludeViewports.includes(this._stateEngine.viewportEngines[r]!.id))
|
|
735
|
-
this._stateEngine.viewportEngines[r]!.update(`SessionEngine(${this.id}).customize`);
|
|
736
|
-
}, 0);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
return this.node;
|
|
740
|
-
} catch (e) {
|
|
741
|
-
const eventCancel: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customization failed' };
|
|
742
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel);
|
|
743
|
-
|
|
744
|
-
this.removeBusyMode(customizationId);
|
|
745
|
-
|
|
746
|
-
throw this._httpClient.convertError(e);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
public async customizeParallel(parameterValues: { [key: string]: unknown }, loadOutputs = true): Promise<ISessionTreeNode | ShapeDiverResponseDto> {
|
|
751
|
-
const eventId = this._uuidGenerator.create();
|
|
752
|
-
|
|
753
|
-
const eventStart: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0, data: { sessionId: this.id }, status: 'Customizing session' };
|
|
754
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
|
|
755
|
-
|
|
756
|
-
// upload file parameters
|
|
757
|
-
await this.uploadFileParameters(parameterValues);
|
|
758
|
-
|
|
759
|
-
const parameterSet: {
|
|
760
|
-
[key: string]: string
|
|
761
|
-
} = {};
|
|
762
|
-
|
|
763
|
-
// create a set of the current validated parameter values
|
|
764
|
-
for (const parameterId in this.parameters)
|
|
765
|
-
parameterSet[parameterId] = (' ' + this.parameters[parameterId].stringify(parameterValues[parameterId])).slice(1);
|
|
766
|
-
|
|
767
|
-
const result = await this.customizeSession(parameterSet, () => false, {
|
|
768
|
-
eventId,
|
|
769
|
-
type: TASK_TYPE.SESSION_CUSTOMIZATION,
|
|
770
|
-
progressRange: {
|
|
771
|
-
min: 0.0,
|
|
772
|
-
max: 1
|
|
773
|
-
},
|
|
774
|
-
data: { sessionId: this.id }
|
|
775
|
-
}, true, loadOutputs);
|
|
776
|
-
|
|
777
|
-
if (result instanceof SessionTreeNode)
|
|
778
|
-
result.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
|
|
779
|
-
|
|
780
|
-
const eventEnd: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customized' };
|
|
781
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
|
|
782
|
-
return result;
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
public async getFileInfo(parameterId: string, fileId: string): Promise<ShapeDiverResponseFileInfo> {
|
|
786
|
-
this.checkAvailability();
|
|
787
|
-
try {
|
|
788
|
-
return await this._sdk.file.info(this._sessionId!, parameterId, fileId);
|
|
789
|
-
} catch (e) {
|
|
790
|
-
throw this._httpClient.convertError(e);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
public async goBack(): Promise<ITreeNode> {
|
|
795
|
-
if (!this.canGoBack()) {
|
|
796
|
-
this._logger.debug(`Session(${this.id}).goBack: Cannot go further back.`);
|
|
797
|
-
return new TreeNode();
|
|
798
|
-
}
|
|
799
|
-
// get the current parameter set and store it in the forward history later on
|
|
800
|
-
const currentParameterSet = this.#parameterHistory.pop()!;
|
|
801
|
-
|
|
802
|
-
// adjust the parameters according to the last parameter set
|
|
803
|
-
const lastParameterSet = this.#parameterHistory[this.#parameterHistory.length - 1];
|
|
804
|
-
for (const parameterId in lastParameterSet)
|
|
805
|
-
this.parameters[parameterId].value = lastParameterSet[parameterId].value;
|
|
806
|
-
|
|
807
|
-
// call the customization function with the parameterHistoryCall value set to true
|
|
808
|
-
this.#parameterHistoryCall = true;
|
|
809
|
-
const node = await this.customize();
|
|
810
|
-
this.#parameterHistoryCall = false;
|
|
811
|
-
|
|
812
|
-
// add the current (not anymore current) parameter set to the forward history
|
|
813
|
-
this.#parameterHistoryForward.push(currentParameterSet);
|
|
814
|
-
return node;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
public async goForward(): Promise<ITreeNode> {
|
|
818
|
-
if (!this.canGoForward()) {
|
|
819
|
-
this._logger.debug(`Session(${this.id}).goForward: Cannot go further forward.`);
|
|
820
|
-
return new TreeNode();
|
|
821
|
-
}
|
|
822
|
-
// get the last undone parameter set and apply the values to the parameters
|
|
823
|
-
const lastParameterSet = this.#parameterHistoryForward.pop()!;
|
|
824
|
-
for (const parameterId in lastParameterSet)
|
|
825
|
-
this.parameters[parameterId].value = lastParameterSet[parameterId].value;
|
|
826
|
-
|
|
827
|
-
// call the customization function with the parameterHistoryCall value set to true
|
|
828
|
-
this.#parameterHistoryCall = true;
|
|
829
|
-
const node = await this.customize();
|
|
830
|
-
this.#parameterHistoryCall = false;
|
|
831
|
-
|
|
832
|
-
// add the current parameter set to the history
|
|
833
|
-
this.#parameterHistory.push(lastParameterSet);
|
|
834
|
-
return node;
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
/**
|
|
838
|
-
* Initializes the session with the ticket and modelViewUrl.
|
|
839
|
-
*
|
|
840
|
-
* @returns promise with a scene graph node
|
|
841
|
-
*/
|
|
842
|
-
public async init(parameterValues?: {
|
|
843
|
-
[key: string]: string;
|
|
844
|
-
}, retry = false): Promise<void> {
|
|
845
|
-
if (this._initialized === true)
|
|
846
|
-
throw new ShapeDiverViewerSessionError('Session.init: Session already initialized.');
|
|
847
|
-
|
|
848
|
-
try {
|
|
849
|
-
this._performanceEvaluator.startSection('sessionResponse');
|
|
850
|
-
|
|
851
|
-
const parameterSet: { [key: string]: string } = {};
|
|
852
|
-
// the slice here is done as a way for deep copying the string values
|
|
853
|
-
for (const parameterNameOrId in parameterValues)
|
|
854
|
-
parameterSet[parameterNameOrId] = (' ' + parameterValues[parameterNameOrId]).slice(1);
|
|
855
|
-
|
|
856
|
-
if (this._ticket) {
|
|
857
|
-
this._responseDto = await this._sdk.session.init(this._ticket, parameterSet, this._modelStateId, this._modelStateValidationMode);
|
|
858
|
-
} else if (this._guid) {
|
|
859
|
-
this._responseDto = await this._sdk.session.initForModel(this._guid, parameterSet, this._modelStateId, this._modelStateValidationMode);
|
|
860
|
-
} else {
|
|
861
|
-
// we should never get here
|
|
862
|
-
throw new ShapeDiverViewerSessionError('Session.init: Initialization of session failed. Neither a ticket nor a guid are available.');
|
|
863
|
-
}
|
|
864
|
-
this._performanceEvaluator.endSection('sessionResponse');
|
|
865
|
-
|
|
866
|
-
this._viewerSettings = this._responseDto.viewer?.config;
|
|
867
|
-
this._viewerSettingsVersionBackend = this._responseDto.viewerSettingsVersion || latestVersion;
|
|
868
|
-
this._sessionId = this._responseDto.sessionId;
|
|
869
|
-
this._modelId = this._responseDto.model?.id;
|
|
870
|
-
this._modelState = this._responseDto.modelState;
|
|
871
|
-
|
|
872
|
-
this._httpClient.addDataLoading(this._sessionId!, {
|
|
873
|
-
getAsset: this._sdk.asset.getAsset.bind(this._sdk.asset),
|
|
874
|
-
downloadTexture: this._sdk.asset.downloadImage.bind(this._sdk.asset),
|
|
875
|
-
});
|
|
876
|
-
|
|
877
|
-
this._settingsEngine.loadSettings(this._viewerSettings);
|
|
878
|
-
|
|
879
|
-
if (!this._sessionId)
|
|
880
|
-
throw new ShapeDiverViewerSessionError('Session.init: Initialization of session failed. ResponseDto did not have a sessionId.');
|
|
881
|
-
if (!this._modelId)
|
|
882
|
-
throw new ShapeDiverViewerSessionError('Session.init: Initialization of session failed. ResponseDto did not have a model.id.');
|
|
883
|
-
|
|
884
|
-
this.updateResponseDto(this._responseDto, parameterSet);
|
|
885
|
-
this._initialized = true;
|
|
886
|
-
} catch (e) {
|
|
887
|
-
await this.handleError(e, retry);
|
|
888
|
-
return await this.init(parameterValues, true);
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
public async loadCachedOutputsParallel(outputMapping: { [key: string]: string }, taskEventInfo?: OutputLoaderTaskEventInfo, retry = false): Promise<{ [key: string]: ITreeNode | undefined }> {
|
|
893
|
-
this.checkAvailability();
|
|
894
|
-
// if there is already task event info, use it
|
|
895
|
-
// this happens after a retry
|
|
896
|
-
const eventId = taskEventInfo ? taskEventInfo.eventId : this._uuidGenerator.create();
|
|
897
|
-
const eventType = taskEventInfo ? taskEventInfo.type : TASK_TYPE.SESSION_OUTPUTS_LOADING;
|
|
898
|
-
const eventData = taskEventInfo ? taskEventInfo.data : { sessionId: this.id };
|
|
899
|
-
|
|
900
|
-
taskEventInfo = taskEventInfo ? taskEventInfo : {
|
|
901
|
-
eventId,
|
|
902
|
-
type: eventType,
|
|
903
|
-
progressRange: {
|
|
904
|
-
min: 0,
|
|
905
|
-
max: 1
|
|
906
|
-
},
|
|
907
|
-
data: eventData
|
|
908
|
-
};
|
|
909
|
-
|
|
910
|
-
try {
|
|
911
|
-
// send start event if this function was called initially
|
|
912
|
-
if (!taskEventInfo) {
|
|
913
|
-
const eventStart: ITaskEvent = { type: eventType, id: eventId, progress: 0, data: eventData, status: 'Loading cached outputs' };
|
|
914
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
// get the cached outputs
|
|
918
|
-
const responseDto = await this._sdk.output.getCache(this._sessionId!, outputMapping);
|
|
919
|
-
|
|
920
|
-
// create atomic output api objects for them
|
|
921
|
-
const outputs: {
|
|
922
|
-
[key: string]: IOutput;
|
|
923
|
-
} = {};
|
|
924
|
-
for (const outputId in responseDto.outputs) {
|
|
925
|
-
responseDto.outputs[outputId].id = outputId;
|
|
926
|
-
outputs[outputId] = new Output(<ShapeDiverResponseOutput>responseDto.outputs[outputId], this);
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
// process the output data
|
|
930
|
-
const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', outputs, {}, taskEventInfo, false);
|
|
931
|
-
|
|
932
|
-
// send the end event once done
|
|
933
|
-
const eventEnd: ITaskEvent = { type: eventType, id: eventId, progress: 1, data: eventData, status: 'Loaded cached outputs' };
|
|
934
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
|
|
935
|
-
|
|
936
|
-
// create a mapping with a dictionary for the id of the outputs
|
|
937
|
-
const outputNodeMapping: { [key: string]: ITreeNode | undefined } = {};
|
|
938
|
-
for (const outputId in outputMapping)
|
|
939
|
-
outputNodeMapping[outputId] = node.children.find(n => n.name === outputId);
|
|
940
|
-
|
|
941
|
-
return outputNodeMapping;
|
|
942
|
-
}
|
|
943
|
-
catch (e) {
|
|
944
|
-
await this.handleError(e, retry);
|
|
945
|
-
return await this.loadCachedOutputsParallel(outputMapping, taskEventInfo, true);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
/**
|
|
950
|
-
* Load the outputs and return the scene graph node of the result.
|
|
951
|
-
* In case the outputs have a delay property, another customization request with the parameter set is sent.
|
|
952
|
-
*
|
|
953
|
-
* @param parameters the parameter set to update the session
|
|
954
|
-
* @param outputs the outputs to load
|
|
955
|
-
* @returns promise with a scene graph node
|
|
956
|
-
*/
|
|
957
|
-
public async loadOutputs(cancelRequest: () => boolean = () => false, taskEventInfo: OutputLoaderTaskEventInfo, retry = false): Promise<ISessionTreeNode> {
|
|
958
|
-
this.checkAvailability();
|
|
959
|
-
|
|
960
|
-
const o = Object.assign({}, this._outputs);
|
|
961
|
-
const of = Object.assign({}, this._outputsFreeze);
|
|
962
|
-
try {
|
|
963
|
-
const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', o, of, taskEventInfo);
|
|
964
|
-
node.data.push(new SessionData(this._responseDto!));
|
|
965
|
-
if (cancelRequest()) return node;
|
|
966
|
-
node.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
|
|
967
|
-
return node;
|
|
968
|
-
}
|
|
969
|
-
catch (e) {
|
|
970
|
-
if (e instanceof OutputDelayException) {
|
|
971
|
-
await this.timeout(e.delay);
|
|
972
|
-
} else {
|
|
973
|
-
await this.handleError(e, retry);
|
|
974
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
975
|
-
return await this.loadOutputs(cancelRequest, taskEventInfo, true);
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
979
|
-
const outputMapping: { [key: string]: string } = {};
|
|
980
|
-
for (const output in o)
|
|
981
|
-
outputMapping[output] = o[output].version;
|
|
982
|
-
|
|
983
|
-
try {
|
|
984
|
-
const responseDto = await this._sdk.output.getCache(this._sessionId!, outputMapping);
|
|
985
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
986
|
-
this.updateResponseDto(responseDto);
|
|
987
|
-
return await this.loadOutputs(cancelRequest, taskEventInfo);
|
|
988
|
-
} catch (e) {
|
|
989
|
-
await this.handleError(e, retry);
|
|
990
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
991
|
-
return await this.loadOutputs(cancelRequest, taskEventInfo, true);
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
/**
|
|
997
|
-
* Load the outputs and return the scene graph node of the result.
|
|
998
|
-
* In case the outputs have a delay property, another customization request with the parameter set is sent.
|
|
999
|
-
*
|
|
1000
|
-
* @param parameters the parameter set to update the session
|
|
1001
|
-
* @param outputs the outputs to load
|
|
1002
|
-
* @returns promise with a scene graph node
|
|
1003
|
-
*/
|
|
1004
|
-
public async loadOutputsParallel(responseDto: ShapeDiverResponseDto, cancelRequest: () => boolean = () => false, taskEventInfo: OutputLoaderTaskEventInfo, retry = false): Promise<ISessionTreeNode> {
|
|
1005
|
-
this.checkAvailability();
|
|
1006
|
-
|
|
1007
|
-
const outputs: {
|
|
1008
|
-
[key: string]: IOutput;
|
|
1009
|
-
} = {};
|
|
1010
|
-
const outputsFreeze: {
|
|
1011
|
-
[key: string]: boolean;
|
|
1012
|
-
} = {};
|
|
1013
|
-
|
|
1014
|
-
for (const outputId in responseDto.outputs) {
|
|
1015
|
-
responseDto.outputs[outputId].id = outputId;
|
|
1016
|
-
if (this.outputsFreeze[outputId] === undefined) outputsFreeze[outputId] = false;
|
|
1017
|
-
outputs[outputId] = new Output(<ShapeDiverResponseOutput>responseDto.outputs[outputId], this);
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
try {
|
|
1021
|
-
const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', outputs, outputsFreeze, taskEventInfo);
|
|
1022
|
-
node.data.push(new SessionData(responseDto));
|
|
1023
|
-
return node;
|
|
1024
|
-
}
|
|
1025
|
-
catch (e) {
|
|
1026
|
-
if (e instanceof OutputDelayException) {
|
|
1027
|
-
await this.timeout(e.delay);
|
|
1028
|
-
} else {
|
|
1029
|
-
await this.handleError(e, retry);
|
|
1030
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
1031
|
-
return await this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo, true);
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
1035
|
-
const outputMapping: { [key: string]: string } = {};
|
|
1036
|
-
for (const output in outputs)
|
|
1037
|
-
outputMapping[output] = outputs[output].version;
|
|
1038
|
-
|
|
1039
|
-
try {
|
|
1040
|
-
const responseDto = await this._sdk.output.getCache(this._sessionId!, outputMapping);
|
|
1041
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
1042
|
-
this.updateResponseDto(responseDto);
|
|
1043
|
-
return await this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo);
|
|
1044
|
-
} catch (e) {
|
|
1045
|
-
await this.handleError(e, retry);
|
|
1046
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
1047
|
-
return await this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo, true);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
public async requestExport(exportId: string, parameters: { [key: string]: unknown }, maxWaitTime: number, retry = false): Promise<ShapeDiverResponseExport> {
|
|
1053
|
-
this.checkAvailability('export');
|
|
1054
|
-
try {
|
|
1055
|
-
await this.uploadFileParameters(parameters);
|
|
1056
|
-
const requestParameterSet = this.cleanExportParameters(parameters);
|
|
1057
|
-
const responseDto = await this._sdk.utils.submitAndWaitForExport(this._sdk, this._sessionId!, { exports: { id: exportId }, parameters: requestParameterSet }, maxWaitTime);
|
|
1058
|
-
this.updateResponseDto(responseDto);
|
|
1059
|
-
return this.exports[exportId];
|
|
1060
|
-
} catch (e) {
|
|
1061
|
-
await this.handleError(e, retry);
|
|
1062
|
-
return await this.requestExport(exportId, parameters, maxWaitTime, true);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
public async requestExports(body: ShapeDiverRequestExport, loadOutputs: boolean = false, maxWaitMsec?: number, retry = false): Promise<ShapeDiverResponseDto> {
|
|
1067
|
-
let processId;
|
|
1068
|
-
this.checkAvailability('export');
|
|
1069
|
-
try {
|
|
1070
|
-
// activate the busy mode if outputs are loaded
|
|
1071
|
-
if (loadOutputs === true && this._allowOutputLoading === true &&
|
|
1072
|
-
body.outputs && Object.keys(body.outputs).length > 0) {
|
|
1073
|
-
processId = this._uuidGenerator.create();
|
|
1074
|
-
this.addBusyMode(processId);
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
await this.uploadFileParameters(body.parameters as { [key: string]: string | File | Blob });
|
|
1078
|
-
const requestParameterSet = this.cleanExportParameters(body.parameters);
|
|
1079
|
-
|
|
1080
|
-
const responseDto = await this._sdk.utils.submitAndWaitForExport(this._sdk, this._sessionId!, { exports: body.exports, parameters: requestParameterSet, outputs: body.outputs, max_wait_time: body.max_wait_time }, maxWaitMsec);
|
|
1081
|
-
this.updateResponseDto(responseDto);
|
|
1082
|
-
if (loadOutputs === true && this._allowOutputLoading === true) this.updateOutputs();
|
|
1083
|
-
|
|
1084
|
-
if (processId) this.removeBusyMode(processId);
|
|
1085
|
-
return responseDto;
|
|
1086
|
-
} catch (e) {
|
|
1087
|
-
if (processId) this.removeBusyMode(processId);
|
|
1088
|
-
await this.handleError(e, retry);
|
|
1089
|
-
return await this.requestExports(body, loadOutputs, maxWaitMsec, true);
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
public resetSettings(sections?: ISettingsSections): void {
|
|
1094
|
-
if (!this._responseDto)
|
|
1095
|
-
throw new ShapeDiverViewerSessionError('Session.resetSettings: responseDto not available.');
|
|
1096
|
-
|
|
1097
|
-
sections = sections || {};
|
|
1098
|
-
if (sections.session === undefined) {
|
|
1099
|
-
sections.session = {
|
|
1100
|
-
parameter: { displayname: true, order: true, hidden: true },
|
|
1101
|
-
export: { displayname: true, order: true, hidden: true }
|
|
1102
|
-
};
|
|
1103
|
-
}
|
|
1104
|
-
if (sections.session.parameter === undefined)
|
|
1105
|
-
sections.session.parameter = { displayname: true, order: true, hidden: true, value: true };
|
|
1106
|
-
if (sections.session.export === undefined)
|
|
1107
|
-
sections.session.export = { displayname: true, order: true, hidden: true };
|
|
1108
|
-
if (sections.viewport === undefined)
|
|
1109
|
-
sections.viewport = { ar: true, scene: true, camera: true, light: true, environment: true, general: true, postprocessing: true };
|
|
1110
|
-
|
|
1111
|
-
return this.applySettings(this._responseDto, sections);
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
public async saveDefaultParameterValues(): Promise<boolean> {
|
|
1115
|
-
this._logger.debugLow(`Session(${this.id}).saveDefaultParameters: Saving default parameters.`);
|
|
1116
|
-
const response = await this.saveDefaultParameters();
|
|
1117
|
-
if (response) {
|
|
1118
|
-
this._logger.debug(`Session(${this.id}).saveDefaultParameters: Saved default parameters.`);
|
|
1119
|
-
} else {
|
|
1120
|
-
throw new ShapeDiverViewerSessionError(`Session(${this.id}).saveDefaultParameters: Could not save default parameters.`);
|
|
1121
|
-
}
|
|
1122
|
-
return response;
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
public async saveDefaultParameters(retry = false): Promise<boolean> {
|
|
1126
|
-
this.checkAvailability('defaultparam', true);
|
|
1127
|
-
try {
|
|
1128
|
-
await this._sdk.model.setDefaultParams(this._modelId!, this._parameterValues);
|
|
1129
|
-
return true;
|
|
1130
|
-
} catch (e) {
|
|
1131
|
-
await this.handleError(e, retry);
|
|
1132
|
-
return await this.saveDefaultParameters(true);
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
/**
|
|
1137
|
-
* Save the export properties for displayname, order, tooltip and hidden
|
|
1138
|
-
*
|
|
1139
|
-
* @param exports
|
|
1140
|
-
* @returns
|
|
1141
|
-
*/
|
|
1142
|
-
public async saveExportProperties(exports: {
|
|
1143
|
-
[key: string]: {
|
|
1144
|
-
displayname: string,
|
|
1145
|
-
hidden: boolean,
|
|
1146
|
-
order: number,
|
|
1147
|
-
tooltip: string
|
|
1148
|
-
}
|
|
1149
|
-
}, retry = false): Promise<boolean> {
|
|
1150
|
-
this.checkAvailability('export-definition', true);
|
|
1151
|
-
try {
|
|
1152
|
-
await this._sdk.export.updateDefinitions(this._modelId!, exports);
|
|
1153
|
-
return true;
|
|
1154
|
-
} catch (e) {
|
|
1155
|
-
await this.handleError(e, retry);
|
|
1156
|
-
return await this.saveExportProperties(exports, true);
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
/**
|
|
1161
|
-
* Save the output properties for displayname, order, tooltip and hidden
|
|
1162
|
-
*
|
|
1163
|
-
* @param outputs
|
|
1164
|
-
* @returns
|
|
1165
|
-
*/
|
|
1166
|
-
public async saveOutputProperties(outputs: {
|
|
1167
|
-
[key: string]: {
|
|
1168
|
-
displayname: string,
|
|
1169
|
-
hidden: boolean,
|
|
1170
|
-
order: number,
|
|
1171
|
-
tooltip: string
|
|
1172
|
-
}
|
|
1173
|
-
}, retry = false): Promise<boolean> {
|
|
1174
|
-
this.checkAvailability('output-definition', true);
|
|
1175
|
-
try {
|
|
1176
|
-
await this._sdk.output.updateDefinitions(this._modelId!, outputs);
|
|
1177
|
-
return true;
|
|
1178
|
-
} catch (e) {
|
|
1179
|
-
await this.handleError(e, retry);
|
|
1180
|
-
return await this.saveOutputProperties(outputs, true);
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
/**
|
|
1185
|
-
* Save the parameter properties for displayname, order, tooltip and hidden
|
|
1186
|
-
*
|
|
1187
|
-
* @param parameters
|
|
1188
|
-
* @returns
|
|
1189
|
-
*/
|
|
1190
|
-
public async saveParameterProperties(parameters: {
|
|
1191
|
-
[key: string]: {
|
|
1192
|
-
displayname: string,
|
|
1193
|
-
hidden: boolean,
|
|
1194
|
-
order: number,
|
|
1195
|
-
tooltip: string
|
|
1196
|
-
}
|
|
1197
|
-
}, retry = false): Promise<boolean> {
|
|
1198
|
-
this.checkAvailability('parameter-definition', true);
|
|
1199
|
-
try {
|
|
1200
|
-
await this._sdk.model.updateParameterDefinitions(this._modelId!, parameters);
|
|
1201
|
-
return true;
|
|
1202
|
-
} catch (e) {
|
|
1203
|
-
await this.handleError(e, retry);
|
|
1204
|
-
return await this.saveParameterProperties(parameters, true);
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
public async saveSettings(json: unknown, retry = false): Promise<boolean> {
|
|
1209
|
-
this.checkAvailability('configure', true);
|
|
1210
|
-
|
|
1211
|
-
try {
|
|
1212
|
-
validate(json, <versions>this._viewerSettingsVersion);
|
|
1213
|
-
|
|
1214
|
-
// if viewer settings version is higher than backend settings version
|
|
1215
|
-
// convert to backend settings version
|
|
1216
|
-
if (+this._viewerSettingsVersion > +this._viewerSettingsVersionBackend)
|
|
1217
|
-
json = convert(json, <versions>this._viewerSettingsVersionBackend);
|
|
1218
|
-
} catch (e) {
|
|
1219
|
-
throw new ShapeDiverViewerSettingsError('Session.saveSettings: Settings could not be validated. ' + (<Error>e).message, <Error>e);
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
try {
|
|
1223
|
-
await this._sdk.model.updateConfig(this._modelId!, json as ShapeDiverRequestConfigure);
|
|
1224
|
-
return true;
|
|
1225
|
-
} catch (e) {
|
|
1226
|
-
await this.handleError(e, retry);
|
|
1227
|
-
return await this.saveSettings(json, true);
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
public async saveUiProperties(saveInSettings: boolean = true): Promise<boolean> {
|
|
1232
|
-
this._logger.debugLow(`Session(${this.id}).saveSessionProperties: Saving session properties.`);
|
|
1233
|
-
|
|
1234
|
-
// settings saving
|
|
1235
|
-
this._saveSessionSettings();
|
|
1236
|
-
|
|
1237
|
-
let properties: {
|
|
1238
|
-
[key: string]: {
|
|
1239
|
-
displayname: string,
|
|
1240
|
-
hidden: boolean,
|
|
1241
|
-
order: number,
|
|
1242
|
-
tooltip: string
|
|
1243
|
-
}
|
|
1244
|
-
} = {};
|
|
1245
|
-
for (const p in this.parameters) {
|
|
1246
|
-
properties[p] = {
|
|
1247
|
-
displayname: this.parameters[p].displayname !== undefined ? this.parameters[p].displayname! : '',
|
|
1248
|
-
hidden: this.parameters[p].hidden !== undefined ? this.parameters[p].hidden : false,
|
|
1249
|
-
order: this.parameters[p].order !== undefined ? this.parameters[p].order! : 0,
|
|
1250
|
-
tooltip: this.parameters[p].tooltip !== undefined ? this.parameters[p].tooltip! : '',
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
const responseP = Object.values(properties).length !== 0 ? await this.saveParameterProperties(properties) : true;
|
|
1254
|
-
|
|
1255
|
-
properties = {};
|
|
1256
|
-
for (const e in this.exports) {
|
|
1257
|
-
properties[e] = {
|
|
1258
|
-
displayname: this.exports[e].displayname !== undefined ? this.exports[e].displayname! : '',
|
|
1259
|
-
hidden: this.exports[e].hidden !== undefined ? this.exports[e].hidden : false,
|
|
1260
|
-
order: this.exports[e].order !== undefined ? this.exports[e].order! : 0,
|
|
1261
|
-
tooltip: this.exports[e].tooltip !== undefined ? this.exports[e].tooltip! : '',
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
const responseE = Object.values(properties).length !== 0 ? await this.saveExportProperties(properties) : true;
|
|
1265
|
-
|
|
1266
|
-
properties = {};
|
|
1267
|
-
for (const o in this.outputs) {
|
|
1268
|
-
properties[o] = {
|
|
1269
|
-
displayname: this.outputs[o].displayname !== undefined ? this.outputs[o].displayname! : '',
|
|
1270
|
-
hidden: this.outputs[o].hidden !== undefined ? this.outputs[o].hidden : false,
|
|
1271
|
-
order: this.outputs[o].order !== undefined ? this.outputs[o].order! : 0,
|
|
1272
|
-
tooltip: this.outputs[o].tooltip !== undefined ? this.outputs[o].tooltip! : '',
|
|
1273
|
-
};
|
|
1274
|
-
}
|
|
1275
|
-
const responseO = Object.values(properties).length !== 0 ? await this.saveOutputProperties(properties) : true;
|
|
1276
|
-
|
|
1277
|
-
// save partial settings
|
|
1278
|
-
const response = saveInSettings ? await this.saveSettings(this._settingsEngine.settings) : true;
|
|
1279
|
-
|
|
1280
|
-
if (response && responseP && responseO && responseE) {
|
|
1281
|
-
this._logger.debug(`Session(${this.id}).saveSessionProperties: Saved session properties.`);
|
|
1282
|
-
} else {
|
|
1283
|
-
this._logger.warn(`Session(${this.id}).saveSessionProperties: Could not save session properties.`);
|
|
1284
|
-
}
|
|
1285
|
-
return response && responseP && responseO && responseE;
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
public async setJwtToken(value: string) {
|
|
1289
|
-
this.checkAvailability();
|
|
1290
|
-
|
|
1291
|
-
this._jwtToken = value;
|
|
1292
|
-
try {
|
|
1293
|
-
this._sdk.setConfigurationValue(ShapeDiverSdkConfigType.JWT_TOKEN, value);
|
|
1294
|
-
const responseDto = await this._sdk.session.default(this._sessionId!);
|
|
1295
|
-
if (this._responseDto) this._responseDto.actions = responseDto.actions;
|
|
1296
|
-
} catch (e) {
|
|
1297
|
-
throw this._httpClient.convertError(e);
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
public async updateOutputs(taskEventInfo?: OutputLoaderTaskEventInfo, waitForViewportUpdate: boolean = false): Promise<ITreeNode> {
|
|
1302
|
-
const eventId = taskEventInfo ? taskEventInfo.eventId : this._uuidGenerator.create();
|
|
1303
|
-
const eventType = taskEventInfo ? taskEventInfo.type : TASK_TYPE.SESSION_OUTPUTS_UPDATE;
|
|
1304
|
-
const eventData = taskEventInfo ? taskEventInfo.data : { sessionId: this.id };
|
|
1305
|
-
|
|
1306
|
-
if (!taskEventInfo) {
|
|
1307
|
-
const eventStart: ITaskEvent = { type: eventType, id: eventId, progress: 0, data: eventData, status: 'Updating outputs' };
|
|
1308
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
const customizationId = this._uuidGenerator.create();
|
|
1312
|
-
const oldNode = this.node;
|
|
1313
|
-
this.#customizationProcess = customizationId;
|
|
1314
|
-
|
|
1315
|
-
this._logger.debugLow(`Session(${this.id}).updateOutputs: Updating Outputs.`);
|
|
1316
|
-
|
|
1317
|
-
this.addBusyMode(customizationId);
|
|
1318
|
-
|
|
1319
|
-
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' };
|
|
1320
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
|
|
1321
|
-
|
|
1322
|
-
const oldOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
1323
|
-
|
|
1324
|
-
const newNode = await this.loadOutputs(() => this.#customizationProcess !== customizationId, {
|
|
1325
|
-
eventId,
|
|
1326
|
-
type: eventType,
|
|
1327
|
-
progressRange: {
|
|
1328
|
-
min: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.1 + taskEventInfo.progressRange.min : 0.1,
|
|
1329
|
-
max: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.9 + taskEventInfo.progressRange.min : 0.9
|
|
1330
|
-
},
|
|
1331
|
-
data: eventData
|
|
1332
|
-
});
|
|
1333
|
-
|
|
1334
|
-
const newOutputVersions = this._outputLoader.getCurrentOutputVersions();
|
|
1335
|
-
|
|
1336
|
-
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' };
|
|
1337
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
|
|
1338
|
-
|
|
1339
|
-
// OPTION TO SKIP - PART 1
|
|
1340
|
-
const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
|
|
1341
|
-
if (cancelResult) return cancelResult;
|
|
1342
|
-
|
|
1343
|
-
// call the update callbacks
|
|
1344
|
-
if (waitForViewportUpdate === false) {
|
|
1345
|
-
for (const outputId in this.outputs) {
|
|
1346
|
-
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
1347
|
-
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
|
|
1348
|
-
outputId: outputId,
|
|
1349
|
-
outputVersion: newOutputVersions[outputId],
|
|
1350
|
-
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
1351
|
-
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
1352
|
-
});
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
1357
|
-
|
|
1358
|
-
// OPTION TO SKIP - PART 2
|
|
1359
|
-
const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
|
|
1360
|
-
if (cancelResult) return cancelResult;
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
|
-
if (this.automaticSceneUpdate) this.removeFromSceneTree(this.node);
|
|
1364
|
-
this._node = newNode;
|
|
1365
|
-
if (this.automaticSceneUpdate && this._closed === false) this.addToSceneTree(this.node);
|
|
1366
|
-
|
|
1367
|
-
this._logger.debug(`Session(${this.id}).updateOutputs: Updating outputs finished, updating geometry.`);
|
|
1368
|
-
|
|
1369
|
-
// set the output content to what has been updated
|
|
1370
|
-
for (const outputId in this.outputs) {
|
|
1371
|
-
this.outputs[outputId].updateOutput(
|
|
1372
|
-
newNode.children.find(c => c.name === outputId)!,
|
|
1373
|
-
oldNode.children.find(c => c.name === outputId)!
|
|
1374
|
-
);
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
// set the export definitions
|
|
1378
|
-
for (const exportId in this.exports)
|
|
1379
|
-
this.exports[exportId].updateExport();
|
|
1380
|
-
|
|
1381
|
-
this._warningCreator();
|
|
1382
|
-
this.node.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
|
|
1383
|
-
|
|
1384
|
-
this.removeBusyMode(customizationId);
|
|
1385
|
-
|
|
1386
|
-
this._logger.debug(`Session(${this.id}).updateOutputs: Updated outputs.`);
|
|
1387
|
-
|
|
1388
|
-
if (!taskEventInfo) {
|
|
1389
|
-
const eventEnd: ITaskEvent = { type: eventType, id: eventId, progress: 1, data: eventData, status: 'Outputs updated' };
|
|
1390
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
// update the viewports
|
|
1394
|
-
if (waitForViewportUpdate) {
|
|
1395
|
-
for (const r in this._stateEngine.viewportEngines)
|
|
1396
|
-
if (this._stateEngine.viewportEngines[r] && !this.excludeViewports.includes(this._stateEngine.viewportEngines[r]!.id))
|
|
1397
|
-
this._stateEngine.viewportEngines[r]!.update(`SessionEngine(${this.id}).updateOutputs`);
|
|
1398
|
-
|
|
1399
|
-
for (const outputId in this.outputs) {
|
|
1400
|
-
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
1401
|
-
this._eventEngine.emitEvent(EVENTTYPE.OUTPUT.OUTPUT_UPDATED, {
|
|
1402
|
-
outputId: outputId,
|
|
1403
|
-
outputVersion: newOutputVersions[outputId],
|
|
1404
|
-
newNode: newNode.children.find(c => c.name === outputId)!,
|
|
1405
|
-
oldNode: oldNode.children.find(c => c.name === outputId)!
|
|
1406
|
-
});
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
await this.waitForUpdateCallbacks(newOutputVersions, oldOutputVersions, newNode, oldNode);
|
|
1411
|
-
|
|
1412
|
-
// OPTION TO SKIP - PART 3
|
|
1413
|
-
const cancelResult = this.cancelProcess(customizationId, eventId, eventType, taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, eventData, newNode);
|
|
1414
|
-
if (cancelResult) return cancelResult;
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
return this.node;
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
public async uploadFile(parameterId: string, data: File, type: string, retry = false): Promise<string> {
|
|
1421
|
-
this.checkAvailability('file-upload');
|
|
1422
|
-
try {
|
|
1423
|
-
const result = await this._sdk.file.requestUpload(this._sessionId!, {
|
|
1424
|
-
[parameterId]: {
|
|
1425
|
-
size: data.size,
|
|
1426
|
-
format: type,
|
|
1427
|
-
filename: data.name === '' ? undefined : data.name
|
|
1428
|
-
}
|
|
1429
|
-
});
|
|
1430
|
-
|
|
1431
|
-
if (result && result.asset && result.asset.file && result.asset.file[parameterId]) {
|
|
1432
|
-
const fileAsset = result.asset.file[parameterId];
|
|
1433
|
-
await this._sdk.utils.uploadAsset(
|
|
1434
|
-
fileAsset.href,
|
|
1435
|
-
await data.arrayBuffer(),
|
|
1436
|
-
fileAsset.headers
|
|
1437
|
-
);
|
|
1438
|
-
return fileAsset.id;
|
|
1439
|
-
} else {
|
|
1440
|
-
throw new ShapeDiverViewerSessionError('Session.uploadFile: Upload reply has not the required format.');
|
|
1441
|
-
}
|
|
1442
|
-
} catch (e) {
|
|
1443
|
-
await this.handleError(e, retry);
|
|
1444
|
-
return await this.uploadFile(parameterId, data, type, true);
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
/**
|
|
1449
|
-
* Uploads all file parameters and returns the file parameter values.
|
|
1450
|
-
* If parameterValues is provided, the file parameter values are added to it.
|
|
1451
|
-
*
|
|
1452
|
-
* @param parameterValues
|
|
1453
|
-
* @returns
|
|
1454
|
-
*/
|
|
1455
|
-
public async uploadFileParameters(parameterValues?: { [key: string]: unknown }): Promise<{ [key: string]: string }> {
|
|
1456
|
-
const parameterValueSet = parameterValues !== undefined ? this.getFileParameterSet(parameterValues) : undefined;
|
|
1457
|
-
|
|
1458
|
-
const fileParameterValues: { [key: string]: string } = {};
|
|
1459
|
-
// load file parameter first
|
|
1460
|
-
for (const parameterId in this.parameters) {
|
|
1461
|
-
if (this.parameters[parameterId] instanceof FileParameter) {
|
|
1462
|
-
fileParameterValues[parameterId] = await (<IFileParameter>this.parameters[parameterId]).upload(parameterValueSet ? parameterValueSet[parameterId] : undefined);
|
|
1463
|
-
if (parameterValues) {
|
|
1464
|
-
parameterValues[parameterId] = fileParameterValues[parameterId];
|
|
1465
|
-
|
|
1466
|
-
// if the parameter value of the file parameter was used, set the value to the parameter
|
|
1467
|
-
if (parameterValues[parameterId] === undefined && this.parameters[parameterId].value !== fileParameterValues[parameterId])
|
|
1468
|
-
this.parameters[parameterId].value = fileParameterValues[parameterId];
|
|
1469
|
-
} else if (this.parameters[parameterId].value !== fileParameterValues[parameterId]) {
|
|
1470
|
-
this.parameters[parameterId].value = fileParameterValues[parameterId];
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
return fileParameterValues;
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
|
-
public async uploadGLTF(blob: Blob, conversion: ShapeDiverRequestGltfUploadQueryConversion = ShapeDiverRequestGltfUploadQueryConversion.NONE, retry = false): Promise<ShapeDiverResponseDto> {
|
|
1479
|
-
this.checkAvailability('gltf-upload');
|
|
1480
|
-
try {
|
|
1481
|
-
const responseDto = await this._sdk.gltf.upload(this._sessionId!, await blob.arrayBuffer(), 'model/gltf-binary', conversion);
|
|
1482
|
-
if (!responseDto || !responseDto.gltf || !responseDto.gltf.href)
|
|
1483
|
-
throw new ShapeDiverViewerSessionError('Session.uploadGLTF: Upload reply has not the required format.');
|
|
1484
|
-
return responseDto;
|
|
1485
|
-
} catch (e) {
|
|
1486
|
-
await this.handleError(e, retry);
|
|
1487
|
-
return await this.uploadGLTF(blob, conversion, true);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
// #endregion Public Methods (30)
|
|
1492
|
-
|
|
1493
|
-
// #region Private Methods (18)
|
|
1494
|
-
|
|
1495
|
-
private _saveSessionSettings() {
|
|
1496
|
-
const parameters = this.parameters;
|
|
1497
|
-
const exports = this.exports;
|
|
1498
|
-
|
|
1499
|
-
const sessionProperties: {
|
|
1500
|
-
[key: string]: {
|
|
1501
|
-
order: number;
|
|
1502
|
-
displayname: string;
|
|
1503
|
-
hidden: boolean;
|
|
1504
|
-
}
|
|
1505
|
-
} = {};
|
|
1506
|
-
for (const p in parameters) {
|
|
1507
|
-
sessionProperties[p] = {
|
|
1508
|
-
order: parameters[p].order || 0,
|
|
1509
|
-
displayname: parameters[p].displayname || '',
|
|
1510
|
-
hidden: parameters[p].hidden
|
|
1511
|
-
};
|
|
1512
|
-
}
|
|
1513
|
-
for (const e in exports) {
|
|
1514
|
-
sessionProperties[e] = {
|
|
1515
|
-
order: exports[e].order || 0,
|
|
1516
|
-
displayname: exports[e].displayname || '',
|
|
1517
|
-
hidden: exports[e].hidden
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
|
-
this._settingsEngine.session = sessionProperties;
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
private _warningCreator() {
|
|
1524
|
-
// set the output content to what has been updated
|
|
1525
|
-
for (const outputId in this.outputs) {
|
|
1526
|
-
let warning: string = '';
|
|
1527
|
-
if (this.outputs[outputId].msg)
|
|
1528
|
-
warning += `\n\t- ${this.outputs[outputId].msg}`;
|
|
1529
|
-
if (this.outputs[outputId].status_collect && this.outputs[outputId].status_collect !== ShapeDiverResponseModelComputationStatus.SUCCESS)
|
|
1530
|
-
warning += `\n\t- status_collect is ${this.outputs[outputId].status_collect}`;
|
|
1531
|
-
if (this.outputs[outputId].status_computation && this.outputs[outputId].status_computation !== ShapeDiverResponseModelComputationStatus.SUCCESS)
|
|
1532
|
-
warning += `\n\t- status_computation is ${this.outputs[outputId].status_computation}`;
|
|
1533
|
-
if (warning)
|
|
1534
|
-
this._logger.warn(`\nOutput(${outputId}):${warning}`);
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
|
-
// set the export definitions
|
|
1538
|
-
for (const exportId in this.exports) {
|
|
1539
|
-
let warning: string = '';
|
|
1540
|
-
if (this.exports[exportId].msg)
|
|
1541
|
-
warning += `\n\t- ${this.exports[exportId].msg}`;
|
|
1542
|
-
if (this.exports[exportId].status_collect && this.exports[exportId].status_collect !== ShapeDiverResponseModelComputationStatus.SUCCESS)
|
|
1543
|
-
warning += `\n\t- status_collect is ${this.exports[exportId].status_collect}`;
|
|
1544
|
-
if (this.exports[exportId].status_computation && this.exports[exportId].status_computation !== ShapeDiverResponseModelComputationStatus.SUCCESS)
|
|
1545
|
-
warning += `\n\t- status_computation is ${this.exports[exportId].status_computation}`;
|
|
1546
|
-
if (warning)
|
|
1547
|
-
this._logger.warn(`\nExport(${exportId}):${warning}`);
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
private addBusyMode(busyId: string) {
|
|
1552
|
-
for (const r in this._stateEngine.viewportEngines) {
|
|
1553
|
-
if (this._stateEngine.viewportEngines[r] && !this.excludeViewports.includes(r)) {
|
|
1554
|
-
this._stateEngine.viewportEngines[r]!.busy.push(busyId);
|
|
1555
|
-
this.#customizationBusyModes.push(busyId);
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
private addToSceneTree(node: ITreeNode) {
|
|
1561
|
-
this._sceneTree.addNode(node);
|
|
1562
|
-
this._sceneTree.root.updateVersion();
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
private cancelProcess(customizationId: string, eventId: string, eventType: TASK_TYPE, eventProgress: number, eventData: unknown, newNode: ITreeNode = new SessionTreeNode()): ITreeNode | undefined {
|
|
1566
|
-
if (this.#customizationProcess !== customizationId) {
|
|
1567
|
-
this.removeBusyMode(customizationId);
|
|
1568
|
-
|
|
1569
|
-
const eventCancel: ITaskEvent = {
|
|
1570
|
-
type: eventType,
|
|
1571
|
-
id: eventId,
|
|
1572
|
-
progress: eventProgress,
|
|
1573
|
-
data: eventData,
|
|
1574
|
-
status: 'The request was exceeded by another customization request'
|
|
1575
|
-
};
|
|
1576
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel);
|
|
1577
|
-
this._logger.debug(`Session(${this.id}).cancelProcess: The request was was exceeded by another request.`);
|
|
1578
|
-
return newNode;
|
|
1579
|
-
} else if ((this._closed as boolean) === true) {
|
|
1580
|
-
this.removeBusyMode(customizationId);
|
|
1581
|
-
|
|
1582
|
-
this._logger.debug(`Session(${this.id}).cancelProcess: The session was closed during the request.`);
|
|
1583
|
-
|
|
1584
|
-
const eventCancel: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'The session was closed during the request.' };
|
|
1585
|
-
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel);
|
|
1586
|
-
return new SessionTreeNode();
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
|
-
|
|
1590
|
-
private checkAvailability(action?: string, checkForModelId = false) {
|
|
1591
|
-
if (!this._responseDto)
|
|
1592
|
-
throw new ShapeDiverViewerSessionError('Session.checkAvailability: responseDto not available.');
|
|
1593
|
-
|
|
1594
|
-
if (!this._sessionId)
|
|
1595
|
-
throw new ShapeDiverViewerSessionError('Session.checkAvailability: sessionId not available.');
|
|
1596
|
-
|
|
1597
|
-
if (checkForModelId && !this._modelId)
|
|
1598
|
-
throw new ShapeDiverViewerSessionError('Session.checkAvailability: modelId not available.');
|
|
1599
|
-
|
|
1600
|
-
if (action && !this._responseDto.actions)
|
|
1601
|
-
throw new ShapeDiverViewerSessionError('Session.checkAvailability: actions not available.');
|
|
1602
|
-
|
|
1603
|
-
const responseDtoAction = this._responseDto.actions?.find(a => a.name === action);
|
|
1604
|
-
if (action && !responseDtoAction)
|
|
1605
|
-
throw new ShapeDiverViewerSessionError(`Session.checkAvailability: action ${action} not available.`);
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
private cleanExportParameters(parameters: { [key: string]: unknown }): ShapeDiverRequestCustomization {
|
|
1609
|
-
const requestParameterSet: ShapeDiverRequestCustomization = {};
|
|
1610
|
-
|
|
1611
|
-
// first step, we convert all our names and displaynames to ids
|
|
1612
|
-
for (const parameterIdOrName in parameters) {
|
|
1613
|
-
// we prioritize id, then name and then displayname
|
|
1614
|
-
// if there are two parameters with the same name or displayname, we take the one that is found first (no way for us to evaluate which one the user meant)
|
|
1615
|
-
const parameterObject = Object.values(this._parameters).find(p => p.id === parameterIdOrName || p.name === parameterIdOrName || p.displayname === parameterIdOrName);
|
|
1616
|
-
|
|
1617
|
-
// in case the key of the key value pair was neither the id, name or displayname, skip
|
|
1618
|
-
if (!parameterObject) continue;
|
|
1619
|
-
|
|
1620
|
-
// copy into new dictionary
|
|
1621
|
-
requestParameterSet[parameterObject.id] = (' ' + parameterObject.stringify(parameters[parameterIdOrName])).slice(1);
|
|
1622
|
-
}
|
|
1623
|
-
|
|
1624
|
-
// seconds step, fill all other parameter values that are currently not set
|
|
1625
|
-
const currentParameters = this.parameterValues;
|
|
1626
|
-
for (const parameterId in currentParameters) {
|
|
1627
|
-
// if already set by input values, skip
|
|
1628
|
-
if (requestParameterSet[parameterId] !== undefined) continue;
|
|
1629
|
-
|
|
1630
|
-
// deep copy into new dictionary
|
|
1631
|
-
requestParameterSet[parameterId] = (' ' + currentParameters[parameterId]).slice(1);
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
return requestParameterSet;
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
/**
|
|
1638
|
-
* Create an interaction parameter based on the parameter definition.
|
|
1639
|
-
*
|
|
1640
|
-
* @param parameter
|
|
1641
|
-
* @returns
|
|
1642
|
-
*/
|
|
1643
|
-
private createInteractionParameter(parameter: ShapeDiverResponseParameter): IParameter<unknown> {
|
|
1644
|
-
const result = validateInteractionParameterSettings(parameter.settings);
|
|
1645
|
-
if (result.success) {
|
|
1646
|
-
switch ((parameter.settings as IInteractionParameterSettings).type) {
|
|
1647
|
-
case 'selection':
|
|
1648
|
-
return new SelectionParameter(parameter, this);
|
|
1649
|
-
case 'gumball':
|
|
1650
|
-
return new GumballParameter(parameter, this);
|
|
1651
|
-
}
|
|
1652
|
-
} else {
|
|
1653
|
-
this._logger.warn(`SessionEngine.createInteractionParameter: The value ${parameter.settings} is not a valid InteractionParameter: ${result.error.message}`);
|
|
1654
|
-
}
|
|
1655
|
-
return new Parameter<string>(parameter, this);
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
private async customizeInternal(cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo): Promise<ISessionTreeNode> {
|
|
1659
|
-
return this.customizeSession(this._parameterValues, cancelRequest, taskEventInfo);
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
|
-
private async customizeSession(parameters: { [key: string]: string }, cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo, parallel = false, loadOutputs = true, retry = false): Promise<ISessionTreeNode> {
|
|
1663
|
-
this.checkAvailability('customize');
|
|
1664
|
-
try {
|
|
1665
|
-
this._performanceEvaluator.startSection('sessionResponse');
|
|
1666
|
-
const responseDto = await this._sdk.utils.submitAndWaitForCustomization(this._sdk, this._sessionId!, parameters);
|
|
1667
|
-
this._performanceEvaluator.endSection('sessionResponse');
|
|
1668
|
-
if (loadOutputs === true && this._allowOutputLoading === true) {
|
|
1669
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
1670
|
-
if (parallel === true) {
|
|
1671
|
-
// special case, we load the outputs put don't add them to the scene
|
|
1672
|
-
return this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo);
|
|
1673
|
-
} else {
|
|
1674
|
-
// default case, we load the outputs and return the nodes
|
|
1675
|
-
this.updateResponseDto(responseDto);
|
|
1676
|
-
return this.loadOutputs(cancelRequest, taskEventInfo);
|
|
1677
|
-
}
|
|
1678
|
-
} else {
|
|
1679
|
-
// special case, we don't load the outputs and only return the responseDto
|
|
1680
|
-
const node = new SessionTreeNode();
|
|
1681
|
-
node.data.push(new SessionData(responseDto));
|
|
1682
|
-
return node;
|
|
1683
|
-
}
|
|
1684
|
-
} catch (e) {
|
|
1685
|
-
await this.handleError(e, retry);
|
|
1686
|
-
if (cancelRequest()) return new SessionTreeNode();
|
|
1687
|
-
return await this.customizeSession(parameters, cancelRequest, taskEventInfo, parallel, loadOutputs, true);
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
/**
|
|
1692
|
-
* Get all file parameters from the parameter set.
|
|
1693
|
-
* If the parameter is not set in the parameter set, the value from the parameter object is used.
|
|
1694
|
-
*
|
|
1695
|
-
* @param parameters
|
|
1696
|
-
* @returns
|
|
1697
|
-
*/
|
|
1698
|
-
private getFileParameterSet(parameters: { [key: string]: unknown }): { [key: string]: string | File | Blob } {
|
|
1699
|
-
const fileParameterSet: { [key: string]: string | File | Blob } = {};
|
|
1700
|
-
for (const parameterId in this.parameters) {
|
|
1701
|
-
if (this.parameters[parameterId] instanceof FileParameter) {
|
|
1702
|
-
fileParameterSet[parameterId] = parameters[parameterId] !== undefined ? parameters[parameterId] as string | File | Blob : (this.parameters[parameterId] as FileParameter).value;
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
return fileParameterSet;
|
|
1706
|
-
}
|
|
1707
|
-
|
|
1708
|
-
private async handleError(e: ShapeDiverBackendError | ShapeDiverViewerError | Error | unknown, retry = false) {
|
|
1709
|
-
if (isGBResponseError(e)) {
|
|
1710
|
-
if (e.error === ShapeDiverResponseErrorType.SESSION_GONE_ERROR) {
|
|
1711
|
-
// case 1: the session is no longer available
|
|
1712
|
-
// we try to re-initialize the session 3 times, if that does not work, we close it
|
|
1713
|
-
|
|
1714
|
-
this._logger.warn('The session has been closed, trying to re-initialize.');
|
|
1715
|
-
if (this._sessionId) this._httpClient.removeDataLoading(this._sessionId);
|
|
1716
|
-
|
|
1717
|
-
if (this._retryCounter < 3) {
|
|
1718
|
-
// we retry this 3 times, the `retry` option in the init function is set to true and passed on
|
|
1719
|
-
this._retryCounter = retry ? this._retryCounter + 1 : 1;
|
|
1720
|
-
this._initialized = false;
|
|
1721
|
-
await this.init(this.parameterValues, true);
|
|
1722
|
-
} else {
|
|
1723
|
-
// the retries were exceeded, we close the session
|
|
1724
|
-
this._logger.warn('Tried to retry the connect multiple times, bearer token still not valid. Closing Session.');
|
|
1725
|
-
// eslint-disable-next-line no-empty
|
|
1726
|
-
try { await this._closeOnFailure(); } catch (e) { }
|
|
1727
|
-
throw this._httpClient.convertError(e);
|
|
1728
|
-
}
|
|
1729
|
-
} else if (e.error === ShapeDiverResponseErrorType.JWT_VALIDATION_ERROR) {
|
|
1730
|
-
// if any of the above errors occur, we try to get a new bearer token
|
|
1731
|
-
// if we get a new one, we retry 3 times (by requiring new bearer tokens every time)
|
|
1732
|
-
if (this._retryCounter < 3) {
|
|
1733
|
-
if (this._refreshJwtToken) {
|
|
1734
|
-
await this.setJwtToken(await this._refreshJwtToken());
|
|
1735
|
-
this._retryCounter = retry ? this._retryCounter + 1 : 1;
|
|
1736
|
-
this._logger.warn('Re-trying with new bearer token.');
|
|
1737
|
-
} else {
|
|
1738
|
-
// no bearer tokens are supplied, we close the session
|
|
1739
|
-
this._logger.warn('No retry possible, no new bearer token was supplied. Closing Session.');
|
|
1740
|
-
// eslint-disable-next-line no-empty
|
|
1741
|
-
try { await this._closeOnFailure(); } catch (e) { }
|
|
1742
|
-
throw this._httpClient.convertError(e);
|
|
1743
|
-
}
|
|
1744
|
-
} else {
|
|
1745
|
-
// the retries were exceeded, we close the session
|
|
1746
|
-
this._logger.warn('Tried to retry the connect multiple times, bearer token still not valid. Closing Session.');
|
|
1747
|
-
// eslint-disable-next-line no-empty
|
|
1748
|
-
try { await this._closeOnFailure(); } catch (e) { }
|
|
1749
|
-
throw this._httpClient.convertError(e);
|
|
1750
|
-
}
|
|
1751
|
-
} else {
|
|
1752
|
-
throw this._httpClient.convertError(e);
|
|
1753
|
-
}
|
|
1754
|
-
} else {
|
|
1755
|
-
throw this._httpClient.convertError(e);
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
|
|
1759
|
-
/**
|
|
1760
|
-
* Process the image input and return the image data and array buffer.
|
|
1761
|
-
*
|
|
1762
|
-
* In the case of the image being a Blob or File, the image data is constructed from the Blob or File.
|
|
1763
|
-
* In the case of the image being a string, we check if it is a data URL or a URL.
|
|
1764
|
-
* If it is a data URL, we convert it to a Blob and construct the image data from the Blob.
|
|
1765
|
-
* If it is a URL, we download the image and return the image data and array buffer.
|
|
1766
|
-
*
|
|
1767
|
-
* @param image
|
|
1768
|
-
* @returns
|
|
1769
|
-
*/
|
|
1770
|
-
private async processImageInput(image: (() => string) | string | Blob | File): Promise<{
|
|
1771
|
-
imageData: ShapeDiverRequestFileUploadPart,
|
|
1772
|
-
arrayBuffer: ArrayBuffer
|
|
1773
|
-
}> {
|
|
1774
|
-
if (image instanceof File || image instanceof Blob)
|
|
1775
|
-
return this._converter.constructImageData(image);
|
|
1776
|
-
|
|
1777
|
-
let imageString: string;
|
|
1778
|
-
if (typeof image === 'function') {
|
|
1779
|
-
imageString = image();
|
|
1780
|
-
} else {
|
|
1781
|
-
imageString = image;
|
|
1782
|
-
}
|
|
1783
|
-
|
|
1784
|
-
if (imageString.startsWith('data:')) {
|
|
1785
|
-
// case where the image is a data URL
|
|
1786
|
-
const { blob, arrayBuffer } = this._converter.dataURLtoBlob(imageString);
|
|
1787
|
-
return {
|
|
1788
|
-
imageData: {
|
|
1789
|
-
format: blob.type,
|
|
1790
|
-
size: blob.size
|
|
1791
|
-
},
|
|
1792
|
-
arrayBuffer
|
|
1793
|
-
};
|
|
1794
|
-
} else {
|
|
1795
|
-
// case where the image is a URL
|
|
1796
|
-
const [arrayBuffer, type] = await this._sdk.asset.downloadImage(this._sessionId!, imageString);
|
|
1797
|
-
return {
|
|
1798
|
-
imageData: {
|
|
1799
|
-
format: type,
|
|
1800
|
-
size: arrayBuffer.byteLength
|
|
1801
|
-
},
|
|
1802
|
-
arrayBuffer
|
|
1803
|
-
};
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
|
|
1807
|
-
private removeBusyMode(busyId: string) {
|
|
1808
|
-
for (const r in this._stateEngine.viewportEngines) {
|
|
1809
|
-
if (this._stateEngine.viewportEngines[r] && this._stateEngine.viewportEngines[r]!.busy.includes(busyId))
|
|
1810
|
-
this._stateEngine.viewportEngines[r]!.busy.splice(this._stateEngine.viewportEngines[r]!.busy.indexOf(busyId), 1);
|
|
1811
|
-
|
|
1812
|
-
if (this.#customizationBusyModes.includes(busyId))
|
|
1813
|
-
this.#customizationBusyModes.splice(this.#customizationBusyModes.indexOf(busyId), 1);
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
|
|
1817
|
-
private removeFromSceneTree(node: ITreeNode) {
|
|
1818
|
-
this._sceneTree.removeNode(node);
|
|
1819
|
-
this._sceneTree.root.updateVersion();
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
/**
|
|
1823
|
-
* Returns a promise that resolves after the amount of milliseconds provided.
|
|
1824
|
-
*
|
|
1825
|
-
* @param ms the milliseconds
|
|
1826
|
-
* @returns promise that resolve after specified milliseconds
|
|
1827
|
-
*/
|
|
1828
|
-
private async timeout(ms: number): Promise<unknown> {
|
|
1829
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
1830
|
-
}
|
|
1831
|
-
|
|
1832
|
-
private updateResponseDto(responseDto: ShapeDiverResponseDto, initialParameters?: {
|
|
1833
|
-
[key: string]: string;
|
|
1834
|
-
}) {
|
|
1835
|
-
if (!this._responseDto) {
|
|
1836
|
-
this._responseDto = responseDto;
|
|
1837
|
-
return;
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
// convert parameters
|
|
1841
|
-
if (responseDto.parameters) {
|
|
1842
|
-
for (const parameterId in responseDto.parameters) {
|
|
1843
|
-
this._responseDto.parameters = this._responseDto.parameters || {};
|
|
1844
|
-
this._responseDto.parameters[parameterId] = this._responseDto.parameters[parameterId] || responseDto.parameters[parameterId];
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
// convert outputs
|
|
1849
|
-
if (responseDto.outputs) {
|
|
1850
|
-
for (const outputId in responseDto.outputs) {
|
|
1851
|
-
this._responseDto.outputs = this._responseDto.outputs || {};
|
|
1852
|
-
if ('version' in responseDto.outputs[outputId] || !(this._responseDto.outputs[outputId] && 'version' in this._responseDto.outputs[outputId]))
|
|
1853
|
-
this._responseDto.outputs[outputId] = responseDto.outputs[outputId];
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
// convert exports
|
|
1858
|
-
if (responseDto.exports) {
|
|
1859
|
-
for (const exportId in responseDto.exports) {
|
|
1860
|
-
this._responseDto.exports = this._responseDto.exports || {};
|
|
1861
|
-
if ('version' in responseDto.exports[exportId] || !(this._responseDto.exports[exportId] && 'version' in this._responseDto.exports[exportId]))
|
|
1862
|
-
this._responseDto.exports[exportId] = responseDto.exports[exportId];
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
const parameterSet: {
|
|
1867
|
-
[key: string]: {
|
|
1868
|
-
value: unknown,
|
|
1869
|
-
valueString: string
|
|
1870
|
-
}
|
|
1871
|
-
} = {};
|
|
1872
|
-
|
|
1873
|
-
for (const parameterId in this._responseDto.parameters) {
|
|
1874
|
-
if (this.parameters[parameterId]) continue;
|
|
1875
|
-
this._responseDto.parameters[parameterId].id = parameterId;
|
|
1876
|
-
|
|
1877
|
-
/**
|
|
1878
|
-
*
|
|
1879
|
-
* REMOVE THIS LOGIC - START
|
|
1880
|
-
*
|
|
1881
|
-
*/
|
|
1882
|
-
const fakeSelectionParameterName = 'FAKE_SELECTION_PARAMETER';
|
|
1883
|
-
const nameStartsWithFakeSelectionParameter = this._responseDto.parameters[parameterId].name.startsWith(fakeSelectionParameterName);
|
|
1884
|
-
const displaynameStartsWithFakeSelectionParameter = this._responseDto.parameters[parameterId].displayname?.startsWith(fakeSelectionParameterName);
|
|
1885
|
-
|
|
1886
|
-
if (nameStartsWithFakeSelectionParameter || displaynameStartsWithFakeSelectionParameter) {
|
|
1887
|
-
this._responseDto.parameters[parameterId].type = PARAMETER_TYPE.INTERACTION;
|
|
1888
|
-
const name = nameStartsWithFakeSelectionParameter ? this._responseDto.parameters[parameterId].name : this._responseDto.parameters[parameterId].displayname!;
|
|
1889
|
-
const urlParams = new URLSearchParams(name.replace(fakeSelectionParameterName + '?', ''));
|
|
1890
|
-
const jsonString = urlParams.get('settings');
|
|
1891
|
-
if (jsonString)
|
|
1892
|
-
this._responseDto.parameters[parameterId].settings = JSON.parse(jsonString);
|
|
1893
|
-
}
|
|
1894
|
-
|
|
1895
|
-
const fakeGumballParameterName = 'FAKE_GUMBALL_PARAMETER';
|
|
1896
|
-
const nameStartsWithFakeGumballParameter = this._responseDto.parameters[parameterId].name.startsWith(fakeGumballParameterName);
|
|
1897
|
-
const displaynameStartsWithFakeGumballParameter = this._responseDto.parameters[parameterId].displayname?.startsWith(fakeGumballParameterName);
|
|
1898
|
-
|
|
1899
|
-
if (nameStartsWithFakeGumballParameter || displaynameStartsWithFakeGumballParameter) {
|
|
1900
|
-
this._responseDto.parameters[parameterId].type = PARAMETER_TYPE.INTERACTION;
|
|
1901
|
-
const name = nameStartsWithFakeGumballParameter ? this._responseDto.parameters[parameterId].name : this._responseDto.parameters[parameterId].displayname!;
|
|
1902
|
-
const urlParams = new URLSearchParams(name.replace(fakeGumballParameterName + '?', ''));
|
|
1903
|
-
const jsonString = urlParams.get('settings');
|
|
1904
|
-
if (jsonString)
|
|
1905
|
-
this._responseDto.parameters[parameterId].settings = JSON.parse(jsonString);
|
|
1906
|
-
}
|
|
1907
|
-
/**
|
|
1908
|
-
*
|
|
1909
|
-
* REMOVE THIS LOGIC - END
|
|
1910
|
-
*
|
|
1911
|
-
*/
|
|
1912
|
-
|
|
1913
|
-
switch (true) {
|
|
1914
|
-
case this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.BOOL:
|
|
1915
|
-
this.parameters[parameterId] = new Parameter<boolean>(this._responseDto.parameters[parameterId], this);
|
|
1916
|
-
break;
|
|
1917
|
-
case this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.COLOR:
|
|
1918
|
-
this.parameters[parameterId] = new Parameter<number | vec3>(this._responseDto.parameters[parameterId], this);
|
|
1919
|
-
break;
|
|
1920
|
-
case this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.FILE:
|
|
1921
|
-
this.parameters[parameterId] = new FileParameter(this._responseDto.parameters[parameterId], this);
|
|
1922
|
-
break;
|
|
1923
|
-
case this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.EVEN || this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.FLOAT || this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.INT || this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.ODD:
|
|
1924
|
-
this.parameters[parameterId] = new Parameter<number>(this._responseDto.parameters[parameterId], this);
|
|
1925
|
-
break;
|
|
1926
|
-
case this._responseDto.parameters[parameterId].type === PARAMETER_TYPE.INTERACTION:
|
|
1927
|
-
this.parameters[parameterId] = this.createInteractionParameter(this._responseDto.parameters[parameterId]);
|
|
1928
|
-
break;
|
|
1929
|
-
default:
|
|
1930
|
-
this.parameters[parameterId] = new Parameter<string>(this._responseDto.parameters[parameterId], this);
|
|
1931
|
-
break;
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
// we don't have to do larger restrictions for this as the backend would have already thrown an error if the values were not correct
|
|
1935
|
-
if (initialParameters) {
|
|
1936
|
-
// check if the id is within the initial parameters
|
|
1937
|
-
if (initialParameters[parameterId] !== undefined) {
|
|
1938
|
-
this.parameters[parameterId].value = initialParameters[parameterId];
|
|
1939
|
-
}
|
|
1940
|
-
// check if the name is within the initial parameters
|
|
1941
|
-
else if (initialParameters[this.parameters[parameterId].name] !== undefined) {
|
|
1942
|
-
this.parameters[parameterId].value = initialParameters[this.parameters[parameterId].name];
|
|
1943
|
-
}
|
|
1944
|
-
// NOTE: At some point the checking may also be done with the displayname, this is the code for it
|
|
1945
|
-
// // check if the displayname is within the initial parameters
|
|
1946
|
-
// else if(this.parameters[parameterId].displayname && initialParameters[this.parameters[parameterId].displayname!] !== undefined) {
|
|
1947
|
-
// this.parameters[parameterId].value = initialParameters[this.parameters[parameterId].displayname!];
|
|
1948
|
-
// }
|
|
1949
|
-
}
|
|
1950
|
-
|
|
1951
|
-
parameterSet[parameterId] = {
|
|
1952
|
-
value: this.parameters[parameterId].value,
|
|
1953
|
-
valueString: this.parameters[parameterId].stringify()
|
|
1954
|
-
};
|
|
1955
|
-
|
|
1956
|
-
if (!this.initialized)
|
|
1957
|
-
this.parameterValues[parameterId] = parameterSet[parameterId].valueString;
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1960
|
-
// store the initialization as the first parameter set in the history
|
|
1961
|
-
if (!this.initialized)
|
|
1962
|
-
this.#parameterHistory.push(parameterSet);
|
|
1963
|
-
|
|
1964
|
-
for (const exportId in this._responseDto.exports) {
|
|
1965
|
-
if (this._responseDto.exports[exportId].type === ShapeDiverResponseExportDefinitionType.EMAIL || this._responseDto.exports[exportId].type === ShapeDiverResponseExportDefinitionType.DOWNLOAD) {
|
|
1966
|
-
if (!this.exports[exportId]) {
|
|
1967
|
-
this._responseDto.exports[exportId].id = exportId;
|
|
1968
|
-
this.exports[exportId] = new Export(this._responseDto.exports[exportId], this);
|
|
1969
|
-
} else {
|
|
1970
|
-
this.exports[exportId].updateExportDefinition(this._responseDto.exports[exportId]);
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
|
|
1975
|
-
for (const outputId in this._responseDto.outputs) {
|
|
1976
|
-
if (!this.outputs[outputId]) {
|
|
1977
|
-
this._responseDto.outputs[outputId].id = outputId;
|
|
1978
|
-
if (this.outputsFreeze[outputId] === undefined) this.outputsFreeze[outputId] = false;
|
|
1979
|
-
this.outputs[outputId] = new Output(<ShapeDiverResponseOutput>this._responseDto.outputs[outputId], this);
|
|
1980
|
-
} else {
|
|
1981
|
-
this.outputs[outputId].updateOutputDefinition(<ShapeDiverResponseOutput>this._responseDto.outputs[outputId]);
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
|
|
1986
|
-
private async waitForUpdateCallbacks(newOutputVersions: { [key: string]: string }, oldOutputVersions: { [key: string]: string }, newNode: ITreeNode, oldNode: ITreeNode) {
|
|
1987
|
-
// call the update callback function on the session
|
|
1988
|
-
if (this._updateCallback) await Promise.resolve(this._updateCallback(newNode, oldNode));
|
|
1989
|
-
|
|
1990
|
-
const promises = [];
|
|
1991
|
-
// call the update callback functions on the outputs
|
|
1992
|
-
for (const outputId in this.outputs) {
|
|
1993
|
-
if (oldOutputVersions[outputId] !== newOutputVersions[outputId]) {
|
|
1994
|
-
promises.push(
|
|
1995
|
-
this.outputs[outputId].triggerUpdateCallback(
|
|
1996
|
-
newNode.children.find(c => c.name === outputId)!,
|
|
1997
|
-
oldNode.children.find(c => c.name === outputId)!
|
|
1998
|
-
)
|
|
1999
|
-
);
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2002
|
-
await Promise.all(promises);
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
|
-
// #endregion Private Methods (18)
|
|
2006
|
-
}
|