@configura/babylon-view 1.4.0-alpha.4 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +1 -1
  3. package/dist/animation/AnimatableObject.d.ts +8 -8
  4. package/dist/animation/AnimatableObject.js +3 -3
  5. package/dist/animation/animator/Animator.d.ts +33 -33
  6. package/dist/animation/animator/Animator.js +58 -58
  7. package/dist/animation/animator/AnimatorEasing.d.ts +16 -16
  8. package/dist/animation/animator/AnimatorEasing.js +31 -31
  9. package/dist/animation/animator/AnimatorEasingMatrix.d.ts +14 -14
  10. package/dist/animation/animator/AnimatorEasingMatrix.js +16 -16
  11. package/dist/animation/animator/AnimatorHighlight.d.ts +16 -16
  12. package/dist/animation/animator/AnimatorHighlight.js +32 -32
  13. package/dist/animation/animator/AnimatorPointToPoint.d.ts +8 -8
  14. package/dist/animation/animator/AnimatorPointToPoint.js +14 -14
  15. package/dist/animation/animator/AnimatorQueue.d.ts +13 -13
  16. package/dist/animation/animator/AnimatorQueue.js +57 -57
  17. package/dist/animation/animator/AnimatorScale.d.ts +8 -8
  18. package/dist/animation/animator/AnimatorScale.js +13 -13
  19. package/dist/animation/animator/AnimatorSpin.d.ts +10 -10
  20. package/dist/animation/animator/AnimatorSpin.js +13 -13
  21. package/dist/animation/animator/EasingFunctions.d.ts +35 -35
  22. package/dist/animation/animator/EasingFunctions.js +137 -137
  23. package/dist/animation/coordinator/Coordinator.d.ts +28 -28
  24. package/dist/animation/coordinator/Coordinator.js +47 -47
  25. package/dist/animation/coordinator/CoordinatorDropAndSpin.d.ts +22 -22
  26. package/dist/animation/coordinator/CoordinatorDropAndSpin.js +133 -133
  27. package/dist/animation/coordinator/CoordinatorIdentity.d.ts +11 -11
  28. package/dist/animation/coordinator/CoordinatorIdentity.js +12 -12
  29. package/dist/animation/coordinator/CoordinatorNodeQueues.d.ts +18 -18
  30. package/dist/animation/coordinator/CoordinatorNodeQueues.js +50 -50
  31. package/dist/animation/coordinator/CoordinatorPulse.d.ts +21 -21
  32. package/dist/animation/coordinator/CoordinatorPulse.js +47 -47
  33. package/dist/animation/coordinator/CoordinatorPulseBounce.d.ts +14 -14
  34. package/dist/animation/coordinator/CoordinatorPulseBounce.js +40 -40
  35. package/dist/animation/coordinator/CoordinatorPulseHighlight.d.ts +13 -13
  36. package/dist/animation/coordinator/CoordinatorPulseHighlight.js +34 -34
  37. package/dist/animation/coordinator/CoordinatorPulseInflate.d.ts +14 -14
  38. package/dist/animation/coordinator/CoordinatorPulseInflate.js +30 -30
  39. package/dist/camera/CameraCreator.d.ts +5 -5
  40. package/dist/camera/CameraCreator.js +4 -4
  41. package/dist/camera/CfgArcRotateCameraPointersInput.d.ts +26 -26
  42. package/dist/camera/CfgArcRotateCameraPointersInput.js +264 -264
  43. package/dist/camera/CfgOrbitalCamera.d.ts +68 -68
  44. package/dist/camera/CfgOrbitalCamera.js +250 -250
  45. package/dist/camera/CfgOrbitalCameraControlProps.d.ts +6 -6
  46. package/dist/camera/CfgOrbitalCameraControlProps.js +3 -3
  47. package/dist/camera/GradingApplier.d.ts +3 -3
  48. package/dist/camera/GradingApplier.js +48 -48
  49. package/dist/engine/EngineCreator.d.ts +3 -3
  50. package/dist/engine/EngineCreator.js +10 -10
  51. package/dist/geometry/CfgGeometry.d.ts +29 -29
  52. package/dist/geometry/CfgGeometry.js +146 -146
  53. package/dist/geometry/CfgMesh.d.ts +10 -10
  54. package/dist/geometry/CfgMesh.js +38 -38
  55. package/dist/geometry/geoSplitter.d.ts +8 -8
  56. package/dist/geometry/geoSplitter.js +192 -192
  57. package/dist/geometry/stretch/CfgMorphTarget.d.ts +15 -15
  58. package/dist/geometry/stretch/CfgMorphTarget.js +65 -65
  59. package/dist/geometry/stretch/CfgStretchData.d.ts +114 -114
  60. package/dist/geometry/stretch/CfgStretchData.js +340 -340
  61. package/dist/geometry/stretch/CfgStretchMorphGeometry.d.ts +16 -16
  62. package/dist/geometry/stretch/CfgStretchMorphGeometry.js +95 -95
  63. package/dist/index.d.ts +13 -13
  64. package/dist/index.js +13 -13
  65. package/dist/light/CfgDirectionalLight.d.ts +8 -8
  66. package/dist/light/CfgDirectionalLight.js +18 -18
  67. package/dist/light/CfgHemisphericLight.d.ts +7 -7
  68. package/dist/light/CfgHemisphericLight.js +17 -17
  69. package/dist/light/CfgPointLight.d.ts +8 -8
  70. package/dist/light/CfgPointLight.js +18 -18
  71. package/dist/light/DefaultLightRig.d.ts +19 -19
  72. package/dist/light/DefaultLightRig.js +77 -77
  73. package/dist/light/LightRigCreator.d.ts +9 -9
  74. package/dist/light/LightRigCreator.js +3 -3
  75. package/dist/material/CfgMaterial.d.ts +68 -68
  76. package/dist/material/CfgMaterial.js +482 -482
  77. package/dist/material/DummyMaterialCreator.d.ts +4 -4
  78. package/dist/material/DummyMaterialCreator.js +15 -15
  79. package/dist/material/material.d.ts +18 -18
  80. package/dist/material/material.js +128 -128
  81. package/dist/material/texture.d.ts +14 -14
  82. package/dist/material/texture.js +306 -306
  83. package/dist/nodes/CfgContentRootNode.d.ts +19 -19
  84. package/dist/nodes/CfgContentRootNode.js +75 -75
  85. package/dist/nodes/CfgDeferredMeshNode.d.ts +55 -55
  86. package/dist/nodes/CfgDeferredMeshNode.js +377 -377
  87. package/dist/nodes/CfgProductNode.d.ts +126 -126
  88. package/dist/nodes/CfgProductNode.js +578 -578
  89. package/dist/nodes/CfgSymNode.d.ts +50 -50
  90. package/dist/nodes/CfgSymNode.js +249 -249
  91. package/dist/nodes/CfgSymRootNode.d.ts +45 -45
  92. package/dist/nodes/CfgSymRootNode.js +220 -220
  93. package/dist/nodes/CfgTransformNode.d.ts +33 -33
  94. package/dist/nodes/CfgTransformNode.js +83 -83
  95. package/dist/scene/SceneCreator.d.ts +6 -6
  96. package/dist/scene/SceneCreator.js +22 -22
  97. package/dist/utilities/CfgBoundingBox.d.ts +21 -21
  98. package/dist/utilities/CfgBoundingBox.js +81 -81
  99. package/dist/utilities/anchor/anchor.d.ts +51 -51
  100. package/dist/utilities/anchor/anchor.js +136 -136
  101. package/dist/utilities/anchor/anchorMap.d.ts +20 -20
  102. package/dist/utilities/anchor/anchorMap.js +111 -111
  103. package/dist/utilities/utilities3D.d.ts +70 -70
  104. package/dist/utilities/utilities3D.js +265 -265
  105. package/dist/utilities/utilitiesColor.d.ts +18 -18
  106. package/dist/utilities/utilitiesColor.js +48 -48
  107. package/dist/utilities/utilitiesImage.d.ts +6 -6
  108. package/dist/utilities/utilitiesImage.js +107 -107
  109. package/dist/utilities/utilitiesSymRootIdentifier.d.ts +7 -7
  110. package/dist/utilities/utilitiesSymRootIdentifier.js +26 -26
  111. package/dist/view/BaseView.d.ts +78 -78
  112. package/dist/view/BaseView.js +297 -297
  113. package/dist/view/BaseViewConfiguration.d.ts +32 -32
  114. package/dist/view/BaseViewConfiguration.js +8 -8
  115. package/dist/view/RenderEnv.d.ts +43 -43
  116. package/dist/view/RenderEnv.js +7 -7
  117. package/dist/view/SingleProductDefaultCameraView.d.ts +33 -33
  118. package/dist/view/SingleProductDefaultCameraView.js +141 -141
  119. package/dist/view/SingleProductDefaultCameraViewConfiguration.d.ts +46 -46
  120. package/dist/view/SingleProductDefaultCameraViewConfiguration.js +11 -11
  121. package/dist/view/SingleProductView.d.ts +42 -42
  122. package/dist/view/SingleProductView.js +206 -206
  123. package/dist/view/SingleProductViewConfiguration.d.ts +32 -32
  124. package/dist/view/SingleProductViewConfiguration.js +19 -19
  125. package/package.json +5 -5
