@combeenation/3d-viewer 5.0.3 → 5.1.0-rc1
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/api/classes/element.d.ts +10 -0
- package/dist/lib-cjs/api/classes/element.js +43 -0
- package/dist/lib-cjs/api/classes/element.js.map +1 -1
- package/dist/lib-cjs/api/classes/variant.js +73 -37
- package/dist/lib-cjs/api/classes/variant.js.map +1 -1
- package/dist/lib-cjs/api/classes/viewer.d.ts +7 -0
- package/dist/lib-cjs/api/classes/viewer.js +14 -0
- package/dist/lib-cjs/api/classes/viewer.js.map +1 -1
- package/dist/lib-cjs/api/util/babylonHelper.js +6 -0
- package/dist/lib-cjs/api/util/babylonHelper.js.map +1 -1
- package/dist/lib-cjs/api/util/sceneLoaderHelper.d.ts +16 -6
- package/dist/lib-cjs/api/util/sceneLoaderHelper.js +48 -44
- package/dist/lib-cjs/api/util/sceneLoaderHelper.js.map +1 -1
- package/dist/lib-cjs/buildinfo.json +1 -1
- package/package.json +1 -1
- package/src/api/classes/element.ts +45 -0
- package/src/api/classes/variant.ts +47 -8
- package/src/api/classes/viewer.ts +18 -0
- package/src/api/util/babylonHelper.ts +6 -0
- package/src/api/util/sceneLoaderHelper.ts +101 -0
- package/src/dev.ts +23 -1
- package/src/tsconfig.json +1 -0
- package/src/types.d.ts +25 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Scene } from '@babylonjs/core/scene';
|
|
2
|
+
import { ISceneLoaderPlugin } from '@babylonjs/core/Loading/sceneLoader';
|
|
3
|
+
import { AssetContainer } from '@babylonjs/core/assetContainer';
|
|
4
|
+
import { injectNodeMetadata } from './babylonHelper';
|
|
5
|
+
import has from 'lodash-es/has';
|
|
6
|
+
import { Material } from '@babylonjs/core/Materials/material';
|
|
7
|
+
|
|
8
|
+
const missingMaterialMetadataName = 'missingMaterial';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create and return a custom loader plugin to be registered with SceneLoader, that allows
|
|
12
|
+
* us to run our own code against the input data before using the standard procedure to
|
|
13
|
+
* import.
|
|
14
|
+
* @param previousLoaderPlugin the actual loader that's executed after manipulating the input data
|
|
15
|
+
* @returns Custom loader plugin to be registered with SceneLoader.RegisterPlugin()
|
|
16
|
+
*/
|
|
17
|
+
const getCustomCbnBabylonLoaderPlugin = function (previousLoaderPlugin: ISceneLoaderPlugin): ISceneLoaderPlugin {
|
|
18
|
+
const customLoader: ISceneLoaderPlugin = {
|
|
19
|
+
name: 'cbnCustomBabylonLoader',
|
|
20
|
+
extensions: '.babylon',
|
|
21
|
+
importMesh: previousLoaderPlugin.importMesh,
|
|
22
|
+
load: previousLoaderPlugin.load,
|
|
23
|
+
loadAssetContainer: function (scene, data, rootUrl, onError) {
|
|
24
|
+
//* 1) --- manipulate ORIGINAL data
|
|
25
|
+
const dataParsed = JSON.parse(data);
|
|
26
|
+
//* 2) --- call default (non-custom) loading method
|
|
27
|
+
const importedContainer = previousLoaderPlugin.loadAssetContainer(scene, data, rootUrl);
|
|
28
|
+
//* 3) --- manipulate IMPORTED data
|
|
29
|
+
addMissingMaterialMetadata(dataParsed, importedContainer);
|
|
30
|
+
//* 4) --- return imported data
|
|
31
|
+
return importedContainer;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
return customLoader;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Return an observer to be applied to meshes in order to post-load missing materials
|
|
39
|
+
* upon set enabled/visible.
|
|
40
|
+
* @param targetMeshOrInstance AbstractMesh the observer will be applied to
|
|
41
|
+
* @param concerningMesh Mesh to look for missing materials on, and create/apply to (when found).
|
|
42
|
+
* @returns observer
|
|
43
|
+
*/
|
|
44
|
+
const getMaterialPostLoadObserver = function (targetMeshOrInstance: AbstractMesh, concerningMesh: Mesh) {
|
|
45
|
+
return (_eventData: any, _eventState: any) => {
|
|
46
|
+
const hasBeenEnabled = targetMeshOrInstance.isEnabled(true);
|
|
47
|
+
const materialMissing = has(concerningMesh.metadata, missingMaterialMetadataName);
|
|
48
|
+
if (!hasBeenEnabled || !materialMissing) return;
|
|
49
|
+
// get id of missing material
|
|
50
|
+
const missingMatId = concerningMesh.metadata[missingMaterialMetadataName];
|
|
51
|
+
// try to find material on the scene
|
|
52
|
+
const existingMat = concerningMesh.getScene().getMaterialById(missingMatId);
|
|
53
|
+
// assign either existing material or freshly created one
|
|
54
|
+
concerningMesh.material = existingMat || getMaterialFromCbnAssets(missingMatId, concerningMesh.getScene());
|
|
55
|
+
// since the material is there now, we do not need the related metadata tag anymore
|
|
56
|
+
delete concerningMesh.metadata[missingMaterialMetadataName];
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Internal function that compares the original meshes on a .babylon file with what was loaded,
|
|
62
|
+
* and tags missing materials with respective metadata on respective meshes.
|
|
63
|
+
* @param dataParsed original data
|
|
64
|
+
* @param container loaded data
|
|
65
|
+
*/
|
|
66
|
+
const addMissingMaterialMetadata = function (dataParsed: any, container: AssetContainer) {
|
|
67
|
+
container.meshes.forEach(currMeshImported => {
|
|
68
|
+
for (const currMeshOriginal of dataParsed.meshes) {
|
|
69
|
+
if (currMeshOriginal.name !== currMeshImported.name) continue;
|
|
70
|
+
// we're dealing with the original version of the current imported mesh now
|
|
71
|
+
const materialOnImportedMesh = currMeshImported.material?.id;
|
|
72
|
+
const materialOnOriginalMesh = currMeshOriginal.materialId;
|
|
73
|
+
if (!materialOnOriginalMesh || materialOnImportedMesh === materialOnOriginalMesh) continue;
|
|
74
|
+
// TODO: Just for easier debugging. Remove before publishment...
|
|
75
|
+
console.info(
|
|
76
|
+
`Adding "${missingMaterialMetadataName}" info on mesh "${currMeshOriginal.name}" with material "${currMeshOriginal.materialId}"`
|
|
77
|
+
);
|
|
78
|
+
// if we're here, the imported mesh has different material than original one
|
|
79
|
+
window.Cbn?.Assets.assertMaterialExists(materialOnOriginalMesh);
|
|
80
|
+
injectNodeMetadata(currMeshImported, { [missingMaterialMetadataName]: materialOnOriginalMesh }, false);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Look up the provided materials (see library import) and create and return one if found.
|
|
88
|
+
* @param materialId BabylonJs material-id. E.g. 'concrete".
|
|
89
|
+
* @param scene BabylonJs scene
|
|
90
|
+
* @returns PBRMaterial | null
|
|
91
|
+
*/
|
|
92
|
+
export const getMaterialFromCbnAssets = function (materialId: string, scene: Scene): Material | null {
|
|
93
|
+
const materialDefinition = window.Cbn?.Assets.getMaterial(materialId);
|
|
94
|
+
// The generic `Material.Parse` actually returns a more specific material like `BABYLON.StandardMaterial`,
|
|
95
|
+
// `BABYLON.PBRMaterial` or stuff like `BABYLON.PBRMetallicRoughnessMaterial` etc. based on the given `customType`
|
|
96
|
+
// within the material JSON definition
|
|
97
|
+
const material = materialDefinition && Material.Parse(materialDefinition, scene, '');
|
|
98
|
+
return material || null;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export { getCustomCbnBabylonLoaderPlugin, getMaterialPostLoadObserver, missingMaterialMetadataName };
|
package/src/dev.ts
CHANGED
|
@@ -3,7 +3,14 @@ import { set } from 'lodash-es';
|
|
|
3
3
|
|
|
4
4
|
import { Emitter, Viewer } from '.';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
createSpec,
|
|
8
|
+
beforeBootstrap,
|
|
9
|
+
afterBootstrap,
|
|
10
|
+
createUIelements,
|
|
11
|
+
getMaterial,
|
|
12
|
+
mockMaterials,
|
|
13
|
+
} from '../assets/index';
|
|
7
14
|
|
|
8
15
|
const loadingElement = document.getElementById('loading') as HTMLDivElement;
|
|
9
16
|
|
|
@@ -18,6 +25,21 @@ Emitter.on(Event.BOOTSTRAP_START, () => {
|
|
|
18
25
|
|
|
19
26
|
document.addEventListener('DOMContentLoaded', main);
|
|
20
27
|
|
|
28
|
+
window.Cbn = {
|
|
29
|
+
Assets: {
|
|
30
|
+
getMaterial(materialId: string) {
|
|
31
|
+
const material = getMaterial(materialId);
|
|
32
|
+
if (material) return material;
|
|
33
|
+
|
|
34
|
+
// Fallback to random mock material
|
|
35
|
+
return mockMaterials[Math.floor(Math.random() * mockMaterials.length)];
|
|
36
|
+
},
|
|
37
|
+
assertMaterialExists(materialId: string): boolean {
|
|
38
|
+
return true;
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
21
43
|
async function main() {
|
|
22
44
|
const viewer = await bootstrapViewer();
|
|
23
45
|
// "Export" for console testing...
|
package/src/tsconfig.json
CHANGED
package/src/types.d.ts
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
1
|
/** @ignore **/
|
|
2
2
|
declare let IS_PRODUCTION: boolean;
|
|
3
3
|
declare let VERSION_INFORMATION: string;
|
|
4
|
+
|
|
5
|
+
interface Window {
|
|
6
|
+
Cbn:
|
|
7
|
+
| undefined /* window.Cbn is only available when viewer runs inside Combeenation configurator */
|
|
8
|
+
| {
|
|
9
|
+
Assets: {
|
|
10
|
+
/**
|
|
11
|
+
* Retrieve material definition from configurator
|
|
12
|
+
*
|
|
13
|
+
* @param materialId
|
|
14
|
+
*
|
|
15
|
+
* @return Undefined if no definition for the given material name exists, otherwise an "JSON object" which can
|
|
16
|
+
* be passed to `BABYLON.Material.Parse` to create a runtime material object.
|
|
17
|
+
*/
|
|
18
|
+
getMaterial(materialId: string): object | undefined;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks if a definition for a given material name exists in the configurator and issues a warning if not.
|
|
22
|
+
*
|
|
23
|
+
* @param materialId
|
|
24
|
+
*/
|
|
25
|
+
assertMaterialExists(materialId: string): boolean;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
}
|