fix: resolve gltf companion assets reliably

This commit is contained in:
Tom Boullay
2026-04-27 23:01:29 +02:00
parent aeb0832409
commit 5556364601
5 changed files with 82 additions and 14 deletions
+17 -4
View File
@@ -29,15 +29,28 @@ interface AlphaMapMaterial extends Material {
const alphaMapTextureCache = new WeakMap<Texture, Texture>()
function getRequestedFilename(requestedUrl: string) {
const cleanUrl = decodeURIComponent(requestedUrl.split(/[?#]/)[0] || '')
return cleanUrl.split(/[\\/]/).pop()?.toLowerCase()
}
function resolveSingleBinFallback(filename: string | undefined, assetUrls: Record<string, string>) {
if (!filename?.endsWith('.bin')) return undefined
const binEntries = Object.entries(assetUrls).filter(([assetName]) => assetName.endsWith('.bin'))
return binEntries.length === 1 ? binEntries[0][1] : undefined
}
function resolveAssetUrl(requestedUrl: string, assetUrls: Record<string, string>) {
if (requestedUrl.startsWith('blob:') || requestedUrl.startsWith('data:')) {
if (requestedUrl.startsWith('data:')) {
return requestedUrl
}
const cleanUrl = decodeURIComponent(requestedUrl.split(/[?#]/)[0] || '')
const filename = cleanUrl.split(/[\\/]/).pop()?.toLowerCase()
const filename = getRequestedFilename(requestedUrl)
const exactAssetUrl = filename ? assetUrls[filename] : undefined
const fallbackBinUrl = resolveSingleBinFallback(filename, assetUrls)
return filename ? assetUrls[filename] || requestedUrl : requestedUrl
return exactAssetUrl || fallbackBinUrl || requestedUrl
}
function getOpacityMapEntries(assetUrls: Record<string, string>) {
+5 -5
View File
@@ -72,11 +72,11 @@ export default function FolderDropzone({
const inputRef = useRef<HTMLInputElement>(null)
const [isDragActive, setIsDragActive] = useState(false)
const processFiles = (files: File[], fallbackFolderName = 'folder') => {
const processFiles = async (files: File[], fallbackFolderName = 'folder') => {
if (files.length === 0) return
const folderName = files[0].webkitRelativePath?.split('/')[0] || fallbackFolderName
const validation = validateFolder(files)
const validation = await validateFolder(files)
if (!validation.ok) {
onError(validation.errors.join(' | '))
@@ -107,7 +107,7 @@ export default function FolderDropzone({
const selected = e.target.files
if (!selected || selected.length === 0) return
processFiles(Array.from(selected))
void processFiles(Array.from(selected))
e.target.value = ''
}
@@ -148,14 +148,14 @@ export default function FolderDropzone({
const rootEntry = directoryEntries[0]
const files = await collectEntryFiles(rootEntry)
processFiles(files, rootEntry.name)
await processFiles(files, rootEntry.name)
return
}
const droppedFiles = Array.from(e.dataTransfer.files)
if (droppedFiles.length === 0) return
processFiles(droppedFiles)
await processFiles(droppedFiles)
} catch {
onError('Impossible de lire le dossier depose')
}
+1 -1
View File
@@ -11,7 +11,7 @@ export default function WarningBanner({ warnings }: WarningBannerProps) {
<div className="mt-2 px-3 py-2 bg-yellow-900/20 border border-yellow-700/30 rounded-lg">
<div className="flex items-center gap-2 text-xs text-yellow-400">
<WarningIcon className="w-4 h-4" />
<span>Textures manquantes : {warnings.join(', ')}</span>
<span>{warnings.join(' ')}</span>
</div>
</div>
)