85 lines
2.4 KiB
TypeScript
85 lines
2.4 KiB
TypeScript
import { mkdir, readFile, stat, writeFile } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
|
|
const PRESETS_FILE = path.join(process.cwd(), 'src/lib/3d/material-pbr-presets.ts')
|
|
const OUTPUT_ROOT = path.join(process.cwd(), 'public/materials/pbr/polyhaven')
|
|
const URL_PATTERN = /https:\/\/(?:dl\.polyhaven\.org|polyhaven\.com|cdn\.polyhaven\.com)\/[^\s'"]+/g
|
|
|
|
function toLocalFilePath(remoteUrl: string): string | null {
|
|
try {
|
|
const parsed = new URL(remoteUrl)
|
|
const segments = parsed.pathname.split('/').filter(Boolean)
|
|
const fileName = segments.at(-1)
|
|
if (!fileName) return null
|
|
const assetName = segments.at(-2) || 'misc'
|
|
return path.join(OUTPUT_ROOT, assetName, fileName)
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function exists(filePath: string): Promise<boolean> {
|
|
try {
|
|
await stat(filePath)
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function downloadTexture(remoteUrl: string, localFilePath: string): Promise<void> {
|
|
const response = await fetch(remoteUrl)
|
|
if (!response.ok) {
|
|
throw new Error(`下载失败 ${response.status}: ${remoteUrl}`)
|
|
}
|
|
const buffer = Buffer.from(await response.arrayBuffer())
|
|
await mkdir(path.dirname(localFilePath), { recursive: true })
|
|
await writeFile(localFilePath, buffer)
|
|
}
|
|
|
|
async function main() {
|
|
const source = await readFile(PRESETS_FILE, 'utf8')
|
|
const matches = source.match(URL_PATTERN) || []
|
|
const remoteUrls = Array.from(new Set(matches))
|
|
|
|
if (remoteUrls.length === 0) {
|
|
console.log('未发现需要同步的远程贴图 URL。')
|
|
return
|
|
}
|
|
|
|
let downloaded = 0
|
|
let skipped = 0
|
|
let failed = 0
|
|
|
|
for (const remoteUrl of remoteUrls) {
|
|
const localFilePath = toLocalFilePath(remoteUrl)
|
|
if (!localFilePath) {
|
|
failed += 1
|
|
console.warn(`无法解析路径: ${remoteUrl}`)
|
|
continue
|
|
}
|
|
|
|
if (await exists(localFilePath)) {
|
|
skipped += 1
|
|
continue
|
|
}
|
|
|
|
try {
|
|
await downloadTexture(remoteUrl, localFilePath)
|
|
downloaded += 1
|
|
console.log(`已下载: ${path.relative(process.cwd(), localFilePath)}`)
|
|
} catch (error) {
|
|
failed += 1
|
|
console.warn(`下载失败: ${remoteUrl}`)
|
|
console.warn(error)
|
|
}
|
|
}
|
|
|
|
console.log(`同步完成:下载 ${downloaded},跳过 ${skipped},失败 ${failed}`)
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error('贴图同步脚本执行失败', error)
|
|
process.exit(1)
|
|
})
|