@colijnit/configurator 1.0.21 → 1.0.22

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 (158) hide show
  1. package/app/builder.d.ts +53 -0
  2. package/app/components/answers/answer/answer.component.d.ts +11 -0
  3. package/app/components/answers/answers.component.d.ts +8 -0
  4. package/app/components/answers/answers.module.d.ts +2 -0
  5. package/app/components/selections/selections.component.d.ts +22 -0
  6. package/app/components/selections/selections.module.d.ts +2 -0
  7. package/app/components/shared/loader/loader.component.d.ts +2 -0
  8. package/app/components/shared/shared.module.d.ts +2 -0
  9. package/app/directives/visibility-observer-master.directive.d.ts +9 -0
  10. package/app/directives/visibility-observer.directive.d.ts +13 -0
  11. package/app/services/configurator.service.d.ts +22 -0
  12. package/app/services/image-cache.service.d.ts +10 -0
  13. package/app/services/locator.service.d.ts +4 -0
  14. package/bundles/colijnit-configurator.umd.js +2745 -0
  15. package/bundles/colijnit-configurator.umd.js.map +1 -0
  16. package/bundles/colijnit-configurator.umd.min.js +17 -0
  17. package/bundles/colijnit-configurator.umd.min.js.map +1 -0
  18. package/colijnit-configurator.d.ts +10 -0
  19. package/colijnit-configurator.metadata.json +1 -0
  20. package/esm2015/app/builder.js +477 -0
  21. package/esm2015/app/components/answers/answer/answer.component.js +69 -0
  22. package/esm2015/app/components/answers/answers.component.js +43 -0
  23. package/esm2015/app/components/answers/answers.module.js +29 -0
  24. package/esm2015/app/components/selections/selections.component.js +134 -0
  25. package/esm2015/app/components/selections/selections.module.js +23 -0
  26. package/esm2015/app/components/shared/loader/loader.component.js +24 -0
  27. package/esm2015/app/components/shared/shared.module.js +21 -0
  28. package/esm2015/app/directives/visibility-observer-master.directive.js +51 -0
  29. package/esm2015/app/directives/visibility-observer.directive.js +57 -0
  30. package/esm2015/app/services/configurator.service.js +94 -0
  31. package/esm2015/app/services/image-cache.service.js +66 -0
  32. package/esm2015/app/services/locator.service.js +10 -0
  33. package/esm2015/colijnit-configurator.js +11 -0
  34. package/esm2015/helper/variation-helper.js +216 -0
  35. package/esm2015/model/material.js +11 -0
  36. package/esm2015/model/variation-settings.js +6 -0
  37. package/esm2015/model/variation.js +3 -0
  38. package/esm2015/public_api.js +7 -0
  39. package/esm2015/utils/asset.utils.js +74 -0
  40. package/esm2015/utils/file.utils.js +139 -0
  41. package/esm2015/utils/image.utils.js +52 -0
  42. package/esm2015/utils/object.utils.js +49 -0
  43. package/esm2015/utils/scene-utils.js +94 -0
  44. package/esm2015/utils/threed.utils.js +222 -0
  45. package/esm2015/utils/variation-utils.js +224 -0
  46. package/esm5/app/builder.js +591 -0
  47. package/esm5/app/components/answers/answer/answer.component.js +64 -0
  48. package/esm5/app/components/answers/answers.component.js +27 -0
  49. package/esm5/app/components/answers/answers.module.js +32 -0
  50. package/esm5/app/components/selections/selections.component.js +104 -0
  51. package/esm5/app/components/selections/selections.module.js +26 -0
  52. package/esm5/app/components/shared/loader/loader.component.js +16 -0
  53. package/esm5/app/components/shared/shared.module.js +24 -0
  54. package/esm5/app/directives/visibility-observer-master.directive.js +64 -0
  55. package/esm5/app/directives/visibility-observer.directive.js +59 -0
  56. package/esm5/app/services/configurator.service.js +160 -0
  57. package/esm5/app/services/image-cache.service.js +69 -0
  58. package/esm5/app/services/locator.service.js +13 -0
  59. package/esm5/colijnit-configurator.js +11 -0
  60. package/esm5/helper/variation-helper.js +268 -0
  61. package/esm5/model/material.js +13 -0
  62. package/esm5/model/variation-settings.js +8 -0
  63. package/esm5/model/variation.js +7 -0
  64. package/esm5/public_api.js +7 -0
  65. package/esm5/utils/asset.utils.js +106 -0
  66. package/esm5/utils/file.utils.js +151 -0
  67. package/esm5/utils/image.utils.js +56 -0
  68. package/esm5/utils/object.utils.js +56 -0
  69. package/esm5/utils/scene-utils.js +98 -0
  70. package/esm5/utils/threed.utils.js +279 -0
  71. package/esm5/utils/variation-utils.js +327 -0
  72. package/fesm2015/colijnit-configurator.js +2109 -0
  73. package/fesm2015/colijnit-configurator.js.map +1 -0
  74. package/fesm5/colijnit-configurator.js +2527 -0
  75. package/fesm5/colijnit-configurator.js.map +1 -0
  76. package/helper/variation-helper.d.ts +14 -0
  77. package/model/material.d.ts +17 -0
  78. package/model/variation-settings.d.ts +14 -0
  79. package/model/variation.d.ts +10 -0
  80. package/package.json +12 -45
  81. package/{src/public_api.ts → public_api.d.ts} +6 -6
  82. package/utils/asset.utils.d.ts +13 -0
  83. package/utils/file.utils.d.ts +27 -0
  84. package/utils/image.utils.d.ts +8 -0
  85. package/utils/object.utils.d.ts +7 -0
  86. package/utils/scene-utils.d.ts +7 -0
  87. package/utils/threed.utils.d.ts +16 -0
  88. package/utils/variation-utils.d.ts +12 -0
  89. package/.idea/Configurator.iml +0 -12
  90. package/.idea/codeStyles/Project.xml +0 -21
  91. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  92. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  93. package/.idea/misc.xml +0 -9
  94. package/.idea/modules.xml +0 -8
  95. package/.idea/vcs.xml +0 -6
  96. package/angular.json +0 -193
  97. package/configurator.iml +0 -11
  98. package/dist/configurator/index.html +0 -14
  99. package/dist/configurator/main-es2015.js +0 -3129
  100. package/dist/configurator/main-es2015.js.map +0 -1
  101. package/dist/configurator/main-es5.js +0 -5482
  102. package/dist/configurator/main-es5.js.map +0 -1
  103. package/dist/configurator/polyfills-es2015.js +0 -4520
  104. package/dist/configurator/polyfills-es2015.js.map +0 -1
  105. package/dist/configurator/polyfills-es5.js +0 -18375
  106. package/dist/configurator/polyfills-es5.js.map +0 -1
  107. package/dist/configurator/runtime-es2015.js +0 -155
  108. package/dist/configurator/runtime-es2015.js.map +0 -1
  109. package/dist/configurator/runtime-es5.js +0 -155
  110. package/dist/configurator/runtime-es5.js.map +0 -1
  111. package/dist/configurator/styles-es2015.js +0 -450
  112. package/dist/configurator/styles-es2015.js.map +0 -1
  113. package/dist/configurator/styles-es5.js +0 -432
  114. package/dist/configurator/styles-es5.js.map +0 -1
  115. package/dist/configurator/vendor-es2015.js +0 -155551
  116. package/dist/configurator/vendor-es2015.js.map +0 -1
  117. package/dist/configurator/vendor-es5.js +0 -183588
  118. package/dist/configurator/vendor-es5.js.map +0 -1
  119. package/ng-package.json +0 -9
  120. package/src/app/app.component.ts +0 -222
  121. package/src/app/app.module.ts +0 -34
  122. package/src/app/builder.ts +0 -480
  123. package/src/app/components/answers/answer/answer.component.ts +0 -61
  124. package/src/app/components/answers/answers.component.ts +0 -41
  125. package/src/app/components/answers/answers.module.ts +0 -26
  126. package/src/app/components/selections/selections.component.ts +0 -131
  127. package/src/app/components/selections/selections.module.ts +0 -20
  128. package/src/app/components/shared/loader/loader.component.scss +0 -33
  129. package/src/app/components/shared/loader/loader.component.ts +0 -20
  130. package/src/app/components/shared/shared.module.ts +0 -16
  131. package/src/app/directives/visibility-observer-master.directive.ts +0 -71
  132. package/src/app/directives/visibility-observer.directive.ts +0 -74
  133. package/src/app/services/configurator.service.ts +0 -86
  134. package/src/app/services/image-cache.service.ts +0 -56
  135. package/src/app/services/locator.service.ts +0 -6
  136. package/src/environments/environment.prod.ts +0 -3
  137. package/src/environments/environment.ts +0 -8
  138. package/src/helper/variation-helper.ts +0 -220
  139. package/src/index.html +0 -14
  140. package/src/main.ts +0 -11
  141. package/src/model/material.ts +0 -22
  142. package/src/model/variation-settings.ts +0 -14
  143. package/src/model/variation.ts +0 -11
  144. package/src/polyfills.ts +0 -73
  145. package/src/style/shared.scss +0 -173
  146. package/src/style/styles.scss +0 -45
  147. package/src/tsconfig.app.json +0 -16
  148. package/src/tsconfig.spec.json +0 -19
  149. package/src/utils/asset.utils.ts +0 -88
  150. package/src/utils/file.utils.ts +0 -156
  151. package/src/utils/file.utils.unit.test.ts +0 -8
  152. package/src/utils/image.utils.ts +0 -54
  153. package/src/utils/object.utils.ts +0 -52
  154. package/src/utils/scene-utils.ts +0 -119
  155. package/src/utils/threed.utils.ts +0 -219
  156. package/src/utils/variation-utils.ts +0 -216
  157. package/tsconfig.json +0 -23
  158. package/tslint.json +0 -132
