@shapediver/viewer.session-engine.session-engine 1.15.6 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/implementation/OutputLoader.d.ts +1 -1
- package/dist/implementation/OutputLoader.d.ts.map +1 -1
- package/dist/implementation/OutputLoader.js +2 -5
- package/dist/implementation/OutputLoader.js.map +1 -1
- package/dist/implementation/SessionData.d.ts +4 -3
- package/dist/implementation/SessionData.d.ts.map +1 -1
- package/dist/implementation/SessionData.js.map +1 -1
- package/dist/implementation/{Session.d.ts → SessionEngine.d.ts} +79 -17
- package/dist/implementation/SessionEngine.d.ts.map +1 -0
- package/dist/implementation/SessionEngine.js +1132 -0
- package/dist/implementation/SessionEngine.js.map +1 -0
- package/dist/implementation/SessionOutputData.d.ts +4 -3
- package/dist/implementation/SessionOutputData.d.ts.map +1 -1
- package/dist/implementation/SessionOutputData.js.map +1 -1
- package/dist/implementation/SessionTreeNode.d.ts +4 -4
- package/dist/implementation/SessionTreeNode.d.ts.map +1 -1
- package/dist/implementation/SessionTreeNode.js +1 -4
- package/dist/implementation/SessionTreeNode.js.map +1 -1
- package/dist/implementation/dto/Export.d.ts +37 -0
- package/dist/implementation/dto/Export.d.ts.map +1 -0
- package/dist/implementation/dto/Export.js +204 -0
- package/dist/implementation/dto/Export.js.map +1 -0
- package/dist/implementation/dto/FileParameter.d.ts +10 -0
- package/dist/implementation/dto/FileParameter.d.ts.map +1 -0
- package/dist/implementation/dto/FileParameter.js +99 -0
- package/dist/implementation/dto/FileParameter.js.map +1 -0
- package/dist/implementation/dto/Output.d.ts +42 -0
- package/dist/implementation/dto/Output.d.ts.map +1 -0
- package/dist/implementation/dto/Output.js +200 -0
- package/dist/implementation/dto/Output.js.map +1 -0
- package/dist/implementation/dto/Parameter.d.ts +39 -0
- package/dist/implementation/dto/Parameter.d.ts.map +1 -0
- package/dist/implementation/dto/Parameter.js +341 -0
- package/dist/implementation/dto/Parameter.js.map +1 -0
- package/dist/index.d.ts +15 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/interfaces/ISessionData.d.ts +7 -0
- package/dist/interfaces/ISessionData.d.ts.map +1 -0
- package/dist/interfaces/ISessionData.js +3 -0
- package/dist/interfaces/ISessionData.js.map +1 -0
- package/dist/interfaces/ISessionEngine.d.ts +123 -0
- package/dist/interfaces/ISessionEngine.d.ts.map +1 -0
- package/dist/interfaces/ISessionEngine.js +59 -0
- package/dist/interfaces/ISessionEngine.js.map +1 -0
- package/dist/interfaces/ISessionOutputData.d.ts +7 -0
- package/dist/interfaces/ISessionOutputData.d.ts.map +1 -0
- package/dist/interfaces/ISessionOutputData.js +3 -0
- package/dist/interfaces/ISessionOutputData.js.map +1 -0
- package/dist/interfaces/ISessionTreeNode.d.ts +5 -0
- package/dist/interfaces/ISessionTreeNode.d.ts.map +1 -0
- package/dist/interfaces/ISessionTreeNode.js +3 -0
- package/dist/interfaces/ISessionTreeNode.js.map +1 -0
- package/dist/interfaces/dto/IExport.d.ts +10 -0
- package/dist/interfaces/dto/IExport.d.ts.map +1 -0
- package/dist/interfaces/{ISession.js → dto/IExport.js} +1 -1
- package/dist/interfaces/dto/IExport.js.map +1 -0
- package/dist/interfaces/dto/IFileParameter.d.ts +5 -0
- package/dist/interfaces/dto/IFileParameter.d.ts.map +1 -0
- package/dist/interfaces/dto/IFileParameter.js +3 -0
- package/dist/interfaces/dto/IFileParameter.js.map +1 -0
- package/dist/interfaces/dto/IOutput.d.ts +25 -0
- package/dist/interfaces/dto/IOutput.d.ts.map +1 -0
- package/dist/interfaces/dto/IOutput.js +3 -0
- package/dist/interfaces/dto/IOutput.js.map +1 -0
- package/dist/interfaces/dto/IParameter.d.ts +10 -0
- package/dist/interfaces/dto/IParameter.d.ts.map +1 -0
- package/dist/interfaces/dto/IParameter.js +3 -0
- package/dist/interfaces/dto/IParameter.js.map +1 -0
- package/package.json +18 -11
- package/src/implementation/OutputDelayException.ts +22 -0
- package/src/implementation/OutputLoader.ts +281 -0
- package/src/implementation/SessionData.ts +43 -0
- package/src/implementation/SessionEngine.ts +1267 -0
- package/src/implementation/SessionOutputData.ts +43 -0
- package/src/implementation/SessionTreeNode.ts +41 -0
- package/src/implementation/dto/Export.ts +223 -0
- package/src/implementation/dto/FileParameter.ts +71 -0
- package/src/implementation/dto/Output.ts +221 -0
- package/src/implementation/dto/Parameter.ts +340 -0
- package/src/index.ts +26 -0
- package/src/interfaces/ISessionData.ts +16 -0
- package/src/interfaces/ISessionEngine.ts +123 -0
- package/src/interfaces/ISessionOutputData.ts +16 -0
- package/src/interfaces/ISessionTreeNode.ts +9 -0
- package/src/interfaces/dto/IExport.ts +17 -0
- package/src/interfaces/dto/IFileParameter.ts +9 -0
- package/src/interfaces/dto/IOutput.ts +45 -0
- package/src/interfaces/dto/IParameter.ts +19 -0
- package/tsconfig.json +17 -0
- package/dist/implementation/Session.d.ts.map +0 -1
- package/dist/implementation/Session.js +0 -536
- package/dist/implementation/Session.js.map +0 -1
- package/dist/interfaces/ISession.d.ts +0 -32
- package/dist/interfaces/ISession.d.ts.map +0 -1
- package/dist/interfaces/ISession.js.map +0 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { container } from 'tsyringe'
|
|
2
|
+
import { IMaterialAbstractData, GeometryData, AbstractMaterialData } from '@shapediver/viewer.shared.types'
|
|
3
|
+
import { DataEngine } from '@shapediver/viewer.data-engine.data-engine'
|
|
4
|
+
import { ITreeNode, Tree, TreeNode } from '@shapediver/viewer.shared.node-tree'
|
|
5
|
+
|
|
6
|
+
import { OutputDelayException } from './OutputDelayException'
|
|
7
|
+
import { SessionTreeNode } from './SessionTreeNode'
|
|
8
|
+
import { SessionOutputData } from './SessionOutputData'
|
|
9
|
+
import { PerformanceEvaluator } from '@shapediver/viewer.shared.services'
|
|
10
|
+
import { ShapeDiverResponseDto, ShapeDiverResponseOutput } from '@shapediver/sdk.geometry-api-sdk-v2'
|
|
11
|
+
import { ISessionTreeNode } from '../interfaces/ISessionTreeNode'
|
|
12
|
+
|
|
13
|
+
export class OutputLoader {
|
|
14
|
+
// #region Properties (3)
|
|
15
|
+
|
|
16
|
+
private readonly _dataEngine: DataEngine = <DataEngine>container.resolve(DataEngine);
|
|
17
|
+
private readonly _loadedOutputNodes: {
|
|
18
|
+
[key: string]: {
|
|
19
|
+
[key: string]: ISessionTreeNode
|
|
20
|
+
};
|
|
21
|
+
} = {};
|
|
22
|
+
private readonly _lastOutputNodes: {
|
|
23
|
+
[key: string]: ISessionTreeNode
|
|
24
|
+
} = {};
|
|
25
|
+
private readonly _performanceEvaluator: PerformanceEvaluator = <PerformanceEvaluator>container.resolve(PerformanceEvaluator);
|
|
26
|
+
|
|
27
|
+
// #endregion Properties (3)
|
|
28
|
+
|
|
29
|
+
// #region Constructors (1)
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The output loader takes care of loading the outputs of a session, storing them and returning stored or newly loaded nodes.
|
|
33
|
+
*
|
|
34
|
+
* @param _session the session for this output loader
|
|
35
|
+
*/
|
|
36
|
+
constructor() {}
|
|
37
|
+
|
|
38
|
+
// #endregion Constructors (1)
|
|
39
|
+
|
|
40
|
+
// #region Public Methods (1)
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Load the outputs and return the scene graph node of the result.
|
|
44
|
+
* In case the outputs have a delay property, it throws an OutputDelayException.
|
|
45
|
+
*
|
|
46
|
+
* @param outputs the outputs to load
|
|
47
|
+
* @returns promise with a scene graph node
|
|
48
|
+
*/
|
|
49
|
+
public async loadOutputs(responseDto: ShapeDiverResponseDto, outputs: { [key: string]: ShapeDiverResponseOutput; }, outputsFreeze: { [key: string]: boolean; }): Promise<SessionTreeNode> {
|
|
50
|
+
this._performanceEvaluator.startSection('outputLoading');
|
|
51
|
+
const node = new SessionTreeNode(responseDto.model?.name);
|
|
52
|
+
let currentNodes: {
|
|
53
|
+
[key: string]: {
|
|
54
|
+
[key: string]: ISessionTreeNode
|
|
55
|
+
};
|
|
56
|
+
} = {};
|
|
57
|
+
let promises: Promise<ITreeNode>[] = [];
|
|
58
|
+
let promisesNodes: ISessionTreeNode[] = [];
|
|
59
|
+
let maxDelay = 0;
|
|
60
|
+
|
|
61
|
+
for (let outputID in outputs) {
|
|
62
|
+
currentNodes[outputID] = {};
|
|
63
|
+
if(!this._loadedOutputNodes[outputID])
|
|
64
|
+
this._loadedOutputNodes[outputID] = {};
|
|
65
|
+
|
|
66
|
+
if(outputsFreeze[outputID]) {
|
|
67
|
+
currentNodes[outputID][outputs[outputID].version] = this._lastOutputNodes[outputID];
|
|
68
|
+
} else if(outputs[outputID].delay) {
|
|
69
|
+
maxDelay = Math.max(maxDelay, outputs[outputID].delay!);
|
|
70
|
+
} else if(!this._loadedOutputNodes[outputID][outputs[outputID].version]) {
|
|
71
|
+
currentNodes[outputID][outputs[outputID].version] = new SessionTreeNode(outputID);
|
|
72
|
+
currentNodes[outputID][outputs[outputID].version].data.push(new SessionOutputData(outputs[outputID]));
|
|
73
|
+
if(outputs[outputID].content) {
|
|
74
|
+
for (let i = 0, len = outputs[outputID].content!.length; i < len; i++) {
|
|
75
|
+
promises.push(this._dataEngine.loadContent(outputs[outputID].content![i]))
|
|
76
|
+
promisesNodes.push(currentNodes[outputID][outputs[outputID].version])
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
currentNodes[outputID][outputs[outputID].version] = this._loadedOutputNodes[outputID][outputs[outputID].version];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if(maxDelay)
|
|
85
|
+
throw new OutputDelayException(maxDelay);
|
|
86
|
+
|
|
87
|
+
await Promise.all(promises);
|
|
88
|
+
|
|
89
|
+
// all promises are resolved, await in the next lines is just for structural purposes
|
|
90
|
+
for(let i = 0; i < promises.length; i++)
|
|
91
|
+
promisesNodes[i].addChild(await promises[i])
|
|
92
|
+
|
|
93
|
+
// here we assign all outputs just to the node and return it
|
|
94
|
+
for (let outputID in outputs) {
|
|
95
|
+
node.addChild(currentNodes[outputID][outputs[outputID].version]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// save the nodes as the last available version
|
|
99
|
+
for (let outputID in outputs) {
|
|
100
|
+
this._loadedOutputNodes[outputID] = {};
|
|
101
|
+
this._loadedOutputNodes[outputID][outputs[outputID].version] = currentNodes[outputID][outputs[outputID].version];
|
|
102
|
+
this._lastOutputNodes[outputID] = currentNodes[outputID][outputs[outputID].version];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (let outputID in outputs) {
|
|
106
|
+
if(currentNodes[outputID][outputs[outputID].version].children.length > 1) {
|
|
107
|
+
for (let i = 0, len = outputs[outputID].content!.length; i < len; i++) {
|
|
108
|
+
if(outputs[outputID].content![i].format === 'sdtf') {
|
|
109
|
+
this.mergeContentNodes(currentNodes[outputID][outputs[outputID].version])
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this.assignMaterials(node);
|
|
117
|
+
this._performanceEvaluator.endSection('outputLoading');
|
|
118
|
+
return node;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// #endregion Public Methods (1)
|
|
122
|
+
|
|
123
|
+
// #region Private Methods (2)
|
|
124
|
+
|
|
125
|
+
private assignMaterials(node: ITreeNode) {
|
|
126
|
+
const addMaterialToGeometry = (node: ITreeNode, material: IMaterialAbstractData) => {
|
|
127
|
+
for (let i = 0; i < node.data.length; i++) {
|
|
128
|
+
if (node.data[i] instanceof GeometryData) {
|
|
129
|
+
const geometry = <GeometryData>node.data[i];
|
|
130
|
+
const currentMaterial = geometry.primitive.material;
|
|
131
|
+
if(currentMaterial === null || currentMaterial.materialOutput === true) {
|
|
132
|
+
geometry.primitive.material = material;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
138
|
+
const child = node.children[i];
|
|
139
|
+
if (child) addMaterialToGeometry(child, material);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const getMaterialData = (node: ITreeNode, materials: IMaterialAbstractData[] = []): IMaterialAbstractData[] => {
|
|
144
|
+
for (let k = 0; k < node.data.length; k++) {
|
|
145
|
+
if (node.data[k] instanceof AbstractMaterialData) {
|
|
146
|
+
const material = <IMaterialAbstractData>node.data[k];
|
|
147
|
+
material.materialOutput = true;
|
|
148
|
+
materials.push(material);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
for (let k = 0; k < node.children.length; k++) {
|
|
153
|
+
const child = node.children[k];
|
|
154
|
+
if(!child) continue;
|
|
155
|
+
materials.push(...getMaterialData(child));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return materials;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const getGeometryData = (node: ITreeNode, geometries: GeometryData[] = []): GeometryData[] => {
|
|
162
|
+
for (let k = 0; k < node.data.length; k++)
|
|
163
|
+
if (node.data[k] instanceof GeometryData)
|
|
164
|
+
geometries.push(<GeometryData>node.data[k]);
|
|
165
|
+
|
|
166
|
+
for (let k = 0; k < node.children.length; k++) {
|
|
167
|
+
const child = node.children[k];
|
|
168
|
+
if(!child) continue;
|
|
169
|
+
geometries.push(...getGeometryData(child));
|
|
170
|
+
}
|
|
171
|
+
return geometries;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (let m = 0; m < node.children.length; m++) {
|
|
175
|
+
// per output node, we go through the material assignment process
|
|
176
|
+
const outputNode = node.children[m];
|
|
177
|
+
if (!outputNode) continue;
|
|
178
|
+
|
|
179
|
+
// we go through all data properties, normally, there should ony one, but we just make sure
|
|
180
|
+
for (let i = 0; i < outputNode.data.length; i++) {
|
|
181
|
+
if (!(outputNode.data[i] instanceof SessionOutputData)) continue;
|
|
182
|
+
|
|
183
|
+
// the session output data contains information about this Output
|
|
184
|
+
// most importantly the SessionOutput property with the material and content in it
|
|
185
|
+
const sessionOutputData = <SessionOutputData>outputNode.data[i];
|
|
186
|
+
|
|
187
|
+
// case 1: we have a specific material id defined, let's use that
|
|
188
|
+
if(sessionOutputData.responseOutput.material) {
|
|
189
|
+
let materialNodes: ITreeNode[] = [];
|
|
190
|
+
// now we have id
|
|
191
|
+
// get material with it
|
|
192
|
+
for (let n = 0; n < node.children.length; n++) {
|
|
193
|
+
const materialNode = node.children[n];
|
|
194
|
+
if (!materialNode) continue;
|
|
195
|
+
if (materialNode.name === sessionOutputData.responseOutput.material)
|
|
196
|
+
materialNodes = materialNode.children;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const geometryNodes = outputNode.children;
|
|
200
|
+
|
|
201
|
+
if(materialNodes.length >= geometryNodes.length) {
|
|
202
|
+
for (let n = 0; n < geometryNodes.length; n++) {
|
|
203
|
+
addMaterialToGeometry(geometryNodes[n], getMaterialData(materialNodes[n])[0]);
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
if (materialNodes.length >= 1)
|
|
207
|
+
for (let n = 0; n < geometryNodes.length; n++) {
|
|
208
|
+
addMaterialToGeometry(geometryNodes[n], getMaterialData(materialNodes[0])[0]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// case 2: there is no specific material id defined, maybe in the content we can match geometries to ids
|
|
213
|
+
else {
|
|
214
|
+
// now we hope that in our content, there are exactly the amount of geometries and material, this will be interesting :)
|
|
215
|
+
|
|
216
|
+
const sessionOutputContent = sessionOutputData.responseOutput.content;
|
|
217
|
+
if(sessionOutputContent === undefined) continue;
|
|
218
|
+
|
|
219
|
+
const materialNodes = [];
|
|
220
|
+
const geometryNodes = [];
|
|
221
|
+
for(let i = 0; i < sessionOutputContent.length; i++) {
|
|
222
|
+
if(sessionOutputContent[i].format === 'material') {
|
|
223
|
+
materialNodes.push(outputNode.children[i]);
|
|
224
|
+
} else {
|
|
225
|
+
geometryNodes.push(outputNode.children[i]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if(materialNodes.length >= geometryNodes.length) {
|
|
230
|
+
for (let n = 0; n < geometryNodes.length; n++) {
|
|
231
|
+
addMaterialToGeometry(geometryNodes[n], getMaterialData(materialNodes[n])[0]);
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
if (materialNodes.length >= 1)
|
|
235
|
+
for (let n = 0; n < geometryNodes.length; n++) {
|
|
236
|
+
addMaterialToGeometry(geometryNodes[n], getMaterialData(materialNodes[0])[0]);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private mergeContentNodes(node: ISessionTreeNode) {
|
|
245
|
+
if(!(node.children.length > 1)) return;
|
|
246
|
+
|
|
247
|
+
const children = [];
|
|
248
|
+
while(node.children.length > 0) {
|
|
249
|
+
children.push(...node.children[0].children);
|
|
250
|
+
node.removeChild(node.children[0]);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const mergeNodes = (node1: ITreeNode, node2: ITreeNode) => {
|
|
254
|
+
for(let i = 0; i < node1.data.length; i++)
|
|
255
|
+
node2.data.push(node1.data[i]);
|
|
256
|
+
|
|
257
|
+
for(let i = 0; i < node1.children.length; i++) {
|
|
258
|
+
let childNode;
|
|
259
|
+
for(let j = 0; j < node2.children.length; j++) {
|
|
260
|
+
if(node1.children[i].name === node2.children[j].name) {
|
|
261
|
+
childNode = node2.children[j];
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if(!childNode) {
|
|
266
|
+
childNode = new TreeNode(node1.children[i].name);
|
|
267
|
+
node2.addChild(childNode);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
mergeNodes(node1.children[i], childNode);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const newChild = new TreeNode('content_array');
|
|
275
|
+
node.addChild(newChild);
|
|
276
|
+
for(let i = 0; i < children.length; i++)
|
|
277
|
+
mergeNodes(children[i], newChild)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// #endregion Private Methods (2)
|
|
281
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ShapeDiverResponseDto } from '@shapediver/sdk.geometry-api-sdk-v2';
|
|
2
|
+
import { AbstractTreeNodeData, ITreeNodeData } from '@shapediver/viewer.shared.node-tree'
|
|
3
|
+
import { ISessionData } from '../interfaces/ISessionData';
|
|
4
|
+
|
|
5
|
+
export class SessionData extends AbstractTreeNodeData implements ISessionData {
|
|
6
|
+
// #region Properties (1)
|
|
7
|
+
|
|
8
|
+
#responseDto: ShapeDiverResponseDto;
|
|
9
|
+
|
|
10
|
+
// #endregion Properties (1)
|
|
11
|
+
|
|
12
|
+
// #region Constructors (1)
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
responseDto: ShapeDiverResponseDto,
|
|
16
|
+
id?: string
|
|
17
|
+
) {
|
|
18
|
+
super(id);
|
|
19
|
+
this.#responseDto = responseDto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// #endregion Constructors (1)
|
|
23
|
+
|
|
24
|
+
// #region Public Accessors (2)
|
|
25
|
+
|
|
26
|
+
public get responseDto(): ShapeDiverResponseDto {
|
|
27
|
+
return this.#responseDto;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public set responseDto(value: ShapeDiverResponseDto) {
|
|
31
|
+
this.#responseDto = value;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// #endregion Public Accessors (2)
|
|
35
|
+
|
|
36
|
+
// #region Public Methods (1)
|
|
37
|
+
|
|
38
|
+
public clone(): ISessionData {
|
|
39
|
+
return new SessionData(this.responseDto, this.id);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// #endregion Public Methods (1)
|
|
43
|
+
}
|