gltfjsx-rbl 0.0.1
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/LICENSE +24 -0
- package/README.md +49 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +43 -0
- package/dist/cli.js.map +1 -0
- package/dist/emit.d.ts +16 -0
- package/dist/emit.d.ts.map +1 -0
- package/dist/emit.js +99 -0
- package/dist/emit.js.map +1 -0
- package/dist/graph.d.ts +32 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +64 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/sanitize.d.ts +8 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +18 -0
- package/dist/sanitize.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <https://unlicense.org>
|
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# gltfjsx-rbl
|
|
2
|
+
|
|
3
|
+
Turns `.glb`/`.gltf` files into typed, declarative [react-babylon-lite](https://github.com/brianzinn/react-babylon-lite)
|
|
4
|
+
components — a [pmndrs/gltfjsx](https://github.com/pmndrs/gltfjsx) for Babylon Lite.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npx gltfjsx-rbl public/models/Fox.glb --name FoxModel --url /models/Fox.glb --output src/models/fox-model.tsx
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
<FoxModel scaling={[0.028, 0.028, 0.028]} onAnimations={(api) => api.crossFade('Survey', 'Run', 300)} />
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## How it works
|
|
15
|
+
|
|
16
|
+
The CLI reads ONLY the node graph (names, hierarchy, mesh/skin/material assignments, clip
|
|
17
|
+
names) via `@gltf-transform/core` — no GPU, no `@babylonjs/lite` import (lite cannot load
|
|
18
|
+
glTF headlessly). The generated component references the loaded objects by name at runtime
|
|
19
|
+
through `useGltfGraph(url)` and mounts each mesh with `<Primitive object={nodes.x}>`; when
|
|
20
|
+
the file has animation clips it wires `useAnimations` and exposes the clip api via an
|
|
21
|
+
`onAnimations` callback prop. The output is yours to edit: delete nodes, hang physics/gizmo/
|
|
22
|
+
pointer-event children on them, override transforms and material fields.
|
|
23
|
+
|
|
24
|
+
## Options
|
|
25
|
+
|
|
26
|
+
| Flag | Meaning |
|
|
27
|
+
| ----------------- | ------------------------------------------------------------ |
|
|
28
|
+
| `--name` (`-n`) | Component name (default derived from the file name) |
|
|
29
|
+
| `--url` (`-u`) | Runtime URL the app loads the asset from (default `/<file>`) |
|
|
30
|
+
| `--output` (`-o`) | Output path (default `<ComponentName>.tsx`) |
|
|
31
|
+
| `--shadows` | Emit `receiveShadows` on each mesh |
|
|
32
|
+
|
|
33
|
+
The exact command is echoed into the generated file's header so it is reproducible.
|
|
34
|
+
|
|
35
|
+
## Notes
|
|
36
|
+
|
|
37
|
+
- On Windows, run from PowerShell — Git Bash rewrites `--url /models/x.glb` into a Windows
|
|
38
|
+
path (MSYS argument conversion).
|
|
39
|
+
- Node keys mirror `useGltfGraph`'s runtime indexing exactly; material keys are best-effort
|
|
40
|
+
(lite's loader may not carry every glTF material name through).
|
|
41
|
+
- Multi-primitive meshes are flagged with a comment — lite may split them into one mesh per
|
|
42
|
+
primitive at load; verify the runtime names.
|
|
43
|
+
- Clips live on the renderer's shared animation manager (the container is never scene-added),
|
|
44
|
+
which also makes remounting safe.
|
|
45
|
+
- **glTF cameras are noted, not used.** Babylon Lite's glTF loader does not parse cameras
|
|
46
|
+
(they never reach the runtime container), so a camera in the file is reported in the header
|
|
47
|
+
comment — supply your own (`<ArcRotateCamera>`).
|
|
48
|
+
- Nameless nodes aren't addressable at runtime (lite drops them from the graph), so a file
|
|
49
|
+
whose only mesh is nameless generates a component that renders nothing.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { writeFile } from 'node:fs/promises';
|
|
3
|
+
import { basename, resolve } from 'node:path';
|
|
4
|
+
import { parseArgs } from 'node:util';
|
|
5
|
+
import { emitComponent } from './emit.js';
|
|
6
|
+
import { readGraphModel } from './graph.js';
|
|
7
|
+
const { values, positionals } = parseArgs({
|
|
8
|
+
allowPositionals: true,
|
|
9
|
+
options: {
|
|
10
|
+
output: { type: 'string', short: 'o' },
|
|
11
|
+
url: { type: 'string', short: 'u' },
|
|
12
|
+
name: { type: 'string', short: 'n' },
|
|
13
|
+
shadows: { type: 'boolean' },
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
const file = positionals[0];
|
|
17
|
+
if (file === undefined) {
|
|
18
|
+
console.error('usage: gltfjsx-rbl <file.glb|file.gltf> [--name Model] [--url /models/x.glb] [--output Model.tsx] [--shadows]');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const toComponentName = (fileName) => {
|
|
22
|
+
const stem = fileName.replace(/\.(glb|gltf)$/i, '');
|
|
23
|
+
const pascal = stem
|
|
24
|
+
.split(/[^A-Za-z0-9]+/)
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
.map((part) => part[0].toUpperCase() + part.slice(1))
|
|
27
|
+
.join('');
|
|
28
|
+
return /^[0-9]/.test(pascal) || pascal.length === 0 ? `Model${pascal}` : `${pascal}Model`;
|
|
29
|
+
};
|
|
30
|
+
const model = await readGraphModel(resolve(file));
|
|
31
|
+
const componentName = values.name ?? toComponentName(basename(file));
|
|
32
|
+
const code = await emitComponent(model, {
|
|
33
|
+
componentName,
|
|
34
|
+
url: values.url ?? `/${basename(file)}`,
|
|
35
|
+
version: process.env['npm_package_version'] ?? '',
|
|
36
|
+
// Echo the exact invocation so the generated file records how to reproduce it.
|
|
37
|
+
command: `npx gltfjsx-rbl ${process.argv.slice(2).join(' ')}`,
|
|
38
|
+
shadows: values.shadows === true,
|
|
39
|
+
});
|
|
40
|
+
const outPath = resolve(values.output ?? `${componentName}.tsx`);
|
|
41
|
+
await writeFile(outPath, code, 'utf8');
|
|
42
|
+
console.log(`wrote ${outPath} (${model.flat.length} nodes, ${model.materials.length} materials, ${model.animations.length} clips)`);
|
|
43
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IACxC,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE;QACP,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;QACtC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;QACnC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;QACpC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;KAC7B;CACF,CAAC,CAAC;AAEH,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC5B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;IACvB,OAAO,CAAC,KAAK,CACX,+GAA+G,CAChH,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAU,EAAE;IACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI;SAChB,KAAK,CAAC,eAAe,CAAC;SACtB,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACrD,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,OAAO,CAAC;AAC5F,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACrE,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE;IACtC,aAAa;IACb,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE;IACvC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,EAAE;IACjD,+EAA+E;IAC/E,OAAO,EAAE,mBAAmB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;IAC7D,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI;CACjC,CAAC,CAAC;AACH,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,aAAa,MAAM,CAAC,CAAC;AACjE,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACvC,OAAO,CAAC,GAAG,CACT,SAAS,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,WAAW,KAAK,CAAC,SAAS,CAAC,MAAM,eAAe,KAAK,CAAC,UAAU,CAAC,MAAM,SAAS,CACvH,CAAC"}
|
package/dist/emit.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GraphModel } from './graph.js';
|
|
2
|
+
export interface EmitOptions {
|
|
3
|
+
/** Generated component name, e.g. "FoxModel". */
|
|
4
|
+
componentName: string;
|
|
5
|
+
/** Runtime URL the app loads the asset from, e.g. "/models/Fox.glb". */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Tool version stamped into the header. */
|
|
8
|
+
version?: string;
|
|
9
|
+
/** The exact CLI invocation, echoed into the header so the file is reproducible. */
|
|
10
|
+
command?: string;
|
|
11
|
+
/** Emit `receiveShadows` on each mesh (gltfjsx `--shadows`). */
|
|
12
|
+
shadows?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Graph model → a typed react-babylon-lite component module (TSX source, prettier-formatted). */
|
|
15
|
+
export declare const emitComponent: (model: GraphModel, options: EmitOptions) => Promise<string>;
|
|
16
|
+
//# sourceMappingURL=emit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,YAAY,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAWD,kGAAkG;AAClG,eAAO,MAAM,aAAa,GAAU,OAAO,UAAU,EAAE,SAAS,WAAW,KAAG,OAAO,CAAC,MAAM,CA6G3F,CAAC"}
|
package/dist/emit.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { format } from 'prettier';
|
|
2
|
+
const primitiveLine = (node, shadows) => {
|
|
3
|
+
const receiveShadows = shadows ? ' receiveShadows' : '';
|
|
4
|
+
const warning = node.primitiveCount > 1
|
|
5
|
+
? ` {/* ${node.primitiveCount} primitives — lite may split this mesh; verify the runtime name */}`
|
|
6
|
+
: '';
|
|
7
|
+
return ` <Primitive object={nodes.${node.identifier}}${receiveShadows} />${warning}`;
|
|
8
|
+
};
|
|
9
|
+
/** Graph model → a typed react-babylon-lite component module (TSX source, prettier-formatted). */
|
|
10
|
+
export const emitComponent = async (model, options) => {
|
|
11
|
+
const { componentName, url, shadows = false } = options;
|
|
12
|
+
// Babylon Lite's glTF loader drops camera nodes entirely (they never reach the runtime
|
|
13
|
+
// AssetContainer), so cameras are NOTED but never emitted as runtime nodes — doing so would
|
|
14
|
+
// type `nodes.x` as present when it is actually undefined at runtime.
|
|
15
|
+
const runtime = model.flat.filter((node) => node.kind !== 'camera');
|
|
16
|
+
const named = runtime.filter((node) => node.identifier !== null);
|
|
17
|
+
const meshNodes = named.filter((node) => node.kind === 'mesh');
|
|
18
|
+
const plainNodes = named.filter((node) => node.kind === 'node');
|
|
19
|
+
const cameraCount = model.flat.filter((node) => node.kind === 'camera').length;
|
|
20
|
+
const nameless = runtime.length - named.length;
|
|
21
|
+
const hasAnimations = model.animations.length > 0;
|
|
22
|
+
const hasMaterials = model.materials.length > 0;
|
|
23
|
+
const nodesType = named.length > 0
|
|
24
|
+
? `export interface ${componentName}Nodes {
|
|
25
|
+
${named.map((node) => ` ${node.identifier}: ${node.kind === 'mesh' ? 'Mesh' : 'SceneNode'};`).join('\n')}
|
|
26
|
+
}`
|
|
27
|
+
: `export type ${componentName}Nodes = Record<string, never>;`;
|
|
28
|
+
// Import only the types actually referenced (verbatimModuleSyntax + no-unused-vars).
|
|
29
|
+
const liteTypes = [
|
|
30
|
+
meshNodes.length > 0 ? 'Mesh' : '',
|
|
31
|
+
hasMaterials ? 'PbrMaterialProps' : '',
|
|
32
|
+
plainNodes.length > 0 ? 'SceneNode' : '',
|
|
33
|
+
].filter(Boolean);
|
|
34
|
+
const liteTypeImport = liteTypes.length > 0 ? `import type { ${liteTypes.join(', ')} } from '@babylonjs/lite';\n` : '';
|
|
35
|
+
const commandLine = options.command !== undefined ? `\n * Command: ${options.command}` : '';
|
|
36
|
+
const cameraNote = cameraCount > 0
|
|
37
|
+
? `\n * Note: the source declares ${cameraCount} camera(s), but Babylon Lite's glTF loader
|
|
38
|
+
* does not parse cameras — supply your own (e.g. <ArcRotateCamera>).`
|
|
39
|
+
: '';
|
|
40
|
+
const header = `/*
|
|
41
|
+
* Auto-generated by gltfjsx-rbl ${options.version ?? ''} — edit freely, it's yours.${commandLine}
|
|
42
|
+
* Source: ${model.source} (${named.length} named nodes, ${model.materials.length} materials${hasAnimations ? `, clips: ${model.animations.join(', ')}` : ''})
|
|
43
|
+
* Node keys mirror useGltfGraph's runtime indexing; material keys are best-effort (lite's
|
|
44
|
+
* loader may not carry every glTF material name through).${nameless > 0 ? `\n * ${nameless} nameless node(s) are not addressable at runtime.` : ''}${cameraNote}
|
|
45
|
+
*/`;
|
|
46
|
+
const animationImports = hasAnimations
|
|
47
|
+
? `import { useAnimations } from 'react-babylon-lite/animation';
|
|
48
|
+
import type { AnimationsApi } from 'react-babylon-lite/animation';
|
|
49
|
+
import { useEffect } from 'react';
|
|
50
|
+
`
|
|
51
|
+
: '';
|
|
52
|
+
const materialsType = hasMaterials
|
|
53
|
+
? `export interface ${componentName}Materials {
|
|
54
|
+
${model.materials.map((material) => ` ${material.identifier}: PbrMaterialProps;`).join('\n')}
|
|
55
|
+
}`
|
|
56
|
+
: `export type ${componentName}Materials = Record<string, never>;`;
|
|
57
|
+
const propsType = hasAnimations
|
|
58
|
+
? `export interface ${componentName}Props extends ComponentProps<typeof TransformNode> {
|
|
59
|
+
/** Clip api (play / crossFade / setSpeed / …). Clips: ${model.animations.join(', ')}. */
|
|
60
|
+
onAnimations?: (animations: AnimationsApi) => void;
|
|
61
|
+
}`
|
|
62
|
+
: `export type ${componentName}Props = ComponentProps<typeof TransformNode>;`;
|
|
63
|
+
const signature = hasAnimations
|
|
64
|
+
? `{ onAnimations, ...props }: ${componentName}Props`
|
|
65
|
+
: `props: ${componentName}Props`;
|
|
66
|
+
const graphDestructure = hasAnimations ? '{ nodes, animationGroups }' : '{ nodes }';
|
|
67
|
+
const animationBody = hasAnimations
|
|
68
|
+
? ` const animations = useAnimations(animationGroups);
|
|
69
|
+
useEffect(() => onAnimations?.(animations), [animations, onAnimations]);
|
|
70
|
+
`
|
|
71
|
+
: '';
|
|
72
|
+
const children = meshNodes.length > 0
|
|
73
|
+
? meshNodes.map((node) => primitiveLine(node, shadows)).join('\n')
|
|
74
|
+
: ' {/* no mesh nodes in this file */}';
|
|
75
|
+
const code = `${header}
|
|
76
|
+
${liteTypeImport}import type { ComponentProps } from 'react';
|
|
77
|
+
${animationImports}import { useGltfGraph } from 'react-babylon-lite';
|
|
78
|
+
import { Primitive, TransformNode } from 'react-babylon-lite/components';
|
|
79
|
+
|
|
80
|
+
export const MODEL_URL = '${url}';
|
|
81
|
+
|
|
82
|
+
${nodesType}
|
|
83
|
+
|
|
84
|
+
${materialsType}
|
|
85
|
+
|
|
86
|
+
${propsType}
|
|
87
|
+
|
|
88
|
+
export function ${componentName}(${signature}) {
|
|
89
|
+
const ${graphDestructure} = useGltfGraph<${componentName}Nodes, ${componentName}Materials>(MODEL_URL);
|
|
90
|
+
${animationBody} return (
|
|
91
|
+
<TransformNode name="${componentName}" {...props}>
|
|
92
|
+
${children}
|
|
93
|
+
</TransformNode>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
return format(code, { parser: 'typescript', singleQuote: true, printWidth: 110 });
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=emit.js.map
|
package/dist/emit.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"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"}
|
package/dist/graph.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface GraphNodeModel {
|
|
2
|
+
/** Unique JS identifier (null when the glTF node is nameless — unreachable at runtime). */
|
|
3
|
+
identifier: string | null;
|
|
4
|
+
name: string;
|
|
5
|
+
kind: 'mesh' | 'camera' | 'node';
|
|
6
|
+
skinned: boolean;
|
|
7
|
+
/** >1 means lite may split this into one Mesh per primitive — flagged in the output. */
|
|
8
|
+
primitiveCount: number;
|
|
9
|
+
/** Identifiers of the materials this node's mesh primitives use. */
|
|
10
|
+
materials: string[];
|
|
11
|
+
children: GraphNodeModel[];
|
|
12
|
+
}
|
|
13
|
+
export interface GraphMaterialModel {
|
|
14
|
+
identifier: string;
|
|
15
|
+
name: string;
|
|
16
|
+
}
|
|
17
|
+
export interface GraphModel {
|
|
18
|
+
source: string;
|
|
19
|
+
roots: GraphNodeModel[];
|
|
20
|
+
/** Depth-first flattening of roots — the emission and runtime-claim order. */
|
|
21
|
+
flat: GraphNodeModel[];
|
|
22
|
+
materials: GraphMaterialModel[];
|
|
23
|
+
/** Clip names in file order (lite auto-plays the first). */
|
|
24
|
+
animations: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Reads ONLY the node graph — names, hierarchy, mesh/material/skin assignments, clip names —
|
|
28
|
+
* via @gltf-transform/core. No geometry decoding, no GPU, so this runs anywhere node does
|
|
29
|
+
* (lite itself cannot load glTF headlessly — it needs a WebGPU engine).
|
|
30
|
+
*/
|
|
31
|
+
export declare const readGraphModel: (filePath: string) => Promise<GraphModel>;
|
|
32
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,2FAA2F;IAC3F,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,cAAc,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,8EAA8E;IAC9E,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,UAAU,CA0DzE,CAAC"}
|
package/dist/graph.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { NodeIO } from '@gltf-transform/core';
|
|
2
|
+
import { basename } from 'node:path';
|
|
3
|
+
import { claimName, sanitizeName } from './sanitize.js';
|
|
4
|
+
/**
|
|
5
|
+
* Reads ONLY the node graph — names, hierarchy, mesh/material/skin assignments, clip names —
|
|
6
|
+
* via @gltf-transform/core. No geometry decoding, no GPU, so this runs anywhere node does
|
|
7
|
+
* (lite itself cannot load glTF headlessly — it needs a WebGPU engine).
|
|
8
|
+
*/
|
|
9
|
+
export const readGraphModel = async (filePath) => {
|
|
10
|
+
const document = await new NodeIO().read(filePath);
|
|
11
|
+
const root = document.getRoot();
|
|
12
|
+
const nodeNames = new Set();
|
|
13
|
+
const materialNames = new Set();
|
|
14
|
+
const materialIds = new Map();
|
|
15
|
+
const materials = [];
|
|
16
|
+
let materialIndex = 0;
|
|
17
|
+
const flat = [];
|
|
18
|
+
// Mirrors the runtime walk: materials claimed at first encounter during the node DFS,
|
|
19
|
+
// nameless ones falling back to their discovery index.
|
|
20
|
+
const claimMaterial = (material) => {
|
|
21
|
+
const existing = materialIds.get(material);
|
|
22
|
+
if (existing !== undefined)
|
|
23
|
+
return existing;
|
|
24
|
+
const rawName = material.getName();
|
|
25
|
+
const base = rawName.length > 0 ? rawName : `material_${materialIndex}`;
|
|
26
|
+
materialIndex += 1;
|
|
27
|
+
const identifier = claimName(sanitizeName(base), materialNames);
|
|
28
|
+
materialIds.set(material, identifier);
|
|
29
|
+
materials.push({ identifier, name: rawName });
|
|
30
|
+
return identifier;
|
|
31
|
+
};
|
|
32
|
+
const visit = (node) => {
|
|
33
|
+
const name = node.getName();
|
|
34
|
+
const mesh = node.getMesh();
|
|
35
|
+
const primitives = mesh?.listPrimitives() ?? [];
|
|
36
|
+
const model = {
|
|
37
|
+
identifier: name.length > 0 ? claimName(sanitizeName(name), nodeNames) : null,
|
|
38
|
+
name,
|
|
39
|
+
kind: mesh !== null ? 'mesh' : node.getCamera() !== null ? 'camera' : 'node',
|
|
40
|
+
skinned: node.getSkin() !== null,
|
|
41
|
+
primitiveCount: primitives.length,
|
|
42
|
+
materials: [],
|
|
43
|
+
children: [],
|
|
44
|
+
};
|
|
45
|
+
for (const primitive of primitives) {
|
|
46
|
+
const material = primitive.getMaterial();
|
|
47
|
+
if (material !== null) {
|
|
48
|
+
const id = claimMaterial(material);
|
|
49
|
+
if (!model.materials.includes(id))
|
|
50
|
+
model.materials.push(id);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
flat.push(model);
|
|
54
|
+
model.children = node.listChildren().map(visit);
|
|
55
|
+
return model;
|
|
56
|
+
};
|
|
57
|
+
const scene = root.getDefaultScene() ?? root.listScenes()[0];
|
|
58
|
+
const roots = scene === undefined ? [] : scene.listChildren().map(visit);
|
|
59
|
+
const animations = root
|
|
60
|
+
.listAnimations()
|
|
61
|
+
.map((animation, index) => (animation.getName().length > 0 ? animation.getName() : `animation_${index}`));
|
|
62
|
+
return { source: basename(filePath), roots, flat, materials, animations };
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { readGraphModel } from './graph.js';
|
|
2
|
+
export type { GraphMaterialModel, GraphModel, GraphNodeModel } from './graph.js';
|
|
3
|
+
export { emitComponent } from './emit.js';
|
|
4
|
+
export type { EmitOptions } from './emit.js';
|
|
5
|
+
export { claimName, sanitizeName } from './sanitize.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* glTF names → JS identifiers. MUST stay in sync with react-babylon-lite's sanitizeGraphName
|
|
3
|
+
* and its claim() suffixing — the generated component's keys are only valid because the
|
|
4
|
+
* runtime hook reproduces them from the same names in the same depth-first order.
|
|
5
|
+
*/
|
|
6
|
+
export declare const sanitizeName: (name: string) => string;
|
|
7
|
+
export declare const claimName: (base: string, taken: Set<string>) => string;
|
|
8
|
+
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MAG3C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,CAAC,KAAG,MAM5D,CAAC"}
|
package/dist/sanitize.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* glTF names → JS identifiers. MUST stay in sync with react-babylon-lite's sanitizeGraphName
|
|
3
|
+
* and its claim() suffixing — the generated component's keys are only valid because the
|
|
4
|
+
* runtime hook reproduces them from the same names in the same depth-first order.
|
|
5
|
+
*/
|
|
6
|
+
export const sanitizeName = (name) => {
|
|
7
|
+
const cleaned = name.replace(/[^A-Za-z0-9_$]/g, '_');
|
|
8
|
+
return /^[0-9]/.test(cleaned) || cleaned.length === 0 ? `_${cleaned}` : cleaned;
|
|
9
|
+
};
|
|
10
|
+
export const claimName = (base, taken) => {
|
|
11
|
+
let name = base;
|
|
12
|
+
let suffix = 1;
|
|
13
|
+
while (taken.has(name))
|
|
14
|
+
name = `${base}_${suffix++}`;
|
|
15
|
+
taken.add(name);
|
|
16
|
+
return name;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAU,EAAE;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAClF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,KAAkB,EAAU,EAAE;IACpE,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,IAAI,GAAG,GAAG,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC;IACrD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gltfjsx-rbl",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Turns glTF/GLB files into typed, declarative react-babylon-lite components (a pmndrs/gltfjsx for Babylon Lite)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"gltfjsx",
|
|
7
|
+
"gltf",
|
|
8
|
+
"glb",
|
|
9
|
+
"react",
|
|
10
|
+
"babylon-lite",
|
|
11
|
+
"react-babylon-lite",
|
|
12
|
+
"codegen"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"bin": {
|
|
16
|
+
"gltfjsx-rbl": "./dist/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"author": "Brian Zinn <542756+brianzinn@users.noreply.github.com>",
|
|
31
|
+
"license": "Unlicense",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/brianzinn/react-babylon-lite.git",
|
|
35
|
+
"directory": "packages/gltfjsx"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/brianzinn/react-babylon-lite#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/brianzinn/react-babylon-lite/issues"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@gltf-transform/core": "^4.0.0",
|
|
43
|
+
"prettier": "^3.0.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^24.0.0",
|
|
47
|
+
"rimraf": "^6.1.3",
|
|
48
|
+
"typescript": "^6.0.3",
|
|
49
|
+
"vitest": "^4.1.10"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.build.json",
|
|
53
|
+
"clean": "rimraf dist",
|
|
54
|
+
"prebuild": "npm run clean",
|
|
55
|
+
"typecheck": "tsc --noEmit",
|
|
56
|
+
"test": "vitest run"
|
|
57
|
+
}
|
|
58
|
+
}
|