Store object urls only for textures so they can safely revoked when the model is disposed.

This commit is contained in:
Viktor Kovacs 2021-03-30 01:53:24 +02:00
parent 3a02cb8f8e
commit becbe31a9e
6 changed files with 130 additions and 107 deletions

View File

@ -14,21 +14,6 @@ OV.File = class
this.name = OV.GetFileName (file.name); this.name = OV.GetFileName (file.name);
this.extension = OV.GetFileExtension (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; this.content = null;
} }
}; };
@ -148,7 +133,6 @@ OV.FileList = class
{ {
let callbacks = { let callbacks = {
success : function (content) { success : function (content) {
file.url = OV.CreateObjectUrl (content);
file.content = content; file.content = content;
}, },
error : function () { error : function () {
@ -158,7 +142,7 @@ OV.FileList = class
complete (); complete ();
} }
}; };
if (file.HasContent ()) { if (file.content !== null) {
complete (); complete ();
return; return;
} }
@ -193,14 +177,6 @@ OV.FileList = class
} }
return null; return null;
} }
Dispose ()
{
for (let i = 0; i < this.files.length; i++) {
let file = this.files[i];
file.Dispose ();
}
}
}; };
OV.ImporterErrorCode = OV.ImporterErrorCode =
@ -231,6 +207,58 @@ OV.ImportResult = class
} }
}; };
OV.FileBufferCache = class
{
constructor (fileList, missingFiles, importResult)
{
this.fileList = fileList;
this.missingFiles = missingFiles;
this.importResult = importResult;
this.fileNameToBuffer = {};
this.textureNameToBuffer = {};
}
GetFileBuffer (filePath)
{
return this.GetCommonBuffer (filePath, this.fileNameToBuffer, false);
}
GetTextureBuffer (filePath)
{
return this.GetCommonBuffer (filePath, this.textureNameToBuffer, true);
}
GetCommonBuffer (filePath, nameToBuffer, withUrl)
{
let fileName = OV.GetFileName (filePath);
let fileBuffer = nameToBuffer[fileName];
if (fileBuffer === undefined) {
let file = this.fileList.FindFileByPath (filePath);
if (file === null || file.content === null) {
this.importResult.missingFiles.push (fileName);
this.missingFiles.push (fileName);
fileBuffer = null;
} else {
this.importResult.usedFiles.push (fileName);
if (withUrl) {
fileBuffer = {
url : OV.CreateObjectUrl (file.content),
buffer : file.content
};
} else {
fileBuffer = {
url : null,
buffer : file.content
};
}
}
nameToBuffer[fileName] = fileBuffer;
}
return fileBuffer;
}
};
OV.Importer = class OV.Importer = class
{ {
constructor () constructor ()
@ -260,7 +288,7 @@ OV.Importer = class
Import (callbacks) Import (callbacks)
{ {
let mainFile = this.fileList.GetMainFile (); let mainFile = this.fileList.GetMainFile ();
if (mainFile === null || mainFile.file === null || !mainFile.file.HasContent ()) { if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
callbacks.error (new OV.ImporterError (OV.ImporterErrorCode.NoImportableFile, null)); callbacks.error (new OV.ImporterError (OV.ImporterErrorCode.NoImportableFile, null));
return; return;
} }
@ -269,9 +297,8 @@ OV.Importer = class
result.mainFile = mainFile.file.name; result.mainFile = mainFile.file.name;
result.usedFiles.push (mainFile.file.name); result.usedFiles.push (mainFile.file.name);
let obj = this;
let importer = mainFile.importer; let importer = mainFile.importer;
let fileNameToBuffer = {}; let fileBufferCache = new OV.FileBufferCache (this.fileList, this.missingFiles, result);
importer.Import (mainFile.file.content, mainFile.file.extension, { importer.Import (mainFile.file.content, mainFile.file.extension, {
getDefaultMaterial : function () { getDefaultMaterial : function () {
let material = new OV.Material (); let material = new OV.Material ();
@ -279,24 +306,10 @@ OV.Importer = class
return material; return material;
}, },
getFileBuffer : function (filePath) { getFileBuffer : function (filePath) {
let fileName = OV.GetFileName (filePath); return fileBufferCache.GetFileBuffer (filePath);
let fileBuffer = fileNameToBuffer[fileName]; },
if (fileBuffer === undefined) { getTextureBuffer : function (filePath) {
let file = obj.fileList.FindFileByPath (filePath); return fileBufferCache.GetTextureBuffer (filePath);
if (file === null || file.content === null) {
result.missingFiles.push (fileName);
obj.missingFiles.push (fileName);
fileBuffer = null;
} else {
result.usedFiles.push (fileName);
fileBuffer = {
url : file.url,
buffer : file.content
};
}
fileNameToBuffer[fileName] = fileBuffer;
}
return fileBuffer;
} }
}); });
@ -340,7 +353,6 @@ OV.Importer = class
} }
} }
if (reset) { if (reset) {
this.fileList.Dispose ();
this.fileList = newFileList; this.fileList = newFileList;
} }
this.missingFiles = []; this.missingFiles = [];

