Skip to content

Commit 466fdbe

Browse files
committed
Revert "fix(soba): remove gltf generator (gonna make a separate CLI instead)"
This reverts commit ab1603a.
1 parent ab1603a commit 466fdbe

File tree

6 files changed

+281
-1
lines changed

6 files changed

+281
-1
lines changed

libs/plugin/generators.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
"factory": "./src/generators/add-soba/generator",
1111
"schema": "./src/generators/add-soba/schema.json",
1212
"description": "Add angular-three-soba to your project"
13+
},
14+
"gltf": {
15+
"factory": "./src/generators/gltf/generator",
16+
"schema": "./src/generators/gltf/schema.json",
17+
"description": "gltf generator"
1318
}
1419
},
1520
"schematics": {
@@ -22,6 +27,11 @@
2227
"factory": "./src/generators/add-soba/compat",
2328
"schema": "./src/generators/add-soba/schema.json",
2429
"description": "Add angular-three-soba to your project"
25-
}
30+
},
31+
"gltf": {
32+
"factory": "./src/generators/gltf/compat",
33+
"schema": "./src/generators/gltf/schema.json",
34+
"description": "gltf generator"
35+
}
2636
}
2737
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { convertNxGenerator } from '@nx/devkit';
2+
import gltfGenerator from './generator';
3+
4+
export default convertNxGenerator(gltfGenerator);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { CUSTOM_ELEMENTS_SCHEMA, Component, ChangeDetectionStrategy } from '@angular/core';
2+
import { extend, NgtGroup } from 'angular-three';
3+
import { injectGLTF } from 'angular-three-soba/loaders';
4+
import * as THREE from 'three';
5+
import { GLTF } from 'three-stdlib';
6+
7+
interface <%= className %>GLTFResult extends GLTF {
8+
nodes: {},
9+
materials: {}
10+
}
11+
12+
interface <%= className %>Options extends Partial<NgtGroup> {
13+
/* more options */
14+
}
15+
16+
@Component({
17+
selector: '<%= selector %>',
18+
standalone: true,
19+
template: `
20+
@if (gltf(); as gltf) {
21+
<ngt-group [dispose]="null" [parameters]="options()">
22+
</ngt-group>
23+
}
24+
`,
25+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
26+
changeDetection: ChangeDetectionStrategy.OnPush,
27+
})
28+
export class <%= className %> {
29+
options = input({} as <%= className %>Options);
30+
31+
gltf = injectGLTF(() => '<%= runtimeGltfPath %>') as Signal<<%= className %>GLTFResult | null>;
32+
33+
constructor() {
34+
extend({ Group: THREE.Group });
35+
}
36+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Tree } from '@nx/devkit';
2+
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
3+
4+
describe('gltf generator', () => {
5+
let tree: Tree;
6+
7+
beforeEach(() => {
8+
tree = createTreeWithEmptyWorkspace();
9+
});
10+
11+
it('should run successfully', async () => {
12+
expect(true).toBe(true);
13+
});
14+
15+
// it('should run successfully', async () => {
16+
// await gltfGenerator(tree, options);
17+
// const config = readProjectConfiguration(tree, 'test');
18+
// expect(config).toBeDefined();
19+
// });
20+
});
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import { formatFiles, logger, names, readJson, readProjectConfiguration, Tree, workspaceRoot } from '@nx/devkit';
2+
import { prompt } from 'enquirer';
3+
import { readFileSync } from 'node:fs';
4+
import { DRACOLoader, GLTFLoader, MeshoptDecoder } from 'three-stdlib';
5+
import { addSobaGenerator } from '../add-soba/generator';
6+
7+
export interface GltfGeneratorSchema {
8+
gltfPath: string;
9+
project: string;
10+
console: boolean;
11+
modelName: string;
12+
meshopt: boolean;
13+
outputPath?: string;
14+
draco?: boolean | string;
15+
}
16+
17+
function normalizeOptions(options: GltfGeneratorSchema) {
18+
let { gltfPath, project, console, modelName, outputPath, draco, meshopt } = options;
19+
20+
if (draco == null) {
21+
draco = true;
22+
}
23+
24+
return { gltfPath, project, console, modelName, outputPath, draco, meshopt };
25+
}
26+
27+
function buildSelector(fileName: string, prefix: string) {
28+
return `${prefix}-${fileName}`;
29+
}
30+
31+
function toArrayBuffer(buf: Buffer) {
32+
const ab = new ArrayBuffer(buf.length);
33+
const view = new Uint8Array(ab);
34+
for (let i = 0; i < buf.length; ++i) view[i] = buf[i];
35+
return ab;
36+
}
37+
38+
let dracoLoader: DRACOLoader | null = null;
39+
let decoderPath = 'https://www.gstatic.com/draco/versioned/decoders/1.5.5/';
40+
const loader = new GLTFLoader();
41+
42+
function load(input: string, draco: boolean | string, meshopt: boolean) {
43+
if (draco) {
44+
if (!dracoLoader) {
45+
dracoLoader = new DRACOLoader();
46+
}
47+
48+
dracoLoader.setDecoderPath(typeof draco === 'string' ? draco : decoderPath);
49+
(loader as GLTFLoader).setDRACOLoader(dracoLoader);
50+
}
51+
52+
if (meshopt) {
53+
(loader as GLTFLoader).setMeshoptDecoder(typeof MeshoptDecoder === 'function' ? MeshoptDecoder() : MeshoptDecoder);
54+
}
55+
56+
const data = input.startsWith('http')
57+
? null
58+
: (() => {
59+
const fileContent = readFileSync(input);
60+
return toArrayBuffer(fileContent);
61+
})();
62+
const operationFactory = (onLoad: (data: any) => void, onError: (error: ErrorEvent) => void) => {
63+
return input.startsWith('http')
64+
? loader.load.call(loader, input, onLoad, () => {}, onError)
65+
: loader.parse.call(loader, data, input, onLoad, onError);
66+
};
67+
68+
return new Promise((resolve, reject) => {
69+
operationFactory(resolve, reject);
70+
});
71+
}
72+
73+
export async function gltfGenerator(tree: Tree, options: GltfGeneratorSchema) {
74+
const packageJson = readJson(tree, 'package.json');
75+
const hasAngularThreeSoba =
76+
packageJson['dependencies']['angular-three-soba'] || packageJson['devDependencies']['angular-three-soba'];
77+
78+
if (!hasAngularThreeSoba) {
79+
logger.warn(`[NGT] angular-three-soba must be installed to use the GLTF generator`);
80+
const { initSoba } = await prompt<{ initSoba: boolean }>({
81+
type: 'confirm',
82+
name: 'initSoba',
83+
message: 'Would you like to initialize angular-three-soba?',
84+
initial: true,
85+
});
86+
if (!initSoba) return;
87+
await addSobaGenerator(tree);
88+
}
89+
90+
try {
91+
// const injectGLTF = await loadEsmModule<typeof import('angular-three-soba/loaders')>(
92+
// 'angular-three-soba/loaders',
93+
// ).then((m) => m.injectGLTF);
94+
// // const injectGLTF = await import('angular-three-soba/loaders').then((m) => m.injectGLTF);
95+
// const injectGLTF = require('angular-three-soba/loaders').injectGLTF;
96+
97+
const { gltfPath, project, console: toConsole, modelName, outputPath, draco, meshopt } = normalizeOptions(options);
98+
99+
let runtimeGltfPath: string;
100+
101+
if (!gltfPath.startsWith('http')) {
102+
const { path } = await prompt<{ path: string }>({
103+
type: 'input',
104+
name: 'path',
105+
message: 'What is the path to the asset file to be used at runtime (with injectGLTF)?',
106+
required: true,
107+
});
108+
runtimeGltfPath = path;
109+
} else {
110+
runtimeGltfPath = gltfPath;
111+
}
112+
113+
await load(runtimeGltfPath, draco, meshopt);
114+
115+
// injectGLTF.preload(() => runtimeGltfPath, {
116+
// useDraco: draco,
117+
// useMeshOpt: meshopt,
118+
// onLoad: (data) => {
119+
// console.log('data', data);
120+
// },
121+
// });
122+
123+
const projectConfig = readProjectConfiguration(tree, project);
124+
const modelNames = names(modelName);
125+
const tmpPath = `${workspaceRoot}/tmp/ngt-gltf/${modelNames.fileName}`;
126+
const output = toConsole ? tmpPath : (outputPath ?? (projectConfig.sourceRoot || `${projectConfig.root}/src`));
127+
128+
// NOTE: even if user passes in "console", we still generate the files.
129+
// But we generate them to a temporary destination then we'll remove them printing to console.
130+
// generateFiles(tree, 'files', output, {
131+
// tmpl: '',
132+
// fileName: modelNames.fileName,
133+
// className: modelNames.className,
134+
// selector: buildSelector(
135+
// modelNames.fileName,
136+
// 'prefix' in projectConfig && typeof projectConfig.prefix === 'string' ? projectConfig.prefix : 'app',
137+
// ),
138+
// runtimeGltfPath,
139+
// });
140+
141+
await formatFiles(tree);
142+
143+
if (toConsole) {
144+
// print to console
145+
// delete the files in tmp
146+
}
147+
} catch (e) {
148+
logger.error(`[NGT] Error generating GLTF files: ${e}`);
149+
}
150+
}
151+
152+
export default gltfGenerator;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"$schema": "https://json-schema.org/schema",
3+
"$id": "Gltf",
4+
"title": "",
5+
"type": "object",
6+
"properties": {
7+
"gltfPath": {
8+
"type": "string",
9+
"description": "",
10+
"$default": {
11+
"$source": "argv",
12+
"index": 0
13+
},
14+
"x-prompt": "Where is your gltf file located?"
15+
},
16+
"project": {
17+
"type": "string",
18+
"description": "The name of the project to generate the model component for.",
19+
"x-prompt": "What project would you like to generate the model component for?",
20+
"pattern": "(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$",
21+
"x-dropdown": "projects",
22+
"x-priority": "important"
23+
},
24+
"console": {
25+
"type": "boolean",
26+
"description": "Print to console instead of writing to file",
27+
"default": false
28+
},
29+
"modelName": {
30+
"type": "string",
31+
"description": "Name of the model",
32+
"default": "Model"
33+
},
34+
"outputPath": {
35+
"type": "string",
36+
"description": "The output path of the generated component",
37+
"alias": ["o", "output"]
38+
},
39+
"draco": {
40+
"oneOf": [
41+
{
42+
"type": "boolean",
43+
"description": "Use Draco compression"
44+
},
45+
{
46+
"type": "string",
47+
"description": "Use Draco compression with a specific path"
48+
}
49+
]
50+
},
51+
"meshopt": {
52+
"type": "boolean",
53+
"description": "Use Meshopt compression",
54+
"default": true
55+
}
56+
},
57+
"required": ["gltfPath", "project"]
58+
}

0 commit comments

Comments
 (0)