@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.
Files changed (97) hide show
  1. package/dist/implementation/OutputLoader.d.ts +1 -1
  2. package/dist/implementation/OutputLoader.d.ts.map +1 -1
  3. package/dist/implementation/OutputLoader.js +2 -5
  4. package/dist/implementation/OutputLoader.js.map +1 -1
  5. package/dist/implementation/SessionData.d.ts +4 -3
  6. package/dist/implementation/SessionData.d.ts.map +1 -1
  7. package/dist/implementation/SessionData.js.map +1 -1
  8. package/dist/implementation/{Session.d.ts → SessionEngine.d.ts} +79 -17
  9. package/dist/implementation/SessionEngine.d.ts.map +1 -0
  10. package/dist/implementation/SessionEngine.js +1132 -0
  11. package/dist/implementation/SessionEngine.js.map +1 -0
  12. package/dist/implementation/SessionOutputData.d.ts +4 -3
  13. package/dist/implementation/SessionOutputData.d.ts.map +1 -1
  14. package/dist/implementation/SessionOutputData.js.map +1 -1
  15. package/dist/implementation/SessionTreeNode.d.ts +4 -4
  16. package/dist/implementation/SessionTreeNode.d.ts.map +1 -1
  17. package/dist/implementation/SessionTreeNode.js +1 -4
  18. package/dist/implementation/SessionTreeNode.js.map +1 -1
  19. package/dist/implementation/dto/Export.d.ts +37 -0
  20. package/dist/implementation/dto/Export.d.ts.map +1 -0
  21. package/dist/implementation/dto/Export.js +204 -0
  22. package/dist/implementation/dto/Export.js.map +1 -0
  23. package/dist/implementation/dto/FileParameter.d.ts +10 -0
  24. package/dist/implementation/dto/FileParameter.d.ts.map +1 -0
  25. package/dist/implementation/dto/FileParameter.js +99 -0
  26. package/dist/implementation/dto/FileParameter.js.map +1 -0
  27. package/dist/implementation/dto/Output.d.ts +42 -0
  28. package/dist/implementation/dto/Output.d.ts.map +1 -0
  29. package/dist/implementation/dto/Output.js +200 -0
  30. package/dist/implementation/dto/Output.js.map +1 -0
  31. package/dist/implementation/dto/Parameter.d.ts +39 -0
  32. package/dist/implementation/dto/Parameter.d.ts.map +1 -0
  33. package/dist/implementation/dto/Parameter.js +341 -0
  34. package/dist/implementation/dto/Parameter.js.map +1 -0
  35. package/dist/index.d.ts +15 -5
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +14 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/interfaces/ISessionData.d.ts +7 -0
  40. package/dist/interfaces/ISessionData.d.ts.map +1 -0
  41. package/dist/interfaces/ISessionData.js +3 -0
  42. package/dist/interfaces/ISessionData.js.map +1 -0
  43. package/dist/interfaces/ISessionEngine.d.ts +123 -0
  44. package/dist/interfaces/ISessionEngine.d.ts.map +1 -0
  45. package/dist/interfaces/ISessionEngine.js +59 -0
  46. package/dist/interfaces/ISessionEngine.js.map +1 -0
  47. package/dist/interfaces/ISessionOutputData.d.ts +7 -0
  48. package/dist/interfaces/ISessionOutputData.d.ts.map +1 -0
  49. package/dist/interfaces/ISessionOutputData.js +3 -0
  50. package/dist/interfaces/ISessionOutputData.js.map +1 -0
  51. package/dist/interfaces/ISessionTreeNode.d.ts +5 -0
  52. package/dist/interfaces/ISessionTreeNode.d.ts.map +1 -0
  53. package/dist/interfaces/ISessionTreeNode.js +3 -0
  54. package/dist/interfaces/ISessionTreeNode.js.map +1 -0
  55. package/dist/interfaces/dto/IExport.d.ts +10 -0
  56. package/dist/interfaces/dto/IExport.d.ts.map +1 -0
  57. package/dist/interfaces/{ISession.js → dto/IExport.js} +1 -1
  58. package/dist/interfaces/dto/IExport.js.map +1 -0
  59. package/dist/interfaces/dto/IFileParameter.d.ts +5 -0
  60. package/dist/interfaces/dto/IFileParameter.d.ts.map +1 -0
  61. package/dist/interfaces/dto/IFileParameter.js +3 -0
  62. package/dist/interfaces/dto/IFileParameter.js.map +1 -0
  63. package/dist/interfaces/dto/IOutput.d.ts +25 -0
  64. package/dist/interfaces/dto/IOutput.d.ts.map +1 -0
  65. package/dist/interfaces/dto/IOutput.js +3 -0
  66. package/dist/interfaces/dto/IOutput.js.map +1 -0
  67. package/dist/interfaces/dto/IParameter.d.ts +10 -0
  68. package/dist/interfaces/dto/IParameter.d.ts.map +1 -0
  69. package/dist/interfaces/dto/IParameter.js +3 -0
  70. package/dist/interfaces/dto/IParameter.js.map +1 -0
  71. package/package.json +18 -11
  72. package/src/implementation/OutputDelayException.ts +22 -0
  73. package/src/implementation/OutputLoader.ts +281 -0
  74. package/src/implementation/SessionData.ts +43 -0
  75. package/src/implementation/SessionEngine.ts +1267 -0
  76. package/src/implementation/SessionOutputData.ts +43 -0
  77. package/src/implementation/SessionTreeNode.ts +41 -0
  78. package/src/implementation/dto/Export.ts +223 -0
  79. package/src/implementation/dto/FileParameter.ts +71 -0
  80. package/src/implementation/dto/Output.ts +221 -0
  81. package/src/implementation/dto/Parameter.ts +340 -0
  82. package/src/index.ts +26 -0
  83. package/src/interfaces/ISessionData.ts +16 -0
  84. package/src/interfaces/ISessionEngine.ts +123 -0
  85. package/src/interfaces/ISessionOutputData.ts +16 -0
  86. package/src/interfaces/ISessionTreeNode.ts +9 -0
  87. package/src/interfaces/dto/IExport.ts +17 -0
  88. package/src/interfaces/dto/IFileParameter.ts +9 -0
  89. package/src/interfaces/dto/IOutput.ts +45 -0
  90. package/src/interfaces/dto/IParameter.ts +19 -0
  91. package/tsconfig.json +17 -0
  92. package/dist/implementation/Session.d.ts.map +0 -1
  93. package/dist/implementation/Session.js +0 -536
  94. package/dist/implementation/Session.js.map +0 -1
  95. package/dist/interfaces/ISession.d.ts +0 -32
  96. package/dist/interfaces/ISession.d.ts.map +0 -1
  97. 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
+ }