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