@@ -1,578 +1,578 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { Matrix } from "@babylonjs/core/Maths/math.vector.js";
11
- import { InspectableType } from "@babylonjs/core/Misc/iInspectable.js";
12
- import { aggregateAllMaterialApplications, CfgMtrlApplication, CfgMtrlApplicationSource, logMaterialMappingToConsole, } from "@configura/web-api";
13
- import { LogObservable, readFileToArrayBuffer } from "@configura/web-utilities";
14
- import { CfgAnchorRef, getAnchorTargetPriorityComparer, updatedStretchedAnchorPointMatrix, } from "../utilities/anchor/anchor.js";
15
- import { makeAnchoredToAnchorMap } from "../utilities/anchor/anchorMap.js";
16
- import { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
17
- import { modelTransformToSymTransform, symTransformToMatrix } from "../utilities/utilities3D.js";
18
- import { isSameRootNodeSource } from "../utilities/utilitiesSymRootIdentifier.js";
19
- import { CfgSymRootNode, isSymRootNode } from "./CfgSymRootNode.js";
20
- import { CfgTransformNode } from "./CfgTransformNode.js";
21
- export function isProductNode(value) {
22
- return value instanceof CfgProductNode;
23
- }
24
- export function isCfgSymRootNode(value) {
25
- return value instanceof CfgSymRootNode;
26
- }
27
- export function isCfgAnchorableNode(value) {
28
- return isProductNode(value) || isCfgSymRootNode(value);
29
- }
30
- export class CfgProductNode extends CfgTransformNode {
31
- constructor(renderEnvironment, _product) {
32
- super(renderEnvironment, `(Product) ${_product.sku}`);
33
- this._product = _product;
34
- this.logger = new LogObservable();
35
- this._destroyed = false;
36
- this._applicationAreas = [];
37
- this._mtrlApplications = [];
38
- this._debugMtrlApplications = [];
39
- this._scheduledForRemoval = [];
40
- this._anchoredToAnchors = new Map();
41
- this._symRootLoadings = [];
42
- /**
43
- * The passed function is recursively applied on every descendant CfgProductNode in the tree.
44
- * This node is included. Destroyed products are not included.
45
- */
46
- this._applyOnDescendantProductNodes = (fn) => {
47
- const result = [];
48
- result.push(fn(this));
49
- for (const additionalProduct of this._getAdditionalProductNodes()) {
50
- result.push(...additionalProduct._applyOnDescendantProductNodes(fn));
51
- }
52
- return result;
53
- };
54
- this.key = _product.key;
55
- // Useful debug tool:
56
- if (false) {
57
- window.product = this;
58
- console.log(`Use "window.product" to access "${this.key}" product node.`);
59
- }
60
- this.anchorRef = CfgAnchorRef.make(this._product._internal.anchor);
61
- const modelTransform = _product.transform;
62
- if (modelTransform !== undefined) {
63
- const modelSymTransform = modelTransformToSymTransform(modelTransform);
64
- this._modelMatrix = symTransformToMatrix(modelSymTransform.transform());
65
- }
66
- this.initTransform();
67
- }
68
- static make(renderEnvironment, product) {
69
- return new this(renderEnvironment, product);
70
- }
71
- get cfgClassName() {
72
- return "CfgProductNode";
73
- }
74
- destroy() {
75
- this._destroyed = true;
76
- this._symRootLoadings.length = 0;
77
- for (const symRoot of this._getSymRootChildren().filter((c) => !c.isForDebug)) {
78
- this.scheduleForRemoval(symRoot);
79
- }
80
- }
81
- get product() {
82
- return this._product;
83
- }
84
- /**
85
- * We want to be able to animate nodes that are on the way out.
86
- * So we do not immediately remove them from the tree.
87
- */
88
- scheduleForRemoval(node) {
89
- node.destroy();
90
- this._scheduledForRemoval.push(node);
91
- }
92
- isDestroyed() {
93
- return this._destroyed;
94
- }
95
- /**
96
- * This function will apply either of tree passed functions on the additional products/ in the
97
- * passed CfgProduct and the additional products in the CfgProductNode.
98
- * It is not applied recursively.
99
- */
100
- _syncAdditionalProductNodes(parentProduct, fn) {
101
- const { both, productNodeButNoProduct, productButNoProductNode } = fn;
102
- const additionalProducts = parentProduct.additionalProducts.filter((c) => c.selected);
103
- const additionalProductNodes = this._getAdditionalProductNodes();
104
- for (const additionalProductNode of additionalProductNodes) {
105
- const index = additionalProducts.findIndex((p) => additionalProductNode.product.isBackedBySame(p));
106
- if (index === -1) {
107
- if (productNodeButNoProduct === undefined) {
108
- throw Error(`ProductNode ${additionalProductNode.key} exist, but no data for it. There is no handler for this.`);
109
- }
110
- productNodeButNoProduct(additionalProductNode);
111
- }
112
- else {
113
- const additionalProduct = additionalProducts.splice(index, 1)[0];
114
- if (both === undefined) {
115
- throw Error(`ProductNode ${additionalProductNode.key} and data ${additionalProduct.key} exists. There is no handler for this.`);
116
- }
117
- both(additionalProduct, additionalProductNode);
118
- }
119
- }
120
- for (const additionalProduct of additionalProducts) {
121
- if (productButNoProductNode === undefined) {
122
- throw Error(`Data ${additionalProduct.key} exists, but no ProductNode for it. There is no handler for this.`);
123
- }
124
- productButNoProductNode(additionalProduct);
125
- }
126
- }
127
- /**
128
- * Application areas are essentially catalogue level material mappings.
129
- * This function is recursively applied on additional products.
130
- */
131
- setApplicationAreas(applicationAreas) {
132
- this._applyOnDescendantProductNodes((p) => {
133
- p._applicationAreas = applicationAreas;
134
- });
135
- }
136
- /**
137
- * Start loading the geometry, but do not yet show it.
138
- * This function is recursively applied on additional products.
139
- */
140
- loadGeo(coordinatorWithMeta) {
141
- return __awaiter(this, void 0, void 0, function* () {
142
- const product = this._product;
143
- const rootNodeSources = product._internal.rootNodeSources || [];
144
- const updateRootNodeSources = rootNodeSources.slice();
145
- const allSymRootLoadings = this._symRootLoadings;
146
- let i = allSymRootLoadings.length;
147
- while (i--) {
148
- const symRootLoading = allSymRootLoadings[i];
149
- const updateIndex = updateRootNodeSources.findIndex((rootNodeSource) => isSameRootNodeSource(rootNodeSource, symRootLoading.rootNodeSource));
150
- if (updateIndex === -1) {
151
- // We remove the inProgress, because the thing which is in progress will not be
152
- // wanted when it arrives.
153
- allSymRootLoadings.splice(i, 1);
154
- }
155
- }
156
- for (const symRootChild of this._getSymRootChildren().filter((c) => !c.isForDebug)) {
157
- const updateIndex = updateRootNodeSources.findIndex((m) => symRootChild.isSameIdentifierTransformAndAnchor(m));
158
- if (updateIndex === -1) {
159
- // Not found, remove
160
- this.scheduleForRemoval(symRootChild);
161
- }
162
- else {
163
- // Found, no need to change anything
164
- updateRootNodeSources.splice(updateIndex, 1);
165
- }
166
- }
167
- const batchSymRootLoadings = updateRootNodeSources.map((rootNodeSource) => {
168
- let symRootLoading = allSymRootLoadings.find((s) => isSameRootNodeSource(rootNodeSource, s.rootNodeSource));
169
- if (symRootLoading === undefined) {
170
- symRootLoading = {
171
- rootNodeSource,
172
- rootNodePromise: CfgSymRootNode.makeCfgSymRootFromRootNodeSource(this.logger, false, this._renderEnvironment, this, rootNodeSource),
173
- };
174
- allSymRootLoadings.push(symRootLoading);
175
- }
176
- return symRootLoading;
177
- });
178
- yield Promise.all([
179
- ...batchSymRootLoadings.map((s) => s.rootNodePromise),
180
- this._loadAdditionalProducts(coordinatorWithMeta),
181
- ]);
182
- const addedSymRoots = (yield Promise.all(batchSymRootLoadings.map((s) => s.rootNodePromise)))
183
- .filter((symRoot) => symRoot !== undefined)
184
- .filter((symRoot) => {
185
- const loadInProgressIndex = allSymRootLoadings.findIndex((symRootLoadInProgress) => symRoot.isSameIdentifierTransformAndAnchor(symRootLoadInProgress.rootNodeSource));
186
- if (loadInProgressIndex === -1) {
187
- // This node no longer shall be added
188
- return false;
189
- }
190
- // We'll add this, so it moves from "loading" to being a proper child
191
- allSymRootLoadings.splice(loadInProgressIndex, 1);
192
- this.add(symRoot);
193
- return true;
194
- });
195
- // Updated symRootChildren
196
- const anchorableChildren = this._getAnchorableNodes();
197
- // Make a map of who is anchored to who
198
- const anchoredToAnchors = makeAnchoredToAnchorMap(anchorableChildren, getAnchorTargetPriorityComparer(this.product._internal.measureDefinitions));
199
- this._anchoredToAnchors = anchoredToAnchors;
200
- for (const child of anchorableChildren) {
201
- child.setAnchorTarget(anchoredToAnchors.get(child));
202
- }
203
- this.refreshStretch();
204
- for (const symRoot of addedSymRoots) {
205
- if (coordinatorWithMeta === undefined) {
206
- continue;
207
- }
208
- const c = coordinatorWithMeta.coordinator;
209
- yield c.prepareForEnter.bind(c)(symRoot, coordinatorWithMeta.isNewProduct);
210
- }
211
- });
212
- }
213
- _loadAdditionalProducts(coordinatorWithMeta) {
214
- return __awaiter(this, void 0, void 0, function* () {
215
- const additionalProductLoadPromises = [];
216
- this._syncAdditionalProductNodes(this._product, {
217
- productNodeButNoProduct: (additionalProductNode) => {
218
- this.scheduleForRemoval(additionalProductNode);
219
- },
220
- productButNoProductNode: (additionalProduct) => {
221
- const additionalProductNode = CfgProductNode.make(this._renderEnvironment, additionalProduct);
222
- this.add(additionalProductNode);
223
- additionalProductLoadPromises.push(additionalProductNode.loadGeo(coordinatorWithMeta));
224
- },
225
- both: (_additionalProduct, additionalProductNode) => {
226
- additionalProductLoadPromises.push(additionalProductNode.loadGeo(coordinatorWithMeta));
227
- },
228
- });
229
- yield Promise.all(additionalProductLoadPromises);
230
- });
231
- }
232
- /**
233
- * Run any animations and then permanently removes the nodes from the tree
234
- * This function is recursively applied on additional products.
235
- */
236
- flushScheduledForRemove(animationCoordinator) {
237
- return __awaiter(this, void 0, void 0, function* () {
238
- const thisBatch = this._scheduledForRemoval.slice();
239
- this._scheduledForRemoval.length = 0;
240
- yield Promise.all(this._getAdditionalProductNodes(true).map((additionalProductNode) => additionalProductNode.flushScheduledForRemove(animationCoordinator)));
241
- yield Promise.all(thisBatch.map((node) => (() => __awaiter(this, void 0, void 0, function* () {
242
- if (node instanceof CfgSymRootNode) {
243
- if (animationCoordinator !== undefined) {
244
- const c = animationCoordinator.coordinator;
245
- yield c.prepareForExit.bind(c)(node);
246
- }
247
- }
248
- this.remove(true, node);
249
- }))()));
250
- });
251
- }
252
- /**
253
- * Are all materials currently needed loaded and ready to be applied?
254
- * This function does not take additional products into account.
255
- */
256
- _isAllMeshMaterialsReady() {
257
- return this._getSymRootChildren().reduce((a, c) => a && c.isAllMeshMaterialsReady(), true);
258
- }
259
- /**
260
- * Resolves when all materials currently needed have been loaded and are ready to be applied.
261
- * This function does not take additional products into account.
262
- */
263
- _awaitAllMeshMaterialsReady() {
264
- return __awaiter(this, void 0, void 0, function* () {
265
- return new Promise((resolve, reject) => {
266
- let maxTries = 60 * 60; // Assuming 60 fps this gives a minute, which is absurdly long
267
- const frame = () => {
268
- if (this._isAllMeshMaterialsReady()) {
269
- resolve();
270
- return;
271
- }
272
- if (maxTries === 0) {
273
- reject("Materials not ready in time");
274
- return;
275
- }
276
- window.requestAnimationFrame(frame);
277
- maxTries--;
278
- };
279
- frame();
280
- });
281
- });
282
- }
283
- /**
284
- * Loads the materials needed.
285
- * This function is recursively applied on additional products.
286
- */
287
- loadMaterials(animationCoordinator) {
288
- return __awaiter(this, void 0, void 0, function* () {
289
- const product = this._product;
290
- const productMtrlApplications = (product._internal.mtrlApplications || []).map((m) => CfgMtrlApplication.fromMtrlLikeApplication(CfgMtrlApplicationSource.Product, m));
291
- this._mtrlApplications = productMtrlApplications;
292
- this._configuration = product.configuration;
293
- yield Promise.all([
294
- this._aggregateMaterialsPushToChildrenAndLoad(animationCoordinator),
295
- ...this._getAdditionalProductNodes().map((additionalProductNode) => additionalProductNode.loadMaterials(animationCoordinator)),
296
- ]);
297
- });
298
- }
299
- /**
300
- * Update the tag (area) to material mapping and gives them to sym children
301
- * This function does not take additional products into account.
302
- */
303
- _aggregateMaterialsPushToChildrenAndLoad(animationCoordinator) {
304
- return __awaiter(this, void 0, void 0, function* () {
305
- if (this._applicationAreas === undefined || this._configuration === undefined) {
306
- return;
307
- }
308
- const areasToMaterials = aggregateAllMaterialApplications(this._applicationAreas, this._mtrlApplications, this._configuration, this._debugMtrlApplications);
309
- this._areasToMaterials = areasToMaterials;
310
- yield this._pushMaterialToSymRootChildrenAndLoad(animationCoordinator);
311
- });
312
- }
313
- /**
314
- * Starts loading the materials on the sym children (but does not apply)
315
- * This function does not take additional products into account.
316
- */
317
- _pushMaterialToSymRootChildrenAndLoad(animationCoordinator) {
318
- return __awaiter(this, void 0, void 0, function* () {
319
- const areasToMaterials = this._areasToMaterials;
320
- if (areasToMaterials === undefined) {
321
- return;
322
- }
323
- yield Promise.all(this._getSymRootChildren().map((child) => child.setMaterialsAndLoad(areasToMaterials, animationCoordinator)));
324
- });
325
- }
326
- _getSymRootChildren() {
327
- return this.getChildren()
328
- .filter(isSymRootNode)
329
- .filter((c) => !c.isDestroyed());
330
- }
331
- _getAdditionalProductNodes(includeDestroyed = false) {
332
- return this.getChildren()
333
- .filter(isProductNode)
334
- .filter((c) => includeDestroyed || !c.isDestroyed());
335
- }
336
- _getAnchorableNodes() {
337
- return this.getChildren()
338
- .filter(isCfgAnchorableNode)
339
- .filter((c) => !c.isDestroyed());
340
- }
341
- /**
342
- * Applies and thereby shows the geometry. Finally flushes scheduled for remove.
343
- * This function is recursively applied on additional products.
344
- */
345
- applyGeo(animationCoordinator) {
346
- return __awaiter(this, void 0, void 0, function* () {
347
- yield Promise.all(this._applyOnDescendantProductNodes((p) => (() => __awaiter(this, void 0, void 0, function* () {
348
- p._getSymRootChildren().forEach((child) => {
349
- child.applyGeo();
350
- });
351
- // Wait until materials have been loaded so that we don't get any blinking.
352
- // It might seem wrong that this is done after we apply, but the material
353
- // will not be ready unless it is applied. So we wait after applying.
354
- yield p._awaitAllMeshMaterialsReady();
355
- }))()));
356
- this.flushScheduledForRemove(animationCoordinator);
357
- });
358
- }
359
- /**
360
- * Applies and thereby shows the right materials.
361
- * This function is recursively applied on additional products.
362
- */
363
- applyMaterials() {
364
- return __awaiter(this, void 0, void 0, function* () {
365
- yield Promise.all(this._applyOnDescendantProductNodes((p) => (() => __awaiter(this, void 0, void 0, function* () {
366
- p._getSymRootChildren().forEach((child) => {
367
- child.applyMaterial();
368
- });
369
- // Wait until materials have been loaded so that we don't get any blinking.
370
- // It might seem wrong that this is done after we apply, but the material
371
- // will not be ready unless it is applied. So we wait after applying.
372
- yield p._awaitAllMeshMaterialsReady();
373
- }))()));
374
- });
375
- }
376
- setAnchorTarget(anchorTarget) {
377
- this._anchorTarget = anchorTarget;
378
- }
379
- refreshStretch() {
380
- const updated = updatedStretchedAnchorPointMatrix(this.anchorRef, this._anchorTarget, this._stretchedAnchorPointMatrix, true);
381
- if (updated !== undefined) {
382
- this._stretchedAnchorPointMatrix = updated;
383
- this._originalMatrixWithModelTransform = undefined; // Reset the matrix
384
- this.initTransform();
385
- }
386
- // anchoredToAnchors is sorted so that anchors always are before what
387
- // is anchored to them. That way we know that if we refreshStretch on
388
- // them first anchor-on-anchor will work correctly.
389
- const anchorableChildren = this._getAnchorableNodes().slice();
390
- for (const anchor of this._anchoredToAnchors.values()) {
391
- const i = anchorableChildren.indexOf(anchor);
392
- if (i === -1) {
393
- // As multiple anchors can anchor to the same anchor this will happen
394
- continue;
395
- }
396
- anchor.refreshStretch();
397
- anchorableChildren.splice(i, 1);
398
- }
399
- // Refresh for the un-anchored
400
- for (const child of anchorableChildren) {
401
- child.refreshStretch();
402
- }
403
- }
404
- get originalMatrix() {
405
- var _a;
406
- if (this._originalMatrixWithModelTransform === undefined) {
407
- let originalMatrix = (_a = this._modelMatrix) !== null && _a !== void 0 ? _a : Matrix.Identity();
408
- const stretchedAnchorPointMatrix = this._stretchedAnchorPointMatrix;
409
- if (stretchedAnchorPointMatrix !== undefined) {
410
- originalMatrix = originalMatrix.multiply(stretchedAnchorPointMatrix);
411
- }
412
- this._originalMatrixWithModelTransform = originalMatrix;
413
- }
414
- return this._originalMatrixWithModelTransform;
415
- }
416
- initTransform() {
417
- this.setPreTransformMatrix(this.originalMatrix);
418
- }
419
- _applyDebugSymRoots(symRootPromises) {
420
- return __awaiter(this, void 0, void 0, function* () {
421
- const allSymRoots = yield Promise.all(symRootPromises);
422
- allSymRoots.forEach((symRoot) => {
423
- if (symRoot === undefined) {
424
- return;
425
- }
426
- this.add(symRoot);
427
- });
428
- yield this.applyGeo();
429
- yield this._pushMaterialToSymRootChildrenAndLoad();
430
- yield this.applyMaterials();
431
- this._renderEnvironment.scheduleRerender();
432
- });
433
- }
434
- _addDebugMtrlApplication(debugMtrlApplication) {
435
- return __awaiter(this, void 0, void 0, function* () {
436
- this._debugMtrlApplications.push(debugMtrlApplication);
437
- yield this._aggregateMaterialsPushToChildrenAndLoad();
438
- this.applyMaterials();
439
- this._renderEnvironment.scheduleRerender();
440
- });
441
- }
442
- get boundingBox() {
443
- const bb = [...this._getSymRootChildren(), ...this._getAdditionalProductNodes()].reduce((a, m) => {
444
- a.expand(m.boundingBox);
445
- return a;
446
- }, new CfgBoundingBox());
447
- bb.applyMatrix(this.originalMatrix);
448
- return bb;
449
- }
450
- addInspectorProperties() {
451
- super.addInspectorProperties();
452
- this.addInspectableCustomProperty({
453
- label: "Log materialMappings",
454
- propertyName: "_inspectorLogMaterialMappings",
455
- type: InspectableType.Checkbox,
456
- });
457
- this.addInspectableCustomProperty({
458
- label: "Add material to mapping from File",
459
- propertyName: "_inspectorAddMaterialToMaterialMappingFromFile",
460
- type: InspectableType.Checkbox,
461
- });
462
- this.addInspectableCustomProperty({
463
- label: "Add material to mapping from Url",
464
- propertyName: "_inspectorAddMaterialToMaterialMappingFromUrl",
465
- type: InspectableType.Checkbox,
466
- });
467
- this.addInspectableCustomProperty({
468
- label: "Add CmSym from File",
469
- propertyName: "_inspectorAddCmSymFile",
470
- type: InspectableType.Checkbox,
471
- });
472
- this.addInspectableCustomProperty({
473
- label: "Add CmSym from Url",
474
- propertyName: "_inspectorAddCmSymUrl",
475
- type: InspectableType.Checkbox,
476
- });
477
- }
478
- get _inspectorLogMaterialMappings() {
479
- return this._areasToMaterials === undefined;
480
- }
481
- set _inspectorLogMaterialMappings(x) {
482
- if (this._areasToMaterials === undefined) {
483
- return;
484
- }
485
- logMaterialMappingToConsole(this._areasToMaterials);
486
- }
487
- get _inspectorAddMaterialToMaterialMappingFromFile() {
488
- return this._areasToMaterials === undefined;
489
- }
490
- set _inspectorAddMaterialToMaterialMappingFromFile(x) {
491
- if (this._areasToMaterials === undefined) {
492
- return;
493
- }
494
- const tag = window.prompt("Please provide a Tag for the mapping");
495
- if (tag === null || tag.trim().length === 0) {
496
- alert("You must provide a tag for the mapping");
497
- return;
498
- }
499
- const fileUpload = document.createElement("input");
500
- fileUpload.type = "file";
501
- fileUpload.style.display = "none";
502
- const body = document.getElementsByTagName("body")[0];
503
- body.appendChild(fileUpload);
504
- fileUpload.addEventListener("change", (event) => {
505
- (() => __awaiter(this, void 0, void 0, function* () {
506
- const files = fileUpload.files;
507
- if (files !== null) {
508
- const mtrlApplications = yield Promise.all(Array.from(files)
509
- .map(readFileToArrayBuffer)
510
- .map((bufferAndNamePromise) => __awaiter(this, void 0, void 0, function* () {
511
- const bufferAndName = yield bufferAndNamePromise;
512
- return CfgMtrlApplication.fromBufferForDebug([tag], bufferAndName.fileName, bufferAndName.buffer);
513
- })));
514
- mtrlApplications.forEach((mtrlApplication) => {
515
- this._addDebugMtrlApplication(mtrlApplication);
516
- });
517
- }
518
- body.removeChild(fileUpload);
519
- }))();
520
- });
521
- fileUpload.click();
522
- }
523
- get _inspectorAddMaterialToMaterialMappingFromUrl() {
524
- return this._areasToMaterials === undefined;
525
- }
526
- set _inspectorAddMaterialToMaterialMappingFromUrl(x) {
527
- if (this._areasToMaterials === undefined) {
528
- return;
529
- }
530
- const tag = window.prompt("Please provide a Tag for the mapping");
531
- if (tag === null || tag.trim().length === 0) {
532
- alert("You must provide a tag for the mapping");
533
- return;
534
- }
535
- const url = window.prompt("Please provide a material-url");
536
- if (url === null || url.trim().length === 0) {
537
- alert("You must provide an URL to a material-file");
538
- return;
539
- }
540
- const mtrlApplication = CfgMtrlApplication.fromUrlForDebug([tag], url);
541
- this._addDebugMtrlApplication(mtrlApplication);
542
- }
543
- get _inspectorAddCmSymFile() {
544
- return false;
545
- }
546
- set _inspectorAddCmSymFile(x) {
547
- const fileUpload = document.createElement("input");
548
- fileUpload.type = "file";
549
- fileUpload.style.display = "none";
550
- const body = document.getElementsByTagName("body")[0];
551
- body.appendChild(fileUpload);
552
- const logger = this.logger;
553
- const renderEnvironment = this._renderEnvironment;
554
- fileUpload.addEventListener("change", (event) => {
555
- const files = fileUpload.files;
556
- if (files !== null) {
557
- const symRootPromises = Array.from(files).map((file) => {
558
- return CfgSymRootNode.makeCfgSymRootFromFile(logger, true, renderEnvironment, this, file);
559
- });
560
- this._applyDebugSymRoots(symRootPromises);
561
- }
562
- body.removeChild(fileUpload);
563
- });
564
- fileUpload.click();
565
- }
566
- get _inspectorAddCmSymUrl() {
567
- return false;
568
- }
569
- set _inspectorAddCmSymUrl(x) {
570
- const url = window.prompt("Please provide a CmSym-url");
571
- if (url === null || url.trim().length === 0) {
572
- alert("You must provide an URL to a CmSym-file");
573
- return;
574
- }
575
- const symRootNode = CfgSymRootNode.makeCfgSymRootFromUrl(this.logger, true, this._renderEnvironment, this, url, undefined, undefined);
576
- this._applyDebugSymRoots([symRootNode]);
577
- }
578
- }
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { Matrix } from "@babylonjs/core/Maths/math.vector.js";
11
+ import { InspectableType } from "@babylonjs/core/Misc/iInspectable.js";
12
+ import { aggregateAllMaterialApplications, CfgMtrlApplication, CfgMtrlApplicationSource, logMaterialMappingToConsole, } from "@configura/web-api";
13
+ import { LogObservable, readFileToArrayBuffer } from "@configura/web-utilities";
14
+ import { CfgAnchorRef, getAnchorTargetPriorityComparer, updatedStretchedAnchorPointMatrix, } from "../utilities/anchor/anchor.js";
15
+ import { makeAnchoredToAnchorMap } from "../utilities/anchor/anchorMap.js";
16
+ import { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
17
+ import { modelTransformToSymTransform, symTransformToMatrix } from "../utilities/utilities3D.js";
18
+ import { isSameRootNodeSource } from "../utilities/utilitiesSymRootIdentifier.js";
19
+ import { CfgSymRootNode, isSymRootNode } from "./CfgSymRootNode.js";
20
+ import { CfgTransformNode } from "./CfgTransformNode.js";
21
+ export function isProductNode(value) {
22
+ return value instanceof CfgProductNode;
23
+ }
24
+ export function isCfgSymRootNode(value) {
25
+ return value instanceof CfgSymRootNode;
26
+ }
27
+ export function isCfgAnchorableNode(value) {
28
+ return isProductNode(value) || isCfgSymRootNode(value);
29
+ }
30
+ export class CfgProductNode extends CfgTransformNode {
31
+ constructor(renderEnvironment, _product) {
32
+ super(renderEnvironment, `(Product) ${_product.sku}`);
33
+ this._product = _product;
34
+ this.logger = new LogObservable();
35
+ this._destroyed = false;
36
+ this._applicationAreas = [];
37
+ this._mtrlApplications = [];
38
+ this._debugMtrlApplications = [];
39
+ this._scheduledForRemoval = [];
40
+ this._anchoredToAnchors = new Map();
41
+ this._symRootLoadings = [];
42
+ /**
43
+ * The passed function is recursively applied on every descendant CfgProductNode in the tree.
44
+ * This node is included. Destroyed products are not included.
45
+ */
46
+ this._applyOnDescendantProductNodes = (fn) => {
47
+ const result = [];
48
+ result.push(fn(this));
49
+ for (const additionalProduct of this._getAdditionalProductNodes()) {
50
+ result.push(...additionalProduct._applyOnDescendantProductNodes(fn));
51
+ }
52
+ return result;
53
+ };
54
+ this.key = _product.key;
55
+ // Useful debug tool:
56
+ if (false) {
57
+ window.product = this;
58
+ console.log(`Use "window.product" to access "${this.key}" product node.`);
59
+ }
60
+ this.anchorRef = CfgAnchorRef.make(this._product._internal.anchor);
61
+ const modelTransform = _product.transform;
62
+ if (modelTransform !== undefined) {
63
+ const modelSymTransform = modelTransformToSymTransform(modelTransform);
64
+ this._modelMatrix = symTransformToMatrix(modelSymTransform.transform());
65
+ }
66
+ this.initTransform();
67
+ }
68
+ static make(renderEnvironment, product) {
69
+ return new this(renderEnvironment, product);
70
+ }
71
+ get cfgClassName() {
72
+ return "CfgProductNode";
73
+ }
74
+ destroy() {
75
+ this._destroyed = true;
76
+ this._symRootLoadings.length = 0;
77
+ for (const symRoot of this._getSymRootChildren().filter((c) => !c.isForDebug)) {
78
+ this.scheduleForRemoval(symRoot);
79
+ }
80
+ }
81
+ get product() {
82
+ return this._product;
83
+ }
84
+ /**
85
+ * We want to be able to animate nodes that are on the way out.
86
+ * So we do not immediately remove them from the tree.
87
+ */
88
+ scheduleForRemoval(node) {
89
+ node.destroy();
90
+ this._scheduledForRemoval.push(node);
91
+ }
92
+ isDestroyed() {
93
+ return this._destroyed;
94
+ }
95
+ /**
96
+ * This function will apply either of tree passed functions on the additional products/ in the
97
+ * passed CfgProduct and the additional products in the CfgProductNode.
98
+ * It is not applied recursively.
99
+ */
100
+ _syncAdditionalProductNodes(parentProduct, fn) {
101
+ const { both, productNodeButNoProduct, productButNoProductNode } = fn;
102
+ const additionalProducts = parentProduct.additionalProducts.filter((c) => c.selected);
103
+ const additionalProductNodes = this._getAdditionalProductNodes();
104
+ for (const additionalProductNode of additionalProductNodes) {
105
+ const index = additionalProducts.findIndex((p) => additionalProductNode.product.isBackedBySame(p));
106
+ if (index === -1) {
107
+ if (productNodeButNoProduct === undefined) {
108
+ throw Error(`ProductNode ${additionalProductNode.key} exist, but no data for it. There is no handler for this.`);
109
+ }
110
+ productNodeButNoProduct(additionalProductNode);
111
+ }
112
+ else {
113
+ const additionalProduct = additionalProducts.splice(index, 1)[0];
114
+ if (both === undefined) {
115
+ throw Error(`ProductNode ${additionalProductNode.key} and data ${additionalProduct.key} exists. There is no handler for this.`);
116
+ }
117
+ both(additionalProduct, additionalProductNode);
118
+ }
119
+ }
120
+ for (const additionalProduct of additionalProducts) {
121
+ if (productButNoProductNode === undefined) {
122
+ throw Error(`Data ${additionalProduct.key} exists, but no ProductNode for it. There is no handler for this.`);
123
+ }
124
+ productButNoProductNode(additionalProduct);
125
+ }
126
+ }
127
+ /**
128
+ * Application areas are essentially catalogue level material mappings.
129
+ * This function is recursively applied on additional products.
130
+ */
131
+ setApplicationAreas(applicationAreas) {
132
+ this._applyOnDescendantProductNodes((p) => {
133
+ p._applicationAreas = applicationAreas;
134
+ });
135
+ }
136
+ /**
137
+ * Start loading the geometry, but do not yet show it.
138
+ * This function is recursively applied on additional products.
139
+ */
140
+ loadGeo(coordinatorWithMeta) {
141
+ return __awaiter(this, void 0, void 0, function* () {
142
+ const product = this._product;
143
+ const rootNodeSources = product._internal.rootNodeSources || [];
144
+ const updateRootNodeSources = rootNodeSources.slice();
145
+ const allSymRootLoadings = this._symRootLoadings;
146
+ let i = allSymRootLoadings.length;
147
+ while (i--) {
148
+ const symRootLoading = allSymRootLoadings[i];
149
+ const updateIndex = updateRootNodeSources.findIndex((rootNodeSource) => isSameRootNodeSource(rootNodeSource, symRootLoading.rootNodeSource));
150
+ if (updateIndex === -1) {
151
+ // We remove the inProgress, because the thing which is in progress will not be
152
+ // wanted when it arrives.
153
+ allSymRootLoadings.splice(i, 1);
154
+ }
155
+ }
156
+ for (const symRootChild of this._getSymRootChildren().filter((c) => !c.isForDebug)) {
157
+ const updateIndex = updateRootNodeSources.findIndex((m) => symRootChild.isSameIdentifierTransformAndAnchor(m));
158
+ if (updateIndex === -1) {
159
+ // Not found, remove
160
+ this.scheduleForRemoval(symRootChild);
161
+ }
162
+ else {
163
+ // Found, no need to change anything
164
+ updateRootNodeSources.splice(updateIndex, 1);
165
+ }
166
+ }
167
+ const batchSymRootLoadings = updateRootNodeSources.map((rootNodeSource) => {
168
+ let symRootLoading = allSymRootLoadings.find((s) => isSameRootNodeSource(rootNodeSource, s.rootNodeSource));
169
+ if (symRootLoading === undefined) {
170
+ symRootLoading = {
171
+ rootNodeSource,
172
+ rootNodePromise: CfgSymRootNode.makeCfgSymRootFromRootNodeSource(this.logger, false, this._renderEnvironment, this, rootNodeSource),
173
+ };
174
+ allSymRootLoadings.push(symRootLoading);
175
+ }
176
+ return symRootLoading;
177
+ });
178
+ yield Promise.all([
179
+ ...batchSymRootLoadings.map((s) => s.rootNodePromise),
180
+ this._loadAdditionalProducts(coordinatorWithMeta),
181
+ ]);
182
+ const addedSymRoots = (yield Promise.all(batchSymRootLoadings.map((s) => s.rootNodePromise)))
183
+ .filter((symRoot) => symRoot !== undefined)
184
+ .filter((symRoot) => {
185
+ const loadInProgressIndex = allSymRootLoadings.findIndex((symRootLoadInProgress) => symRoot.isSameIdentifierTransformAndAnchor(symRootLoadInProgress.rootNodeSource));
186
+ if (loadInProgressIndex === -1) {
187
+ // This node no longer shall be added
188
+ return false;
189
+ }
190
+ // We'll add this, so it moves from "loading" to being a proper child
191
+ allSymRootLoadings.splice(loadInProgressIndex, 1);
192
+ this.add(symRoot);
193
+ return true;
194
+ });
195
+ // Updated symRootChildren
196
+ const anchorableChildren = this._getAnchorableNodes();
197
+ // Make a map of who is anchored to who
198
+ const anchoredToAnchors = makeAnchoredToAnchorMap(anchorableChildren, getAnchorTargetPriorityComparer(this.product._internal.measureDefinitions));
199
+ this._anchoredToAnchors = anchoredToAnchors;
200
+ for (const child of anchorableChildren) {
201
+ child.setAnchorTarget(anchoredToAnchors.get(child));
202
+ }
203
+ this.refreshStretch();
204
+ for (const symRoot of addedSymRoots) {
205
+ if (coordinatorWithMeta === undefined) {
206
+ continue;
207
+ }
208
+ const c = coordinatorWithMeta.coordinator;
209
+ yield c.prepareForEnter.bind(c)(symRoot, coordinatorWithMeta.isNewProduct);
210
+ }
211
+ });
212
+ }
213
+ _loadAdditionalProducts(coordinatorWithMeta) {
214
+ return __awaiter(this, void 0, void 0, function* () {
215
+ const additionalProductLoadPromises = [];
216
+ this._syncAdditionalProductNodes(this._product, {
217
+ productNodeButNoProduct: (additionalProductNode) => {
218
+ this.scheduleForRemoval(additionalProductNode);
219
+ },
220
+ productButNoProductNode: (additionalProduct) => {
221
+ const additionalProductNode = CfgProductNode.make(this._renderEnvironment, additionalProduct);
222
+ this.add(additionalProductNode);
223
+ additionalProductLoadPromises.push(additionalProductNode.loadGeo(coordinatorWithMeta));
224
+ },
225
+ both: (_additionalProduct, additionalProductNode) => {
226
+ additionalProductLoadPromises.push(additionalProductNode.loadGeo(coordinatorWithMeta));
227
+ },
228
+ });
229
+ yield Promise.all(additionalProductLoadPromises);
230
+ });
231
+ }
232
+ /**
233
+ * Run any animations and then permanently removes the nodes from the tree
234
+ * This function is recursively applied on additional products.
235
+ */
236
+ flushScheduledForRemove(animationCoordinator) {
237
+ return __awaiter(this, void 0, void 0, function* () {
238
+ const thisBatch = this._scheduledForRemoval.slice();
239
+ this._scheduledForRemoval.length = 0;
240
+ yield Promise.all(this._getAdditionalProductNodes(true).map((additionalProductNode) => additionalProductNode.flushScheduledForRemove(animationCoordinator)));
241
+ yield Promise.all(thisBatch.map((node) => (() => __awaiter(this, void 0, void 0, function* () {
242
+ if (node instanceof CfgSymRootNode) {
243
+ if (animationCoordinator !== undefined) {
244
+ const c = animationCoordinator.coordinator;
245
+ yield c.prepareForExit.bind(c)(node);
246
+ }
247
+ }
248
+ this.remove(true, node);
249
+ }))()));
250
+ });
251
+ }
252
+ /**
253
+ * Are all materials currently needed loaded and ready to be applied?
254
+ * This function does not take additional products into account.
255
+ */
256
+ _isAllMeshMaterialsReady() {
257
+ return this._getSymRootChildren().reduce((a, c) => a && c.isAllMeshMaterialsReady(), true);
258
+ }
259
+ /**
260
+ * Resolves when all materials currently needed have been loaded and are ready to be applied.
261
+ * This function does not take additional products into account.
262
+ */
263
+ _awaitAllMeshMaterialsReady() {
264
+ return __awaiter(this, void 0, void 0, function* () {
265
+ return new Promise((resolve, reject) => {
266
+ let maxTries = 60 * 60; // Assuming 60 fps this gives a minute, which is absurdly long
267
+ const frame = () => {
268
+ if (this._isAllMeshMaterialsReady()) {
269
+ resolve();
270
+ return;
271
+ }
272
+ if (maxTries === 0) {
273
+ reject("Materials not ready in time");
274
+ return;
275
+ }
276
+ window.requestAnimationFrame(frame);
277
+ maxTries--;
278
+ };
279
+ frame();
280
+ });
281
+ });
282
+ }
283
+ /**
284
+ * Loads the materials needed.
285
+ * This function is recursively applied on additional products.
286
+ */
287
+ loadMaterials(animationCoordinator) {
288
+ return __awaiter(this, void 0, void 0, function* () {
289
+ const product = this._product;
290
+ const productMtrlApplications = (product._internal.mtrlApplications || []).map((m) => CfgMtrlApplication.fromMtrlLikeApplication(CfgMtrlApplicationSource.Product, m));
291
+ this._mtrlApplications = productMtrlApplications;
292
+ this._configuration = product.configuration;
293
+ yield Promise.all([
294
+ this._aggregateMaterialsPushToChildrenAndLoad(animationCoordinator),
295
+ ...this._getAdditionalProductNodes().map((additionalProductNode) => additionalProductNode.loadMaterials(animationCoordinator)),
296
+ ]);
297
+ });
298
+ }
299
+ /**
300
+ * Update the tag (area) to material mapping and gives them to sym children
301
+ * This function does not take additional products into account.
302
+ */
303
+ _aggregateMaterialsPushToChildrenAndLoad(animationCoordinator) {
304
+ return __awaiter(this, void 0, void 0, function* () {
305
+ if (this._applicationAreas === undefined || this._configuration === undefined) {
306
+ return;
307
+ }
308
+ const areasToMaterials = aggregateAllMaterialApplications(this._applicationAreas, this._mtrlApplications, this._configuration, this._debugMtrlApplications);
309
+ this._areasToMaterials = areasToMaterials;
310
+ yield this._pushMaterialToSymRootChildrenAndLoad(animationCoordinator);
311
+ });
312
+ }
313
+ /**
314
+ * Starts loading the materials on the sym children (but does not apply)
315
+ * This function does not take additional products into account.
316
+ */
317
+ _pushMaterialToSymRootChildrenAndLoad(animationCoordinator) {
318
+ return __awaiter(this, void 0, void 0, function* () {
319
+ const areasToMaterials = this._areasToMaterials;
320
+ if (areasToMaterials === undefined) {
321
+ return;
322
+ }
323
+ yield Promise.all(this._getSymRootChildren().map((child) => child.setMaterialsAndLoad(areasToMaterials, animationCoordinator)));
324
+ });
325
+ }
326
+ _getSymRootChildren() {
327
+ return this.getChildren()
328
+ .filter(isSymRootNode)
329
+ .filter((c) => !c.isDestroyed());
330
+ }
331
+ _getAdditionalProductNodes(includeDestroyed = false) {
332
+ return this.getChildren()
333
+ .filter(isProductNode)
334
+ .filter((c) => includeDestroyed || !c.isDestroyed());
335
+ }
336
+ _getAnchorableNodes() {
337
+ return this.getChildren()
338
+ .filter(isCfgAnchorableNode)
339
+ .filter((c) => !c.isDestroyed());
340
+ }
341
+ /**
342
+ * Applies and thereby shows the geometry. Finally flushes scheduled for remove.
343
+ * This function is recursively applied on additional products.
344
+ */
345
+ applyGeo(animationCoordinator) {
346
+ return __awaiter(this, void 0, void 0, function* () {
347
+ yield Promise.all(this._applyOnDescendantProductNodes((p) => (() => __awaiter(this, void 0, void 0, function* () {
348
+ p._getSymRootChildren().forEach((child) => {
349
+ child.applyGeo();
350
+ });
351
+ // Wait until materials have been loaded so that we don't get any blinking.
352
+ // It might seem wrong that this is done after we apply, but the material
353
+ // will not be ready unless it is applied. So we wait after applying.
354
+ yield p._awaitAllMeshMaterialsReady();
355
+ }))()));
356
+ this.flushScheduledForRemove(animationCoordinator);
357
+ });
358
+ }
359
+ /**
360
+ * Applies and thereby shows the right materials.
361
+ * This function is recursively applied on additional products.
362
+ */
363
+ applyMaterials() {
364
+ return __awaiter(this, void 0, void 0, function* () {
365
+ yield Promise.all(this._applyOnDescendantProductNodes((p) => (() => __awaiter(this, void 0, void 0, function* () {
366
+ p._getSymRootChildren().forEach((child) => {
367
+ child.applyMaterial();
368
+ });
369
+ // Wait until materials have been loaded so that we don't get any blinking.
370
+ // It might seem wrong that this is done after we apply, but the material
371
+ // will not be ready unless it is applied. So we wait after applying.
372
+ yield p._awaitAllMeshMaterialsReady();
373
+ }))()));
374
+ });
375
+ }
376
+ setAnchorTarget(anchorTarget) {
377
+ this._anchorTarget = anchorTarget;
378
+ }
379
+ refreshStretch() {
380
+ const updated = updatedStretchedAnchorPointMatrix(this.anchorRef, this._anchorTarget, this._stretchedAnchorPointMatrix, true);
381
+ if (updated !== undefined) {
382
+ this._stretchedAnchorPointMatrix = updated;
383
+ this._originalMatrixWithModelTransform = undefined; // Reset the matrix
384
+ this.initTransform();
385
+ }
386
+ // anchoredToAnchors is sorted so that anchors always are before what
387
+ // is anchored to them. That way we know that if we refreshStretch on
388
+ // them first anchor-on-anchor will work correctly.
389
+ const anchorableChildren = this._getAnchorableNodes().slice();
390
+ for (const anchor of this._anchoredToAnchors.values()) {
391
+ const i = anchorableChildren.indexOf(anchor);
392
+ if (i === -1) {
393
+ // As multiple anchors can anchor to the same anchor this will happen
394
+ continue;
395
+ }
396
+ anchor.refreshStretch();
397
+ anchorableChildren.splice(i, 1);
398
+ }
399
+ // Refresh for the un-anchored
400
+ for (const child of anchorableChildren) {
401
+ child.refreshStretch();
402
+ }
403
+ }
404
+ get originalMatrix() {
405
+ var _a;
406
+ if (this._originalMatrixWithModelTransform === undefined) {
407
+ let originalMatrix = (_a = this._modelMatrix) !== null && _a !== void 0 ? _a : Matrix.Identity();
408
+ const stretchedAnchorPointMatrix = this._stretchedAnchorPointMatrix;
409
+ if (stretchedAnchorPointMatrix !== undefined) {
410
+ originalMatrix = originalMatrix.multiply(stretchedAnchorPointMatrix);
411
+ }
412
+ this._originalMatrixWithModelTransform = originalMatrix;
413
+ }
414
+ return this._originalMatrixWithModelTransform;
415
+ }
416
+ initTransform() {
417
+ this.setPreTransformMatrix(this.originalMatrix);
418
+ }
419
+ _applyDebugSymRoots(symRootPromises) {
420
+ return __awaiter(this, void 0, void 0, function* () {
421
+ const allSymRoots = yield Promise.all(symRootPromises);
422
+ allSymRoots.forEach((symRoot) => {
423
+ if (symRoot === undefined) {
424
+ return;
425
+ }
426
+ this.add(symRoot);
427
+ });
428
+ yield this.applyGeo();
429
+ yield this._pushMaterialToSymRootChildrenAndLoad();
430
+ yield this.applyMaterials();
431
+ this._renderEnvironment.scheduleRerender();
432
+ });
433
+ }
434
+ _addDebugMtrlApplication(debugMtrlApplication) {
435
+ return __awaiter(this, void 0, void 0, function* () {
436
+ this._debugMtrlApplications.push(debugMtrlApplication);
437
+ yield this._aggregateMaterialsPushToChildrenAndLoad();
438
+ this.applyMaterials();
439
+ this._renderEnvironment.scheduleRerender();
440
+ });
441
+ }
442
+ get boundingBox() {
443
+ const bb = [...this._getSymRootChildren(), ...this._getAdditionalProductNodes()].reduce((a, m) => {
444
+ a.expand(m.boundingBox);
445
+ return a;
446
+ }, new CfgBoundingBox());
447
+ bb.applyMatrix(this.originalMatrix);
448
+ return bb;
449
+ }
450
+ addInspectorProperties() {
451
+ super.addInspectorProperties();
452
+ this.addInspectableCustomProperty({
453
+ label: "Log materialMappings",
454
+ propertyName: "_inspectorLogMaterialMappings",
455
+ type: InspectableType.Checkbox,
456
+ });
457
+ this.addInspectableCustomProperty({
458
+ label: "Add material to mapping from File",
459
+ propertyName: "_inspectorAddMaterialToMaterialMappingFromFile",
460
+ type: InspectableType.Checkbox,
461
+ });
462
+ this.addInspectableCustomProperty({
463
+ label: "Add material to mapping from Url",
464
+ propertyName: "_inspectorAddMaterialToMaterialMappingFromUrl",
465
+ type: InspectableType.Checkbox,
466
+ });
467
+ this.addInspectableCustomProperty({
468
+ label: "Add CmSym from File",
469
+ propertyName: "_inspectorAddCmSymFile",
470
+ type: InspectableType.Checkbox,
471
+ });
472
+ this.addInspectableCustomProperty({
473
+ label: "Add CmSym from Url",
474
+ propertyName: "_inspectorAddCmSymUrl",
475
+ type: InspectableType.Checkbox,
476
+ });
477
+ }
478
+ get _inspectorLogMaterialMappings() {
479
+ return this._areasToMaterials === undefined;
480
+ }
481
+ set _inspectorLogMaterialMappings(x) {
482
+ if (this._areasToMaterials === undefined) {
483
+ return;
484
+ }
485
+ logMaterialMappingToConsole(this._areasToMaterials);
486
+ }
487
+ get _inspectorAddMaterialToMaterialMappingFromFile() {
488
+ return this._areasToMaterials === undefined;
489
+ }
490
+ set _inspectorAddMaterialToMaterialMappingFromFile(x) {
491
+ if (this._areasToMaterials === undefined) {
492
+ return;
493
+ }
494
+ const tag = window.prompt("Please provide a Tag for the mapping");
495
+ if (tag === null || tag.trim().length === 0) {
496
+ alert("You must provide a tag for the mapping");
497
+ return;
498
+ }
499
+ const fileUpload = document.createElement("input");
500
+ fileUpload.type = "file";
501
+ fileUpload.style.display = "none";
502
+ const body = document.getElementsByTagName("body")[0];
503
+ body.appendChild(fileUpload);
504
+ fileUpload.addEventListener("change", (event) => {
505
+ (() => __awaiter(this, void 0, void 0, function* () {
506
+ const files = fileUpload.files;
507
+ if (files !== null) {
508
+ const mtrlApplications = yield Promise.all(Array.from(files)
509
+ .map(readFileToArrayBuffer)
510
+ .map((bufferAndNamePromise) => __awaiter(this, void 0, void 0, function* () {
511
+ const bufferAndName = yield bufferAndNamePromise;
512
+ return CfgMtrlApplication.fromBufferForDebug([tag], bufferAndName.fileName, bufferAndName.buffer);
513
+ })));
514
+ mtrlApplications.forEach((mtrlApplication) => {
515
+ this._addDebugMtrlApplication(mtrlApplication);
516
+ });
517
+ }
518
+ body.removeChild(fileUpload);
519
+ }))();
520
+ });
521
+ fileUpload.click();
522
+ }
523
+ get _inspectorAddMaterialToMaterialMappingFromUrl() {
524
+ return this._areasToMaterials === undefined;
525
+ }
526
+ set _inspectorAddMaterialToMaterialMappingFromUrl(x) {
527
+ if (this._areasToMaterials === undefined) {
528
+ return;
529
+ }
530
+ const tag = window.prompt("Please provide a Tag for the mapping");
531
+ if (tag === null || tag.trim().length === 0) {
532
+ alert("You must provide a tag for the mapping");
533
+ return;
534
+ }
535
+ const url = window.prompt("Please provide a material-url");
536
+ if (url === null || url.trim().length === 0) {
537
+ alert("You must provide an URL to a material-file");
538
+ return;
539
+ }
540
+ const mtrlApplication = CfgMtrlApplication.fromUrlForDebug([tag], url);
541
+ this._addDebugMtrlApplication(mtrlApplication);
542
+ }
543
+ get _inspectorAddCmSymFile() {
544
+ return false;
545
+ }
546
+ set _inspectorAddCmSymFile(x) {
547
+ const fileUpload = document.createElement("input");
548
+ fileUpload.type = "file";
549
+ fileUpload.style.display = "none";
550
+ const body = document.getElementsByTagName("body")[0];
551
+ body.appendChild(fileUpload);
552
+ const logger = this.logger;
553
+ const renderEnvironment = this._renderEnvironment;
554
+ fileUpload.addEventListener("change", (event) => {
555
+ const files = fileUpload.files;
556
+ if (files !== null) {
557
+ const symRootPromises = Array.from(files).map((file) => {
558
+ return CfgSymRootNode.makeCfgSymRootFromFile(logger, true, renderEnvironment, this, file);
559
+ });
560
+ this._applyDebugSymRoots(symRootPromises);
561
+ }
562
+ body.removeChild(fileUpload);
563
+ });
564
+ fileUpload.click();
565
+ }
566
+ get _inspectorAddCmSymUrl() {
567
+ return false;
568
+ }
569
+ set _inspectorAddCmSymUrl(x) {
570
+ const url = window.prompt("Please provide a CmSym-url");
571
+ if (url === null || url.trim().length === 0) {
572
+ alert("You must provide an URL to a CmSym-file");
573
+ return;
574
+ }
575
+ const symRootNode = CfgSymRootNode.makeCfgSymRootFromUrl(this.logger, true, this._renderEnvironment, this, url, undefined, undefined);
576
+ this._applyDebugSymRoots([symRootNode]);
577
+ }
578
+ }