@combeenation/3d-viewer 3.1.1-alpha7 → 3.1.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/README.md +111 -111
- package/dist/lib-cjs/api/classes/animationInterface.d.ts +8 -8
- package/dist/lib-cjs/api/classes/animationInterface.js +1 -1
- package/dist/lib-cjs/api/classes/dottedPath.d.ts +79 -79
- package/dist/lib-cjs/api/classes/dottedPath.js +190 -190
- package/dist/lib-cjs/api/classes/element.d.ts +125 -126
- package/dist/lib-cjs/api/classes/element.js +678 -674
- package/dist/lib-cjs/api/classes/element.js.map +1 -1
- package/dist/lib-cjs/api/classes/elementParameterizable.d.ts +14 -14
- package/dist/lib-cjs/api/classes/elementParameterizable.js +134 -134
- package/dist/lib-cjs/api/classes/event.d.ts +312 -312
- package/dist/lib-cjs/api/classes/event.js +357 -357
- package/dist/lib-cjs/api/classes/eventBroadcaster.d.ts +26 -26
- package/dist/lib-cjs/api/classes/eventBroadcaster.js +53 -53
- package/dist/lib-cjs/api/classes/parameter.d.ts +165 -165
- package/dist/lib-cjs/api/classes/parameter.js +267 -267
- package/dist/lib-cjs/api/classes/parameterObservable.d.ts +36 -36
- package/dist/lib-cjs/api/classes/parameterObservable.js +126 -126
- package/dist/lib-cjs/api/classes/parameterizable.d.ts +15 -15
- package/dist/lib-cjs/api/classes/parameterizable.js +149 -149
- package/dist/lib-cjs/api/classes/placementAnimation.d.ts +38 -38
- package/dist/lib-cjs/api/classes/placementAnimation.js +138 -138
- package/dist/lib-cjs/api/classes/variant.d.ts +180 -190
- package/dist/lib-cjs/api/classes/variant.js +863 -873
- package/dist/lib-cjs/api/classes/variant.js.map +1 -1
- package/dist/lib-cjs/api/classes/variantInstance.d.ts +41 -41
- package/dist/lib-cjs/api/classes/variantInstance.js +98 -98
- package/dist/lib-cjs/api/classes/variantParameterizable.d.ts +17 -17
- package/dist/lib-cjs/api/classes/variantParameterizable.js +92 -92
- package/dist/lib-cjs/api/classes/viewer.d.ts +128 -128
- package/dist/lib-cjs/api/classes/viewer.js +486 -486
- package/dist/lib-cjs/api/classes/viewerLight.d.ts +65 -66
- package/dist/lib-cjs/api/classes/viewerLight.js +322 -389
- package/dist/lib-cjs/api/classes/viewerLight.js.map +1 -1
- package/dist/lib-cjs/api/internal/debugViewer.d.ts +13 -13
- package/dist/lib-cjs/api/internal/debugViewer.js +87 -87
- package/dist/lib-cjs/api/internal/lensRendering.d.ts +8 -8
- package/dist/lib-cjs/api/internal/lensRendering.js +11 -11
- package/dist/lib-cjs/api/internal/sceneSetup.d.ts +6 -6
- package/dist/lib-cjs/api/internal/sceneSetup.js +227 -227
- package/dist/lib-cjs/api/manager/animationManager.d.ts +29 -29
- package/dist/lib-cjs/api/manager/animationManager.js +121 -121
- package/dist/lib-cjs/api/manager/sceneManager.d.ts +32 -32
- package/dist/lib-cjs/api/manager/sceneManager.js +132 -132
- package/dist/lib-cjs/api/manager/variantInstanceManager.d.ts +90 -90
- package/dist/lib-cjs/api/manager/variantInstanceManager.js +321 -321
- package/dist/lib-cjs/api/store/specStorage.d.ts +24 -24
- package/dist/lib-cjs/api/store/specStorage.js +51 -51
- package/dist/lib-cjs/api/util/babylonHelper.d.ts +125 -125
- package/dist/lib-cjs/api/util/babylonHelper.js +368 -368
- package/dist/lib-cjs/api/util/globalTypes.d.ts +275 -275
- package/dist/lib-cjs/api/util/globalTypes.js +1 -1
- package/dist/lib-cjs/api/util/resourceHelper.d.ts +30 -30
- package/dist/lib-cjs/api/util/resourceHelper.js +247 -203
- package/dist/lib-cjs/api/util/resourceHelper.js.map +1 -1
- package/dist/lib-cjs/api/util/stringHelper.d.ts +9 -9
- package/dist/lib-cjs/api/util/stringHelper.js +25 -25
- package/dist/lib-cjs/buildinfo.json +3 -3
- package/dist/lib-cjs/index.d.ts +46 -46
- package/dist/lib-cjs/index.js +82 -82
- package/dist/webpack-stats.json +0 -0
- package/package.json +83 -83
- package/src/api/classes/animationInterface.ts +11 -11
- package/src/api/classes/dottedPath.ts +189 -189
- package/src/api/classes/element.ts +608 -606
- package/src/api/classes/elementParameterizable.ts +78 -78
- package/src/api/classes/event.ts +355 -355
- package/src/api/classes/eventBroadcaster.ts +54 -54
- package/src/api/classes/parameter.ts +277 -277
- package/src/api/classes/parameterObservable.ts +121 -121
- package/src/api/classes/placementAnimation.ts +133 -133
- package/src/api/classes/variant.ts +659 -670
- package/src/api/classes/variantInstance.ts +81 -81
- package/src/api/classes/viewer.ts +421 -421
- package/src/api/internal/debugViewer.ts +81 -81
- package/src/api/internal/lensRendering.ts +10 -10
- package/src/api/internal/sceneSetup.ts +203 -203
- package/src/api/manager/animationManager.ts +116 -116
- package/src/api/manager/sceneManager.ts +105 -105
- package/src/api/manager/variantInstanceManager.ts +236 -236
- package/src/api/store/specStorage.ts +53 -53
- package/src/api/util/babylonHelper.ts +392 -392
- package/src/api/util/globalTypes.ts +314 -314
- package/src/api/util/resourceHelper.ts +168 -155
- package/src/buildinfo.json +2 -2
- package/src/commonjs.tsconfig.json +13 -13
- package/src/declaration.tsconfig.json +10 -10
- package/src/dev.ts +44 -46
- package/src/es6.tsconfig.json +13 -13
- package/src/index.ts +87 -87
- package/src/pagesconfig.json +47 -47
- package/src/tsconfig.json +43 -43
- package/src/tsconfig.types.json +9 -9
- package/src/types.d.ts +4 -4
|
@@ -1,392 +1,392 @@
|
|
|
1
|
-
import { HighlightLayer } from '@babylonjs/core/Layers/highlightLayer';
|
|
2
|
-
import { Material } from '@babylonjs/core/Materials/material';
|
|
3
|
-
import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial';
|
|
4
|
-
import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
|
|
5
|
-
import { Color3 } from '@babylonjs/core/Maths/math.color';
|
|
6
|
-
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
|
|
7
|
-
import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
|
|
8
|
-
import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
|
|
9
|
-
import { Mesh } from '@babylonjs/core/Meshes/mesh';
|
|
10
|
-
import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
|
|
11
|
-
import { Node } from '@babylonjs/core/node';
|
|
12
|
-
import { Scene } from '@babylonjs/core/scene';
|
|
13
|
-
import { cloneDeep, merge } from 'lodash-es';
|
|
14
|
-
import { DottedPath } from '../classes/dottedPath';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @param nodes
|
|
18
|
-
* @param predicate
|
|
19
|
-
* @return Map<DottedPath, T>
|
|
20
|
-
*/
|
|
21
|
-
const mapToDottedNodes = function <T>( nodes: Node[],
|
|
22
|
-
predicate?: ( node: Node ) => boolean ): Map<DottedPath, T> {
|
|
23
|
-
const map = new Map<DottedPath, T>();
|
|
24
|
-
const addNodes = function( _node: Node ) {
|
|
25
|
-
if( predicate && predicate( _node ) ) {
|
|
26
|
-
map.set( _node.metadata.dottedPath, _node as any );
|
|
27
|
-
}
|
|
28
|
-
_node.getChildren().forEach( child => {
|
|
29
|
-
addNodes( child );
|
|
30
|
-
} );
|
|
31
|
-
};
|
|
32
|
-
nodes.forEach( node => {
|
|
33
|
-
addNodes( node );
|
|
34
|
-
} );
|
|
35
|
-
return map;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param node
|
|
40
|
-
* @return DottedPath
|
|
41
|
-
*/
|
|
42
|
-
const getDottedPathForTransformNode = function( node: TransformNode ): DottedPath {
|
|
43
|
-
const dottedPath = DottedPath.create( node.name );
|
|
44
|
-
let _parent = node;
|
|
45
|
-
while( _parent.parent ) {
|
|
46
|
-
_parent = _parent.parent as TransformNode;
|
|
47
|
-
dottedPath.unshiftPart( _parent.name );
|
|
48
|
-
}
|
|
49
|
-
return dottedPath;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* @param node
|
|
55
|
-
* @param predicate
|
|
56
|
-
* @param deep
|
|
57
|
-
* @return TransformNode | null
|
|
58
|
-
*/
|
|
59
|
-
const cloneTransformNode = function( node: TransformNode,
|
|
60
|
-
predicate?: ( node: TransformNode ) => boolean,
|
|
61
|
-
deep: boolean = true ): TransformNode | null {
|
|
62
|
-
if( predicate && !predicate( node ) ) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
const clone = node.clone( node.name, node.parent, true );
|
|
66
|
-
if( clone ) {
|
|
67
|
-
clone.metadata = cloneDeep( node.metadata );
|
|
68
|
-
}
|
|
69
|
-
if( deep ) {
|
|
70
|
-
const children = node.getChildTransformNodes( true );
|
|
71
|
-
children.forEach( child => {
|
|
72
|
-
const clonedChild = cloneTransformNode( child, predicate, deep );
|
|
73
|
-
if( clonedChild ) {
|
|
74
|
-
clonedChild.parent = clone;
|
|
75
|
-
}
|
|
76
|
-
} );
|
|
77
|
-
}
|
|
78
|
-
return clone;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @param node
|
|
83
|
-
* @param deep
|
|
84
|
-
* @param prefix
|
|
85
|
-
* @return TransformNode
|
|
86
|
-
*/
|
|
87
|
-
const cloneTransformNodeMaterial = function( node: TransformNode,
|
|
88
|
-
prefix: DottedPathArgument = '',
|
|
89
|
-
deep: boolean = true ): TransformNode {
|
|
90
|
-
if( node instanceof AbstractMesh && node.material ) {
|
|
91
|
-
const _prefix = DottedPath.create( prefix ).addParts([
|
|
92
|
-
'node',
|
|
93
|
-
node.uniqueId.toString()
|
|
94
|
-
]);
|
|
95
|
-
node.material = node.material.clone( _prefix.path );
|
|
96
|
-
}
|
|
97
|
-
if( deep ) {
|
|
98
|
-
const children = node.getChildTransformNodes( true );
|
|
99
|
-
children.forEach( child => cloneTransformNodeMaterial( child, prefix, deep ) );
|
|
100
|
-
}
|
|
101
|
-
return node;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* @param node
|
|
106
|
-
* @param deep
|
|
107
|
-
* @param metadata
|
|
108
|
-
*/
|
|
109
|
-
const injectTransformNodeMetadata = function( node: TransformNode, metadata: {}, deep: boolean = true ) {
|
|
110
|
-
node.metadata = merge( {}, node.metadata, metadata );
|
|
111
|
-
if( deep ) {
|
|
112
|
-
const children = node.getChildTransformNodes( true );
|
|
113
|
-
children.forEach( child => injectTransformNodeMetadata( child, metadata, deep ) );
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @param node
|
|
119
|
-
* @param assertCallable
|
|
120
|
-
* @param callableParameters
|
|
121
|
-
* @param deep
|
|
122
|
-
*/
|
|
123
|
-
const assertTransformNode = function( node: TransformNode,
|
|
124
|
-
assertCallable: CallableFunction,
|
|
125
|
-
callableParameters: any[] = [],
|
|
126
|
-
deep: boolean = true ) {
|
|
127
|
-
assertCallable(node, ...callableParameters);
|
|
128
|
-
if( deep ) {
|
|
129
|
-
const children = node.getChildTransformNodes( true );
|
|
130
|
-
children.forEach( child => assertTransformNode( child, assertCallable, callableParameters, deep ) );
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* @param node
|
|
136
|
-
* @param deep
|
|
137
|
-
*/
|
|
138
|
-
const activateTransformNode = function( node: TransformNode, deep: boolean = true ) {
|
|
139
|
-
node.setEnabled( true );
|
|
140
|
-
/*
|
|
141
|
-
if( node instanceof AbstractMesh ) {
|
|
142
|
-
node.visibility = 1;
|
|
143
|
-
node.isPickable = true;
|
|
144
|
-
}
|
|
145
|
-
*/
|
|
146
|
-
if( deep ) {
|
|
147
|
-
node.getChildTransformNodes( true ).forEach( child => activateTransformNode( child, deep ) );
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @param node
|
|
153
|
-
* @param deep
|
|
154
|
-
*/
|
|
155
|
-
const deactivateTransformNode = function( node: TransformNode, deep: boolean = true ) {
|
|
156
|
-
node.setEnabled( false );
|
|
157
|
-
/*
|
|
158
|
-
if( node instanceof AbstractMesh ) {
|
|
159
|
-
node.visibility = 0;
|
|
160
|
-
node.isPickable = false;
|
|
161
|
-
}
|
|
162
|
-
*/
|
|
163
|
-
if( deep ) {
|
|
164
|
-
node.getChildTransformNodes( true ).forEach( child => deactivateTransformNode( child, deep ) );
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @param node
|
|
170
|
-
* @param material
|
|
171
|
-
* @param deep
|
|
172
|
-
*/
|
|
173
|
-
const setMaterial = function( node: TransformNode, material: Material, deep: boolean = true ) {
|
|
174
|
-
if( node instanceof AbstractMesh ) {
|
|
175
|
-
node.material = material;
|
|
176
|
-
}
|
|
177
|
-
if( deep ) {
|
|
178
|
-
node.getChildTransformNodes( true ).forEach( child => setMaterial( child, material, deep ) );
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* !!! Warning !!!
|
|
184
|
-
* This function is not public API. Whilst it can help solving certain problems, it only works reliably in well defined
|
|
185
|
-
* situations and can cause unwanted side effects under some conditions. Use carefully at your own risk!
|
|
186
|
-
*
|
|
187
|
-
* See https://combeenation.myjetbrains.com/youtrack/issue/CB-5906 for further details regarding this warning.
|
|
188
|
-
*
|
|
189
|
-
* Set material of an instanced meshes source mesh.
|
|
190
|
-
* Changes the material of all instanced meshes which have the same source mesh.
|
|
191
|
-
*
|
|
192
|
-
* @param node
|
|
193
|
-
* @param material
|
|
194
|
-
* @param deep
|
|
195
|
-
*
|
|
196
|
-
* @ignore
|
|
197
|
-
*/
|
|
198
|
-
const setSourceNodeMaterial = function( node: TransformNode, material: Material, deep: boolean = true ) {
|
|
199
|
-
const warn = ` You're using "setSourceNodeMaterial" which is not public API.
|
|
200
|
-
Whilst it can help solving certain problems, it only works reliably in well defined situations and can cause unwanted side effects under some conditions.
|
|
201
|
-
Use carefully at your own risk!`;
|
|
202
|
-
console.warn(`!!! Warning !!!\n${warn}`);
|
|
203
|
-
|
|
204
|
-
if( node instanceof InstancedMesh ) {
|
|
205
|
-
node.sourceMesh.material = material;
|
|
206
|
-
}
|
|
207
|
-
if( deep ) {
|
|
208
|
-
node.getChildTransformNodes( true ).forEach( child => setSourceNodeMaterial( child, material, deep ) );
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* @param node
|
|
214
|
-
* @param color
|
|
215
|
-
* @param deep
|
|
216
|
-
*/
|
|
217
|
-
const setMaterialColor = function( node: TransformNode, color: Color3, deep: boolean = true ) {
|
|
218
|
-
if( node instanceof AbstractMesh && node.material ) {
|
|
219
|
-
const materialCls = node.material.getClassName();
|
|
220
|
-
switch( materialCls ) {
|
|
221
|
-
case 'PBRMaterial':
|
|
222
|
-
(node.material as PBRMaterial).albedoColor = color.toLinearSpace();
|
|
223
|
-
break;
|
|
224
|
-
case 'StandardMaterial':
|
|
225
|
-
(node.material as StandardMaterial).diffuseColor = color;
|
|
226
|
-
break;
|
|
227
|
-
default:
|
|
228
|
-
throw new Error( `Setting color for material of instance "${materialCls}" not implemented (yet).` );
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
if( deep ) {
|
|
232
|
-
node.getChildTransformNodes( true ).forEach( child => setMaterialColor( child, color, deep ) );
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* @param node
|
|
238
|
-
* @param texture
|
|
239
|
-
* @param deep
|
|
240
|
-
*/
|
|
241
|
-
const setMaterialTexture = function( node: TransformNode, texture: Texture, deep: boolean = true ) {
|
|
242
|
-
if( node instanceof AbstractMesh && node.material ) {
|
|
243
|
-
const materialCls = node.material.getClassName();
|
|
244
|
-
switch( materialCls ) {
|
|
245
|
-
case 'PBRMaterial':
|
|
246
|
-
(node.material as PBRMaterial).albedoTexture = texture;
|
|
247
|
-
break;
|
|
248
|
-
case 'StandardMaterial':
|
|
249
|
-
(node.material as StandardMaterial).diffuseTexture = texture;
|
|
250
|
-
break;
|
|
251
|
-
default:
|
|
252
|
-
throw new Error( `Setting texture for material of instance "${materialCls}" not implemented (yet).` );
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if( deep ) {
|
|
256
|
-
node.getChildTransformNodes( true ).forEach( child => setMaterialTexture( child, texture, deep ) );
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* @param node
|
|
262
|
-
* @param metallness
|
|
263
|
-
* @param deep
|
|
264
|
-
*/
|
|
265
|
-
const setMaterialMetallness = function( node: TransformNode, metallness: number, deep: boolean = true ) {
|
|
266
|
-
if( node instanceof AbstractMesh && node.material ) {
|
|
267
|
-
const materialCls = node.material.getClassName();
|
|
268
|
-
switch( materialCls ) {
|
|
269
|
-
case 'PBRMaterial':
|
|
270
|
-
(node.material as PBRMaterial).metallic = metallness;
|
|
271
|
-
break;
|
|
272
|
-
default:
|
|
273
|
-
throw new Error( `Setting metallness for material of instance "${materialCls}" not implemented (yet).` );
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
if( deep ) {
|
|
277
|
-
node.getChildTransformNodes( true ).forEach( child => setMaterialMetallness( child, metallness, deep ) );
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* @param node
|
|
283
|
-
* @param roughness
|
|
284
|
-
* @param deep
|
|
285
|
-
*/
|
|
286
|
-
const setMaterialRoughness = function( node: TransformNode, roughness: number, deep: boolean = true ) {
|
|
287
|
-
if( node instanceof AbstractMesh && node.material ) {
|
|
288
|
-
const materialCls = node.material.getClassName();
|
|
289
|
-
switch( materialCls ) {
|
|
290
|
-
case 'PBRMaterial':
|
|
291
|
-
(node.material as PBRMaterial).roughness = roughness;
|
|
292
|
-
break;
|
|
293
|
-
case 'StandardMaterial':
|
|
294
|
-
(node.material as StandardMaterial).roughness = roughness;
|
|
295
|
-
break;
|
|
296
|
-
default:
|
|
297
|
-
throw new Error( `Setting roughness for material of instance "${materialCls}" not implemented (yet).` );
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
if( deep ) {
|
|
301
|
-
node.getChildTransformNodes( true ).forEach( child => setMaterialRoughness( child, roughness, deep ) );
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* @param node
|
|
307
|
-
* @param layer
|
|
308
|
-
* @param color
|
|
309
|
-
* @param deep
|
|
310
|
-
*/
|
|
311
|
-
const addToHighlightLayer = function( layer: HighlightLayer, color: Color3, node: TransformNode, deep: boolean = true ) {
|
|
312
|
-
if( node instanceof AbstractMesh ) {
|
|
313
|
-
layer.addMesh( (node as Mesh), color );
|
|
314
|
-
}
|
|
315
|
-
if( deep ) {
|
|
316
|
-
node.getChildTransformNodes( true ).forEach(
|
|
317
|
-
child => addToHighlightLayer( layer, color, child, deep )
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* @param node
|
|
324
|
-
* @param layer
|
|
325
|
-
* @param deep
|
|
326
|
-
*/
|
|
327
|
-
const removeFromHighlightLayer = function( layer: HighlightLayer, node: TransformNode, deep: boolean = true ) {
|
|
328
|
-
if( node instanceof AbstractMesh ) {
|
|
329
|
-
layer.removeMesh( (node as Mesh) );
|
|
330
|
-
}
|
|
331
|
-
if( deep ) {
|
|
332
|
-
node.getChildTransformNodes( true ).forEach(
|
|
333
|
-
child => removeFromHighlightLayer( layer, child, deep )
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* https://forum.babylonjs.com/t/get-mesh-bounding-box-position-and-size-in-2d-screen-coordinates/1058/3
|
|
340
|
-
* @param mesh
|
|
341
|
-
* @param scene
|
|
342
|
-
* @param canvas
|
|
343
|
-
*/
|
|
344
|
-
const getClientRectFromMesh = function( mesh: AbstractMesh, scene: Scene, canvas: HTMLCanvasElement ): ClientRect {
|
|
345
|
-
// get bounding box of the mesh
|
|
346
|
-
const meshVectors = mesh.getBoundingInfo().boundingBox.vectors;
|
|
347
|
-
// get the matrix and viewport needed to project the vectors onto the screen
|
|
348
|
-
const worldMatrix = mesh.getWorldMatrix();
|
|
349
|
-
const transformMatrix = scene.getTransformMatrix();
|
|
350
|
-
const viewport = scene.activeCamera!.viewport;
|
|
351
|
-
// loop though all the vectors and project them against the current camera viewport to get a set of coordinates
|
|
352
|
-
const coordinates = meshVectors.map( vector => {
|
|
353
|
-
const projection = Vector3.Project( vector, worldMatrix, transformMatrix, viewport );
|
|
354
|
-
projection.x = projection.x * canvas.clientWidth;
|
|
355
|
-
projection.y = projection.y * canvas.clientHeight;
|
|
356
|
-
return projection;
|
|
357
|
-
} );
|
|
358
|
-
// get the min and max for all the coordinates so we can calculate the largest possible screen size
|
|
359
|
-
const maxX = Math.max.apply( Math, coordinates.map( o => o.x ) );
|
|
360
|
-
const minX = Math.min.apply( Math, coordinates.map( o => o.x ) );
|
|
361
|
-
const maxY = Math.max.apply( Math, coordinates.map( o => o.y ) );
|
|
362
|
-
const minY = Math.min.apply( Math, coordinates.map( o => o.y ) );
|
|
363
|
-
// return a ClientRect from this
|
|
364
|
-
return {
|
|
365
|
-
width: maxX - minX,
|
|
366
|
-
height: maxY - minY,
|
|
367
|
-
left: minX,
|
|
368
|
-
top: minY,
|
|
369
|
-
right: maxX,
|
|
370
|
-
bottom: maxY,
|
|
371
|
-
} as ClientRect;
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
export {
|
|
375
|
-
mapToDottedNodes,
|
|
376
|
-
getDottedPathForTransformNode,
|
|
377
|
-
cloneTransformNode,
|
|
378
|
-
cloneTransformNodeMaterial,
|
|
379
|
-
injectTransformNodeMetadata,
|
|
380
|
-
assertTransformNode,
|
|
381
|
-
activateTransformNode,
|
|
382
|
-
deactivateTransformNode,
|
|
383
|
-
setMaterial,
|
|
384
|
-
setSourceNodeMaterial,
|
|
385
|
-
setMaterialColor,
|
|
386
|
-
setMaterialTexture,
|
|
387
|
-
setMaterialMetallness,
|
|
388
|
-
setMaterialRoughness,
|
|
389
|
-
addToHighlightLayer,
|
|
390
|
-
removeFromHighlightLayer,
|
|
391
|
-
getClientRectFromMesh
|
|
392
|
-
};
|
|
1
|
+
import { HighlightLayer } from '@babylonjs/core/Layers/highlightLayer';
|
|
2
|
+
import { Material } from '@babylonjs/core/Materials/material';
|
|
3
|
+
import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial';
|
|
4
|
+
import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
|
|
5
|
+
import { Color3 } from '@babylonjs/core/Maths/math.color';
|
|
6
|
+
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
|
|
7
|
+
import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
|
|
8
|
+
import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
|
|
9
|
+
import { Mesh } from '@babylonjs/core/Meshes/mesh';
|
|
10
|
+
import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
|
|
11
|
+
import { Node } from '@babylonjs/core/node';
|
|
12
|
+
import { Scene } from '@babylonjs/core/scene';
|
|
13
|
+
import { cloneDeep, merge } from 'lodash-es';
|
|
14
|
+
import { DottedPath } from '../classes/dottedPath';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param nodes
|
|
18
|
+
* @param predicate
|
|
19
|
+
* @return Map<DottedPath, T>
|
|
20
|
+
*/
|
|
21
|
+
const mapToDottedNodes = function <T>( nodes: Node[],
|
|
22
|
+
predicate?: ( node: Node ) => boolean ): Map<DottedPath, T> {
|
|
23
|
+
const map = new Map<DottedPath, T>();
|
|
24
|
+
const addNodes = function( _node: Node ) {
|
|
25
|
+
if( predicate && predicate( _node ) ) {
|
|
26
|
+
map.set( _node.metadata.dottedPath, _node as any );
|
|
27
|
+
}
|
|
28
|
+
_node.getChildren().forEach( child => {
|
|
29
|
+
addNodes( child );
|
|
30
|
+
} );
|
|
31
|
+
};
|
|
32
|
+
nodes.forEach( node => {
|
|
33
|
+
addNodes( node );
|
|
34
|
+
} );
|
|
35
|
+
return map;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param node
|
|
40
|
+
* @return DottedPath
|
|
41
|
+
*/
|
|
42
|
+
const getDottedPathForTransformNode = function( node: TransformNode ): DottedPath {
|
|
43
|
+
const dottedPath = DottedPath.create( node.name );
|
|
44
|
+
let _parent = node;
|
|
45
|
+
while( _parent.parent ) {
|
|
46
|
+
_parent = _parent.parent as TransformNode;
|
|
47
|
+
dottedPath.unshiftPart( _parent.name );
|
|
48
|
+
}
|
|
49
|
+
return dottedPath;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param node
|
|
55
|
+
* @param predicate
|
|
56
|
+
* @param deep
|
|
57
|
+
* @return TransformNode | null
|
|
58
|
+
*/
|
|
59
|
+
const cloneTransformNode = function( node: TransformNode,
|
|
60
|
+
predicate?: ( node: TransformNode ) => boolean,
|
|
61
|
+
deep: boolean = true ): TransformNode | null {
|
|
62
|
+
if( predicate && !predicate( node ) ) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const clone = node.clone( node.name, node.parent, true );
|
|
66
|
+
if( clone ) {
|
|
67
|
+
clone.metadata = cloneDeep( node.metadata );
|
|
68
|
+
}
|
|
69
|
+
if( deep ) {
|
|
70
|
+
const children = node.getChildTransformNodes( true );
|
|
71
|
+
children.forEach( child => {
|
|
72
|
+
const clonedChild = cloneTransformNode( child, predicate, deep );
|
|
73
|
+
if( clonedChild ) {
|
|
74
|
+
clonedChild.parent = clone;
|
|
75
|
+
}
|
|
76
|
+
} );
|
|
77
|
+
}
|
|
78
|
+
return clone;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param node
|
|
83
|
+
* @param deep
|
|
84
|
+
* @param prefix
|
|
85
|
+
* @return TransformNode
|
|
86
|
+
*/
|
|
87
|
+
const cloneTransformNodeMaterial = function( node: TransformNode,
|
|
88
|
+
prefix: DottedPathArgument = '',
|
|
89
|
+
deep: boolean = true ): TransformNode {
|
|
90
|
+
if( node instanceof AbstractMesh && node.material ) {
|
|
91
|
+
const _prefix = DottedPath.create( prefix ).addParts([
|
|
92
|
+
'node',
|
|
93
|
+
node.uniqueId.toString()
|
|
94
|
+
]);
|
|
95
|
+
node.material = node.material.clone( _prefix.path );
|
|
96
|
+
}
|
|
97
|
+
if( deep ) {
|
|
98
|
+
const children = node.getChildTransformNodes( true );
|
|
99
|
+
children.forEach( child => cloneTransformNodeMaterial( child, prefix, deep ) );
|
|
100
|
+
}
|
|
101
|
+
return node;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param node
|
|
106
|
+
* @param deep
|
|
107
|
+
* @param metadata
|
|
108
|
+
*/
|
|
109
|
+
const injectTransformNodeMetadata = function( node: TransformNode, metadata: {}, deep: boolean = true ) {
|
|
110
|
+
node.metadata = merge( {}, node.metadata, metadata );
|
|
111
|
+
if( deep ) {
|
|
112
|
+
const children = node.getChildTransformNodes( true );
|
|
113
|
+
children.forEach( child => injectTransformNodeMetadata( child, metadata, deep ) );
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param node
|
|
119
|
+
* @param assertCallable
|
|
120
|
+
* @param callableParameters
|
|
121
|
+
* @param deep
|
|
122
|
+
*/
|
|
123
|
+
const assertTransformNode = function( node: TransformNode,
|
|
124
|
+
assertCallable: CallableFunction,
|
|
125
|
+
callableParameters: any[] = [],
|
|
126
|
+
deep: boolean = true ) {
|
|
127
|
+
assertCallable(node, ...callableParameters);
|
|
128
|
+
if( deep ) {
|
|
129
|
+
const children = node.getChildTransformNodes( true );
|
|
130
|
+
children.forEach( child => assertTransformNode( child, assertCallable, callableParameters, deep ) );
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @param node
|
|
136
|
+
* @param deep
|
|
137
|
+
*/
|
|
138
|
+
const activateTransformNode = function( node: TransformNode, deep: boolean = true ) {
|
|
139
|
+
node.setEnabled( true );
|
|
140
|
+
/*
|
|
141
|
+
if( node instanceof AbstractMesh ) {
|
|
142
|
+
node.visibility = 1;
|
|
143
|
+
node.isPickable = true;
|
|
144
|
+
}
|
|
145
|
+
*/
|
|
146
|
+
if( deep ) {
|
|
147
|
+
node.getChildTransformNodes( true ).forEach( child => activateTransformNode( child, deep ) );
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @param node
|
|
153
|
+
* @param deep
|
|
154
|
+
*/
|
|
155
|
+
const deactivateTransformNode = function( node: TransformNode, deep: boolean = true ) {
|
|
156
|
+
node.setEnabled( false );
|
|
157
|
+
/*
|
|
158
|
+
if( node instanceof AbstractMesh ) {
|
|
159
|
+
node.visibility = 0;
|
|
160
|
+
node.isPickable = false;
|
|
161
|
+
}
|
|
162
|
+
*/
|
|
163
|
+
if( deep ) {
|
|
164
|
+
node.getChildTransformNodes( true ).forEach( child => deactivateTransformNode( child, deep ) );
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param node
|
|
170
|
+
* @param material
|
|
171
|
+
* @param deep
|
|
172
|
+
*/
|
|
173
|
+
const setMaterial = function( node: TransformNode, material: Material, deep: boolean = true ) {
|
|
174
|
+
if( node instanceof AbstractMesh ) {
|
|
175
|
+
node.material = material;
|
|
176
|
+
}
|
|
177
|
+
if( deep ) {
|
|
178
|
+
node.getChildTransformNodes( true ).forEach( child => setMaterial( child, material, deep ) );
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* !!! Warning !!!
|
|
184
|
+
* This function is not public API. Whilst it can help solving certain problems, it only works reliably in well defined
|
|
185
|
+
* situations and can cause unwanted side effects under some conditions. Use carefully at your own risk!
|
|
186
|
+
*
|
|
187
|
+
* See https://combeenation.myjetbrains.com/youtrack/issue/CB-5906 for further details regarding this warning.
|
|
188
|
+
*
|
|
189
|
+
* Set material of an instanced meshes source mesh.
|
|
190
|
+
* Changes the material of all instanced meshes which have the same source mesh.
|
|
191
|
+
*
|
|
192
|
+
* @param node
|
|
193
|
+
* @param material
|
|
194
|
+
* @param deep
|
|
195
|
+
*
|
|
196
|
+
* @ignore
|
|
197
|
+
*/
|
|
198
|
+
const setSourceNodeMaterial = function( node: TransformNode, material: Material, deep: boolean = true ) {
|
|
199
|
+
const warn = ` You're using "setSourceNodeMaterial" which is not public API.
|
|
200
|
+
Whilst it can help solving certain problems, it only works reliably in well defined situations and can cause unwanted side effects under some conditions.
|
|
201
|
+
Use carefully at your own risk!`;
|
|
202
|
+
console.warn(`!!! Warning !!!\n${warn}`);
|
|
203
|
+
|
|
204
|
+
if( node instanceof InstancedMesh ) {
|
|
205
|
+
node.sourceMesh.material = material;
|
|
206
|
+
}
|
|
207
|
+
if( deep ) {
|
|
208
|
+
node.getChildTransformNodes( true ).forEach( child => setSourceNodeMaterial( child, material, deep ) );
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @param node
|
|
214
|
+
* @param color
|
|
215
|
+
* @param deep
|
|
216
|
+
*/
|
|
217
|
+
const setMaterialColor = function( node: TransformNode, color: Color3, deep: boolean = true ) {
|
|
218
|
+
if( node instanceof AbstractMesh && node.material ) {
|
|
219
|
+
const materialCls = node.material.getClassName();
|
|
220
|
+
switch( materialCls ) {
|
|
221
|
+
case 'PBRMaterial':
|
|
222
|
+
(node.material as PBRMaterial).albedoColor = color.toLinearSpace();
|
|
223
|
+
break;
|
|
224
|
+
case 'StandardMaterial':
|
|
225
|
+
(node.material as StandardMaterial).diffuseColor = color;
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
throw new Error( `Setting color for material of instance "${materialCls}" not implemented (yet).` );
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if( deep ) {
|
|
232
|
+
node.getChildTransformNodes( true ).forEach( child => setMaterialColor( child, color, deep ) );
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @param node
|
|
238
|
+
* @param texture
|
|
239
|
+
* @param deep
|
|
240
|
+
*/
|
|
241
|
+
const setMaterialTexture = function( node: TransformNode, texture: Texture, deep: boolean = true ) {
|
|
242
|
+
if( node instanceof AbstractMesh && node.material ) {
|
|
243
|
+
const materialCls = node.material.getClassName();
|
|
244
|
+
switch( materialCls ) {
|
|
245
|
+
case 'PBRMaterial':
|
|
246
|
+
(node.material as PBRMaterial).albedoTexture = texture;
|
|
247
|
+
break;
|
|
248
|
+
case 'StandardMaterial':
|
|
249
|
+
(node.material as StandardMaterial).diffuseTexture = texture;
|
|
250
|
+
break;
|
|
251
|
+
default:
|
|
252
|
+
throw new Error( `Setting texture for material of instance "${materialCls}" not implemented (yet).` );
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if( deep ) {
|
|
256
|
+
node.getChildTransformNodes( true ).forEach( child => setMaterialTexture( child, texture, deep ) );
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* @param node
|
|
262
|
+
* @param metallness
|
|
263
|
+
* @param deep
|
|
264
|
+
*/
|
|
265
|
+
const setMaterialMetallness = function( node: TransformNode, metallness: number, deep: boolean = true ) {
|
|
266
|
+
if( node instanceof AbstractMesh && node.material ) {
|
|
267
|
+
const materialCls = node.material.getClassName();
|
|
268
|
+
switch( materialCls ) {
|
|
269
|
+
case 'PBRMaterial':
|
|
270
|
+
(node.material as PBRMaterial).metallic = metallness;
|
|
271
|
+
break;
|
|
272
|
+
default:
|
|
273
|
+
throw new Error( `Setting metallness for material of instance "${materialCls}" not implemented (yet).` );
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if( deep ) {
|
|
277
|
+
node.getChildTransformNodes( true ).forEach( child => setMaterialMetallness( child, metallness, deep ) );
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* @param node
|
|
283
|
+
* @param roughness
|
|
284
|
+
* @param deep
|
|
285
|
+
*/
|
|
286
|
+
const setMaterialRoughness = function( node: TransformNode, roughness: number, deep: boolean = true ) {
|
|
287
|
+
if( node instanceof AbstractMesh && node.material ) {
|
|
288
|
+
const materialCls = node.material.getClassName();
|
|
289
|
+
switch( materialCls ) {
|
|
290
|
+
case 'PBRMaterial':
|
|
291
|
+
(node.material as PBRMaterial).roughness = roughness;
|
|
292
|
+
break;
|
|
293
|
+
case 'StandardMaterial':
|
|
294
|
+
(node.material as StandardMaterial).roughness = roughness;
|
|
295
|
+
break;
|
|
296
|
+
default:
|
|
297
|
+
throw new Error( `Setting roughness for material of instance "${materialCls}" not implemented (yet).` );
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if( deep ) {
|
|
301
|
+
node.getChildTransformNodes( true ).forEach( child => setMaterialRoughness( child, roughness, deep ) );
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @param node
|
|
307
|
+
* @param layer
|
|
308
|
+
* @param color
|
|
309
|
+
* @param deep
|
|
310
|
+
*/
|
|
311
|
+
const addToHighlightLayer = function( layer: HighlightLayer, color: Color3, node: TransformNode, deep: boolean = true ) {
|
|
312
|
+
if( node instanceof AbstractMesh ) {
|
|
313
|
+
layer.addMesh( (node as Mesh), color );
|
|
314
|
+
}
|
|
315
|
+
if( deep ) {
|
|
316
|
+
node.getChildTransformNodes( true ).forEach(
|
|
317
|
+
child => addToHighlightLayer( layer, color, child, deep )
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @param node
|
|
324
|
+
* @param layer
|
|
325
|
+
* @param deep
|
|
326
|
+
*/
|
|
327
|
+
const removeFromHighlightLayer = function( layer: HighlightLayer, node: TransformNode, deep: boolean = true ) {
|
|
328
|
+
if( node instanceof AbstractMesh ) {
|
|
329
|
+
layer.removeMesh( (node as Mesh) );
|
|
330
|
+
}
|
|
331
|
+
if( deep ) {
|
|
332
|
+
node.getChildTransformNodes( true ).forEach(
|
|
333
|
+
child => removeFromHighlightLayer( layer, child, deep )
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* https://forum.babylonjs.com/t/get-mesh-bounding-box-position-and-size-in-2d-screen-coordinates/1058/3
|
|
340
|
+
* @param mesh
|
|
341
|
+
* @param scene
|
|
342
|
+
* @param canvas
|
|
343
|
+
*/
|
|
344
|
+
const getClientRectFromMesh = function( mesh: AbstractMesh, scene: Scene, canvas: HTMLCanvasElement ): ClientRect {
|
|
345
|
+
// get bounding box of the mesh
|
|
346
|
+
const meshVectors = mesh.getBoundingInfo().boundingBox.vectors;
|
|
347
|
+
// get the matrix and viewport needed to project the vectors onto the screen
|
|
348
|
+
const worldMatrix = mesh.getWorldMatrix();
|
|
349
|
+
const transformMatrix = scene.getTransformMatrix();
|
|
350
|
+
const viewport = scene.activeCamera!.viewport;
|
|
351
|
+
// loop though all the vectors and project them against the current camera viewport to get a set of coordinates
|
|
352
|
+
const coordinates = meshVectors.map( vector => {
|
|
353
|
+
const projection = Vector3.Project( vector, worldMatrix, transformMatrix, viewport );
|
|
354
|
+
projection.x = projection.x * canvas.clientWidth;
|
|
355
|
+
projection.y = projection.y * canvas.clientHeight;
|
|
356
|
+
return projection;
|
|
357
|
+
} );
|
|
358
|
+
// get the min and max for all the coordinates so we can calculate the largest possible screen size
|
|
359
|
+
const maxX = Math.max.apply( Math, coordinates.map( o => o.x ) );
|
|
360
|
+
const minX = Math.min.apply( Math, coordinates.map( o => o.x ) );
|
|
361
|
+
const maxY = Math.max.apply( Math, coordinates.map( o => o.y ) );
|
|
362
|
+
const minY = Math.min.apply( Math, coordinates.map( o => o.y ) );
|
|
363
|
+
// return a ClientRect from this
|
|
364
|
+
return {
|
|
365
|
+
width: maxX - minX,
|
|
366
|
+
height: maxY - minY,
|
|
367
|
+
left: minX,
|
|
368
|
+
top: minY,
|
|
369
|
+
right: maxX,
|
|
370
|
+
bottom: maxY,
|
|
371
|
+
} as ClientRect;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
export {
|
|
375
|
+
mapToDottedNodes,
|
|
376
|
+
getDottedPathForTransformNode,
|
|
377
|
+
cloneTransformNode,
|
|
378
|
+
cloneTransformNodeMaterial,
|
|
379
|
+
injectTransformNodeMetadata,
|
|
380
|
+
assertTransformNode,
|
|
381
|
+
activateTransformNode,
|
|
382
|
+
deactivateTransformNode,
|
|
383
|
+
setMaterial,
|
|
384
|
+
setSourceNodeMaterial,
|
|
385
|
+
setMaterialColor,
|
|
386
|
+
setMaterialTexture,
|
|
387
|
+
setMaterialMetallness,
|
|
388
|
+
setMaterialRoughness,
|
|
389
|
+
addToHighlightLayer,
|
|
390
|
+
removeFromHighlightLayer,
|
|
391
|
+
getClientRectFromMesh
|
|
392
|
+
};
|