@configura/babylon-view 1.3.0-alpha.3 → 1.3.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 -10
  42. package/dist/camera/CfgArcRotateCameraPointersInput.js +264 -262
  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 -12
  52. package/dist/geometry/CfgGeometry.js +146 -117
  53. package/dist/geometry/CfgMesh.d.ts +10 -7
  54. package/dist/geometry/CfgMesh.js +38 -8
  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 +16 -0
  58. package/dist/geometry/stretch/CfgMorphTarget.js +65 -0
  59. package/dist/geometry/stretch/CfgStretchData.d.ts +115 -0
  60. package/dist/geometry/stretch/CfgStretchData.js +340 -0
  61. package/dist/geometry/stretch/CfgStretchMorphGeometry.d.ts +17 -0
  62. package/dist/geometry/stretch/CfgStretchMorphGeometry.js +95 -0
  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 -53
  76. package/dist/material/CfgMaterial.js +482 -454
  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 -304
  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 -48
  86. package/dist/nodes/CfgDeferredMeshNode.js +377 -347
  87. package/dist/nodes/CfgProductNode.d.ts +126 -61
  88. package/dist/nodes/CfgProductNode.js +578 -486
  89. package/dist/nodes/CfgSymNode.d.ts +50 -42
  90. package/dist/nodes/CfgSymNode.js +249 -216
  91. package/dist/nodes/CfgSymRootNode.d.ts +45 -33
  92. package/dist/nodes/CfgSymRootNode.js +220 -175
  93. package/dist/nodes/CfgTransformNode.d.ts +33 -29
  94. package/dist/nodes/CfgTransformNode.js +83 -81
  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 -16
  98. package/dist/utilities/CfgBoundingBox.js +81 -64
  99. package/dist/utilities/anchor/anchor.d.ts +52 -0
  100. package/dist/utilities/anchor/anchor.js +136 -0
  101. package/dist/utilities/anchor/anchorMap.d.ts +21 -0
  102. package/dist/utilities/anchor/anchorMap.js +111 -0
  103. package/dist/utilities/utilities3D.d.ts +70 -26
  104. package/dist/utilities/utilities3D.js +265 -187
  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 -5
  110. package/dist/utilities/utilitiesSymRootIdentifier.js +26 -20
  111. package/dist/view/BaseView.d.ts +78 -70
  112. package/dist/view/BaseView.js +297 -291
  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 -38
  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 +49 -42
  122. package/dist/view/SingleProductView.js +206 -205
  123. package/dist/view/SingleProductViewConfiguration.d.ts +32 -32
  124. package/dist/view/SingleProductViewConfiguration.js +19 -19
  125. package/package.json +5 -5
