@combeenation/3d-viewer 15.1.0-beta1 → 16.0.0-alpha1
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/dist/lib-cjs/buildinfo.json +1 -1
- package/dist/lib-cjs/commonjs.tsconfig.tsbuildinfo +1 -1
- package/dist/lib-cjs/helper/decals-helper.d.ts +45 -0
- package/dist/lib-cjs/helper/decals-helper.js +49 -0
- package/dist/lib-cjs/helper/decals-helper.js.map +1 -0
- package/dist/lib-cjs/index.d.ts +1 -0
- package/dist/lib-cjs/index.js +1 -0
- package/dist/lib-cjs/index.js.map +1 -1
- package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.d.ts +22 -4
- package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js +84 -21
- package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js.map +1 -1
- package/dist/lib-cjs/internal/metadata-helper.d.ts +1 -1
- package/dist/lib-cjs/manager/model-manager.d.ts +10 -1
- package/dist/lib-cjs/manager/model-manager.js +40 -1
- package/dist/lib-cjs/manager/model-manager.js.map +1 -1
- package/dist/lib-cjs/viewer-error.d.ts +1 -0
- package/dist/lib-cjs/viewer-error.js +1 -0
- package/dist/lib-cjs/viewer-error.js.map +1 -1
- package/package.json +1 -1
- package/src/helper/decals-helper.ts +95 -0
- package/src/index.ts +1 -0
- package/src/internal/cbn-custom-babylon-loader-plugin.ts +106 -34
- package/src/internal/metadata-helper.ts +1 -1
- package/src/manager/model-manager.ts +56 -1
- package/src/viewer-error.ts +1 -0
|
@@ -1,16 +1,54 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AssetContainer,
|
|
3
|
+
DecalConfiguration,
|
|
4
|
+
ISceneLoaderPlugin,
|
|
5
|
+
InstancedMesh,
|
|
6
|
+
SceneLoader,
|
|
7
|
+
ViewerError,
|
|
8
|
+
ViewerErrorIds,
|
|
9
|
+
createDecalMesh,
|
|
10
|
+
} from '../index';
|
|
2
11
|
import { setInternalMetadataValue } from './metadata-helper';
|
|
3
12
|
import { deleteAllTags, getTags, setTagsAsString } from './tags-helper';
|
|
4
|
-
import { isArray, isString } from 'lodash-es';
|
|
13
|
+
import { isArray, isNumber, isString } from 'lodash-es';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Contains cbn custom data, like decals.
|
|
17
|
+
* This is just a temporary type, as the `loadAssetContainer` function only returns an asset container, which can be
|
|
18
|
+
* altered by our file loader plugin.
|
|
19
|
+
* After loading the model, `cbnData` is cropped and a pure asset container is available for further processing.
|
|
20
|
+
*/
|
|
21
|
+
export class ExtendedAssetContainer extends AssetContainer {
|
|
22
|
+
cbnData?: CbnBabylonFileData;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type CbnBabylonFileData = { decals?: ParsedDecalConfiguration[] };
|
|
26
|
+
export type ParsedDecalConfiguration = DecalConfiguration & { materialId?: string };
|
|
27
|
+
|
|
28
|
+
type DataWithMeshes = { meshes: unknown[] };
|
|
29
|
+
type DataWithDecalConfigurations = { cbnData: { decals: unknown[] } };
|
|
30
|
+
|
|
31
|
+
type MeshData = {
|
|
32
|
+
name: string;
|
|
33
|
+
materialId?: string;
|
|
34
|
+
instances?: unknown[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type InstanceData = {
|
|
38
|
+
name: string;
|
|
39
|
+
tags?: string;
|
|
40
|
+
};
|
|
5
41
|
|
|
6
42
|
/**
|
|
7
43
|
* Create and return a custom loader plugin to be registered with SceneLoader, that allows
|
|
8
44
|
* us to run our own code against the input data before using the standard procedure to
|
|
9
45
|
* import.
|
|
10
|
-
* The main use
|
|
11
|
-
* dedicated mesh gets
|
|
12
|
-
* This is the case if the babylon file is a Combeenation "3d asset" which comes without materials, as the
|
|
13
|
-
* are defined as "material assets".
|
|
46
|
+
* The main use cases are:
|
|
47
|
+
* - Marking missing material in meshes, which will get loaded on demand at the first time the dedicated mesh gets
|
|
48
|
+
* visible. This is the case if the babylon file is a Combeenation "3d asset" which comes without materials, as the
|
|
49
|
+
* materials are defined as "material assets".
|
|
50
|
+
* - Interpreting custom cbn data that have been injected in the babylon file, e.g. by the "decals editor" in the asset
|
|
51
|
+
* editor area
|
|
14
52
|
*/
|
|
15
53
|
export function registerCustomCbnBabylonLoaderPlugin(): void {
|
|
16
54
|
// get original plugin for babylon files
|
|
@@ -23,46 +61,32 @@ export function registerCustomCbnBabylonLoaderPlugin(): void {
|
|
|
23
61
|
extensions: '.babylon',
|
|
24
62
|
importMesh: previousLoaderPlugin.importMesh,
|
|
25
63
|
load: previousLoaderPlugin.load,
|
|
26
|
-
loadAssetContainer:
|
|
27
|
-
// temporarily remove all morph target managers from scene before loading the model to avoid clashes with existing
|
|
28
|
-
// unique ids => see CB-9928
|
|
29
|
-
// NOTE: morph target managers still exist on the dedicated mesh when getting removed from the scene, only
|
|
30
|
-
// `scene.getMorphTargetManagerById` is affected, which is used internally in the `loadAssetContainer` function
|
|
31
|
-
const curMorphTargetManagers = scene.morphTargetManagers;
|
|
32
|
-
scene.morphTargetManagers = [];
|
|
33
|
-
|
|
64
|
+
loadAssetContainer: (scene, data, rootUrl, onError): ExtendedAssetContainer => {
|
|
34
65
|
const dataParsed = JSON.parse(data as string);
|
|
35
66
|
const importedContainer = previousLoaderPlugin.loadAssetContainer(scene, data, rootUrl);
|
|
36
67
|
|
|
37
68
|
_addMissingMaterialMetadata(dataParsed, importedContainer);
|
|
38
69
|
_reconstructTagsForInstancedMeshes(dataParsed, importedContainer);
|
|
70
|
+
_createDecals(dataParsed, importedContainer);
|
|
39
71
|
|
|
40
|
-
//
|
|
41
|
-
|
|
72
|
+
// add `cbnData` to output asset container, so that this information can be store as metadata for the model
|
|
73
|
+
const extendedContainer = importedContainer as ExtendedAssetContainer;
|
|
74
|
+
extendedContainer.cbnData = dataParsed.cbnData;
|
|
42
75
|
|
|
43
|
-
return
|
|
76
|
+
return extendedContainer;
|
|
44
77
|
},
|
|
45
78
|
};
|
|
46
79
|
|
|
47
80
|
SceneLoader.RegisterPlugin(customLoader);
|
|
48
81
|
}
|
|
49
82
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
tags?: string;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
function _isMeshInstanceData(data: any): data is InstanceData {
|
|
56
|
-
const hasName = isString(data.name);
|
|
57
|
-
const hasValidTags = !data.tags || isString(data.tags);
|
|
58
|
-
return hasName && hasValidTags;
|
|
83
|
+
function _isDataWithMeshes(data: any): data is DataWithMeshes {
|
|
84
|
+
return isArray(data?.meshes);
|
|
59
85
|
}
|
|
60
86
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
instances?: unknown[];
|
|
65
|
-
};
|
|
87
|
+
function _isDataWithDecalConfigurations(data: any): data is DataWithDecalConfigurations {
|
|
88
|
+
return isArray(data?.cbnData?.decals);
|
|
89
|
+
}
|
|
66
90
|
|
|
67
91
|
function _isMeshData(data: any): data is MeshData {
|
|
68
92
|
const hasName = isString(data.name);
|
|
@@ -71,10 +95,31 @@ function _isMeshData(data: any): data is MeshData {
|
|
|
71
95
|
return hasName && hasValidMaterialId;
|
|
72
96
|
}
|
|
73
97
|
|
|
74
|
-
|
|
98
|
+
function _isMeshInstanceData(data: any): data is InstanceData {
|
|
99
|
+
const hasName = isString(data.name);
|
|
100
|
+
const hasValidTags = !data.tags || isString(data.tags);
|
|
75
101
|
|
|
76
|
-
|
|
77
|
-
|
|
102
|
+
return hasName && hasValidTags;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function _isDecalConfiguration(data: any): data is ParsedDecalConfiguration {
|
|
106
|
+
const hasValidProps =
|
|
107
|
+
isString(data.name) &&
|
|
108
|
+
isString(data.sourceMeshName) &&
|
|
109
|
+
isArray(data.position) &&
|
|
110
|
+
isArray(data.normal) &&
|
|
111
|
+
isArray(data.size) &&
|
|
112
|
+
isNumber(data.angle) &&
|
|
113
|
+
isNumber(data.offset);
|
|
114
|
+
|
|
115
|
+
if (!hasValidProps) {
|
|
116
|
+
throw new ViewerError({
|
|
117
|
+
id: ViewerErrorIds.InvalidDecalConfiguration,
|
|
118
|
+
message: `Configuration for decal "${data.name}" invalid`,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return hasValidProps;
|
|
78
123
|
}
|
|
79
124
|
|
|
80
125
|
/**
|
|
@@ -138,3 +183,30 @@ function _reconstructTagsForInstancedMeshes(dataParsed: unknown, container: Asse
|
|
|
138
183
|
}
|
|
139
184
|
});
|
|
140
185
|
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* This function interprets the decal configuration, that is stored top level in the babylon file (`dataParsed`) and
|
|
189
|
+
* creates decal meshes in the given `container`.
|
|
190
|
+
*
|
|
191
|
+
* Having the decal information stored in that way is required for the "decals editor" in the asset manager, as meshes
|
|
192
|
+
* created from decals have to be updateable.
|
|
193
|
+
*
|
|
194
|
+
* @param container This is being manipulated, by adding decal meshes to it based on the decal configuration read from
|
|
195
|
+
* `dataParsed`.
|
|
196
|
+
*/
|
|
197
|
+
function _createDecals(dataParsed: unknown, container: AssetContainer): void {
|
|
198
|
+
if (!_isDataWithDecalConfigurations(dataParsed)) return;
|
|
199
|
+
|
|
200
|
+
const validatedDecals = dataParsed.cbnData.decals.filter(_isDecalConfiguration);
|
|
201
|
+
|
|
202
|
+
validatedDecals.forEach(decalConfig => {
|
|
203
|
+
const { materialId, ...decalMeshConfig } = decalConfig;
|
|
204
|
+
const decalMesh = createDecalMesh(decalMeshConfig, container, false);
|
|
205
|
+
|
|
206
|
+
// optionally set material directly
|
|
207
|
+
if (materialId) {
|
|
208
|
+
window.Cbn?.Assets.assertMaterialExists(materialId);
|
|
209
|
+
setInternalMetadataValue(decalMesh, 'deferredMaterial', materialId);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseTexture, Material, Node } from '../index';
|
|
2
2
|
import { cloneDeep } from 'lodash-es';
|
|
3
3
|
|
|
4
|
-
type MetadataValue = string | number | boolean | undefined;
|
|
4
|
+
type MetadataValue = string | number | boolean | object | undefined;
|
|
5
5
|
type MetadataTarget = Node | Material | BaseTexture;
|
|
6
6
|
type MetadataKeys =
|
|
7
7
|
// CBN babylon loader
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AssetContainer,
|
|
3
3
|
BuiltInParameter,
|
|
4
|
+
DecalConfiguration,
|
|
4
5
|
MaterialManager,
|
|
5
6
|
MeshBuilder,
|
|
6
7
|
ParameterManager,
|
|
@@ -10,6 +11,11 @@ import {
|
|
|
10
11
|
ViewerError,
|
|
11
12
|
ViewerErrorIds,
|
|
12
13
|
} from '../index';
|
|
14
|
+
import {
|
|
15
|
+
CbnBabylonFileData,
|
|
16
|
+
ExtendedAssetContainer,
|
|
17
|
+
ParsedDecalConfiguration,
|
|
18
|
+
} from '../internal/cbn-custom-babylon-loader-plugin';
|
|
13
19
|
import { cloneModelAssetContainer } from '../internal/cloning-helper';
|
|
14
20
|
import { getInternalMetadataValue } from '../internal/metadata-helper';
|
|
15
21
|
import { isArray } from 'lodash-es';
|
|
@@ -43,6 +49,7 @@ type Model = {
|
|
|
43
49
|
url: string;
|
|
44
50
|
state: ModelAssetState;
|
|
45
51
|
assetContainer: AssetContainer;
|
|
52
|
+
cbnBabylonFileData?: CbnBabylonFileData;
|
|
46
53
|
isClone: boolean;
|
|
47
54
|
visibilityCallId?: number;
|
|
48
55
|
};
|
|
@@ -359,6 +366,43 @@ export class ModelManager {
|
|
|
359
366
|
return model.assetContainer;
|
|
360
367
|
}
|
|
361
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Returns the decals configuration of a certain model.\
|
|
371
|
+
* The model will be loaded before being able to access this configuration.\
|
|
372
|
+
* Decals are already converted to "normal" meshes when loading a model, still the original decals configuration can
|
|
373
|
+
* be useful e.g. for alterning decals.
|
|
374
|
+
*/
|
|
375
|
+
public async getDecalsConfigurationOfModel(name: string): Promise<DecalConfiguration[]> {
|
|
376
|
+
const model = this._getModel(name);
|
|
377
|
+
if (!model) {
|
|
378
|
+
throw new ViewerError({
|
|
379
|
+
id: ViewerErrorIds.ModelNotRegistered,
|
|
380
|
+
message: `Can't get decals configuration of model "${name}" as model is not registered`,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (model.state === 'notLoaded') {
|
|
385
|
+
await this._loadModel(model);
|
|
386
|
+
} else if (model.state === 'loading') {
|
|
387
|
+
await this._loadModelPromises[model.name];
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (model.state !== 'inScene') {
|
|
391
|
+
await this._prepareModelForScene(model);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// crop materialId as this is not part of `DecalConfiguration`
|
|
395
|
+
const decals = ((model.cbnBabylonFileData?.decals ?? []) as ParsedDecalConfiguration[]).map<DecalConfiguration>(
|
|
396
|
+
parsedDecal => {
|
|
397
|
+
const croppedDecal = parsedDecal;
|
|
398
|
+
delete croppedDecal.materialId;
|
|
399
|
+
return croppedDecal;
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
return decals;
|
|
404
|
+
}
|
|
405
|
+
|
|
362
406
|
/**
|
|
363
407
|
* Get model by name
|
|
364
408
|
*/
|
|
@@ -384,7 +428,18 @@ export class ModelManager {
|
|
|
384
428
|
|
|
385
429
|
let assetContainer;
|
|
386
430
|
try {
|
|
387
|
-
|
|
431
|
+
const fullContainer = (await SceneLoader.LoadAssetContainerAsync(
|
|
432
|
+
'',
|
|
433
|
+
model.url,
|
|
434
|
+
this.viewer.scene
|
|
435
|
+
)) as ExtendedAssetContainer;
|
|
436
|
+
|
|
437
|
+
// crop and store custom cbn data from .babylon file
|
|
438
|
+
model.cbnBabylonFileData = fullContainer.cbnData;
|
|
439
|
+
delete fullContainer.cbnData;
|
|
440
|
+
|
|
441
|
+
// from here it's a basic asset container again
|
|
442
|
+
assetContainer = fullContainer as AssetContainer;
|
|
388
443
|
} catch (e) {
|
|
389
444
|
throw new ViewerError({
|
|
390
445
|
id: ViewerErrorIds.AssetLoadingFailed,
|
package/src/viewer-error.ts
CHANGED
|
@@ -29,6 +29,7 @@ export const ViewerErrorIds = {
|
|
|
29
29
|
TextureCouldNotBeParsed: 'TextureCouldNotBeParsed',
|
|
30
30
|
MaterialAlreadyExists: 'MaterialAlreadyExists',
|
|
31
31
|
NotAClonedMaterial: 'NotAClonedMaterial',
|
|
32
|
+
InvalidDecalConfiguration: 'InvalidDecalConfiguration',
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
/** @internal */
|