()
| 109 | } |
| 110 | |
| 111 | function main() { |
| 112 | const argv = process.argv.slice(2); |
| 113 | if (argv.length !== 2) { |
| 114 | console.error('usage: build-materials-from-json.ts <input-dir> <output-ts>'); |
| 115 | process.exit(2); |
| 116 | } |
| 117 | const inputDir = path.resolve(argv[0]); |
| 118 | const outputFile = path.resolve(argv[1]); |
| 119 | |
| 120 | if (!fs.existsSync(inputDir) || !fs.statSync(inputDir).isDirectory()) { |
| 121 | console.error(`input dir not found or not a directory: ${inputDir}`); |
| 122 | process.exit(2); |
| 123 | } |
| 124 | |
| 125 | const files = fs |
| 126 | .readdirSync(inputDir) |
| 127 | .filter((f) => f.endsWith('.json')) |
| 128 | .sort(); |
| 129 | |
| 130 | if (files.length === 0) { |
| 131 | console.error(`no .json files in ${inputDir}`); |
| 132 | process.exit(2); |
| 133 | } |
| 134 | |
| 135 | type Entry = { name: string; pascalName: string; constName: string; desc: MaterialJson }; |
| 136 | const entries: Entry[] = files.map((f) => { |
| 137 | const stem = path.basename(f, '.json'); |
| 138 | const raw = fs.readFileSync(path.join(inputDir, f), 'utf8'); |
| 139 | let parsed: unknown; |
| 140 | try { parsed = JSON.parse(raw); } |
| 141 | catch (e) { console.error(`${f}: invalid JSON: ${(e as Error).message}`); process.exit(1); } |
| 142 | try { |
| 143 | return { |
| 144 | name: stem, |
| 145 | pascalName: pascal(stem), |
| 146 | constName: `MAT_${snakeUpper(stem)}_DESC`, |
| 147 | desc: validate(f, parsed), |
| 148 | }; |
| 149 | } catch (e) { |
| 150 | console.error((e as Error).message); |
| 151 | process.exit(1); |
| 152 | } |
| 153 | }); |
| 154 | |
| 155 | const lines: string[] = []; |
| 156 | lines.push('// AUTO-GENERATED by engine/tools/build-materials-from-json.ts.'); |
| 157 | lines.push('// Do not edit. Regenerate from the source JSON via the build script.'); |
| 158 | lines.push('//'); |
| 159 | lines.push(`// Source: ${path.relative(process.cwd(), inputDir)}/*.json (${entries.length} file${entries.length === 1 ? '' : 's'})`); |
| 160 | lines.push(''); |
| 161 | lines.push("import { loadMaterial, MaterialDesc } from 'bloom/models';"); |
| 162 | lines.push(''); |
| 163 | |
| 164 | for (const e of entries) { |
| 165 | lines.push(`export const ${e.constName}: MaterialDesc = {`); |
| 166 | lines.push(` shader: ${JSON.stringify(e.desc.shader)},`); |
| 167 | lines.push(` bucket: ${JSON.stringify(e.desc.bucket)}${emitParams(e.desc.params)}`); |
| 168 | lines.push('};'); |
no test coverage detected