Fix the editor hanging when opening a scene with hundreds of instances of 3D model objects (#5470)

This commit is contained in:
AlexandreS
2023-07-10 17:31:29 +02:00
committed by GitHub
parent 556d13c881
commit a1dcf03a5b

View File

@@ -16,7 +16,9 @@ const loadedTextures = {};
const invalidTexture = PIXI.Texture.from('res/error48.png');
const loadedThreeTextures = {};
const loadedThreeMaterials = {};
const loaded3DModels = {};
const loadedOrLoading3DModelPromises: {
[resourceName: string]: Promise<THREE.THREE_ADDONS.GLTF>,
} = {};
const createInvalidModel = (): GLTF => {
/**
@@ -53,6 +55,37 @@ const getOrCreateGltfLoader = () => {
return gltfLoader;
};
const load3DModel = (
project: gdProject,
resourceName: string
): Promise<THREE.THREE_ADDONS.GLTF> => {
if (!project.getResourcesManager().hasResource(resourceName))
return Promise.resolve(invalidModel);
const resource = project.getResourcesManager().getResource(resourceName);
if (resource.getKind() !== 'model3D') return Promise.resolve(invalidModel);
const url = ResourcesLoader.getResourceFullUrl(project, resourceName, {
isResourceForPixi: true,
});
const gltfLoader = getOrCreateGltfLoader();
gltfLoader.withCredentials = checkIfCredentialsRequired(url);
return new Promise((resolve, reject) => {
gltfLoader.load(
url,
gltf => {
traverseToSetBasicMaterialFromMeshes(gltf.scene);
resolve(gltf);
},
undefined,
error => {
reject(error);
}
);
});
};
const determineCrossOrigin = (url: string) => {
// Any resource stored on the GDevelop Cloud buckets needs the "credentials" of the user,
// i.e: its gdevelop.io cookie, to be passed.
@@ -308,37 +341,12 @@ export default class PixiResourcesLoader {
project: gdProject,
resourceName: string
): Promise<THREE.THREE_ADDONS.GLTF> {
const loaded3DModel = loaded3DModels[resourceName];
if (loaded3DModel) return Promise.resolve(loaded3DModel);
const promise = loadedOrLoading3DModelPromises[resourceName];
if (promise) return promise;
if (!project.getResourcesManager().hasResource(resourceName))
return Promise.resolve(invalidModel);
const resource = project.getResourcesManager().getResource(resourceName);
if (resource.getKind() !== 'model3D') return Promise.resolve(invalidModel);
const url = ResourcesLoader.getResourceFullUrl(project, resourceName, {
isResourceForPixi: true,
});
const gltfLoader = getOrCreateGltfLoader();
gltfLoader.withCredentials = checkIfCredentialsRequired(url);
// TODO Cache promises that are not yet resolved to void `load` being
// called more than once for the same resource.
return new Promise((resolve, reject) => {
gltfLoader.load(
url,
gltf => {
traverseToSetBasicMaterialFromMeshes(gltf.scene);
loaded3DModels[resourceName] = gltf;
resolve(gltf);
},
undefined,
error => {
reject(error);
}
);
});
const loadingPromise = load3DModel(project, resourceName);
loadedOrLoading3DModelPromises[resourceName] = loadingPromise;
return loadingPromise;
}
/**