View File

@ -177,7 +177,7 @@ OV.Importer3ds = class extends OV.ImporterBase
this.ReadChunks (reader, endByte, function (chunkId, chunkLength) { this.ReadChunks (reader, endByte, function (chunkId, chunkLength) {
if (chunkId === OV.CHUNK3DS.MAT_TEXMAP_NAME) { if (chunkId === OV.CHUNK3DS.MAT_TEXMAP_NAME) {
let textureName = obj.ReadName (reader); let textureName = obj.ReadName (reader);
let textureBuffer = obj.callbacks.getFileBuffer (textureName); let textureBuffer = obj.callbacks.getTextureBuffer (textureName);
texture.name = textureName; texture.name = textureName;
if (textureBuffer !== null) { if (textureBuffer !== null) {
texture.url = textureBuffer.url; texture.url = textureBuffer.url;

View File

@ -636,7 +636,7 @@ OV.ImporterGltf = class extends OV.ImporterBase
textureParams.url = OV.CreateObjectUrlWithMimeType (base64Buffer.buffer, base64Buffer.mimeType); textureParams.url = OV.CreateObjectUrlWithMimeType (base64Buffer.buffer, base64Buffer.mimeType);
textureParams.buffer = base64Buffer.buffer; textureParams.buffer = base64Buffer.buffer;
} else { } else {
let textureBuffer = this.callbacks.getFileBuffer (gltfImage.uri); let textureBuffer = this.callbacks.getTextureBuffer (gltfImage.uri);
textureParams.name = gltfImage.uri; textureParams.name = gltfImage.uri;
if (textureBuffer !== null) { if (textureBuffer !== null) {
textureParams.url = textureBuffer.url; textureParams.url = textureBuffer.url;

View File

@ -170,7 +170,7 @@ OV.ImporterObj = class extends OV.ImporterBase
{ {
let texture = new OV.TextureMap (); let texture = new OV.TextureMap ();
let textureName = OV.NameFromLine (line, keyword.length, '#'); let textureName = OV.NameFromLine (line, keyword.length, '#');
let textureBuffer = callbacks.getFileBuffer (textureName); let textureBuffer = callbacks.getTextureBuffer (textureName);
texture.name = textureName; texture.name = textureName;
if (textureBuffer !== null) { if (textureBuffer !== null) {
texture.url = textureBuffer.url; texture.url = textureBuffer.url;

View File

@ -292,47 +292,50 @@ describe ('Exporter', function () {
}); });
it ('Gltf Ascii Export', function () { it ('Gltf Ascii Export', function () {
let model = CreateTestModel (); let model = CreateTestModel ();
let exporter = new OV.Exporter (); let exporter = new OV.Exporter ();
let result = exporter.Export (model, OV.FileFormat.Text, 'gltf'); let result = exporter.Export (model, OV.FileFormat.Text, 'gltf');
assert.strictEqual (result.length, 3); assert.strictEqual (result.length, 3);
let gltfFile = result[0]; let gltfFile = result[0];
let binFile = result[1]; let binFile = result[1];
let textureFile = result[2]; let textureFile = result[2];
assert.strictEqual (gltfFile.GetName (), 'model.gltf'); assert.strictEqual (gltfFile.GetName (), 'model.gltf');
assert.strictEqual (binFile.GetName (), 'model.bin'); assert.strictEqual (binFile.GetName (), 'model.bin');
assert.strictEqual (textureFile.GetName (), 'texture1.png'); assert.strictEqual (textureFile.GetName (), 'texture1.png');
assert.strictEqual (textureFile.GetUrl (), 'texture1_url'); assert.strictEqual (textureFile.GetUrl (), 'texture1_url');
assert.strictEqual (textureFile.GetContent (), null); assert.strictEqual (textureFile.GetContent (), null);
let contentBuffer = gltfFile.GetContent (); let contentBuffer = gltfFile.GetContent ();
let importer = new OV.ImporterGltf (); let importer = new OV.ImporterGltf ();
importer.Import (contentBuffer, 'gltf', { importer.Import (contentBuffer, 'gltf', {
getDefaultMaterial () { getDefaultMaterial () {
return new OV.Material (); return new OV.Material ();
}, },
getFileBuffer (filePath) { getFileBuffer (filePath) {
if (filePath == 'model.bin') { if (filePath == 'model.bin') {
return { return {
url : null, url : null,
buffer : binFile.GetContent () buffer : binFile.GetContent ()
}; };
} }
return null; return null;
} },
}); getTextureBuffer (filePath) {
return null;
}
});
let importedModel = importer.GetModel (); let importedModel = importer.GetModel ();
assert (OV.CheckModel (importedModel)); assert (OV.CheckModel (importedModel));
assert.strictEqual (importedModel.MaterialCount (), 2); assert.strictEqual (importedModel.MaterialCount (), 2);
assert.strictEqual (importedModel.MeshCount (), 2); assert.strictEqual (importedModel.MeshCount (), 2);
assert.strictEqual (importedModel.GetMesh (0).GetName (), 'TestMesh1'); assert.strictEqual (importedModel.GetMesh (0).GetName (), 'TestMesh1');
assert.strictEqual (importedModel.GetMesh (1).GetName (), 'TestMesh2'); assert.strictEqual (importedModel.GetMesh (1).GetName (), 'TestMesh2');
assert.strictEqual (importedModel.VertexCount (), 12); assert.strictEqual (importedModel.VertexCount (), 12);
assert.strictEqual (importedModel.TriangleCount (), 4); assert.strictEqual (importedModel.TriangleCount (), 4);
}); });
it ('Gltf Binary Export', function () { it ('Gltf Binary Export', function () {

View File

@ -66,7 +66,27 @@ module.exports =
ImportFile : function (importer, format, folder, fileName) ImportFile : function (importer, format, folder, fileName)
{ {
var myThis = this; function GetFileBuffer (filePath, importer, obj)
{
let extension = OV.GetFileExtension (filePath);
let knownFormats = importer.GetKnownFileFormats ();
let format = OV.FileFormat.Binary;
if (knownFormats[extension] !== undefined) {
format = knownFormats[extension];
}
let fileContent = null;
if (format == OV.FileFormat.Text) {
fileContent = obj.GetTextFileContent (folder, filePath);
} else if (format == OV.FileFormat.Binary) {
fileContent = obj.GetArrayBufferFileContent (folder, filePath);
}
return {
url : null,
buffer : fileContent
};
}
var obj = this;
var content = null; var content = null;
if (format == OV.FileFormat.Text) { if (format == OV.FileFormat.Text) {
content = this.GetTextFileContent (folder, fileName); content = this.GetTextFileContent (folder, fileName);
@ -79,23 +99,11 @@ module.exports =
var material = new OV.Material (); var material = new OV.Material ();
return material; return material;
}, },
getFileBuffer : function (requestedFileName) { getFileBuffer : function (filePath) {
let extension = OV.GetFileExtension (requestedFileName); return GetFileBuffer (filePath, importer, obj);
let knownFormats = importer.GetKnownFileFormats (); },
let format = OV.FileFormat.Binary; getTextureBuffer : function (filePath) {
if (knownFormats[extension] !== undefined) { return GetFileBuffer (filePath, importer, obj);
format = knownFormats[extension];
}
let fileContent = null;
if (format == OV.FileFormat.Text) {
fileContent = myThis.GetTextFileContent (folder, requestedFileName);
} else if (format == OV.FileFormat.Binary) {
fileContent = myThis.GetArrayBufferFileContent (folder, requestedFileName);
}
return {
url : null,
buffer : fileContent
};
} }
}); });
let model = importer.GetModel (); let model = importer.GetModel ();