Load dropped files into AssetContainer

We are building a specialized editor and want to be able to drop GLTF files in similar to how it works in Sandbox (drag in the gltf and the bin file). I’ve reviewed the code used in Sandbox to allow gltf files to be dropped and loaded via FilesInput, but I want to have more control over how the assets get added to the scene. Specifically, I want the assets to be added to an asset container. I understand how I can get the file content as a blob when the file is dropped, and I think I have seen how that blob can be used to load assets. But a GLTF file has a corresponding bin file. Is there a way to load assets into a scene from an array of blobs (one for each file)?

1 Like

Paging @bghgary, our glTF loading master. :smile:

I’m not sure using blobs is the right choice here. glTF files reference other files via url. If you convert everything into blobs, you will need to remap all the reference urls to the blob urls you created. You can do this using preprocessUrlAsync, but I think you don’t need to do this.

If you look at the code for the filesInput class, you’ll see that it uses the file: syntax to access dropped files. Maybe we can augment filesInput class to support using LoadAssetContainer instead of LoadAsync, but you should be able to do this without that. Just make sure to use the file: way instead of using blobs and put the dropped files in FilesInputStore.FilesToLoad.

I tried doing as @bghgary suggested, but I got an error:
Access to XMLHttpRequest at 'file:///meterCube.bin' from origin 'http://localhost:3600' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
followed by
Uncaught (in promise) LoadFileError: /buffers/0/uri: Failed to load 'meterCube.bin': 0.

This is my code that I used to try to process the result of dropping the files:

            // Apparently FileList is not an array so have to iterate it the old-fashioned way
for (let i = 0; i < files.length; i++) {
    console.log(files[i]);
    const fileParts = files[i].name.split('.')
    if (fileParts.length > 1 && fileParts[1] == 'gltf') {
        gltfFile = files[i];
    }
    // Set files to be loaded by scene loader
    FilesInputStore.FilesToLoad[files[i].name] = files[i]
}
if (!gltfFile) {
    _errorHandler("No gltf file dropped.")
}

getSceneLoader().LoadAssetContainerAsync("file:", gltfFile, getBaseScene())
.then(processAssetContainer);

Can you see what I might be doing wrong?

Updated: I realized that FilesToLoad is a dictionary so I updated my code to set it in the loop. Same error, so that did not appear to be the issue.

I don’t see anything from your code, but the fact that it’s trying to access file:///<file> doesn’t seem right. What are the paths being put into FilesToLoad?

I thought the same thing about it trying to use a file url. This is the console log output for the files. I’m just adding these objects to FilesToLoad using the file name as the key.

File {name: “meterCube.bin”, lastModified: 1560775664000, lastModifiedDate: Mon Jun 17 2019 08:47:44 GMT-0400 (Eastern Daylight Time), webkitRelativePath: “”, size: 1224, …}
lastModified: 1560775664000
lastModifiedDate: Mon Jun 17 2019 08:47:44 GMT-0400 (Eastern Daylight Time) {}
name: “meterCube.bin”
size: 1224
type: “application/macbinary”
webkitRelativePath: “”
proto: File

File {name: "meterCube.gltf", lastModified: 1560775664000, lastModifiedDate: Mon Jun 17 2019 08:47:44 GMT-0400 (Eastern Daylight Time), webkitRelativePath: "", size: 1208, …}
lastModified: 1560775664000
lastModifiedDate: Mon Jun 17 2019 08:47:44 GMT-0400 (Eastern Daylight Time) {}
name: "meterCube.gltf"
size: 1208
type: ""
webkitRelativePath: ""
__proto__: File

The issue was that the file names used as keys in FilesInputStore need to be lowercased. Once I did that I was able to load GLTF files via drag and drop.

2 Likes