Revoke object urls from file list and model when they are no longer needed.

This commit is contained in:
Viktor Kovacs 2021-03-30 00:45:43 +02:00
parent f65ae54b2b
commit 3a02cb8f8e
6 changed files with 126 additions and 32 deletions

View File

@ -14,6 +14,21 @@ OV.File = class
this.name = OV.GetFileName (file.name);
this.extension = OV.GetFileExtension (file.name);
}
this.url = null;
this.content = null;
}
HasContent ()
{
return this.url !== null && this.content !== null;
}
Dispose ()
{
if (this.url !== null) {
OV.RevokeObjectUrl (this.url);
}
this.url = null;
this.content = null;
}
};
@ -133,6 +148,7 @@ OV.FileList = class
{
let callbacks = {
success : function (content) {
file.url = OV.CreateObjectUrl (content);
file.content = content;
},
error : function () {
@ -142,7 +158,7 @@ OV.FileList = class
complete ();
}
};
if (file.content !== null) {
if (file.HasContent ()) {
complete ();
return;
}
@ -177,6 +193,14 @@ OV.FileList = class
}
return null;
}
Dispose ()
{
for (let i = 0; i < this.files.length; i++) {
let file = this.files[i];
file.Dispose ();
}
}
};
OV.ImporterErrorCode =
@ -236,7 +260,7 @@ OV.Importer = class
Import (callbacks)
{
let mainFile = this.fileList.GetMainFile ();
if (mainFile === null || mainFile.file.content === null) {
if (mainFile === null || mainFile.file === null || !mainFile.file.HasContent ()) {
callbacks.error (new OV.ImporterError (OV.ImporterErrorCode.NoImportableFile, null));
return;
}
@ -265,10 +289,8 @@ OV.Importer = class
fileBuffer = null;
} else {
result.usedFiles.push (fileName);
let blob = new Blob ([file.content]);
let blobURL = URL.createObjectURL (blob);
fileBuffer = {
url : blobURL,
url : file.url,
buffer : file.content
};
}
@ -318,6 +340,7 @@ OV.Importer = class
}
}
if (reset) {
this.fileList.Dispose ();
this.fileList = newFileList;
}
this.missingFiles = [];
@ -334,5 +357,20 @@ OV.Importer = class
IsOnlyFileSource (source)
{
return this.fileList.IsOnlySource (source);
}
DisposeModel (model)
{
if (model === null) {
return;
}
for (let i = 0; i < model.MaterialCount (); i++) {
let material = model.GetMaterial (i);
material.EnumerateTextureMaps (function (texture) {
if (texture.url !== null) {
OV.RevokeObjectUrl (texture.url);
}
});
}
}
};

View File

