74 lines
2.1 KiB
JavaScript
74 lines
2.1 KiB
JavaScript
import { access, mkdir } from 'node:fs/promises'
|
|
import { constants } from 'node:fs'
|
|
import { dirname, resolve } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { spawn } from 'node:child_process'
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url))
|
|
const harnessRoot = resolve(here, '..')
|
|
const projectRoot = resolve(harnessRoot, '..')
|
|
const blendFile = resolve(projectRoot, 'blender_prototype', 'sanctification_card_material_prototype.blend')
|
|
const pythonScript = resolve(here, 'export_card_mesh.py')
|
|
const outputFile = resolve(harnessRoot, 'public', 'reference', 'card-mesh.glb')
|
|
|
|
const explicit = process.env.BLENDER_EXECUTABLE
|
|
const platformCandidates = process.platform === 'win32'
|
|
? [
|
|
'C:\\Program Files\\Blender Foundation\\Blender 5.2\\blender.exe',
|
|
'C:\\Program Files\\Blender Foundation\\Blender 5.1\\blender.exe',
|
|
'C:\\Program Files\\Blender Foundation\\Blender 5.0\\blender.exe',
|
|
]
|
|
: [
|
|
'/usr/bin/blender',
|
|
'/usr/local/bin/blender',
|
|
'/snap/bin/blender',
|
|
]
|
|
|
|
async function exists(path) {
|
|
try {
|
|
await access(path, constants.X_OK)
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
let blender = explicit
|
|
if (blender && !(await exists(blender))) {
|
|
throw new Error(`BLENDER_EXECUTABLE does not exist or is not executable: ${blender}`)
|
|
}
|
|
if (!blender) {
|
|
for (const candidate of platformCandidates) {
|
|
if (await exists(candidate)) {
|
|
blender = candidate
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if (!blender) blender = 'blender'
|
|
|
|
await mkdir(dirname(outputFile), { recursive: true })
|
|
|
|
const args = [
|
|
'--background',
|
|
blendFile,
|
|
'--python',
|
|
pythonScript,
|
|
'--',
|
|
'--output',
|
|
outputFile,
|
|
]
|
|
|
|
console.log(`Exporting card mesh with ${blender}`)
|
|
const child = spawn(blender, args, { stdio: 'inherit', shell: false })
|
|
const exitCode = await new Promise((resolveExit, reject) => {
|
|
child.once('error', reject)
|
|
child.once('exit', (code) => resolveExit(code ?? 1))
|
|
})
|
|
|
|
if (exitCode !== 0) {
|
|
throw new Error(`Blender export failed with exit code ${exitCode}`)
|
|
}
|
|
|
|
console.log(`Card mesh exported to ${outputFile}`)
|