Skip to content

Commit 9fe74fc

Browse files
committed
feat(Rendering): report missing view node profile imports
fixes #3343
1 parent 9d00695 commit 9fe74fc

File tree

4 files changed

+134
-1
lines changed

4 files changed

+134
-1
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { registerProfileHints } from 'vtk.js/Sources/Rendering/SceneGraph/ViewNodeFactory/profileHints';
2+
3+
registerProfileHints(
4+
[
5+
'vtkActor',
6+
'vtkActor2D',
7+
'vtkCamera',
8+
'vtkCubeAxesActor',
9+
'vtkMapper',
10+
'vtkMapper2D',
11+
'vtkPixelSpaceCallbackMapper',
12+
'vtkRenderWindow',
13+
'vtkRenderer',
14+
'vtkScalarBarActor',
15+
'vtkSkybox',
16+
'vtkTexture',
17+
],
18+
'Geometry'
19+
);
20+
21+
registerProfileHints(
22+
[
23+
'vtkAbstractImageMapper',
24+
'vtkImageCPRMapper',
25+
'vtkImageMapper',
26+
'vtkImageResliceMapper',
27+
'vtkImageSlice',
28+
'vtkVolume',
29+
'vtkVolumeMapper',
30+
],
31+
'Volume'
32+
);
33+
34+
registerProfileHints(['vtkGlyph3DMapper'], 'Glyph');
35+
registerProfileHints(['vtkSphereMapper', 'vtkStickMapper'], 'Molecule');
36+
registerProfileHints(['vtkSurfaceLICMapper'], 'LIC');

Sources/Rendering/SceneGraph/ViewNodeFactory/index.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,45 @@
11
import macro from 'vtk.js/Sources/macros';
2+
import { getProfileForClass, getSuggestedProfile } from './profileHints';
3+
import 'vtk.js/Sources/Rendering/OpenGL/Profiles/profileHintManifest';
4+
import 'vtk.js/Sources/Rendering/WebGPU/Profiles/profileHintManifest';
5+
6+
const { vtkOnceErrorMacro } = macro;
7+
8+
function listClassHierarchy(dataObject) {
9+
const classNames = [];
10+
let depth = 0;
11+
let className = dataObject.getClassName(depth++);
12+
while (className) {
13+
classNames.push(className);
14+
className = dataObject.getClassName(depth++);
15+
}
16+
return classNames;
17+
}
18+
19+
function buildMissingImplementationMessage(factoryName, classNames) {
20+
const classList = classNames.join(' → ');
21+
const suggestedClass = getSuggestedProfile(classNames);
22+
const suggestedProfile = suggestedClass && getProfileForClass(suggestedClass);
23+
24+
if (suggestedProfile) {
25+
return [
26+
`No ${factoryName} implementation found for ${classNames[0]}.`,
27+
`Class hierarchy: ${classList}.`,
28+
'This usually means the rendering profile import is missing.',
29+
`Try importing '@kitware/vtk.js/Rendering/Profiles/${suggestedProfile}' or 'vtk.js/Sources/Rendering/Profiles/${suggestedProfile}'.`,
30+
"You can also use the full profile imports '@kitware/vtk.js/Rendering/Profiles/All' or 'vtk.js/Sources/Rendering/Profiles/All'.",
31+
].join('\n');
32+
}
33+
34+
return [
35+
`No ${factoryName} implementation found for ${classNames[0]}.`,
36+
`Class hierarchy: ${classList}.`,
37+
'If this is a built-in renderable, a rendering profile import may be missing.',
38+
"Try importing '@kitware/vtk.js/Rendering/Profiles/All' or 'vtk.js/Sources/Rendering/Profiles/All',",
39+
'or import the specific rendering profile needed by this renderable.',
40+
'If this is a custom renderable, register a matching override with the view node factory.',
41+
].join('\n');
42+
}
243

344
// ----------------------------------------------------------------------------
445
// vtkViewNodeFactory methods
@@ -18,8 +59,9 @@ function vtkViewNodeFactory(publicAPI, model) {
1859
return null;
1960
}
2061

62+
const classNames = listClassHierarchy(dataObject);
2163
let cpt = 0;
22-
let className = dataObject.getClassName(cpt++);
64+
let className = classNames[cpt++];
2365
let isObject = false;
2466
const keys = Object.keys(model.overrides);
2567
while (className && !isObject) {
@@ -31,6 +73,9 @@ function vtkViewNodeFactory(publicAPI, model) {
3173
}
3274

3375
if (!isObject) {
76+
vtkOnceErrorMacro(
77+
buildMissingImplementationMessage(publicAPI.getClassName(), classNames)
78+
);
3479
return null;
3580
}
3681
const vn = model.overrides[className]();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const PROFILE_HINTS = Object.create(null);
2+
3+
export function registerProfileHint(className, profile) {
4+
PROFILE_HINTS[className] = profile;
5+
}
6+
7+
export function registerProfileHints(classNames, profile) {
8+
classNames.forEach((className) => {
9+
registerProfileHint(className, profile);
10+
});
11+
}
12+
13+
export function getSuggestedProfile(classNames) {
14+
return classNames.find((className) => PROFILE_HINTS[className]);
15+
}
16+
17+
export function getProfileForClass(className) {
18+
return PROFILE_HINTS[className];
19+
}
20+
21+
export default {
22+
registerProfileHint,
23+
registerProfileHints,
24+
getSuggestedProfile,
25+
getProfileForClass,
26+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { registerProfileHints } from 'vtk.js/Sources/Rendering/SceneGraph/ViewNodeFactory/profileHints';
2+
3+
registerProfileHints(
4+
[
5+
'vtkActor',
6+
'vtkActor2D',
7+
'vtkCamera',
8+
'vtkCubeAxesActor',
9+
'vtkMapper',
10+
'vtkMapper2D',
11+
'vtkPixelSpaceCallbackMapper',
12+
'vtkRenderWindow',
13+
'vtkRenderer',
14+
'vtkScalarBarActor',
15+
'vtkTexture',
16+
],
17+
'Geometry'
18+
);
19+
20+
registerProfileHints(
21+
['vtkImageMapper', 'vtkImageSlice', 'vtkVolume'],
22+
'Volume'
23+
);
24+
registerProfileHints(['vtkGlyph3DMapper'], 'Glyph');
25+
registerProfileHints(['vtkSphereMapper', 'vtkStickMapper'], 'Molecule');
26+
registerProfileHints(['vtkSurfaceLICMapper'], 'LIC');

0 commit comments

Comments
 (0)