@@ -1,486 +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 { CfgBoundingBox } from "../utilities/CfgBoundingBox.js";
15
- import { modelTransformToSymTransform, symTransformToMatrix } from "../utilities/utilities3D.js";
16
- import { isSameRootNodeSource } from "../utilities/utilitiesSymRootIdentifier.js";
17
- import { CfgSymRootNode, isSymRootNode } from "./CfgSymRootNode.js";
18
- import { CfgTransformNode } from "./CfgTransformNode.js";
19
- export function isProductNode(value) {
20
- return value instanceof CfgProductNode;
21
- }
22
- export function isCfgSymRootNode(value) {
23
- return value instanceof CfgSymRootNode;
24
- }
25
- export class CfgProductNode extends CfgTransformNode {
26
- constructor(renderEnvironment, _product) {
27
- super(renderEnvironment, `(Product) ${_product.sku}`);
28
- this._product = _product;
29
- this.logger = new LogObservable();
30
- this._destroyed = false;
31
- this._applicationAreas = [];
32
- this._mtrlApplications = [];
33
- this._debugMtrlApplications = [];
34
- this._scheduledForRemoval = [];
35
- this._symRootLoadings = [];
36
- /// The passed function is recursively applied on every descendant CfgProductNode in
37
- /// the tree. This node is included. Destroyed products are not included.
38
- this._applyOnDescendantProductNodes = (fn) => {
39
- const result = [];
40
- result.push(fn(this));
41
- for (const additionalProduct of this._getAdditionalProductNodes()) {
42
- result.push(...additionalProduct._applyOnDescendantProductNodes(fn));
43
- }
44
- return result;
45
- };
46
- this.key = _product.key;
47
- const modelTransform = _product.transform;
48
- let modelMatrix = Matrix.Identity();
49
- if (modelTransform !== undefined) {
50
- const modelSymTransform = modelTransformToSymTransform(modelTransform);
51
- modelMatrix = symTransformToMatrix(modelSymTransform.transform());
52
- }
53
- this.originalMatrix = modelMatrix;
54
- this.setPreTransformMatrix(modelMatrix);
55
- }
56
- static make(renderEnvironment, product) {
57
- return new CfgProductNode(renderEnvironment, product);
58
- }
59
- get cfgClassName() {
60
- return "CfgProductNode";
61
- }
62
- destroy() {
63
- this._destroyed = true;
64
- this._symRootLoadings.length = 0;
65
- for (const symRoot of this._getSymRootChildren().filter((c) => !c.isForDebug)) {
66
- this.scheduleForRemoval(symRoot);
67
- }
68
- }
69
- get product() {
70
- return this._product;
71
- }
72
- /// We want to be able to animate nodes that are on the way out.
73
- /// So we do not immediately remove them from the tree
74
- scheduleForRemoval(node) {
75
- node.destroy();
76
- this._scheduledForRemoval.push(node);
77
- }
78
- isDestroyed() {
79
- return this._destroyed;
80
- }
81
- /// This function will apply either of tree passed functions on the additional products
82
- /// in the passed CfgProduct and the additional products in the CfgProductNode.
83
- /// It is not applied recursively.
84
- _syncAdditionalProductNodes(parentProduct, fn) {
85
- const { both, productNodeButNoProduct, productButNoProductNode } = fn;
86
- const additionalProducts = parentProduct.additionalProducts.filter((c) => c.selected);
87
- const additionalProductNodes = this._getAdditionalProductNodes();
88
- for (const additionalProductNode of additionalProductNodes) {
89
- const index = additionalProducts.findIndex((p) => additionalProductNode.product.isBackedBySame(p));
90
- if (index === -1) {
91
- if (productNodeButNoProduct === undefined) {
92
- throw Error(`ProductNode ${additionalProductNode.key} exist, but no data for it. There is no handler for this.`);
93
- }
94
- productNodeButNoProduct(additionalProductNode);
95
- }
96
- else {
97
- const additionalProduct = additionalProducts.splice(index, 1)[0];
98
- if (both === undefined) {
99
- throw Error(`ProductNode ${additionalProductNode.key} and data ${additionalProduct.key} exists. There is no handler for this.`);
100
- }
101
- both(additionalProduct, additionalProductNode);
102
- }
103
- }
104
- for (const additionalProduct of additionalProducts) {
105
- if (productButNoProductNode === undefined) {
106
- throw Error(`Data ${additionalProduct.key} exists, but no ProductNode for it. There is no handler for this.`);
107
- }
108
- productButNoProductNode(additionalProduct);
109
- }
110
- }
111
- /// Application areas are essentially catalogue level material mappings
112
- /// This function is recursively applied on additional products.
113
- setApplicationAreas(applicationAreas) {
114
- this._applyOnDescendantProductNodes((p) => {
115
- p._applicationAreas = applicationAreas;
116
- });
117
- }
118
- /// Start loading the geometry, but do not yet show it
119
- /// This function is recursively applied on additional products.
120
- loadGeo(coordinatorWithMeta) {
121
- return __awaiter(this, void 0, void 0, function* () {
122
- const product = this._product;
123
- const rootNodeSources = product._internal.rootNodeSources || [];
124
- const updateRootNodeSources = rootNodeSources.slice();
125
- const allSymRootLoadings = this._symRootLoadings;
126
- let i = allSymRootLoadings.length;
127
- while (i--) {
128
- const symRootLoading = allSymRootLoadings[i];
129
- const updateIndex = updateRootNodeSources.findIndex((rootNodeSource) => isSameRootNodeSource(rootNodeSource, symRootLoading.rootNodeSource));
130
- if (updateIndex === -1) {
131
- // We remove the inProgress, because the thing which is in progress will not be
132
- // wanted when it arrives.
133
- allSymRootLoadings.splice(i, 1);
134
- }
135
- }
136
- for (const symRootChild of this._getSymRootChildren().filter((c) => !c.isForDebug)) {
137
- const updateIndex = updateRootNodeSources.findIndex((m) => symRootChild.isSameIdentifierAndTransform(m));
138
- if (updateIndex === -1) {
139
- // Not found, remove
140
- this.scheduleForRemoval(symRootChild);
141
- }
142
- else {
143
- // Found, no need to change anything
144
- updateRootNodeSources.splice(updateIndex, 1);
145
- }
146
- }
147
- const batchSymRootLoadings = updateRootNodeSources.map((rootNodeSource) => {
148
- let symRootLoading = allSymRootLoadings.find((s) => isSameRootNodeSource(rootNodeSource, s.rootNodeSource));
149
- if (symRootLoading === undefined) {
150
- symRootLoading = {
151
- rootNodeSource,
152
- rootNodePromise: CfgSymRootNode.makeCfgSymRootFromRootNodeSource(this.logger, false, this._renderEnvironment, rootNodeSource),
153
- };
154
- allSymRootLoadings.push(symRootLoading);
155
- }
156
- return symRootLoading;
157
- });
158
- yield Promise.all([
159
- ...batchSymRootLoadings.map((s) => s.rootNodePromise),
160
- this._loadAdditionalProducts(coordinatorWithMeta),
161
- ]);
162
- const addedSymRoots = (yield Promise.all(batchSymRootLoadings.map((s) => s.rootNodePromise)))
163
- .filter((symRoot) => symRoot !== undefined)
164
- .filter((symRoot) => {
165
- const loadInProgressIndex = allSymRootLoadings.findIndex((symRootLoadInProgress) => symRoot.isSameIdentifierAndTransform(symRootLoadInProgress.rootNodeSource));
166
- if (loadInProgressIndex === -1) {
167
- // This node no longer shall be added
168
- return false;
169
- }
170
- // We'll add this, so it moves from "loading" to being a proper child
171
- allSymRootLoadings.splice(loadInProgressIndex, 1);
172
- this.add(symRoot);
173
- return true;
174
- });
175
- for (const symRoot of addedSymRoots) {
176
- if (coordinatorWithMeta === undefined) {
177
- continue;
178
- }
179
- const c = coordinatorWithMeta.coordinator;
180
- yield c.prepareForEnter.bind(c)(symRoot, coordinatorWithMeta.isNewProduct);
181
- }
182
- });
183
- }
184
- _loadAdditionalProducts(coordinatorWithMeta) {
185
- return __awaiter(this, void 0, void 0, function* () {
186
- const additionalProductLoadPromises = [];
187
- this._syncAdditionalProductNodes(this._product, {
188
- productNodeButNoProduct: (additionalProductNode) => {
189
- this.scheduleForRemoval(additionalProductNode);
190
- },
191
- productButNoProductNode: (additionalProduct) => {
192
- const additionalProductNode = CfgProductNode.make(this._renderEnvironment, additionalProduct);
193
- this.add(additionalProductNode);
194
- additionalProductLoadPromises.push(additionalProductNode.loadGeo(coordinatorWithMeta));
195
- },
196
- both: (_additionalProduct, additionalProductNode) => {
197
- additionalProductLoadPromises.push(additionalProductNode.loadGeo(coordinatorWithMeta));
198
- },
199
- });
200
- yield Promise.all(additionalProductLoadPromises);
201
- });
202
- }
203
- /// Run any animations and then permanently removes the nodes from the tree
204
- /// This function is recursively applied on additional products.
205
- flushScheduledForRemove(animationCoordinator) {
206
- return __awaiter(this, void 0, void 0, function* () {
207
- const thisBatch = this._scheduledForRemoval.slice();
208
- this._scheduledForRemoval.length = 0;
209
- yield Promise.all(this._getAdditionalProductNodes(true).map((additionalProductNode) => additionalProductNode.flushScheduledForRemove(animationCoordinator)));
210
- yield Promise.all(thisBatch.map((node) => (() => __awaiter(this, void 0, void 0, function* () {
211
- if (node instanceof CfgSymRootNode) {
212
- if (animationCoordinator !== undefined) {
213
- const c = animationCoordinator.coordinator;
214
- yield c.prepareForExit.bind(c)(node);
215
- }
216
- }
217
- this.remove(true, node);
218
- }))()));
219
- });
220
- }
221
- /// Are all materials currently needed loaded and ready to be applied?
222
- /// This function does not take additional products into account.
223
- _isAllMeshMaterialsReady() {
224
- return this._getSymRootChildren().reduce((a, c) => a && c.isAllMeshMaterialsReady(), true);
225
- }
226
- /// Resolves when all materials currently needed have been loaded and are
227
- /// ready to be applied.
228
- /// This function does not take additional products into account.
229
- _awaitAllMeshMaterialsReady() {
230
- return __awaiter(this, void 0, void 0, function* () {
231
- return new Promise((resolve, reject) => {
232
- let maxTries = 60 * 60; // Assuming 60 fps this gives a minute, which is absurdly long
233
- const frame = () => {
234
- if (this._isAllMeshMaterialsReady()) {
235
- resolve();
236
- return;
237
- }
238
- if (maxTries === 0) {
239
- reject("Materials not ready in time");
240
- return;
241
- }
242
- window.requestAnimationFrame(frame);
243
- maxTries--;
244
- };
245
- frame();
246
- });
247
- });
248
- }
249
- /// Loads the materials needed.
250
- /// This function is recursively applied on additional products.
251
- loadMaterials(animationCoordinator) {
252
- return __awaiter(this, void 0, void 0, function* () {
253
- const product = this._product;
254
- const productMtrlApplications = (product._internal.mtrlApplications || []).map((m) => CfgMtrlApplication.fromMtrlLikeApplication(CfgMtrlApplicationSource.Product, m));
255
- this._mtrlApplications = productMtrlApplications;
256
- this._configuration = product.configuration;
257
- yield Promise.all([
258
- this._aggregateMaterialsPushToChildrenAndLoad(animationCoordinator),
259
- ...this._getAdditionalProductNodes().map((additionalProductNode) => additionalProductNode.loadMaterials(animationCoordinator)),
260
- ]);
261
- });
262
- }
263
- /// Update the tag (area) to material mapping and gives them to sym children
264
- /// This function does not take additional products into account.
265
- _aggregateMaterialsPushToChildrenAndLoad(animationCoordinator) {
266
- return __awaiter(this, void 0, void 0, function* () {
267
- if (this._applicationAreas === undefined || this._configuration === undefined) {
268
- return;
269
- }
270
- const areasToMaterials = aggregateAllMaterialApplications(this._applicationAreas, this._mtrlApplications, this._configuration, this._debugMtrlApplications);
271
- this._areasToMaterials = areasToMaterials;
272
- yield this._pushMaterialToSymRootChildrenAndLoad(animationCoordinator);
273
- });
274
- }
275
- /// Starts loading the materials on the sym children (but does not apply)
276
- /// This function does not take additional products into account.
277
- _pushMaterialToSymRootChildrenAndLoad(animationCoordinator) {
278
- return __awaiter(this, void 0, void 0, function* () {
279
- const areasToMaterials = this._areasToMaterials;
280
- if (areasToMaterials === undefined) {
281
- return;
282
- }
283
- yield Promise.all(this._getSymRootChildren().map((child) => child.setMaterialsAndLoad(areasToMaterials, animationCoordinator)));
284
- });
285
- }
286
- _getSymRootChildren() {
287
- return this.getChildren()
288
- .filter(isSymRootNode)
289
- .filter((c) => !c.isDestroyed());
290
- }
291
- _getAdditionalProductNodes(includeDestroyed = false) {
292
- return this.getChildren()
293
- .filter(isProductNode)
294
- .filter((c) => includeDestroyed || !c.isDestroyed());
295
- }
296
- /// Applies and thereby shows the geometry. Finally flushes scheduled for remove.
297
- /// This function is recursively applied on additional products.
298
- applyGeo(animationCoordinator) {
299
- return __awaiter(this, void 0, void 0, function* () {
300
- yield Promise.all(this._applyOnDescendantProductNodes((p) => (() => __awaiter(this, void 0, void 0, function* () {
301
- p._getSymRootChildren().forEach((child) => {
302
- child.applyGeo();
303
- });
304
- // Wait until materials have been loaded so that we don't get any blinking.
305
- // It might seem wrong that this is done after we apply, but the material
306
- // will not be ready unless it is applied. So we wait after applying.
307
- yield p._awaitAllMeshMaterialsReady();
308
- }))()));
309
- this.flushScheduledForRemove(animationCoordinator);
310
- });
311
- }
312
- /// Applies and thereby shows the right materials.
313
- /// This function is recursively applied on additional products.
314
- applyMaterials() {
315
- return __awaiter(this, void 0, void 0, function* () {
316
- yield Promise.all(this._applyOnDescendantProductNodes((p) => (() => __awaiter(this, void 0, void 0, function* () {
317
- p._getSymRootChildren().forEach((child) => {
318
- child.applyMaterial();
319
- });
320
- // Wait until materials have been loaded so that we don't get any blinking.
321
- // It might seem wrong that this is done after we apply, but the material
322
- // will not be ready unless it is applied. So we wait after applying.
323
- yield p._awaitAllMeshMaterialsReady();
324
- }))()));
325
- });
326
- }
327
- _applyDebugSymRoots(symRootPromises) {
328
- return __awaiter(this, void 0, void 0, function* () {
329
- const allSymRoots = yield Promise.all(symRootPromises);
330
- allSymRoots.forEach((symRoot) => {
331
- if (symRoot === undefined) {
332
- return;
333
- }
334
- this.add(symRoot);
335
- });
336
- yield this.applyGeo();
337
- yield this._pushMaterialToSymRootChildrenAndLoad();
338
- yield this.applyMaterials();
339
- this._renderEnvironment.scheduleRerender();
340
- });
341
- }
342
- _addDebugMtrlApplication(debugMtrlApplication) {
343
- return __awaiter(this, void 0, void 0, function* () {
344
- this._debugMtrlApplications.push(debugMtrlApplication);
345
- yield this._aggregateMaterialsPushToChildrenAndLoad();
346
- this.applyMaterials();
347
- this._renderEnvironment.scheduleRerender();
348
- });
349
- }
350
- get boundingBox() {
351
- const bb = [...this._getSymRootChildren(), ...this._getAdditionalProductNodes()].reduce((a, m) => {
352
- a.expand(m.boundingBox);
353
- return a;
354
- }, new CfgBoundingBox());
355
- bb.applyMatrix(this.originalMatrix);
356
- return bb;
357
- }
358
- addInspectorProperties() {
359
- super.addInspectorProperties();
360
- this.addInspectableCustomProperty({
361
- label: "Log materialMappings",
362
- propertyName: "_inspectorLogMaterialMappings",
363
- type: InspectableType.Checkbox,
364
- });
365
- this.addInspectableCustomProperty({
366
- label: "Add material to mapping from File",
367
- propertyName: "_inspectorAddMaterialToMaterialMappingFromFile",
368
- type: InspectableType.Checkbox,
369
- });
370
- this.addInspectableCustomProperty({
371
- label: "Add material to mapping from Url",
372
- propertyName: "_inspectorAddMaterialToMaterialMappingFromUrl",
373
- type: InspectableType.Checkbox,
374
- });
375
- this.addInspectableCustomProperty({
376
- label: "Add CmSym from File",
377
- propertyName: "_inspectorAddCmSymFile",
378
- type: InspectableType.Checkbox,
379
- });
380
- this.addInspectableCustomProperty({
381
- label: "Add CmSym from Url",
382
- propertyName: "_inspectorAddCmSymUrl",
383
- type: InspectableType.Checkbox,
384
- });
385
- }
386
- get _inspectorLogMaterialMappings() {
387
- return this._areasToMaterials === undefined;
388
- }
389
- set _inspectorLogMaterialMappings(x) {
390
- if (this._areasToMaterials === undefined) {
391
- return;
392
- }
393
- logMaterialMappingToConsole(this._areasToMaterials);
394
- }
395
- get _inspectorAddMaterialToMaterialMappingFromFile() {
396
- return this._areasToMaterials === undefined;
397
- }
398
- set _inspectorAddMaterialToMaterialMappingFromFile(x) {
399
- if (this._areasToMaterials === undefined) {
400
- return;
401
- }
402
- const tag = window.prompt("Please provide a Tag for the mapping");
403
- if (tag === null || tag.trim().length === 0) {
404
- alert("You must provide a tag for the mapping");
405
- return;
406
- }
407
- const fileUpload = document.createElement("input");
408
- fileUpload.type = "file";
409
- fileUpload.style.display = "none";
410
- const body = document.getElementsByTagName("body")[0];
411
- body.appendChild(fileUpload);
412
- fileUpload.addEventListener("change", (event) => {
413
- (() => __awaiter(this, void 0, void 0, function* () {
414
- const files = fileUpload.files;
415
- if (files !== null) {
416
- const mtrlApplications = yield Promise.all(Array.from(files)
417
- .map(readFileToArrayBuffer)
418
- .map((bufferAndNamePromise) => __awaiter(this, void 0, void 0, function* () {
419
- const bufferAndName = yield bufferAndNamePromise;
420
- return CfgMtrlApplication.fromBufferForDebug([tag], bufferAndName.fileName, bufferAndName.buffer);
421
- })));
422
- mtrlApplications.forEach((mtrlApplication) => {
423
- this._addDebugMtrlApplication(mtrlApplication);
424
- });
425
- }
426
- body.removeChild(fileUpload);
427
- }))();
428
- });
429
- fileUpload.click();
430
- }
431
- get _inspectorAddMaterialToMaterialMappingFromUrl() {
432
- return this._areasToMaterials === undefined;
433
- }
434
- set _inspectorAddMaterialToMaterialMappingFromUrl(x) {
435
- if (this._areasToMaterials === undefined) {
436
- return;
437
- }
438
- const tag = window.prompt("Please provide a Tag for the mapping");
439
- if (tag === null || tag.trim().length === 0) {
440
- alert("You must provide a tag for the mapping");
441
- return;
442
- }
443
- const url = window.prompt("Please provide a material-url");
444
- if (url === null || url.trim().length === 0) {
445
- alert("You must provide an URL to a material-file");
446
- return;
447
- }
448
- const mtrlApplication = CfgMtrlApplication.fromUrlForDebug([tag], url);
449
- this._addDebugMtrlApplication(mtrlApplication);
450
- }
451
- get _inspectorAddCmSymFile() {
452
- return false;
453
- }
454
- set _inspectorAddCmSymFile(x) {
455
- const fileUpload = document.createElement("input");
456
- fileUpload.type = "file";
457
- fileUpload.style.display = "none";
458
- const body = document.getElementsByTagName("body")[0];
459
- body.appendChild(fileUpload);
460
- const logger = this.logger;
461
- const renderEnvironment = this._renderEnvironment;
462
- fileUpload.addEventListener("change", (event) => {
463
- const files = fileUpload.files;
464
- if (files !== null) {
465
- const symRootPromises = Array.from(files).map((file) => {
466
- return CfgSymRootNode.makeCfgSymRootFromFile(logger, true, renderEnvironment, file);
467
- });
468
- this._applyDebugSymRoots(symRootPromises);
469
- }
470
- body.removeChild(fileUpload);
471
- });
472
- fileUpload.click();
473
- }
474
- get _inspectorAddCmSymUrl() {
475
- return false;
476
- }
477
- set _inspectorAddCmSymUrl(x) {
478
- const url = window.prompt("Please provide a CmSym-url");
479
- if (url === null || url.trim().length === 0) {
480
- alert("You must provide an URL to a CmSym-file");
481
- return;
482
- }
483
- const symRootNode = CfgSymRootNode.makeCfgSymRootFromUrl(this.logger, true, this._renderEnvironment, url, undefined);
484
- this._applyDebugSymRoots([symRootNode]);
485
- }
486
- }
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
+ }