@@ -0,0 +1,2109 @@
1
+ import { __awaiter, __decorate } from 'tslib';
2
+ import { Mesh, ObjectLoader, Camera, Group, TextureLoader, RepeatWrapping, Object3D, Box3, Vector3, Vector2, Euler, Quaternion, Color, Texture, sRGBEncoding, MeshPhongMaterial, MeshStandardMaterial, Scene } from 'three';
3
+ import { Options } from '@colijnit/ioneconnector/build/model/options';
4
+ import { DecoNode } from '@colijnit/configuratorapi/build/model/deco-node';
5
+ import { BusinessObjectFactory } from '@colijnit/ioneconnector/build/service/business-object-factory';
6
+ import { Selection } from '@colijnit/configuratorapi/build/model/selection';
7
+ import { DecoNodeType } from '@colijnit/configuratorapi/build/enum/deco-node-type.enum';
8
+ import axios from 'axios';
9
+ import { DecoNodeKind } from '@colijnit/configuratorapi/build/enum/deco-node-kind.enum';
10
+ import * as JSZip from 'jszip';
11
+ import { Article } from '@colijnit/configuratorapi/build/model/article';
12
+ import { Injectable, Injector, ɵɵdefineInjectable, ɵɵinject, INJECTOR, EventEmitter, Input, Output, Component, Directive, ElementRef, NgModule } from '@angular/core';
13
+ import { Configurator } from '@colijnit/configuratorapi/build/configurator';
14
+ import { notNill } from '@colijnit/configuratorapi/build/utils/function/not-nill.function';
15
+ import { NodeType } from '@colijnit/configuratorapi/build/enum/node-type.enum';
16
+ import { isNill } from '@colijnit/configuratorapi/build/utils/function/is-nill.function';
17
+ import { BehaviorSubject } from 'rxjs';
18
+ import { CommonModule } from '@angular/common';
19
+ import { trigger, state, style, transition, animate } from '@angular/animations';
20
+
21
+ class ObjectUtils {
22
+ static DisposeMaterial(material) {
23
+ if (!material) {
24
+ return;
25
+ }
26
+ if (Array.isArray(material)) {
27
+ material.forEach(mtrl => {
28
+ this.materialProps
29
+ .filter(mapType => mtrl[mapType])
30
+ .forEach(mapType => mtrl[mapType].dispose());
31
+ mtrl.dispose();
32
+ });
33
+ }
34
+ else {
35
+ this.materialProps
36
+ .filter(mapType => material[mapType] && material[mapType].dispose)
37
+ .forEach(mapType => material[mapType].dispose());
38
+ if (material.dispose) {
39
+ material.dispose();
40
+ }
41
+ }
42
+ }
43
+ static DisposeObject(object) {
44
+ if (!object) {
45
+ return;
46
+ }
47
+ if (object.children.length) {
48
+ object.children.forEach(child => this.DisposeObject(child));
49
+ }
50
+ this.DisposeNode(object);
51
+ }
52
+ static DisposeNode(node) {
53
+ node.traverse((obj) => {
54
+ if (obj instanceof Mesh) {
55
+ if (obj.geometry) {
56
+ obj.geometry.dispose();
57
+ }
58
+ this.DisposeMaterial(obj.material);
59
+ }
60
+ if (typeof obj.dispose === 'function') {
61
+ // @ts-ignore
62
+ obj.dispose();
63
+ }
64
+ });
65
+ }
66
+ }
67
+ ObjectUtils.materialProps = ['map', 'lightMap', 'bumpMap', 'normalMap', 'specularMap', 'envMap', 'aoMap', 'roughnessMap', 'metalnessMap'];
68
+
69
+ // Static utility functions holder related to files.
70
+ // @dynamic
71
+ class FileUtils {
72
+ // Returns the given dataUri string stripped of the mimetype part.
73
+ static StripMimeStringFromDataUri(dataUri) {
74
+ if (!dataUri) {
75
+ return '';
76
+ }
77
+ const mimeString = this.GetMimeStringFromDataUri(dataUri);
78
+ return dataUri.substr(mimeString.length + 1);
79
+ }
80
+ static GetMimeStringFromDataUri(dataUri) {
81
+ if (!dataUri) {
82
+ return '';
83
+ }
84
+ return dataUri.split(',')[0];
85
+ }
86
+ static FileExists(url, assetPath) {
87
+ return __awaiter(this, void 0, void 0, function* () {
88
+ const result = yield axios({
89
+ method: 'get',
90
+ url: `${assetPath}getFiles.php?assetUrl=${url}`,
91
+ responseType: "json"
92
+ });
93
+ return !!result.data;
94
+ });
95
+ }
96
+ /**
97
+ * There is some discrepancy regarding locations of h3d objects
98
+ * Therefor we need to (temporarily?!) fix the content url
99
+ * Also we need to change some additionals
100
+ */
101
+ static FixUrl(assetUrl) {
102
+ if (!assetUrl) {
103
+ return '';
104
+ }
105
+ let fixedUrl = assetUrl;
106
+ if (!fixedUrl.endsWith('glb') && !fixedUrl.endsWith('obj') && !fixedUrl.endsWith('glb.gz') && !fixedUrl.endsWith('obj.gz')) {
107
+ fixedUrl = FileUtils.FixUnityUrl(fixedUrl);
108
+ }
109
+ fixedUrl = fixedUrl.replace('/content/', '/content43/');
110
+ return fixedUrl;
111
+ }
112
+ static FixGlbUrl(assetUrl) {
113
+ if (!assetUrl) {
114
+ return '';
115
+ }
116
+ let fixedUrl = assetUrl;
117
+ if (assetUrl.indexOf('_webplayer') === -1) {
118
+ fixedUrl = assetUrl.concat('_webplayer');
119
+ }
120
+ fixedUrl = fixedUrl.replace('/content/', '/content43/');
121
+ if (!fixedUrl.endsWith('.glb')) {
122
+ fixedUrl = fixedUrl.concat('.glb');
123
+ }
124
+ return fixedUrl;
125
+ }
126
+ // Return the mimetype of the given filename.
127
+ static MimeTypeFromFilename(fileName) {
128
+ const regEx = /(?:\.([^.]+))?$/; // regex to find extension
129
+ const extension = regEx.exec(fileName)[1];
130
+ switch (extension) {
131
+ case 'jpg':
132
+ case 'jpeg':
133
+ return 'image/jpeg';
134
+ case 'png':
135
+ return 'image/png';
136
+ case 'bmp':
137
+ return 'image/bmp';
138
+ }
139
+ }
140
+ /**
141
+ * Downloads the given file to the users default download location.
142
+ * @param fileName With or without extension
143
+ * @param content File content as a string
144
+ * @param [mimeType = 'text/plain']
145
+ */
146
+ static DownloadFile(fileName, content, mimeType = 'text/plain') {
147
+ const element = document.createElement('a');
148
+ element.setAttribute('href', 'data:' + mimeType + ';charset=utf-8,' + encodeURIComponent(content));
149
+ element.setAttribute('download', fileName);
150
+ element.style.display = 'none';
151
+ document.body.appendChild(element);
152
+ element.click();
153
+ document.body.removeChild(element);
154
+ }
155
+ // Returns the contents of given file as a text string.
156
+ static ReadAsText(file) {
157
+ return new Promise((resolve) => {
158
+ const reader = new FileReader();
159
+ reader.readAsText(file);
160
+ reader.onloadend = (event) => {
161
+ if (event.target.readyState === 2) {
162
+ resolve(event.target.result);
163
+ }
164
+ };
165
+ });
166
+ }
167
+ static GetExtensionFromDataUri(dataUri) {
168
+ return dataUri.replace(/(data:image\/)(.*?)(;base64.*)/gi, '$2');
169
+ }
170
+ static CreateDownloadFileNameFromBase64(dataUri) {
171
+ const ext = this.GetExtensionFromDataUri(dataUri);
172
+ return 'preview.' + ext;
173
+ }
174
+ static DownloadFromDataUri(dataUri, fileName) {
175
+ const link = document.createElement('a');
176
+ link.download = fileName;
177
+ link.href = dataUri;
178
+ document.body.appendChild(link);
179
+ link.click();
180
+ document.body.removeChild(link);
181
+ }
182
+ // todo remove once Connector deals with mimetypes and this method isn't used anymore
183
+ static DocumentBodyToDataUri(documentBody, mimeType) {
184
+ if (!!documentBody) {
185
+ return 'data:' + mimeType + ';base64,' + documentBody;
186
+ }
187
+ else {
188
+ return '';
189
+ }
190
+ }
191
+ static FixUnityUrl(url) {
192
+ if (url.indexOf('_webplayer') === -1) {
193
+ url = url.concat('_webplayer.ione3d');
194
+ }
195
+ else {
196
+ url = url.replace('_webplayer', '_webplayer.ione3d');
197
+ }
198
+ if (!url.endsWith('.gz')) {
199
+ url = url.concat('.gz');
200
+ }
201
+ return url.replace('.unity3d', '');
202
+ }
203
+ }
204
+ FileUtils._cachedTextureUploads = new Map();
205
+
206
+ class ThreedUtils {
207
+ constructor() {
208
+ this._objectCache = new Map();
209
+ }
210
+ clearCache() {
211
+ const objs = Array.from(this._objectCache.values());
212
+ objs.forEach(o => ObjectUtils.DisposeObject(o));
213
+ this._objectCache.clear();
214
+ }
215
+ download3DSource(fileName) {
216
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
217
+ fileName = fileName.replace('.unity3d', '');
218
+ let lookupFileName = fileName + (fileName.indexOf('.glb') < 0 ? '.glb' : '');
219
+ if (this._objectCache.has(lookupFileName)) {
220
+ resolve(this._objectCache.get(lookupFileName));
221
+ return;
222
+ }
223
+ if (yield FileUtils.FileExists(lookupFileName, 'https://cdn1.colijn-it.nl/content43/')) {
224
+ this.loadGlbSource(lookupFileName).then((obj) => {
225
+ this._objectCache.set(lookupFileName, obj);
226
+ resolve(obj);
227
+ });
228
+ }
229
+ else {
230
+ reject(`GLB source not found! (${lookupFileName})`);
231
+ }
232
+ }));
233
+ }
234
+ readFileAsText(file) {
235
+ const fileReader = new FileReader();
236
+ return new Promise((resolve, reject) => {
237
+ fileReader.onload = (e) => resolve(e.target.result);
238
+ fileReader.onerror = error => reject(error);
239
+ fileReader.readAsText(file);
240
+ });
241
+ }
242
+ loadJsonModel(filePath) {
243
+ return __awaiter(this, void 0, void 0, function* () {
244
+ if (this._objectCache.has(filePath)) {
245
+ return Promise.resolve(this._objectCache.get(filePath));
246
+ }
247
+ const json = yield this._readJsonFile(filePath);
248
+ const loader = new ObjectLoader();
249
+ loader.crossOrigin = 'Anonymous';
250
+ return new Promise((resolve, reject) => {
251
+ try {
252
+ const obj = loader.parse(json);
253
+ this._objectCache.set(filePath, obj);
254
+ resolve(obj);
255
+ }
256
+ catch (e) {
257
+ reject(null);
258
+ }
259
+ });
260
+ });
261
+ }
262
+ loadJsonObjectModel(filePath) {
263
+ return __awaiter(this, void 0, void 0, function* () {
264
+ if (this._objectCache.has(filePath)) {
265
+ return Promise.resolve(this._objectCache.get(filePath));
266
+ }
267
+ const loader = new ObjectLoader();
268
+ loader.setCrossOrigin('Anonymous');
269
+ loader.setResourcePath('');
270
+ return new Promise((resolve, reject) => {
271
+ loader.load(filePath, (object) => {
272
+ const obj = (object.type === 'Scene' && object.children[0].type === 'Object3D') ? object.children[0] : object;
273
+ this._objectCache.set(filePath, obj);
274
+ resolve(obj);
275
+ }, xhr => null, error => reject(error));
276
+ });
277
+ });
278
+ }
279
+ loadGlbModel(file, cleanUp = true) {
280
+ return __awaiter(this, void 0, void 0, function* () {
281
+ if (this._objectCache.has(file)) {
282
+ return Promise.resolve(this._objectCache.get(file));
283
+ }
284
+ if (!window.hasOwnProperty('loadGLTF')) {
285
+ console.error('loadGLTF not defined in window global');
286
+ return null;
287
+ }
288
+ // const loader = new GLTFLoader();
289
+ const obj = yield window.loadGLTF(file);
290
+ if (obj) {
291
+ this._cleanedUpObjects(obj, cleanUp);
292
+ this._objectCache.set(file, obj);
293
+ return obj;
294
+ }
295
+ else {
296
+ return null;
297
+ }
298
+ });
299
+ }
300
+ loadGlbSource(file) {
301
+ return __awaiter(this, void 0, void 0, function* () {
302
+ const obj = yield this.loadGlbModel(file, false);
303
+ if (obj) {
304
+ obj.children = obj.children.filter(c => !(c instanceof Camera));
305
+ obj.children.sort((a, b) => a['name'] < b['name'] ? 1 : -1);
306
+ obj.children.forEach((c) => {
307
+ c.traverse((t) => {
308
+ t.visible = !t.name.toLowerCase().startsWith('c_');
309
+ });
310
+ c.visible = false;
311
+ });
312
+ if (obj.children.length === 1 && obj.children[0] instanceof Group) { // flatten children
313
+ const children = obj.children[0].children.slice();
314
+ obj.children.length = 0;
315
+ obj.children = children;
316
+ }
317
+ }
318
+ return obj;
319
+ });
320
+ }
321
+ textureFromUrl(url) {
322
+ return __awaiter(this, void 0, void 0, function* () {
323
+ // url = this._includeBaseUrl(url);
324
+ return new Promise((resolve, reject) => {
325
+ const textureLoader = new TextureLoader();
326
+ // textureLoader.setBaseU(this._settingsService.settings.assetPath);
327
+ textureLoader.load(url, (texture) => {
328
+ texture.wrapT = RepeatWrapping;
329
+ texture.wrapS = RepeatWrapping;
330
+ texture.repeat.set(1, 1);
331
+ texture.needsUpdate = true;
332
+ return resolve(texture);
333
+ }, null, reject);
334
+ });
335
+ });
336
+ }
337
+ _cleanedUpObjects(object, cleanUp = true) {
338
+ let obj = new Object3D();
339
+ object.children.forEach((c) => {
340
+ if (!(c instanceof Camera)) {
341
+ if (cleanUp && c instanceof Group || (c.children.length === 1 && c.children[0] instanceof Group)) {
342
+ this._addGroupChildrenToObject(c, obj);
343
+ }
344
+ else if ((cleanUp && !(c instanceof Mesh)) || (!(c instanceof Mesh) && !c.name && c.children.length > 0)) {
345
+ c.children.forEach((child) => {
346
+ child.translateY(c.position.y);
347
+ });
348
+ c.translateY(-c.position.y);
349
+ if (obj.children.length > 0) {
350
+ obj.add(c.clone());
351
+ }
352
+ else {
353
+ obj = c.clone();
354
+ }
355
+ }
356
+ else {
357
+ // if (c.position.y > 0 || c.position.y < 0) {
358
+ // c.children.forEach((child) => {
359
+ // child.translateY(c.position.y);
360
+ // });
361
+ // c.translateY(-c.position.y);
362
+ // }
363
+ obj.add(c.clone());
364
+ }
365
+ }
366
+ });
367
+ const boundingBox = new Box3().setFromObject(obj);
368
+ const bbCenterPivot = new Vector3();
369
+ boundingBox.getCenter(bbCenterPivot);
370
+ const delta = new Vector3().add(bbCenterPivot).negate();
371
+ obj.children.forEach((cc) => {
372
+ cc.position.add(delta);
373
+ });
374
+ return obj;
375
+ }
376
+ _addGroupChildrenToObject(group, obj, cleanUp = true) {
377
+ group.children.forEach((gc) => {
378
+ if (cleanUp && gc instanceof Group) {
379
+ this._addGroupChildrenToObject(gc, obj);
380
+ }
381
+ else {
382
+ // gc.translateX(-group.position.x);
383
+ gc.translateY(group.position.y);
384
+ // gc.translateZ(-group.position.z);
385
+ obj.add(gc.clone());
386
+ }
387
+ });
388
+ }
389
+ _iterateChildren(children, callback) {
390
+ for (let i = 0; i < children.length; i++) {
391
+ const child = children[i];
392
+ if (child instanceof Mesh) {
393
+ callback(child);
394
+ }
395
+ else {
396
+ this._iterateChildren(child.children, callback);
397
+ }
398
+ }
399
+ }
400
+ _readJsonFile(filePath) {
401
+ return __awaiter(this, void 0, void 0, function* () {
402
+ try {
403
+ const response = yield fetch(filePath);
404
+ if (!response.ok) {
405
+ return '';
406
+ }
407
+ else {
408
+ let empty = false;
409
+ yield response.clone().text().then((value) => {
410
+ if (value === '') {
411
+ empty = true;
412
+ }
413
+ });
414
+ return empty ? {} : response.json();
415
+ }
416
+ }
417
+ catch (e) {
418
+ return '';
419
+ }
420
+ });
421
+ }
422
+ }
423
+
424
+ class SceneUtils {
425
+ static TrySelectorConnection(scene, parent, part1, part2, createAddableFn) {
426
+ let addable;
427
+ if (createAddableFn) {
428
+ addable = part2;
429
+ part2 = createAddableFn(addable);
430
+ }
431
+ for (let i = 0; i < part1.children.length; i++) {
432
+ for (let ii = 0; ii < part2.children.length; ii++) {
433
+ const con1 = part1.children[i];
434
+ const con2 = part2.children[ii];
435
+ // if these connectors can connect connect them
436
+ if (!con1['connected'] && !con2['connected'] && this.CanSelectorConnect(con1, con2)) {
437
+ // if addable, continue this loop with a new addable
438
+ if (addable) {
439
+ const newPart2 = createAddableFn(addable, part2, part1);
440
+ // reference of part2 changed, so refresh con2
441
+ this.SelectorConnect(scene, parent, con1, newPart2.children[ii]);
442
+ }
443
+ else {
444
+ return this.SelectorConnect(scene, parent, con1, con2);
445
+ }
446
+ }
447
+ }
448
+ }
449
+ return false;
450
+ }
451
+ static Convert3DPointToScreenPoint(point, camera, width, height) {
452
+ if (!point) {
453
+ return new Vector2();
454
+ }
455
+ const vector = point.clone().project(camera);
456
+ vector.x = (vector.x + 1) / 2 * width;
457
+ vector.y = -(vector.y - 1) / 2 * height;
458
+ return new Vector2(vector.x, vector.y);
459
+ }
460
+ static CanSelectorConnect(con1, con2) {
461
+ const con1Name = con1 instanceof Object3D ? con1.name : con1.connector;
462
+ const con2Name = con2 instanceof Object3D ? con2.name : con2.connector;
463
+ const sameParent = con1 instanceof Object3D && con2 instanceof Object3D ? con1.parent === con2.parent : false;
464
+ const parts1 = con1Name.toUpperCase().split('_'), parts2 = con2Name.toUpperCase().split('_');
465
+ if (parts1.length >= 3 && parts2.length >= 3 && !sameParent) {
466
+ const connectable = parts1[0] === 'C' && parts2[0] === 'C' &&
467
+ parts1[1] === parts2[1] && parts1[2] !== parts2[2];
468
+ return connectable;
469
+ }
470
+ return false;
471
+ }
472
+ static SelectorConnect(scene, parent, con1, con2) {
473
+ if (!scene || !parent) {
474
+ return false;
475
+ }
476
+ con1['connectedTo'] = con2.parent.name;
477
+ con2['connectedTo'] = con1.parent.name;
478
+ const motherRotation = new Euler(0, 0, 0);
479
+ const motherPosition = new Vector3(0, 0, 0);
480
+ scene.updateMatrixWorld(true);
481
+ motherRotation.copy(parent.rotation);
482
+ parent.getWorldPosition(motherPosition);
483
+ parent.rotation.set(0, 0, 0);
484
+ parent.position.set(0, 0, 0);
485
+ const con1Quat = new Quaternion();
486
+ con1.getWorldQuaternion(con1Quat);
487
+ const con2Quat = new Quaternion();
488
+ con2.getWorldQuaternion(con2Quat);
489
+ const con1QuatParent = new Quaternion();
490
+ con1.parent.getWorldQuaternion(con1QuatParent);
491
+ const con2QuatParent = new Quaternion();
492
+ con2.parent.getWorldQuaternion(con2QuatParent);
493
+ const rotation = new Quaternion().multiplyQuaternions(con1Quat.invert(), con2Quat).multiply(new Quaternion().multiplyQuaternions(con1QuatParent, con1QuatParent));
494
+ con2.parent.quaternion.copy(rotation);
495
+ // Update because the matrix has been tempered with
496
+ scene.updateMatrixWorld(true);
497
+ // Move the connectors towards eachother
498
+ const con1Pos = new Vector3();
499
+ con1.getWorldPosition(con1Pos);
500
+ const con2Pos = new Vector3();
501
+ con2.getWorldPosition(con2Pos);
502
+ const move = con1Pos.sub(con2Pos);
503
+ con2.parent.position.x += move.x;
504
+ con2.parent.position.y += move.y;
505
+ con2.parent.position.z += move.z;
506
+ // reset parent's objects rotation and position
507
+ parent.rotation.copy(motherRotation);
508
+ parent.position.copy(motherPosition);
509
+ scene.updateMatrixWorld(true);
510
+ // Set the connected flag
511
+ con1['connected'] = true;
512
+ con2['connected'] = true;
513
+ return true;
514
+ }
515
+ }
516
+
517
+ class Material {
518
+ constructor() {
519
+ this.specular = new Color(0.3, 0.3, 0.3);
520
+ this.shininess = 0;
521
+ this.repeatX = 4;
522
+ this.repeatY = 4;
523
+ this.loaded = false;
524
+ }
525
+ }
526
+
527
+ // @dynamic
528
+ class ImageUtils {
529
+ static CreateTextureFromBase64(id, base64, material) {
530
+ return new Promise((resolve) => {
531
+ if (ImageUtils.textures.has(id)) {
532
+ resolve(ImageUtils.textures.get(id));
533
+ }
534
+ else {
535
+ if (!base64) {
536
+ resolve(new Texture());
537
+ }
538
+ else {
539
+ const loader = new TextureLoader();
540
+ loader.load(base64, (texture) => {
541
+ texture.anisotropy = 16;
542
+ texture.wrapS = RepeatWrapping;
543
+ texture.wrapT = RepeatWrapping;
544
+ texture.repeat = new Vector2(material ? material.repeatX : 1, material ? material.repeatY : 1);
545
+ texture.needsUpdate = true;
546
+ ImageUtils.textures.set(id, texture);
547
+ resolve(texture);
548
+ });
549
+ }
550
+ }
551
+ });
552
+ }
553
+ static getDocBodyWithMimeTypeDefinition(fileName, documentBody) {
554
+ if (documentBody === null) {
555
+ return documentBody;
556
+ }
557
+ const fileExtension = fileName.substr(fileName.lastIndexOf('.') + 1);
558
+ switch (fileExtension.toLowerCase()) {
559
+ case "jpg":
560
+ case "jpeg":
561
+ return "data:image/jpg;base64," + documentBody;
562
+ case "png":
563
+ return "data:image/png;base64," + documentBody;
564
+ case "gif":
565
+ return "data:image/gif;base64," + documentBody;
566
+ case "bmp":
567
+ return "data:image/bmp;base64," + documentBody;
568
+ default:
569
+ return "data:image/png;base64," + documentBody;
570
+ }
571
+ }
572
+ static getFixedImageFilepathUrl(imageFilepathUrl) {
573
+ return imageFilepathUrl.replace("/content/", "/content43/");
574
+ }
575
+ }
576
+ ImageUtils.textures = new Map();
577
+
578
+ class FurnitureMaterial extends Material {
579
+ }
580
+ class AssetUtils {
581
+ static CreateMaterialFromAsset(asset) {
582
+ return __awaiter(this, void 0, void 0, function* () {
583
+ const material = new Material();
584
+ if (!asset) {
585
+ return material;
586
+ }
587
+ if (asset.settings) {
588
+ AssetUtils.setSettingsOfMaterial(material, asset.settings);
589
+ }
590
+ if (asset.texture) {
591
+ material.texture = yield ImageUtils.CreateTextureFromBase64(asset.id + '_texture', asset.texture, material);
592
+ material.texture.encoding = sRGBEncoding;
593
+ material.textureFilename = asset.textureFilename;
594
+ }
595
+ if (asset.normal) {
596
+ material.normal = yield ImageUtils.CreateTextureFromBase64(asset.id + '_normal', asset.normal, material);
597
+ material.normalFilename = asset.normalFilename;
598
+ // material.normal.anisotropy = 1;
599
+ // material.normal.repeat.set(1, 1);
600
+ // material.normal.flipY = false;
601
+ }
602
+ if (asset.ao) {
603
+ material.ao = yield ImageUtils.CreateTextureFromBase64(asset.id + '_ao', asset.ao, material);
604
+ material.aoFilename = asset.aoFilename;
605
+ }
606
+ if (asset.metalness) {
607
+ material.metalness = yield ImageUtils.CreateTextureFromBase64(asset.id + '_metalness', asset.metalness, material);
608
+ material.metalnessFilename = asset.metalnessFilename;
609
+ }
610
+ if (asset.roughness) {
611
+ material.roughness = yield ImageUtils.CreateTextureFromBase64(asset.id + '_roughness', asset.roughness, material);
612
+ material.roughnessFilename = asset.roughnessFilename;
613
+ }
614
+ return material;
615
+ });
616
+ }
617
+ static setSettingsOfMaterial(material, settings) {
618
+ const shininess = parseFloat(settings['power']);
619
+ if (!isNaN(shininess)) {
620
+ material.shininess = shininess;
621
+ // material.roughness = 1 - (shininess / 100);
622
+ }
623
+ const level = parseFloat(settings['level']);
624
+ if (!isNaN(level)) {
625
+ material.specular = new Color(level, level, level);
626
+ }
627
+ const repeatObjectUsed = settings.hasOwnProperty('repeat');
628
+ const repeatx = repeatObjectUsed ? parseFloat(settings['repeat']['repeatx']) : parseFloat(settings['repeatx']);
629
+ if (!isNaN(repeatx)) {
630
+ material.repeatX = Math.max(1, repeatx);
631
+ }
632
+ const repeaty = repeatObjectUsed ? parseFloat(settings['repeat']['repeaty']) : parseFloat(settings['repeaty']);
633
+ if (!isNaN(repeaty)) {
634
+ material.repeatY = Math.max(1, repeaty);
635
+ }
636
+ const metalness = parseFloat(settings['metalness']);
637
+ if (!isNaN(metalness)) {
638
+ material.metalnessValue = Math.min(1, metalness);
639
+ }
640
+ const roughness = parseFloat(settings['roughness']);
641
+ if (!isNaN(roughness)) {
642
+ material.roughnessValue = Math.min(1, roughness);
643
+ }
644
+ }
645
+ }
646
+
647
+ class Variation {
648
+ }
649
+
650
+ class VariationSettings {
651
+ constructor() {
652
+ this.settings = {};
653
+ }
654
+ }
655
+
656
+ // @dynamic
657
+ class VariationUtils {
658
+ static LoadVariation(assetPath, fileName) {
659
+ return __awaiter(this, void 0, void 0, function* () {
660
+ if (!fileName) {
661
+ return null;
662
+ }
663
+ if (fileName.indexOf('ione3d') < 0) {
664
+ fileName = fileName.concat('.ione3d');
665
+ }
666
+ const id = fileName.substr(0, fileName.lastIndexOf('.ione3d'));
667
+ try {
668
+ if (!assetPath.endsWith('/')) {
669
+ assetPath += '/';
670
+ }
671
+ if (!window.hasOwnProperty('downloadVariation')) {
672
+ console.error('downloadVariation not defined in window global');
673
+ return null;
674
+ }
675
+ const file = yield window.downloadVariation(`${assetPath.replace('https://cdn1.colijn-it.nl/', '')}variation/${fileName}`);
676
+ return yield VariationUtils.GetVariationSettingsFromFile(id, file);
677
+ }
678
+ catch (err) {
679
+ const mute = err;
680
+ return null;
681
+ }
682
+ });
683
+ }
684
+ // public static GetMaterialFromName(variationFolder: string, material: any): Promise<MeshStandardMaterial> {
685
+ // return new Promise((resolve: Function) => {
686
+ // if (!material) {
687
+ // resolve(null);
688
+ // }
689
+ // if (this.MaterialCache.has(material.name)) {
690
+ // resolve(this.MaterialCache.get(material.name).clone());
691
+ // } else {
692
+ // VariationUtils.LoadVariation(variationFolder, material.name, false).then((settings: VariationSettings) => {
693
+ // if (settings) {
694
+ // AssetUtils.CreateMaterialFromAsset(settings).then((materialObj: Material) => {
695
+ // const materialParams: MeshStandardMaterialParameters = {};
696
+ // materialParams.name = material.name;
697
+ // materialParams.map = materialObj.texture;
698
+ // materialParams.normalMap = materialObj.normal;
699
+ // materialParams.aoMap = materialObj.ao;
700
+ // materialParams.roughnessMap = materialObj.roughness;
701
+ // materialParams.metalnessMap = materialObj.metalness;
702
+ // materialParams.roughness = 1;
703
+ // materialParams.metalness = 1;
704
+ // const pbrMat: MeshStandardMaterial = new MeshStandardMaterial(materialParams);
705
+ // this.MaterialCache.set(material.name, pbrMat);
706
+ // resolve(pbrMat.clone());
707
+ // });
708
+ // } else {
709
+ // resolve(material);
710
+ // }
711
+ // });
712
+ // }
713
+ // });
714
+ // }
715
+ static GetVariationSettingsFromFile(id, compressedFile) {
716
+ return __awaiter(this, void 0, void 0, function* () {
717
+ if (!compressedFile) {
718
+ return null;
719
+ }
720
+ const zipContent = yield VariationUtils.GetZipContent(compressedFile);
721
+ const variationSettings = new VariationSettings();
722
+ let index;
723
+ variationSettings.id = id;
724
+ if (zipContent.files['index.json']) {
725
+ const indexFile = yield zipContent.files['index.json'].async('string');
726
+ index = JSON.parse(indexFile);
727
+ }
728
+ if (index) {
729
+ yield VariationUtils.CreateSettingsBasedOnIndex(index, variationSettings, zipContent);
730
+ }
731
+ else {
732
+ yield VariationUtils.CreateSettingsBasedOnFileName(variationSettings, zipContent);
733
+ }
734
+ return variationSettings;
735
+ });
736
+ }
737
+ static CreateSettingsBasedOnIndex(index, variationSettings, zipContent) {
738
+ return __awaiter(this, void 0, void 0, function* () {
739
+ if (index.normalFile) {
740
+ variationSettings.normal = yield VariationUtils.LoadFileContentFromZip(zipContent.files[index.normalFile], index.normalFile);
741
+ variationSettings.normalFilename = index.normalFile;
742
+ }
743
+ if (index.aoFile) {
744
+ variationSettings.ao = yield VariationUtils.LoadFileContentFromZip(zipContent.files[index.aoFile], index.aoFile);
745
+ variationSettings.aoFilename = index.aoFile;
746
+ }
747
+ if (index.metalnessFile) {
748
+ variationSettings.metalness = yield VariationUtils.LoadFileContentFromZip(zipContent.files[index.metalnessFile], index.metalnessFile);
749
+ variationSettings.metalnessFilename = index.metalnessFile;
750
+ }
751
+ if (index.roughnessFile) {
752
+ variationSettings.roughness = yield VariationUtils.LoadFileContentFromZip(zipContent.files[index.roughnessFile], index.roughnessFile);
753
+ variationSettings.roughnessFilename = index.roughnessFile;
754
+ }
755
+ if (index.diffuseFile) {
756
+ variationSettings.texture = yield VariationUtils.LoadFileContentFromZip(zipContent.files[index.diffuseFile], index.diffuseFile);
757
+ variationSettings.textureFilename = index.diffuseFile;
758
+ }
759
+ variationSettings.settings =
760
+ (yield VariationUtils.LoadFileContentFromZip(zipContent.files['repeat.json'], 'repeat.json', false)) || {};
761
+ Object.assign(variationSettings.settings, index.repeat);
762
+ variationSettings.settings.metalness = index.metalness;
763
+ variationSettings.settings.roughness = index.roughness;
764
+ });
765
+ }
766
+ static CreateSettingsBasedOnFileName(variationSettings, zipContent) {
767
+ return __awaiter(this, void 0, void 0, function* () {
768
+ const allLoaded = [];
769
+ for (const fileName in zipContent.files) {
770
+ if (zipContent.files[fileName]) {
771
+ const file = yield zipContent.files[fileName];
772
+ if (file.name.toLowerCase().indexOf('normal') > -1 && this.FileIsImage(file.name)) {
773
+ allLoaded.push(zipContent.files[fileName].async('base64').then((normalFile) => {
774
+ variationSettings.normal = `data:image/${this.GetBase64FileType(file.name)};base64,${normalFile}`;
775
+ variationSettings.normalFilename = fileName;
776
+ }));
777
+ }
778
+ else if (file.name.toLowerCase().indexOf('ao') > -1 && this.FileIsImage(file.name)) {
779
+ allLoaded.push(zipContent.files[fileName].async('base64').then((aoFile) => {
780
+ variationSettings.ao = `data:image/${this.GetBase64FileType(file.name)};base64,${aoFile}`;
781
+ variationSettings.aoFilename = fileName;
782
+ }));
783
+ }
784
+ else if (file.name.toLowerCase().indexOf('metalness') > -1 && this.FileIsImage(file.name)) {
785
+ allLoaded.push(zipContent.files[fileName].async('base64').then((metalnessFile) => {
786
+ variationSettings.metalness = `data:image/${this.GetBase64FileType(file.name)};base64,${metalnessFile}`;
787
+ variationSettings.metalnessFilename = fileName;
788
+ }));
789
+ }
790
+ else if (file.name.toLowerCase().indexOf('roughness') > -1 && this.FileIsImage(file.name)) {
791
+ allLoaded.push(zipContent.files[fileName].async('base64').then((roughnessFile) => {
792
+ variationSettings.roughness = `data:image/${this.GetBase64FileType(file.name)};base64,${roughnessFile}`;
793
+ variationSettings.roughnessFilename = fileName;
794
+ }));
795
+ }
796
+ else if (file.name.toLowerCase().indexOf('diffuse') > -1 && this.FileIsImage(file.name)) {
797
+ allLoaded.push(zipContent.files[fileName].async('base64').then((diffuseFile) => {
798
+ variationSettings.texture = `data:image/${this.GetBase64FileType(file.name)};base64,${diffuseFile}`;
799
+ variationSettings.textureFilename = fileName;
800
+ }));
801
+ }
802
+ else if (file.name.indexOf('.jp') > -1) {
803
+ allLoaded.push(zipContent.files[fileName].async('base64').then((textureFile) => {
804
+ variationSettings.texture = 'data:image/jpeg;base64,' + textureFile;
805
+ variationSettings.textureFilename = fileName;
806
+ }));
807
+ }
808
+ else if (file.name.indexOf('.json') > -1) {
809
+ allLoaded.push(zipContent.files[fileName].async('string').then((settingsFile) => {
810
+ const settingsFileObj = JSON.parse(settingsFile);
811
+ for (const key in settingsFileObj) {
812
+ if (settingsFileObj[key]) {
813
+ variationSettings.settings[key] = settingsFileObj[key];
814
+ }
815
+ }
816
+ }));
817
+ }
818
+ }
819
+ }
820
+ yield Promise.all(allLoaded);
821
+ });
822
+ }
823
+ static LoadFileContentFromZip(zip, fileName, base64 = true) {
824
+ return new Promise((resolve) => {
825
+ if (zip && fileName) {
826
+ zip.async(base64 ? 'base64' : 'string').then((fileContent) => {
827
+ if (base64) {
828
+ resolve(`data:image/${this.GetBase64FileType(fileName)};base64,${fileContent}`);
829
+ }
830
+ else {
831
+ resolve(fileContent);
832
+ }
833
+ });
834
+ }
835
+ else {
836
+ resolve(undefined);
837
+ }
838
+ });
839
+ }
840
+ static FileIsImage(fileName) {
841
+ const ext = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length).toLowerCase();
842
+ switch (ext) {
843
+ case 'jpg':
844
+ case 'jpeg':
845
+ case 'png':
846
+ case 'bmp':
847
+ return true;
848
+ default:
849
+ return false;
850
+ }
851
+ }
852
+ static GetBase64FileType(fileName) {
853
+ const ext = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length).toLowerCase();
854
+ switch (ext) {
855
+ case 'jpg':
856
+ case 'jpeg':
857
+ return 'jpeg';
858
+ case 'png':
859
+ return 'png';
860
+ case 'bmp':
861
+ return 'bmp';
862
+ default:
863
+ return 'jpeg';
864
+ }
865
+ }
866
+ // Get the content
867
+ static GetZipContent(file) {
868
+ return __awaiter(this, void 0, void 0, function* () {
869
+ const jszip = new JSZip();
870
+ const content = yield jszip.loadAsync(file);
871
+ return content;
872
+ });
873
+ }
874
+ }
875
+ VariationUtils.MaterialCache = new Map();
876
+
877
+ class VariationHelper {
878
+ constructor() {
879
+ this._lastKnownVariations = new Map();
880
+ }
881
+ clearCache() {
882
+ const valueMap = Array.from(this._lastKnownVariations.values());
883
+ for (let i = 0; i < valueMap.length; i++) {
884
+ const values = Array.from(valueMap[i].values());
885
+ values.forEach((variations) => {
886
+ variations.forEach((variation) => {
887
+ variation.material.texture.dispose();
888
+ variation.material.normal.dispose();
889
+ variation.material.metalness.dispose();
890
+ variation.material.roughness.dispose();
891
+ variation.material.ao.dispose();
892
+ });
893
+ });
894
+ }
895
+ }
896
+ loadPart(obj, parts, usePbr = false) {
897
+ return __awaiter(this, void 0, void 0, function* () {
898
+ try {
899
+ const len = parts.length;
900
+ for (let i = 0; i < len; i++) {
901
+ if (parts[i].decoNode && parts[i].decoNode.gameObjectName && parts[i].decoNode.type === DecoNodeType.Part) {
902
+ const partSettings = yield VariationUtils.LoadVariation(this.assetPath, parts[i].decoNode.gameObjectName || parts[i].decoId);
903
+ if (partSettings) {
904
+ const partVariation = new Variation();
905
+ partVariation.decoId = parseFloat(parts[i].decoNode.id);
906
+ partVariation.brandId = parts[i].decoNode.brandId;
907
+ partVariation.gameObjectName = parts[i].decoNode.gameObjectName;
908
+ partVariation.material = yield AssetUtils.CreateMaterialFromAsset(partSettings);
909
+ // parts[i].variation = partVariation;
910
+ this._applyMaterialPart(obj, partVariation, parts[i].node, usePbr);
911
+ }
912
+ }
913
+ }
914
+ }
915
+ catch (e) {
916
+ console.error(e);
917
+ }
918
+ });
919
+ }
920
+ loadVariation(instanceId, obj, parts, usePbr = false) {
921
+ return __awaiter(this, void 0, void 0, function* () {
922
+ try {
923
+ const len = parts.length;
924
+ for (let i = 0; i < len; i++) {
925
+ const variations = parts[i].variations;
926
+ if (!variations || variations.length === 0) {
927
+ if (this._getLastKnownVariations(instanceId, parts[i].nodeId)) {
928
+ parts[i].variations = this._getLastKnownVariations(instanceId, parts[i].nodeId);
929
+ this._applyVariations(obj, parts[i], usePbr);
930
+ continue;
931
+ }
932
+ else {
933
+ continue;
934
+ }
935
+ }
936
+ const lastKnownVariations = [];
937
+ for (let j = 0; j < variations.length; j++) {
938
+ const variationSettings = yield VariationUtils.LoadVariation(this.assetPath, variations[j].gameObjectName || parts[i].decoId);
939
+ const newVariation = new Variation();
940
+ newVariation.decoId = parseFloat(variations[j].id);
941
+ newVariation.brandId = variations[j].brandId;
942
+ newVariation.gameObjectName = variations[j].gameObjectName;
943
+ newVariation.supplierArticleNr = variations[j].supplierArticleNr;
944
+ newVariation.materialId = variations[j].materialId;
945
+ newVariation.material = yield AssetUtils.CreateMaterialFromAsset(variationSettings);
946
+ lastKnownVariations.push(newVariation);
947
+ }
948
+ this._setLastKnownVariations(instanceId, parts[i].nodeId, lastKnownVariations);
949
+ parts[i].variations = lastKnownVariations;
950
+ this._applyVariations(obj, parts[i], usePbr);
951
+ }
952
+ }
953
+ catch (e) {
954
+ console.error(e);
955
+ }
956
+ });
957
+ }
958
+ _getChildrenFilterByProp(obj, userDataObjectProp, prop, value) {
959
+ return obj.children.filter((child) => {
960
+ return child.userData &&
961
+ child.userData.hasOwnProperty(userDataObjectProp) &&
962
+ child.userData[userDataObjectProp].hasOwnProperty(prop) &&
963
+ child.userData[userDataObjectProp][prop] === value;
964
+ });
965
+ }
966
+ _applyMaterialPart(obj, partMaterial, nodeId, usePbr = false) {
967
+ const children = this._getChildrenFilterByProp(obj, 'selection', 'node', nodeId);
968
+ const len = children.length;
969
+ for (let i = 0; i < len; i++) {
970
+ const child = children[i];
971
+ if (child !== null && child !== undefined) {
972
+ child.traverse((mesh) => {
973
+ if (mesh instanceof Mesh && partMaterial) {
974
+ if (Array.isArray(mesh.material)) { // multimaterial support
975
+ for (let j = 0, jlen = mesh.material.length; j < jlen; j++) {
976
+ if (mesh.material[j].name.toLowerCase().indexOf('fixed_frame') !== -1) {
977
+ mesh.material[j] = this._setMeshMaterialFromVariation(mesh.material[j].name, partMaterial, usePbr);
978
+ }
979
+ }
980
+ }
981
+ else {
982
+ if (mesh.material.name.toLowerCase().indexOf('fixed_frame') !== -1) {
983
+ mesh.material = this._setMeshMaterialFromVariation(mesh.material.name, partMaterial, usePbr);
984
+ }
985
+ }
986
+ }
987
+ });
988
+ }
989
+ }
990
+ }
991
+ _applyVariations(obj, part, usePbr = false) {
992
+ const children = this._getChildrenFilterByProp(obj, 'selection', 'node', part.node);
993
+ const len = children.length;
994
+ for (let i = 0; i < len; i++) {
995
+ const child = children[i];
996
+ if (child !== null && child !== undefined) {
997
+ child.traverse((mesh) => {
998
+ if (mesh instanceof Mesh && part.variations && part.variations.length > 0 && mesh.name.toLowerCase().indexOf('c_')) {
999
+ for (let j = 0; j < part.variations.length; j++) {
1000
+ const variation = part.variations[j];
1001
+ if (variation.material) {
1002
+ const materialToSearch = !!variation.materialId ? variation.materialId.toLowerCase() : 'default';
1003
+ if (Array.isArray(mesh.material)) { // multimaterial support
1004
+ for (let m = 0, mlen = mesh.material.length; m < mlen; m++) {
1005
+ if (mesh.material[m].name.toLowerCase().indexOf(materialToSearch) !== -1) {
1006
+ mesh.material[m] = this._setMeshMaterialFromVariation(mesh.material[m].name, variation, usePbr);
1007
+ }
1008
+ }
1009
+ }
1010
+ else {
1011
+ if (mesh.material.name.toLowerCase().indexOf(materialToSearch) !== -1) {
1012
+ mesh.material = this._setMeshMaterialFromVariation(mesh.material.name, variation, usePbr);
1013
+ }
1014
+ }
1015
+ }
1016
+ }
1017
+ }
1018
+ });
1019
+ }
1020
+ }
1021
+ }
1022
+ _setMeshMaterialFromVariation(name, variation, usePbr = false) {
1023
+ if (variation.material.texture) {
1024
+ variation.material.texture.needsUpdate = true;
1025
+ }
1026
+ if (!usePbr) {
1027
+ const material = new MeshPhongMaterial({
1028
+ name: name,
1029
+ shininess: variation.material.shininess,
1030
+ specular: variation.material.specular,
1031
+ map: variation.material.texture,
1032
+ normalMap: variation.material.normal
1033
+ });
1034
+ // material.color.setRGB(0.8, 0.8, 0.8);
1035
+ material.needsUpdate = true;
1036
+ return material;
1037
+ }
1038
+ else {
1039
+ const params = {
1040
+ // side: DoubleSide,
1041
+ name: name,
1042
+ roughness: variation.material.roughnessValue ? variation.material.roughnessValue : 1,
1043
+ metalness: variation.material.metalnessValue ? variation.material.metalnessValue : 0,
1044
+ };
1045
+ if (variation.material.texture) {
1046
+ params.map = variation.material.texture;
1047
+ }
1048
+ if (variation.material.ao) {
1049
+ params.aoMap = variation.material.ao;
1050
+ }
1051
+ if (variation.material.roughness) {
1052
+ params.roughnessMap = variation.material.roughness;
1053
+ }
1054
+ if (variation.material.metalness) {
1055
+ params.metalnessMap = variation.material.metalness;
1056
+ }
1057
+ if (variation.material.normal) {
1058
+ params.normalMap = variation.material.normal;
1059
+ }
1060
+ const material = new MeshStandardMaterial(params);
1061
+ material.color.setRGB(1, 1, 1);
1062
+ material.needsUpdate = true;
1063
+ return material;
1064
+ }
1065
+ }
1066
+ _setLastKnownVariations(instanceId, id, variation) {
1067
+ if (this._lastKnownVariations.has(instanceId)) {
1068
+ const variations = this._lastKnownVariations.get(instanceId);
1069
+ variations.set(id, variation);
1070
+ }
1071
+ else {
1072
+ const variations = new Map();
1073
+ this._lastKnownVariations.set(instanceId, variations.set(id, variation));
1074
+ }
1075
+ }
1076
+ _getLastKnownVariations(instanceId, id) {
1077
+ if (this._lastKnownVariations.has(instanceId)) {
1078
+ const variations = this._lastKnownVariations.get(instanceId);
1079
+ if (variations.has(id)) {
1080
+ return variations.get(id);
1081
+ }
1082
+ }
1083
+ return null;
1084
+ }
1085
+ }
1086
+
1087
+ let ServiceLocator = class ServiceLocator {
1088
+ };
1089
+ ServiceLocator.injector = undefined;
1090
+ ServiceLocator = __decorate([
1091
+ Injectable()
1092
+ ], ServiceLocator);
1093
+
1094
+ let ConfiguratorService = class ConfiguratorService {
1095
+ constructor(_injector) {
1096
+ this._injector = _injector;
1097
+ if (!ServiceLocator.injector) {
1098
+ ServiceLocator.injector = _injector;
1099
+ }
1100
+ }
1101
+ initApi(options) {
1102
+ this._configuratorApi = new Configurator(options);
1103
+ }
1104
+ initNodeInstance(goodId) {
1105
+ return __awaiter(this, void 0, void 0, function* () {
1106
+ return yield this._configuratorApi.initNodeInstance(goodId);
1107
+ });
1108
+ }
1109
+ setInstanceToConfigure(id, showLoader = false) {
1110
+ return __awaiter(this, void 0, void 0, function* () {
1111
+ return yield this._configuratorApi.setInstanceToConfigure(id, showLoader);
1112
+ });
1113
+ }
1114
+ getGoodIdFromSku(sku, showLoader = false) {
1115
+ return __awaiter(this, void 0, void 0, function* () {
1116
+ return yield this._configuratorApi.getGoodIdFromSku(sku, showLoader);
1117
+ });
1118
+ }
1119
+ getArticleQuickSel(goodId, showLoader = false) {
1120
+ return __awaiter(this, void 0, void 0, function* () {
1121
+ return yield this._configuratorApi.getArticleQuickSel(goodId, showLoader);
1122
+ });
1123
+ }
1124
+ getSelections(showLoader = false, publicationCode = 2) {
1125
+ return __awaiter(this, void 0, void 0, function* () {
1126
+ const selections = yield this._configuratorApi.getSelections(showLoader);
1127
+ selections.resultObjects.filter((s) => {
1128
+ (isNill(s.hierarchicalPublicationCode) || ((s.hierarchicalPublicationCode & publicationCode) > 0)) && ((s.nodeType === NodeType.Question && (((s.questionPublicationCode & publicationCode) > 0) || isNill(s.questionPublicationCode))) ||
1129
+ (s.nodeType === NodeType.Answer && (((s.answerPublicationCode & publicationCode) > 0) || isNill(s.answerPublicationCode))));
1130
+ });
1131
+ return selections;
1132
+ });
1133
+ }
1134
+ getDecos(showLoader = false) {
1135
+ return __awaiter(this, void 0, void 0, function* () {
1136
+ return yield this._configuratorApi.getDecos(showLoader);
1137
+ });
1138
+ }
1139
+ getQuestionAndAnswers(showLoader = false, publicationCode = 2) {
1140
+ return __awaiter(this, void 0, void 0, function* () {
1141
+ const questionAndAnswers = yield this._configuratorApi.getQuestionAndAnswers(showLoader);
1142
+ questionAndAnswers.answers.filter((answer) => {
1143
+ (notNill(answer.hierarchicalPublicationCode) && (answer.hierarchicalPublicationCode & publicationCode) === 0) ||
1144
+ (answer.type === NodeType.Question && (answer.questionPublicationCode & publicationCode) === 0 && notNill(answer.questionPublicationCode)) ||
1145
+ (answer.type === NodeType.Answer && (answer.publicationCode & publicationCode) === 0 && notNill(answer.publicationCode));
1146
+ });
1147
+ return questionAndAnswers;
1148
+ });
1149
+ }
1150
+ getSingleImage(nodeId, publication, includeMimetype, thumb, showLoader) {
1151
+ return __awaiter(this, void 0, void 0, function* () {
1152
+ if (!nodeId) {
1153
+ return null;
1154
+ }
1155
+ return yield this._configuratorApi.getSingleImage(nodeId, publication, includeMimetype, thumb, showLoader);
1156
+ });
1157
+ }
1158
+ selectSelection(selection, showLoader = false) {
1159
+ return __awaiter(this, void 0, void 0, function* () {
1160
+ return yield this._configuratorApi.selectSelection(selection, showLoader);
1161
+ });
1162
+ }
1163
+ selectAnswer(answer, showLoader = false) {
1164
+ return __awaiter(this, void 0, void 0, function* () {
1165
+ return yield this._configuratorApi.selectAnswer(answer, showLoader);
1166
+ });
1167
+ }
1168
+ };
1169
+ ConfiguratorService.ctorParameters = () => [
1170
+ { type: Injector }
1171
+ ];
1172
+ ConfiguratorService.ɵprov = ɵɵdefineInjectable({ factory: function ConfiguratorService_Factory() { return new ConfiguratorService(ɵɵinject(INJECTOR)); }, token: ConfiguratorService, providedIn: "root" });
1173
+ ConfiguratorService = __decorate([
1174
+ Injectable({
1175
+ providedIn: 'root'
1176
+ })
1177
+ ], ConfiguratorService);
1178
+
1179
+ let Builder = class Builder {
1180
+ constructor(scene, options, useInAngular) {
1181
+ this.selectionsReceived = new BehaviorSubject([]);
1182
+ this.answersReceived = new BehaviorSubject([]);
1183
+ this.modelLoaded = new BehaviorSubject(null);
1184
+ this._selections = [];
1185
+ this._answers = [];
1186
+ this._decos = [];
1187
+ this._placedAdjustables = [];
1188
+ this._placedAddables = [];
1189
+ this._adjustables = [];
1190
+ this._addables = [];
1191
+ this._articleCache = new Map();
1192
+ this._boFactory = new BusinessObjectFactory();
1193
+ this._threedUtils = new ThreedUtils();
1194
+ this._variationHelper = new VariationHelper();
1195
+ if (!scene) {
1196
+ throw 'No scene object provided!';
1197
+ }
1198
+ if (!options) {
1199
+ throw 'No connection options provided!';
1200
+ }
1201
+ if (useInAngular) {
1202
+ this._configuratorService = ServiceLocator.injector.get(ConfiguratorService);
1203
+ }
1204
+ else {
1205
+ this._configuratorService = new ConfiguratorService(undefined);
1206
+ }
1207
+ this._configuratorService.initApi(options);
1208
+ this._scene = scene;
1209
+ }
1210
+ buildModel(sku, instanceId, goodId) {
1211
+ return __awaiter(this, void 0, void 0, function* () {
1212
+ if (!this._scene) {
1213
+ return;
1214
+ }
1215
+ try {
1216
+ yield this._setInstanceId(sku, instanceId, goodId);
1217
+ yield this._prepareConfiguration(this._sku, this._goodId);
1218
+ if (this._source) {
1219
+ yield this._configuratorService.setInstanceToConfigure(this._instanceId);
1220
+ const promises = [];
1221
+ promises.push(this.getQuestionAndAnswers());
1222
+ promises.push(this._getSelections(this._instanceId));
1223
+ promises.push(this._getDecos());
1224
+ yield Promise.all(promises);
1225
+ if (this._answers.length > 0) {
1226
+ return;
1227
+ }
1228
+ this._linkSelectionsAndDecos();
1229
+ return this._build(this._instanceId);
1230
+ }
1231
+ else {
1232
+ throw 'GLB source not found!';
1233
+ }
1234
+ }
1235
+ catch (e) {
1236
+ throw e;
1237
+ }
1238
+ });
1239
+ }
1240
+ initNodeInstance(goodId) {
1241
+ return this._configuratorService.initNodeInstance(goodId);
1242
+ }
1243
+ destroy() {
1244
+ this._threedUtils.clearCache();
1245
+ this._variationHelper.clearCache();
1246
+ }
1247
+ selectSelection(selection) {
1248
+ return __awaiter(this, void 0, void 0, function* () {
1249
+ yield this._configuratorService.selectSelection(selection, false);
1250
+ this.getQuestionAndAnswers();
1251
+ });
1252
+ }
1253
+ getQuestionAndAnswers(publicationCode) {
1254
+ return __awaiter(this, void 0, void 0, function* () {
1255
+ const questionsAndAnswers = yield this._configuratorService.getQuestionAndAnswers(false, publicationCode);
1256
+ this._answers = questionsAndAnswers.answers;
1257
+ this.answersReceived.next(questionsAndAnswers.answers);
1258
+ });
1259
+ }
1260
+ selectAnswer(answer) {
1261
+ return __awaiter(this, void 0, void 0, function* () {
1262
+ yield this._configuratorService.selectAnswer(answer, false);
1263
+ this.modelLoaded.next(yield this.buildModel());
1264
+ });
1265
+ }
1266
+ _setInstanceId(sku, instanceId, goodId) {
1267
+ return __awaiter(this, void 0, void 0, function* () {
1268
+ if (!instanceId && !this._instanceId) {
1269
+ if (!goodId) {
1270
+ goodId = yield this._getGoodIdFromSku(sku);
1271
+ }
1272
+ this._goodId = goodId;
1273
+ const result = yield this.initNodeInstance(this._goodId);
1274
+ if (result && result.resultObject) {
1275
+ this._instanceId = result.resultObject;
1276
+ }
1277
+ else {
1278
+ throw 'Failed to initialize node instance';
1279
+ }
1280
+ }
1281
+ else if (!this._instanceId) {
1282
+ this._instanceId = instanceId;
1283
+ }
1284
+ if (!this._sku) {
1285
+ this._sku = sku;
1286
+ }
1287
+ });
1288
+ }
1289
+ _prepareConfiguration(sku, goodId) {
1290
+ return __awaiter(this, void 0, void 0, function* () {
1291
+ const article = yield this._getArticle(sku, goodId);
1292
+ if (article && article.assetUrl) {
1293
+ this._source = yield this._threedUtils.download3DSource(article.assetUrl)
1294
+ .catch((error) => {
1295
+ throw error;
1296
+ });
1297
+ if (article.contentDeliveryUrl) {
1298
+ this._variationHelper.assetPath =
1299
+ article.contentDeliveryUrl +
1300
+ (article.contentDeliveryUrl.endsWith('/') ? '' : '/') +
1301
+ (article.distSchema ? article.distSchema : 'UP_DBA');
1302
+ }
1303
+ }
1304
+ });
1305
+ }
1306
+ _build(instanceId) {
1307
+ return __awaiter(this, void 0, void 0, function* () {
1308
+ this._reset();
1309
+ const adjustables = this._getAdjustables();
1310
+ if (adjustables && adjustables.length > 0) {
1311
+ const obj = new Object3D();
1312
+ obj.visible = false; // no need to render visualy
1313
+ this._scene.add(obj);
1314
+ let connected = false;
1315
+ for (let i = 0, len = adjustables.length; i < len; i++) {
1316
+ const adjustable = this._createAdjustable(obj, adjustables[i]);
1317
+ if (adjustable) {
1318
+ for (let ii = 0, lenii = this._placedAdjustables.length; ii < lenii; ii++) {
1319
+ if (SceneUtils.TrySelectorConnection(this._scene, obj, this._placedAdjustables[ii], adjustable)) {
1320
+ this._placedAdjustables[ii].visible = true;
1321
+ adjustable.visible = true;
1322
+ connected = true;
1323
+ break;
1324
+ }
1325
+ connected = false;
1326
+ }
1327
+ }
1328
+ if (!connected && this._placedAdjustables.length > 1) {
1329
+ console.warn('No connection found for: ', adjustable.name);
1330
+ }
1331
+ }
1332
+ this._placeAddables(obj);
1333
+ this._updatePivot(obj);
1334
+ yield this._loadVariations(obj, instanceId);
1335
+ this._scene.remove(obj);
1336
+ return obj;
1337
+ }
1338
+ else {
1339
+ throw 'No adjustables found!';
1340
+ // this._building = false;
1341
+ // if (this.selections.length < 2) {
1342
+ // this._errorService.addError(this.activeInstance, {message: 'NO_SELECTIONS_OR_DECOS', description: 'NO_SELECTIONS_OR_DECOS_INFO'});
1343
+ // this.buildFinished.next({instanceId: this.activeInstance, resultType: ResultType.NoSelections});
1344
+ // } else if (this.decos.size === 0) {
1345
+ // this._errorService.addError(this.activeInstance, {message: 'NO_SELECTIONS_OR_DECOS', description: 'NO_SELECTIONS_OR_DECOS_INFO'});
1346
+ // this.buildFinished.next({instanceId: this.activeInstance, resultType: ResultType.NoDecoNodes});
1347
+ // } else {
1348
+ // this._errorService.addError(this.activeInstance, {message: 'NO_ADJUSTABLES', description: 'NO_ADJUSTABLES_INFO'});
1349
+ // this.buildFinished.next({instanceId: this.activeInstance, resultType: ResultType.NoAdjustables});
1350
+ // }
1351
+ }
1352
+ });
1353
+ }
1354
+ _prepareTheSelections() {
1355
+ // get generic variations
1356
+ const globalVariations = this._selections
1357
+ .filter(s => s.generic && s.decoNode.variation && !s.decoNode.type)
1358
+ .map((value, index, array) => {
1359
+ // find selection of variation
1360
+ const sel = this._selections.find(s => s.artNodeIdDeco === value.decoNode.variation.id);
1361
+ if (sel) {
1362
+ value.decoNode.variation.supplierArticleNr = sel.supplierArticleNr;
1363
+ }
1364
+ value.decoNode.variation.materialId = value.hdecoGameObject;
1365
+ return value.decoNode.variation;
1366
+ });
1367
+ // const usedVariations: FurniturePartVariation[] = [];
1368
+ let globalVariationsRewrite = true;
1369
+ const len = this._selections.length;
1370
+ let lastAdded;
1371
+ let lastAdjustable;
1372
+ let newPart = false;
1373
+ let previousPresLevel = -1;
1374
+ let positioning;
1375
+ for (let i = 0; i < len; i++) {
1376
+ const selection = this._selections[i];
1377
+ if (selection.presentationLevel === 1) {
1378
+ positioning = selection.hdecoPositioning;
1379
+ }
1380
+ if (selection.presentationLevel > previousPresLevel) {
1381
+ selection.hdecoPositioning = selection.hdecoPositioning || positioning;
1382
+ }
1383
+ if (selection.decoNode) {
1384
+ if (selection.decoNode.type === DecoNodeType.Variation) {
1385
+ if (lastAdded) {
1386
+ if (newPart) {
1387
+ lastAdded.variations = [selection.decoNode];
1388
+ }
1389
+ else {
1390
+ lastAdded.variations.push(selection.decoNode);
1391
+ }
1392
+ newPart = false;
1393
+ }
1394
+ else {
1395
+ if (globalVariationsRewrite) {
1396
+ globalVariations.length = 0;
1397
+ globalVariationsRewrite = false;
1398
+ }
1399
+ globalVariations.push(selection.decoNode);
1400
+ }
1401
+ // const variation: FurniturePartVariation = new FurniturePartVariation();
1402
+ // variation.BrandId = selection.decoNode.brandId;
1403
+ // variation.Description = selection.decoNode.gameObjectName;
1404
+ // variation.MaterialId = (selection.decoNode as any).materialId;
1405
+ // variation.SupplierArticleNr = (selection.decoNode as any).supplierArticleNr;
1406
+ // usedVariations.push(variation);
1407
+ // this._upsertFurniture(this.activeInstance, {
1408
+ // Variation: selection.decoNode.brandId,
1409
+ // VariationDescription: selection.decoNode.gameObjectName,
1410
+ // SupplierArticleNr: (selection.decoNode as any).supplierArticleNr
1411
+ // });
1412
+ }
1413
+ else if (selection.decoNode.type === DecoNodeType.Part &&
1414
+ typeof selection.decoNode.gameObjectName === 'string' &&
1415
+ selection.decoNode.gameObjectName.length) {
1416
+ if (selection.decoNode.kind === DecoNodeKind.Adjustable) {
1417
+ selection.variations = globalVariations;
1418
+ this._adjustables.push(selection);
1419
+ if (!lastAdded || lastAdded.nodeId !== selection.nodeId) {
1420
+ newPart = true;
1421
+ }
1422
+ lastAdded = selection;
1423
+ lastAdjustable = selection;
1424
+ }
1425
+ else if (selection.decoNode.kind === DecoNodeKind.Addable) {
1426
+ selection.variations = lastAdjustable ? lastAdjustable.variations : globalVariations;
1427
+ if (lastAdjustable) {
1428
+ lastAdjustable.addables.push(selection);
1429
+ }
1430
+ this._addables.push(selection);
1431
+ if (!lastAdded || lastAdded.nodeId !== selection.nodeId) {
1432
+ newPart = true;
1433
+ }
1434
+ lastAdded = selection;
1435
+ }
1436
+ }
1437
+ }
1438
+ previousPresLevel = selection.presentationLevel;
1439
+ }
1440
+ // this._upsertFurniture(this.activeInstance,
1441
+ // {Variations: usedVariations});
1442
+ }
1443
+ _createAdjustable(parent, adj) {
1444
+ let obj = this._source ? this._source.getObjectByName(adj.decoNode.gameObjectName) : null;
1445
+ if (!obj) {
1446
+ // in case of glb files, the importer removes dots from names
1447
+ const name = adj.decoNode.gameObjectName.replace(/[.]/g, '');
1448
+ obj = this._source ? this._source.getObjectByName(name) : null;
1449
+ if (!obj) {
1450
+ // console.warn(`No object with name ${adj.decoNode.gameObjectName} found!`);
1451
+ return null;
1452
+ }
1453
+ }
1454
+ let adjustable = obj.clone();
1455
+ adjustable.name = this._createUniqueName(parent, obj);
1456
+ adjustable.userData.selection = adj;
1457
+ adjustable.position.set(0, 0, 0);
1458
+ adjustable.visible = true;
1459
+ parent.add(adjustable);
1460
+ // the object being added to the customFloorGroup is being recreated so we loose the reference
1461
+ // therefor we need to retrieve the created object again
1462
+ // adjustable = parent.getObjectByName(adjustable.name);
1463
+ this._placedAdjustables.push(adjustable);
1464
+ return adjustable;
1465
+ }
1466
+ _createAddable(parent, add, part2, part1) {
1467
+ const obj = this._source.getObjectByName(add.decoNode.gameObjectName);
1468
+ if (!obj) {
1469
+ return null;
1470
+ }
1471
+ // const selection: Selection = this._getSelectionFromId(adj.artNodeIdDeco);
1472
+ const addable = obj.clone();
1473
+ addable.name = this._createUniqueName(parent, obj);
1474
+ addable.userData.selection = add;
1475
+ addable.position.set(0, 0, 0);
1476
+ addable.visible = true;
1477
+ if (part1 && part2) {
1478
+ parent.add(addable);
1479
+ this._placedAddables.push(addable);
1480
+ return addable;
1481
+ }
1482
+ return addable;
1483
+ }
1484
+ _placeAddables(parent) {
1485
+ const len = this._placedAdjustables.length;
1486
+ for (let i = 0; i < len; i++) {
1487
+ if (this._placedAdjustables[i].userData.hasOwnProperty('selection') && this._placedAdjustables[i].userData.selection) {
1488
+ const adjustableSelection = this._placedAdjustables[i].userData.selection;
1489
+ if (adjustableSelection) {
1490
+ const lena = adjustableSelection.addables.length;
1491
+ let conAddable;
1492
+ for (let ia = 0; ia < lena; ia++) {
1493
+ SceneUtils.TrySelectorConnection(this._scene, parent, this._placedAdjustables[i], adjustableSelection.addables[ia], (add, part2, part1) => this._createAddable(parent, add, part2, part1));
1494
+ if (conAddable) {
1495
+ SceneUtils.TrySelectorConnection(this._scene, parent, conAddable, adjustableSelection.addables[ia], (add, part2, part1) => this._createAddable(parent, add, part2, part1));
1496
+ }
1497
+ conAddable = this._placedAddables[this._placedAddables.length - 1];
1498
+ }
1499
+ }
1500
+ }
1501
+ }
1502
+ }
1503
+ _createUniqueName(parent, obj) {
1504
+ let iteration = 0;
1505
+ let name = obj.name;
1506
+ let existingObj = parent.getObjectByName(name);
1507
+ while (existingObj) {
1508
+ iteration++;
1509
+ name = obj.name + (iteration !== 0 ? ('_' + iteration) : '');
1510
+ existingObj = parent.getObjectByName(name);
1511
+ }
1512
+ return name;
1513
+ }
1514
+ _getGoodIdFromSku(sku) {
1515
+ return __awaiter(this, void 0, void 0, function* () {
1516
+ const response = yield this._configuratorService.getGoodIdFromSku(sku, false);
1517
+ if (response.validationResult.success && response.resultObject) {
1518
+ return response.resultObject;
1519
+ }
1520
+ });
1521
+ }
1522
+ _getArticle(sku, goodId) {
1523
+ return __awaiter(this, void 0, void 0, function* () {
1524
+ if (this._articleCache.has(sku)) {
1525
+ return this._articleCache.get(sku);
1526
+ }
1527
+ if (!goodId) {
1528
+ goodId = yield this._getGoodIdFromSku(sku)
1529
+ .catch((error) => {
1530
+ throw `Article with sku ${sku} not found!`;
1531
+ });
1532
+ }
1533
+ let article;
1534
+ const articleResponse = yield this._configuratorService.getArticleQuickSel(goodId, false);
1535
+ if (articleResponse.validationResult.success && articleResponse.resultObject) {
1536
+ if (articleResponse.resultObject.hasOwnProperty('oArticle')) {
1537
+ const obj = Array.isArray(articleResponse.resultObject['oArticle']) ? articleResponse.resultObject['oArticle'][0] : articleResponse.resultObject['oArticle'];
1538
+ article = this._boFactory.makeWithRawBackendData(Article, obj);
1539
+ }
1540
+ else {
1541
+ article = this._boFactory.makeWithRawBackendData(Article, articleResponse.resultObject);
1542
+ }
1543
+ }
1544
+ this._articleCache.set(sku, article);
1545
+ return article;
1546
+ });
1547
+ }
1548
+ _getSelections(instanceId, publicationCode) {
1549
+ return __awaiter(this, void 0, void 0, function* () {
1550
+ this._selections = [];
1551
+ const selectionResponse = yield this._configuratorService.getSelections(false, publicationCode);
1552
+ if (selectionResponse.resultObjects && selectionResponse.resultObjects.length > 0) {
1553
+ this._selections = this._boFactory.makeBOArrayFromRawBackendDataArray(Selection, selectionResponse.resultObjects);
1554
+ this._selections.forEach(s => s.instanceId = instanceId);
1555
+ // const filtered: Selection[] = this._selections.filter(s => s.nodeType !== NodeType.Article && s.presentationLevel === 1);
1556
+ this.selectionsReceived.next(this._selections);
1557
+ }
1558
+ else {
1559
+ throw 'No selections found!';
1560
+ }
1561
+ });
1562
+ }
1563
+ _getDecos() {
1564
+ return __awaiter(this, void 0, void 0, function* () {
1565
+ this._decos = [];
1566
+ const decosResponse = yield this._configuratorService.getDecos(false);
1567
+ if (decosResponse.resultObjects && decosResponse.resultObjects.length > 0) {
1568
+ this._decos = this._boFactory.makeBOArrayFromRawBackendDataArray(DecoNode, decosResponse.resultObjects);
1569
+ }
1570
+ else {
1571
+ throw 'No deconodes found!';
1572
+ }
1573
+ });
1574
+ }
1575
+ _linkSelectionsAndDecos() {
1576
+ const len = this._selections.length;
1577
+ for (let i = 0; i < len; i++) {
1578
+ let id = this._selections[i].artNodeIdDeco;
1579
+ // if (this._useNodeIdToLink) {
1580
+ // id = `${this._selections[i].node}_${this._selections[i].artNodeIdDeco}`;
1581
+ // }
1582
+ let deco = this._decos.find(d => d.id === id);
1583
+ if (!deco) {
1584
+ deco = new DecoNode();
1585
+ }
1586
+ const variation = this._getVariations().find(v => v.parentId === this._selections[i].artNodeIdDeco);
1587
+ if (variation) {
1588
+ deco.variation = variation;
1589
+ }
1590
+ this._selections[i].decoNode = deco;
1591
+ }
1592
+ }
1593
+ _getVariations() {
1594
+ return this._decos.filter((deco) => {
1595
+ return deco.type === DecoNodeType.Variation;
1596
+ });
1597
+ }
1598
+ _loadVariations(obj, instanceId) {
1599
+ return __awaiter(this, void 0, void 0, function* () {
1600
+ yield this._variationHelper.loadPart(obj, this._adjustables, true);
1601
+ yield this._variationHelper.loadVariation(instanceId, obj, this._adjustables, true);
1602
+ yield this._variationHelper.loadVariation(instanceId, obj, this._addables, true);
1603
+ });
1604
+ }
1605
+ _getAdjustables() {
1606
+ return this._selections.filter(s => {
1607
+ const node = s.decoNode;
1608
+ return node && node.gameObjectName && node.type === DecoNodeType.Part && node.kind === DecoNodeKind.Adjustable;
1609
+ });
1610
+ }
1611
+ _updatePivot(obj) {
1612
+ const boundingBox = new Box3().setFromObject(obj);
1613
+ const bbCenterPivot = new Vector3();
1614
+ boundingBox.getCenter(bbCenterPivot);
1615
+ const delta = new Vector3().sub(bbCenterPivot).setY(Math.abs(Math.min(boundingBox.min.y, 0)));
1616
+ obj.children.forEach((child) => {
1617
+ child.position.add(delta);
1618
+ });
1619
+ obj.updateWorldMatrix(false, true);
1620
+ }
1621
+ _reset() {
1622
+ this._placedAddables.length = 0;
1623
+ this._placedAdjustables.length = 0;
1624
+ this._adjustables.length = 0;
1625
+ this._addables.length = 0;
1626
+ this._prepareTheSelections();
1627
+ }
1628
+ };
1629
+ Builder.ctorParameters = () => [
1630
+ { type: Scene },
1631
+ { type: Options },
1632
+ { type: Boolean }
1633
+ ];
1634
+ Builder = __decorate([
1635
+ Injectable()
1636
+ ], Builder);
1637
+
1638
+ let AnswersComponent = class AnswersComponent {
1639
+ constructor() {
1640
+ this.answers = [];
1641
+ this.answerClick = new EventEmitter();
1642
+ }
1643
+ };
1644
+ __decorate([
1645
+ Input()
1646
+ ], AnswersComponent.prototype, "answers", void 0);
1647
+ __decorate([
1648
+ Input()
1649
+ ], AnswersComponent.prototype, "selectionTitle", void 0);
1650
+ __decorate([
1651
+ Output()
1652
+ ], AnswersComponent.prototype, "answerClick", void 0);
1653
+ AnswersComponent = __decorate([
1654
+ Component({
1655
+ selector: "answers",
1656
+ template: `
1657
+ <div class="ione-configurator">
1658
+ <div class="rp-answers-slideout">
1659
+ <h2 class="answers-title" [textContent]="selectionTitle"></h2>
1660
+ <div class="answers-container" visibilityObserverMaster>
1661
+ <answer *ngFor="let answer of answers"
1662
+ (click)="answerClick.emit(answer)"
1663
+ [answer]="answer"
1664
+ visibilityObserver
1665
+ #intersection="intersection"
1666
+ [observerEnabled]="true"
1667
+ [showing]="intersection.isIntersecting"
1668
+ ></answer>
1669
+ </div>
1670
+
1671
+ </div>
1672
+ </div>
1673
+ `,
1674
+ styles: [".ione-configurator .rp-answers-slideout{position:absolute;top:0;right:0;width:400px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content}.ione-configurator .answers-title{margin-left:10px;color:#1a1a1a}.ione-configurator .answers-container{height:100vh;overflow-y:scroll}.ione-configurator .answer-content{position:relative;overflow:hidden;cursor:pointer;font-size:12px;border:1px solid #d3d3d3;padding:10px;display:flex;flex-direction:row;border-radius:3px;margin-bottom:3px;box-shadow:2px 1px rgba(211,211,211,.5);background:#fff}.ione-configurator .thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .img-size{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .answer-wrapper{display:block}.ione-configurator .answer-title{font-size:12px;position:relative;overflow:hidden;cursor:pointer}.ione-configurator .question{font-weight:700;color:#1a1a1a}.ione-configurator .answer{font-size:12px;font-style:italic;margin-top:3px}.ione-configurator .collapse-content,.ione-configurator .collapse-wrapper{display:block}.ione-configurator .collapse-handle{position:absolute;top:10px;right:12px;border:solid #000;border-width:0 3px 3px 0;display:inline-block;padding:3px;transform:rotate(45deg);-webkit-transform:rotate(45deg)}.ione-configurator .collapse-handle.expanded{transform:rotate(-135deg);-webkit-transform:rotate(-135deg)}.ione-configurator .child-selection{margin-left:10px;display:flex;flex-direction:column;margin-top:5px}.ione-configurator .mat-title{margin-left:10px;color:#1a1a1a}.ione-configurator .drawer__header{height:48px}.ione-configurator .rp-selections-summary{height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;background:0 0;overflow:auto;position:absolute;top:0;right:0;width:400px}.ione-configurator .selections-content{overflow-y:auto}.ione-configurator .co-summary-line{position:relative;overflow:hidden;cursor:pointer;font-size:12px;border:1px solid #d3d3d3;padding:10px;display:flex;flex-direction:row;border-radius:3px;margin-bottom:3px;box-shadow:2px 1px rgba(211,211,211,.5);background:#fff}.ione-configurator .selection-thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .selection-img{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .answer-thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .answer-img{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .unloaded{background-color:#d3d3d3}.ione-configurator .titles{margin-left:14px;-ms-grid-row-align:center;align-self:center}.ione-configurator .title-wrapper{display:flex;flex-direction:column}.ione-configurator .answer-title-wrapper{text-align:center;-ms-grid-row-align:center;align-self:center;margin-left:14px}"]
1675
+ })
1676
+ ], AnswersComponent);
1677
+
1678
+ var ImageCacheService_1;
1679
+ let ImageCacheService = ImageCacheService_1 = class ImageCacheService {
1680
+ constructor(_configuratorService) {
1681
+ this._configuratorService = _configuratorService;
1682
+ // Map containing the retrieved images, @number = nodeId, @string = base64 string
1683
+ this._imageCache = new Map();
1684
+ }
1685
+ static _handleResponseData(includeMimetype, thumb, responseData) {
1686
+ if (responseData && responseData.resultObject) {
1687
+ if (responseData.resultObject.filePath !== null && responseData.resultObject.filePath !== "") {
1688
+ return ImageUtils.getFixedImageFilepathUrl(responseData.resultObject.filePath);
1689
+ }
1690
+ else {
1691
+ if (includeMimetype) {
1692
+ return ImageUtils.getDocBodyWithMimeTypeDefinition(responseData.resultObject.fileName, thumb ? responseData.resultObject.thumbnailBody : responseData.resultObject.documentBody);
1693
+ }
1694
+ else {
1695
+ return thumb ? responseData.resultObject.thumbnailBody : responseData.resultObject.documentBody;
1696
+ }
1697
+ }
1698
+ }
1699
+ else {
1700
+ return '';
1701
+ }
1702
+ }
1703
+ getImageForSelectionOrAnswer(object) {
1704
+ const includeMimeType = true, thumb = true;
1705
+ return new Promise((resolve, reject) => {
1706
+ if (object && object.nodeId) {
1707
+ if (!this._imageCache.has(object.nodeId)) {
1708
+ return this._configuratorService.getSingleImage(object.nodeId, 4, includeMimeType, thumb, true)
1709
+ .then((responseData) => {
1710
+ const base64 = ImageCacheService_1._handleResponseData(includeMimeType, thumb, responseData);
1711
+ this._imageCache.set(object.nodeId, base64);
1712
+ resolve(base64);
1713
+ }).catch(() => {
1714
+ reject();
1715
+ });
1716
+ }
1717
+ else {
1718
+ resolve(this._imageCache.get(object.nodeId));
1719
+ }
1720
+ }
1721
+ else {
1722
+ reject();
1723
+ }
1724
+ });
1725
+ }
1726
+ };
1727
+ ImageCacheService.ctorParameters = () => [
1728
+ { type: ConfiguratorService }
1729
+ ];
1730
+ ImageCacheService.ɵprov = ɵɵdefineInjectable({ factory: function ImageCacheService_Factory() { return new ImageCacheService(ɵɵinject(ConfiguratorService)); }, token: ImageCacheService, providedIn: "root" });
1731
+ ImageCacheService = ImageCacheService_1 = __decorate([
1732
+ Injectable({
1733
+ providedIn: 'root'
1734
+ })
1735
+ ], ImageCacheService);
1736
+
1737
+ let AnswerComponent = class AnswerComponent {
1738
+ constructor(_imageCacheService) {
1739
+ this._imageCacheService = _imageCacheService;
1740
+ }
1741
+ set showing(value) {
1742
+ this.answer.imageData = '';
1743
+ if (value && this.answer.answer !== 'Skip / Cancel') {
1744
+ this._loadThumbnail(this.answer);
1745
+ }
1746
+ else {
1747
+ this.answer.imageData = null;
1748
+ }
1749
+ }
1750
+ ngOnInit() {
1751
+ }
1752
+ _loadThumbnail(answer) {
1753
+ return __awaiter(this, void 0, void 0, function* () {
1754
+ yield this._imageCacheService.getImageForSelectionOrAnswer(answer).then((imageSrc) => {
1755
+ answer.imageData = imageSrc === "" ? null : imageSrc;
1756
+ });
1757
+ });
1758
+ }
1759
+ };
1760
+ AnswerComponent.ctorParameters = () => [
1761
+ { type: ImageCacheService }
1762
+ ];
1763
+ __decorate([
1764
+ Input()
1765
+ ], AnswerComponent.prototype, "answer", void 0);
1766
+ __decorate([
1767
+ Input()
1768
+ ], AnswerComponent.prototype, "showing", null);
1769
+ AnswerComponent = __decorate([
1770
+ Component({
1771
+ selector: 'answer',
1772
+ template: `
1773
+ <div class="ione-configurator">
1774
+ <div class="answer-wrapper">
1775
+ <div class="answer-content" @answerAppear>
1776
+ <div class="answer-thumbnail">
1777
+ <rp-loader *ngIf="answer.imageData === ''"></rp-loader>
1778
+ <img *ngIf="answer.imageData !== '' && answer.imageData !== null" class="answer-img" [src]="answer.imageData">
1779
+ </div>
1780
+ <div class="answer-title-wrapper">
1781
+ <span class="answer-title" [textContent]="answer.commercialAnswer"></span>
1782
+ </div>
1783
+ <div class="price">
1784
+ <span class="price-value"></span>
1785
+ </div>
1786
+ </div>
1787
+ </div>
1788
+ </div>
1789
+ `,
1790
+ animations: [
1791
+ trigger('answerAppear', [
1792
+ state('void', style({ 'background': '#dbdbdb' })),
1793
+ state('white', style({ 'background': 'white' })),
1794
+ transition('void <=> *', animate(500))
1795
+ ])
1796
+ ],
1797
+ styles: [".ione-configurator .rp-answers-slideout{position:absolute;top:0;right:0;width:400px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content}.ione-configurator .answers-title{margin-left:10px;color:#1a1a1a}.ione-configurator .answers-container{height:100vh;overflow-y:scroll}.ione-configurator .answer-content{position:relative;overflow:hidden;cursor:pointer;font-size:12px;border:1px solid #d3d3d3;padding:10px;display:flex;flex-direction:row;border-radius:3px;margin-bottom:3px;box-shadow:2px 1px rgba(211,211,211,.5);background:#fff}.ione-configurator .thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .img-size{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .answer-wrapper{display:block}.ione-configurator .answer-title{font-size:12px;position:relative;overflow:hidden;cursor:pointer}.ione-configurator .question{font-weight:700;color:#1a1a1a}.ione-configurator .answer{font-size:12px;font-style:italic;margin-top:3px}.ione-configurator .collapse-content,.ione-configurator .collapse-wrapper{display:block}.ione-configurator .collapse-handle{position:absolute;top:10px;right:12px;border:solid #000;border-width:0 3px 3px 0;display:inline-block;padding:3px;transform:rotate(45deg);-webkit-transform:rotate(45deg)}.ione-configurator .collapse-handle.expanded{transform:rotate(-135deg);-webkit-transform:rotate(-135deg)}.ione-configurator .child-selection{margin-left:10px;display:flex;flex-direction:column;margin-top:5px}.ione-configurator .mat-title{margin-left:10px;color:#1a1a1a}.ione-configurator .drawer__header{height:48px}.ione-configurator .rp-selections-summary{height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;background:0 0;overflow:auto;position:absolute;top:0;right:0;width:400px}.ione-configurator .selections-content{overflow-y:auto}.ione-configurator .co-summary-line{position:relative;overflow:hidden;cursor:pointer;font-size:12px;border:1px solid #d3d3d3;padding:10px;display:flex;flex-direction:row;border-radius:3px;margin-bottom:3px;box-shadow:2px 1px rgba(211,211,211,.5);background:#fff}.ione-configurator .selection-thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .selection-img{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .answer-thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .answer-img{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .unloaded{background-color:#d3d3d3}.ione-configurator .titles{margin-left:14px;-ms-grid-row-align:center;align-self:center}.ione-configurator .title-wrapper{display:flex;flex-direction:column}.ione-configurator .answer-title-wrapper{text-align:center;-ms-grid-row-align:center;align-self:center;margin-left:14px}"]
1798
+ })
1799
+ ], AnswerComponent);
1800
+
1801
+ let VisibilityObserverMasterDirective = class VisibilityObserverMasterDirective {
1802
+ // I initialize the intersection observer parent directive.
1803
+ constructor() {
1804
+ // As each observable child attaches itself to the parent observer, we need to
1805
+ // map Elements to Callbacks so that when an Element's intersection changes,
1806
+ // we'll know which callback to invoke. For this, we'll use an ES6 Map.
1807
+ this._mapping = new Map();
1808
+ this._observer = new IntersectionObserver((entries) => {
1809
+ for (const entry of entries) {
1810
+ const callback = this._mapping.get(entry.target);
1811
+ if (callback) {
1812
+ callback(entry.isIntersecting);
1813
+ }
1814
+ }
1815
+ }, {
1816
+ // This classifies the "intersection" as being a bit outside the
1817
+ // viewport. The intent here is give the elements a little time to react
1818
+ // to the change before the element is actually visible to the user.
1819
+ rootMargin: '300px 0px 300px 0px'
1820
+ });
1821
+ }
1822
+ // I get called once when the host element is being destroyed.
1823
+ ngOnDestroy() {
1824
+ this._mapping.clear();
1825
+ this._observer.disconnect();
1826
+ }
1827
+ // ---
1828
+ // PUBLIC METHODS.
1829
+ // ---
1830
+ // I add the given Element for intersection observation. When the intersection status
1831
+ // changes, the given callback is invoked with the new status.
1832
+ add(element, callback) {
1833
+ this._mapping.set(element, callback);
1834
+ this._observer.observe(element);
1835
+ }
1836
+ // I remove the given Element from intersection observation.
1837
+ remove(element) {
1838
+ this._mapping.delete(element);
1839
+ this._observer.unobserve(element);
1840
+ }
1841
+ };
1842
+ VisibilityObserverMasterDirective = __decorate([
1843
+ Directive({
1844
+ selector: '[visibilityObserverMaster]'
1845
+ })
1846
+ ], VisibilityObserverMasterDirective);
1847
+
1848
+ let VisibilityObserverDirective = class VisibilityObserverDirective {
1849
+ // I initialize the intersection observer directive.
1850
+ constructor(parent, elementRef) {
1851
+ this.observerEnabled = false;
1852
+ // These are just some human-friendly constants to make the HTML template a bit more
1853
+ // readable when being consumed as part of SWTCH/CASE statements.
1854
+ this.IS_INTERSECTING = true;
1855
+ this.IS_NOT_INTERSECTING = false;
1856
+ this._parent = parent;
1857
+ this._elementRef = elementRef;
1858
+ // By default, we're going to assume that the host element is NOT intersecting.
1859
+ // Then, we'll use the IntersectionObserver to asynchronously check for changes
1860
+ // in viewport visibility.
1861
+ this.isIntersecting = false;
1862
+ }
1863
+ // ---
1864
+ // PUBLIC METHODS.
1865
+ // ---
1866
+ // I get called once when the host element is being destroyed.
1867
+ ngOnDestroy() {
1868
+ this._parent.remove(this._elementRef.nativeElement);
1869
+ this._elementRef = undefined;
1870
+ }
1871
+ // I get called once after the inputs have been bound for the first time.
1872
+ ngOnInit() {
1873
+ // In this demo, instead of using an IntersectionObserver per Element, we're
1874
+ // going to use a shared observer in the parent element. However, we're still
1875
+ // going to use a CALLBACK style approach so that we're only reducing the number
1876
+ // of IntersectionObserver instances, not the number of Function calls.
1877
+ if (this.observerEnabled) {
1878
+ this._parent.add(this._elementRef.nativeElement, (isIntersecting) => {
1879
+ this.isIntersecting = isIntersecting;
1880
+ if (this.isIntersecting) {
1881
+ this._parent.remove(this._elementRef.nativeElement);
1882
+ }
1883
+ });
1884
+ }
1885
+ }
1886
+ };
1887
+ VisibilityObserverDirective.ctorParameters = () => [
1888
+ { type: VisibilityObserverMasterDirective },
1889
+ { type: ElementRef }
1890
+ ];
1891
+ __decorate([
1892
+ Input()
1893
+ ], VisibilityObserverDirective.prototype, "observerEnabled", void 0);
1894
+ VisibilityObserverDirective = __decorate([
1895
+ Directive({
1896
+ selector: '[visibilityObserver]',
1897
+ exportAs: 'intersection'
1898
+ })
1899
+ ], VisibilityObserverDirective);
1900
+
1901
+ let LoaderComponent = class LoaderComponent {
1902
+ };
1903
+ LoaderComponent = __decorate([
1904
+ Component({
1905
+ selector: 'rp-loader',
1906
+ template: `
1907
+ <div class="loader-wrapper">
1908
+ <svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 44 44" stroke="#3760a1">
1909
+ <g fill="none" fill-rule="evenodd" stroke-width="3">
1910
+ <circle class="ripple1" cx="22" cy="22" r="19">
1911
+ </circle>
1912
+ <circle class="ripple2" cx="22" cy="22" r="19">
1913
+ </circle>
1914
+ </g>
1915
+ </svg>
1916
+ </div>
1917
+ `,
1918
+ styles: [":host{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}:host .loader-wrapper{z-index:1100;position:absolute;width:54px;height:54px}:host .loader-wrapper svg{width:100%;height:100%}:host .loader-wrapper svg .ripple1{transform-origin:center;-webkit-animation:1.5s infinite ripple;animation:1.5s infinite ripple}:host .loader-wrapper svg .ripple2{transform-origin:center;-webkit-animation:1.5s .4s infinite ripple;animation:1.5s .4s infinite ripple}@-webkit-keyframes ripple{0%{transform:scale(0);opacity:1}100%{transform:scale(1);opacity:0}}@keyframes ripple{0%{transform:scale(0);opacity:1}100%{transform:scale(1);opacity:0}}"]
1919
+ })
1920
+ ], LoaderComponent);
1921
+
1922
+ let SharedModule = class SharedModule {
1923
+ };
1924
+ SharedModule = __decorate([
1925
+ NgModule({
1926
+ imports: [
1927
+ CommonModule
1928
+ ],
1929
+ declarations: [
1930
+ LoaderComponent
1931
+ ],
1932
+ exports: [
1933
+ LoaderComponent
1934
+ ]
1935
+ })
1936
+ ], SharedModule);
1937
+
1938
+ let AnswersModule = class AnswersModule {
1939
+ };
1940
+ AnswersModule = __decorate([
1941
+ NgModule({
1942
+ imports: [
1943
+ CommonModule,
1944
+ SharedModule
1945
+ ],
1946
+ declarations: [
1947
+ AnswersComponent,
1948
+ AnswerComponent,
1949
+ VisibilityObserverDirective,
1950
+ VisibilityObserverMasterDirective
1951
+ ],
1952
+ exports: [
1953
+ AnswersComponent
1954
+ ]
1955
+ })
1956
+ ], AnswersModule);
1957
+
1958
+ class SelectionViewModel {
1959
+ constructor() {
1960
+ this.children = [];
1961
+ this.expanded = false;
1962
+ this.thumbnail = '';
1963
+ }
1964
+ }
1965
+ let SelectionsComponent = class SelectionsComponent {
1966
+ constructor(_imageCacheService) {
1967
+ this._imageCacheService = _imageCacheService;
1968
+ this.selectionViewModels = [];
1969
+ this.selectionClick = new EventEmitter();
1970
+ }
1971
+ set selections(value) {
1972
+ this._prepareSelections(value);
1973
+ this._loadThumbnails();
1974
+ }
1975
+ ngOnInit() {
1976
+ }
1977
+ expandClicked(selectionViewModel, mouseEvent) {
1978
+ mouseEvent.preventDefault();
1979
+ mouseEvent.stopImmediatePropagation();
1980
+ selectionViewModel.expanded = !selectionViewModel.expanded;
1981
+ }
1982
+ selectSelection(selection, mouseEvent) {
1983
+ mouseEvent.preventDefault();
1984
+ mouseEvent.stopImmediatePropagation();
1985
+ this.selectionClick.next(selection);
1986
+ }
1987
+ _loadThumbnails() {
1988
+ return __awaiter(this, void 0, void 0, function* () {
1989
+ if (this.selectionViewModels.length > 0) {
1990
+ this.selectionViewModels.forEach((viewModel) => __awaiter(this, void 0, void 0, function* () {
1991
+ yield this._imageCacheService.getImageForSelectionOrAnswer(viewModel.selection).then((imageSrc) => {
1992
+ viewModel.thumbnail = imageSrc === "" ? null : imageSrc;
1993
+ });
1994
+ }));
1995
+ }
1996
+ });
1997
+ }
1998
+ _prepareSelections(value) {
1999
+ this.selectionViewModels.length = 0;
2000
+ let selectionViewModel;
2001
+ value.forEach(s => {
2002
+ if (s.presentationLevel === 1) {
2003
+ selectionViewModel = new SelectionViewModel();
2004
+ selectionViewModel.selection = s;
2005
+ this.selectionViewModels.push(selectionViewModel);
2006
+ }
2007
+ else if (s.presentationLevel > 1) {
2008
+ if (selectionViewModel) {
2009
+ selectionViewModel.children.push(s);
2010
+ }
2011
+ }
2012
+ });
2013
+ }
2014
+ };
2015
+ SelectionsComponent.ctorParameters = () => [
2016
+ { type: ImageCacheService }
2017
+ ];
2018
+ __decorate([
2019
+ Input()
2020
+ ], SelectionsComponent.prototype, "selections", null);
2021
+ __decorate([
2022
+ Output()
2023
+ ], SelectionsComponent.prototype, "selectionClick", void 0);
2024
+ SelectionsComponent = __decorate([
2025
+ Component({
2026
+ selector: "selections",
2027
+ template: `
2028
+ <div class="ione-configurator">
2029
+ <div class="rp-selections-summary">
2030
+ <header class="drawer__header">
2031
+ <h2 class="mat-title" [textContent]="'Configuratie'"></h2>
2032
+ <!--<button>-->
2033
+ <!---->
2034
+ <!--</button>-->
2035
+ </header>
2036
+ <div class="selections-content">
2037
+ <ng-container *ngFor="let selectionViewModel of selectionViewModels">
2038
+
2039
+ <div class="co-summary-line" (click)="selectSelection(selectionViewModel.selection, $event)">
2040
+ <div class="selection-thumbnail">
2041
+ <rp-loader *ngIf="selectionViewModel.thumbnail === ''"></rp-loader>
2042
+ <img visibilityObserver *ngIf="selectionViewModel.thumbnail !== '' && selectionViewModel.thumbnail !== null" class="selection-img" [src]="selectionViewModel.thumbnail">
2043
+ </div>
2044
+ <div class="titles">
2045
+ <div class="title-wrapper">
2046
+ <label class="question" [textContent]="selectionViewModel.selection.question"></label>
2047
+ <span class="answer" [textContent]="selectionViewModel.selection.answer"></span>
2048
+ <div *ngIf="selectionViewModel.children.length > 0 && selectionViewModel.expanded" @showHideChildren>
2049
+ <div class="child-selection" *ngFor="let selection of selectionViewModel.children"
2050
+ (click)="selectSelection(selection, $event)"
2051
+ >
2052
+ <label class="question" [textContent]="selection.commercialQuestion"></label>
2053
+ <span class="answer" [textContent]="selection.answer"></span>
2054
+ </div>
2055
+ </div>
2056
+ </div>
2057
+ </div>
2058
+
2059
+ <div class="price-wrapper">
2060
+ <span class="price-value"></span>
2061
+ </div>
2062
+
2063
+ <div class="collapse-wrapper">
2064
+ <div class="collapse-content">
2065
+ <div class="collapse-handle" [class.expanded]="selectionViewModel.expanded"
2066
+ *ngIf="selectionViewModel.children.length > 0" (click)="expandClicked(selectionViewModel, $event)"></div>
2067
+ </div>
2068
+ </div>
2069
+ </div>
2070
+
2071
+ </ng-container>
2072
+ </div>
2073
+ </div>
2074
+ </div>
2075
+ `,
2076
+ animations: [
2077
+ trigger('showHideChildren', [
2078
+ state('void', style({ 'height': '0' })),
2079
+ state('*', style({ 'height': '*' })),
2080
+ transition('void <=> *', animate(200))
2081
+ ])
2082
+ ],
2083
+ styles: [".ione-configurator .rp-answers-slideout{position:absolute;top:0;right:0;width:400px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content}.ione-configurator .answers-title{margin-left:10px;color:#1a1a1a}.ione-configurator .answers-container{height:100vh;overflow-y:scroll}.ione-configurator .answer-content{position:relative;overflow:hidden;cursor:pointer;font-size:12px;border:1px solid #d3d3d3;padding:10px;display:flex;flex-direction:row;border-radius:3px;margin-bottom:3px;box-shadow:2px 1px rgba(211,211,211,.5);background:#fff}.ione-configurator .thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .img-size{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .answer-wrapper{display:block}.ione-configurator .answer-title{font-size:12px;position:relative;overflow:hidden;cursor:pointer}.ione-configurator .question{font-weight:700;color:#1a1a1a}.ione-configurator .answer{font-size:12px;font-style:italic;margin-top:3px}.ione-configurator .collapse-content,.ione-configurator .collapse-wrapper{display:block}.ione-configurator .collapse-handle{position:absolute;top:10px;right:12px;border:solid #000;border-width:0 3px 3px 0;display:inline-block;padding:3px;transform:rotate(45deg);-webkit-transform:rotate(45deg)}.ione-configurator .collapse-handle.expanded{transform:rotate(-135deg);-webkit-transform:rotate(-135deg)}.ione-configurator .child-selection{margin-left:10px;display:flex;flex-direction:column;margin-top:5px}.ione-configurator .mat-title{margin-left:10px;color:#1a1a1a}.ione-configurator .drawer__header{height:48px}.ione-configurator .rp-selections-summary{height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;background:0 0;overflow:auto;position:absolute;top:0;right:0;width:400px}.ione-configurator .selections-content{overflow-y:auto}.ione-configurator .co-summary-line{position:relative;overflow:hidden;cursor:pointer;font-size:12px;border:1px solid #d3d3d3;padding:10px;display:flex;flex-direction:row;border-radius:3px;margin-bottom:3px;box-shadow:2px 1px rgba(211,211,211,.5);background:#fff}.ione-configurator .selection-thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .selection-img{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .answer-thumbnail{width:54px;min-width:54px;height:54px;min-height:54px;border:1px solid #d3d3d3;border-radius:5px}.ione-configurator .answer-img{width:54px;min-width:54px;height:54px;min-height:54px;border-radius:5px}.ione-configurator .unloaded{background-color:#d3d3d3}.ione-configurator .titles{margin-left:14px;-ms-grid-row-align:center;align-self:center}.ione-configurator .title-wrapper{display:flex;flex-direction:column}.ione-configurator .answer-title-wrapper{text-align:center;-ms-grid-row-align:center;align-self:center;margin-left:14px}"]
2084
+ })
2085
+ ], SelectionsComponent);
2086
+
2087
+ let SelectionsModule = class SelectionsModule {
2088
+ };
2089
+ SelectionsModule = __decorate([
2090
+ NgModule({
2091
+ imports: [
2092
+ CommonModule,
2093
+ SharedModule
2094
+ ],
2095
+ declarations: [
2096
+ SelectionsComponent
2097
+ ],
2098
+ exports: [
2099
+ SelectionsComponent
2100
+ ]
2101
+ })
2102
+ ], SelectionsModule);
2103
+
2104
+ /**
2105
+ * Generated bundle index. Do not edit.
2106
+ */
2107
+
2108
+ export { AnswersComponent, AnswersModule, Builder, ConfiguratorService, SelectionsComponent, SelectionsModule, SharedModule as ɵa, LoaderComponent as ɵb, AnswerComponent as ɵc, ImageCacheService as ɵd, VisibilityObserverDirective as ɵe, VisibilityObserverMasterDirective as ɵf };
2109
+ //# sourceMappingURL=colijnit-configurator.js.map