fix: canonicalize asset families

This commit is contained in:
Tom Boullay
2026-04-27 23:35:43 +02:00
parent fa77c484f9
commit 31c05a35fc
4 changed files with 39 additions and 13 deletions
+4 -4
View File
@@ -6,19 +6,19 @@ export function classifyAssetCategory(filename: string): AssetCategory {
const name = filename.replace(/\.[^.]+$/, '')
const family = getAssetFamily(name.split('_')[0])
if (family === 'baseColor' || family === 'color') {
if (family === 'color' || family === 'diffuse') {
return 'color'
}
if (family === 'roughness' || family === 'occlusionRoughnessMetallic') {
if (family === 'roughness') {
return 'roughness'
}
if (family === 'normal' || family === 'normalOpengl') {
if (family === 'normal') {
return 'normal'
}
if (family === 'metallic' || family === 'metalness') {
if (family === 'metalness') {
return 'metalness'
}
+14 -4
View File
@@ -1,12 +1,9 @@
export const ASSET_FAMILIES = [
'baseColor',
'color',
'diffuse',
'roughness',
'normal',
'normalOpengl',
'metallic',
'metalness',
'occlusionRoughnessMetallic',
'height',
'opacity',
] as const
@@ -14,11 +11,24 @@ export const ASSET_FAMILIES = [
export type AssetFamily = typeof ASSET_FAMILIES[number]
const ASSET_FAMILY_BY_KEY = new Map(ASSET_FAMILIES.map((family) => [family.toLowerCase(), family]))
const FORBIDDEN_ASSET_FAMILY_ALIASES: ReadonlyMap<string, AssetFamily> = new Map([
['basecolor', 'color'],
['base_color', 'color'],
['normalopengl', 'normal'],
['normal_opengl', 'normal'],
['metallic', 'metalness'],
['occlusionroughnessmetallic', 'roughness'],
['occlusion_roughness_metallic', 'roughness'],
])
export function getAssetFamily(value: string): AssetFamily | undefined {
return ASSET_FAMILY_BY_KEY.get(value.toLowerCase())
}
export function getForbiddenAssetFamilyAlias(value: string): AssetFamily | undefined {
return FORBIDDEN_ASSET_FAMILY_ALIASES.get(value.toLowerCase())
}
export function formatAssetFamilies() {
return ASSET_FAMILIES.join(', ')
}
+18 -2
View File
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
import { ASSET_EXTENSIONS, TEXTURE_EXTENSIONS } from '@/lib/constants'
import { formatAssetFamilies, getAssetFamily } from '@/lib/asset-naming'
import { formatAssetFamilies, getAssetFamily, getForbiddenAssetFamilyAlias } from '@/lib/asset-naming'
import type { TextureFile } from '@/lib/client-types'
const SUPPORT_FILE_EXT_ARRAY = [...TEXTURE_EXTENSIONS, ...ASSET_EXTENSIONS]
@@ -46,15 +46,31 @@ function getTextureNamingError(file: File) {
const stem = getFileStem(file.name)
const [prefix, ...targetParts] = stem.split('_')
const family = getAssetFamily(prefix)
const extension = file.name.split('.').pop()
if (family && targetParts.every(Boolean)) return null
const aliasSuggestion = getForbiddenAssetFamilyAlias(prefix)
if (aliasSuggestion && targetParts.every(Boolean)) {
const target = targetParts.join('_')
return `Convention invalide : ${file.name}. Utilisez ${aliasSuggestion}_${target}.${extension} pour cibler "${target}", ou ${aliasSuggestion}.${extension} pour tout le modele.`
}
const reversedParts = stem.split('_')
const reversedFamily = reversedParts.length > 1 ? getAssetFamily(reversedParts[reversedParts.length - 1]) : undefined
const reversedAliasSuggestion = reversedParts.length > 1
? getForbiddenAssetFamilyAlias(reversedParts[reversedParts.length - 1])
: undefined
if (reversedFamily) {
const target = reversedParts.slice(0, -1).join('_')
return `Convention invalide : ${file.name}. Utilisez ${reversedFamily}_${target}.${file.name.split('.').pop()} pour cibler "${target}", ou ${reversedFamily}.${file.name.split('.').pop()} pour tout le modele.`
return `Convention invalide : ${file.name}. Utilisez ${reversedFamily}_${target}.${extension} pour cibler "${target}", ou ${reversedFamily}.${extension} pour tout le modele.`
}
if (reversedAliasSuggestion) {
const target = reversedParts.slice(0, -1).join('_')
return `Convention invalide : ${file.name}. Utilisez ${reversedAliasSuggestion}_${target}.${extension} pour cibler "${target}", ou ${reversedAliasSuggestion}.${extension} pour tout le modele.`
}
return `Asset inconnu : ${file.name}. Familles autorisees : ${formatAssetFamilies()}. Utilisez asset.png pour tout le modele ou asset_objet.png pour cibler un objet.`