@ -351,12 +351,14 @@ OV.ImporterGltf = class extends OV.ImporterBase
this.bufferContents = null;
this.gltfExtensions = null;
this.imageIndexToTextureParams = null;
}
ResetState ()
{
this.bufferContents = [];
this.gltfExtensions = new OV.GltfExtensions ();
this.imageIndexToTextureParams = {};
}
CanImportExtension (extension)
@ -616,36 +618,48 @@ OV.ImporterGltf = class extends OV.ImporterBase
let texture = new OV.TextureMap ();
let gltfTexture = gltf.textures[gltfTextureRef.index];
let gltfImage = gltf.images[gltfTexture.source];
let gltfImageIndex = gltfTexture.source;
let gltfImage = gltf.images[gltfImageIndex];
let textureIndexString = gltfTexture.source.toString ();
if (gltfImage.uri !== undefined) {
let base64Buffer = OV.Base64DataURIToArrayBuffer (gltfImage.uri);
if (base64Buffer !== null) {
let blob = new Blob ([base64Buffer.buffer], { type : base64Buffer.mimeType });
texture.name = 'Embedded_' + textureIndexString + GetTextureFileExtension (base64Buffer.mimeType);
texture.url = URL.createObjectURL (blob);
texture.buffer = base64Buffer.buffer;
} else {
let textureBuffer = this.callbacks.getFileBuffer (gltfImage.uri);
texture.name = gltfImage.uri;
if (textureBuffer !== null) {
texture.url = textureBuffer.url;
texture.buffer = textureBuffer.buffer;
let textureParams = this.imageIndexToTextureParams[gltfImageIndex];
if (textureParams === undefined) {
textureParams = {
name : null,
url : null,
buffer : null
};
let textureIndexString = gltfImageIndex.toString ();
if (gltfImage.uri !== undefined) {
let base64Buffer = OV.Base64DataURIToArrayBuffer (gltfImage.uri);
if (base64Buffer !== null) {
textureParams.name = 'Embedded_' + textureIndexString + GetTextureFileExtension (base64Buffer.mimeType);
textureParams.url = OV.CreateObjectUrlWithMimeType (base64Buffer.buffer, base64Buffer.mimeType);
textureParams.buffer = base64Buffer.buffer;
} else {
let textureBuffer = this.callbacks.getFileBuffer (gltfImage.uri);
textureParams.name = gltfImage.uri;
if (textureBuffer !== null) {
textureParams.url = textureBuffer.url;
textureParams.buffer = textureBuffer.buffer;
}
}
} else if (gltfImage.bufferView !== undefined) {
let bufferView = gltf.bufferViews[gltfImage.bufferView];
let reader = this.GetReaderFromBufferView (bufferView);
if (reader !== null) {
let buffer = reader.ReadArrayBuffer (bufferView.byteLength);
textureParams.name = 'Binary_' + textureIndexString + GetTextureFileExtension (gltfImage.mimeType);
textureParams.url = OV.CreateObjectUrlWithMimeType (buffer, gltfImage.mimeType);
textureParams.buffer = buffer;
}
}
} else if (gltfImage.bufferView !== undefined) {
let bufferView = gltf.bufferViews[gltfImage.bufferView];
let reader = this.GetReaderFromBufferView (bufferView);
if (reader !== null) {
let buffer = reader.ReadArrayBuffer (bufferView.byteLength);
let blob = new Blob ([buffer], { type: gltfImage.mimeType });
texture.name = 'Binary_' + textureIndexString + GetTextureFileExtension (gltfImage.mimeType);
texture.url = URL.createObjectURL (blob);
texture.buffer = buffer;
}
this.imageIndexToTextureParams[gltfImageIndex] = textureParams;
}
texture.name = textureParams.name;
texture.url = textureParams.url;
texture.buffer = textureParams.buffer;
this.gltfExtensions.ProcessTexture (gltfTextureRef, texture);
return texture;
}

View File

@ -60,3 +60,22 @@ OV.Base64DataURIToArrayBuffer = function (uri)
buffer : buffer
};
};
OV.CreateObjectUrl = function (content)
{
let blob = new Blob ([content]);
let url = URL.createObjectURL (blob);
return url;
};
OV.CreateObjectUrlWithMimeType = function (content, mimeType)
{
let blob = new Blob ([content], { type : mimeType });
let url = URL.createObjectURL (blob);
return url;
};
OV.RevokeObjectUrl = function (url)
{
URL.revokeObjectURL (url);
};

View File

@ -117,6 +117,25 @@ OV.Material = class
this.multiplyDiffuseMap = false;
}
EnumerateTextureMaps (enumerator)
{
if (this.diffuseMap !== null) {
enumerator (this.diffuseMap);
}
if (this.specularMap !== null) {
enumerator (this.specularMap);
}
if (this.bumpMap !== null) {
enumerator (this.bumpMap);
}
if (this.normalMap !== null) {
enumerator (this.normalMap);
}
if (this.emissiveMap !== null) {
enumerator (this.emissiveMap);
}
}
Clone ()
{
let cloned = new OV.Material ();

View File

@ -260,8 +260,8 @@ OV.ShowExportDialog = function (model)
let file = files[i];
let url = file.GetUrl ();
if (url === null) {
let fileBlob = new Blob ([file.GetContent ()]);
url = URL.createObjectURL (fileBlob);
// TODO: revoke on close
url = OV.CreateObjectUrl (file.GetContent ());
}
let fileLink = $('<a>').addClass ('ov_dialog_file_link').appendTo (fileList);
fileLink.attr ('href', url);

View File

@ -71,6 +71,10 @@ OV.Website = class
this.dialog.Hide ();
this.dialog = null;
}
if (this.model !== null) {
let importer = this.modelLoader.GetImporter ();
importer.DisposeModel (this.model);
}
this.model = null;
this.parameters.introDiv.hide ();
this.ShowViewer (false);