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

View File

@ -177,7 +177,7 @@ OV.Importer3ds = class extends OV.ImporterBase
this.ReadChunks (reader, endByte, function (chunkId, chunkLength) {
if (chunkId === OV.CHUNK3DS.MAT_TEXMAP_NAME) {
let textureName = obj.ReadName (reader);
let textureBuffer = obj.callbacks.getFileBuffer (textureName);
let textureBuffer = obj.callbacks.getTextureBuffer (textureName);
texture.name = textureName;
if (textureBuffer !== null) {
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.buffer = base64Buffer.buffer;
} else {
let textureBuffer = this.callbacks.getFileBuffer (gltfImage.uri);
let textureBuffer = this.callbacks.getTextureBuffer (gltfImage.uri);
textureParams.name = gltfImage.uri;
if (textureBuffer !== null) {
textureParams.url = textureBuffer.url;

View File

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

View File

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

View File

@ -65,8 +65,28 @@ module.exports =
},
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;
if (format == OV.FileFormat.Text) {
content = this.GetTextFileContent (folder, fileName);
@ -79,23 +99,11 @@ module.exports =
var material = new OV.Material ();
return material;
},
getFileBuffer : function (requestedFileName) {
let extension = OV.GetFileExtension (requestedFileName);
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 = myThis.GetTextFileContent (folder, requestedFileName);
} else if (format == OV.FileFormat.Binary) {
fileContent = myThis.GetArrayBufferFileContent (folder, requestedFileName);
}
return {
url : null,
buffer : fileContent
};
getFileBuffer : function (filePath) {
return GetFileBuffer (filePath, importer, obj);
},
getTextureBuffer : function (filePath) {
return GetFileBuffer (filePath, importer, obj);
}
});
let model = importer.GetModel ();