408 lines
8.7 KiB
JavaScript
408 lines
8.7 KiB
JavaScript
OV.File = class
|
|
{
|
|
constructor (file, source)
|
|
{
|
|
this.source = source;
|
|
if (source === OV.FileSource.Url) {
|
|
this.fileUrl = file;
|
|
this.fileObject = null;
|
|
this.name = OV.GetFileName (file);
|
|
this.extension = OV.GetFileExtension (file);
|
|
} else if (source === OV.FileSource.File) {
|
|
this.fileUrl = null;
|
|
this.fileObject = file;
|
|
this.name = OV.GetFileName (file.name);
|
|
this.extension = OV.GetFileExtension (file.name);
|
|
}
|
|
this.content = null;
|
|
}
|
|
};
|
|
|
|
OV.FileList = class
|
|
{
|
|
constructor (importers)
|
|
{
|
|
this.files = [];
|
|
this.importers = importers;
|
|
}
|
|
|
|
FillFromFileUrls (fileList)
|
|
{
|
|
this.Fill (fileList, OV.FileSource.Url);
|
|
}
|
|
|
|
FillFromFileObjects (fileList)
|
|
{
|
|
this.Fill (fileList, OV.FileSource.File);
|
|
}
|
|
|
|
ExtendFromFileList (files)
|
|
{
|
|
for (let i = 0; i < files.length; i++) {
|
|
let file = files[i];
|
|
if (!this.ContainsFileByPath (file.name)) {
|
|
this.files.push (file);
|
|
}
|
|
}
|
|
}
|
|
|
|
GetFiles ()
|
|
{
|
|
return this.files;
|
|
}
|
|
|
|
GetContent (onReady)
|
|
{
|
|
let obj = this;
|
|
let taskRunner = new OV.TaskRunner ();
|
|
taskRunner.Run (this.files.length, {
|
|
runTask : function (index, complete) {
|
|
obj.GetFileContent (obj.files[index], complete);
|
|
},
|
|
onReady : onReady
|
|
});
|
|
}
|
|
|
|
ContainsFileByPath (filePath)
|
|
{
|
|
return this.FindFileByPath (filePath) !== null;
|
|
}
|
|
|
|
FindFileByPath (filePath)
|
|
{
|
|
let fileName = OV.GetFileName (filePath).toLowerCase ();
|
|
for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
|
|
let file = this.files[fileIndex];
|
|
if (file.name.toLowerCase () === fileName) {
|
|
return file;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
HasMainFile ()
|
|
{
|
|
return this.GetMainFile () !== null;
|
|
}
|
|
|
|
GetMainFile ()
|
|
{
|
|
for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
|
|
let file = this.files[fileIndex];
|
|
let importer = this.FindImporter (file);
|
|
if (importer !== null) {
|
|
return {
|
|
file : file,
|
|
importer : importer
|
|
};
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
IsOnlySource (source)
|
|
{
|
|
if (this.files.length === 0) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < this.files.length; i++) {
|
|
let file = this.files[i];
|
|
if (file.source !== source) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Fill (fileList, fileSource)
|
|
{
|
|
this.files = [];
|
|
for (let fileIndex = 0; fileIndex < fileList.length; fileIndex++) {
|
|
let fileObject = fileList[fileIndex];
|
|
let file = new OV.File (fileObject, fileSource);
|
|
this.AddFile (file);
|
|
}
|
|
}
|
|
|
|
AddFile (file)
|
|
{
|
|
this.files.push (file);
|
|
}
|
|
|
|
GetFileContent (file, complete)
|
|
{
|
|
let callbacks = {
|
|
success : function (content) {
|
|
file.content = content;
|
|
},
|
|
error : function () {
|
|
|
|
},
|
|
complete : function () {
|
|
complete ();
|
|
}
|
|
};
|
|
if (file.content !== null) {
|
|
complete ();
|
|
return;
|
|
}
|
|
let format = this.GetFileFormat (file);
|
|
if (file.source === OV.FileSource.Url) {
|
|
OV.RequestUrl (file.fileUrl, format, callbacks);
|
|
} else if (file.source === OV.FileSource.File) {
|
|
OV.ReadFile (file.fileObject, format, callbacks);
|
|
}
|
|
}
|
|
|
|
GetFileFormat (file)
|
|
{
|
|
for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
|
|
let importer = this.importers[importerIndex];
|
|
let extension = file.extension.toLowerCase ();
|
|
let knownFormats = importer.GetKnownFileFormats ();
|
|
if (knownFormats[extension] !== undefined) {
|
|
return knownFormats[extension];
|
|
}
|
|
}
|
|
return OV.FileFormat.Binary;
|
|
}
|
|
|
|
FindImporter (file)
|
|
{
|
|
for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
|
|
let importer = this.importers[importerIndex];
|
|
if (importer.CanImportExtension (file.extension.toLowerCase ())) {
|
|
return importer;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
|
|
OV.ImportSettings = class
|
|
{
|
|
constructor ()
|
|
{
|
|
this.defaultColor = new OV.Color (200, 200, 200);
|
|
}
|
|
};
|
|
|
|
OV.ImportErrorCode =
|
|
{
|
|
NoImportableFile : 1,
|
|
ImportFailed : 2,
|
|
UnknownError : 3
|
|
};
|
|
|
|
OV.ImportError = class
|
|
{
|
|
constructor (code, message)
|
|
{
|
|
this.code = code;
|
|
this.message = message;
|
|
}
|
|
};
|
|
|
|
OV.ImportResult = class
|
|
{
|
|
constructor ()
|
|
{
|
|
this.model = null;
|
|
this.mainFile = null;
|
|
this.upVector = null;
|
|
this.usedFiles = null;
|
|
this.missingFiles = null;
|
|
}
|
|
};
|
|
|
|
OV.ImportBuffers = class
|
|
{
|
|
constructor (getBufferCallback)
|
|
{
|
|
this.getBufferCallback = getBufferCallback;
|
|
this.fileBuffers = {};
|
|
this.textureBuffers = {};
|
|
}
|
|
|
|
GetFileBuffer (filePath)
|
|
{
|
|
let fileName = OV.GetFileName (filePath);
|
|
let buffer = this.fileBuffers[fileName];
|
|
if (buffer === undefined) {
|
|
buffer = this.getBufferCallback (fileName);
|
|
this.fileBuffers[fileName] = buffer;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
GetTextureBuffer (filePath)
|
|
{
|
|
let fileName = OV.GetFileName (filePath);
|
|
let buffer = this.textureBuffers[fileName];
|
|
if (buffer === undefined) {
|
|
let textureBuffer = this.getBufferCallback (fileName);
|
|
if (textureBuffer !== null) {
|
|
buffer = {
|
|
url : OV.CreateObjectUrl (textureBuffer),
|
|
buffer : textureBuffer
|
|
};
|
|
} else {
|
|
buffer = null;
|
|
}
|
|
this.textureBuffers[fileName] = buffer;
|
|
}
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
OV.Importer = class
|
|
{
|
|
constructor ()
|
|
{
|
|
this.importers = [
|
|
new OV.ImporterObj (),
|
|
new OV.ImporterStl (),
|
|
new OV.ImporterOff (),
|
|
new OV.ImporterPly (),
|
|
new OV.Importer3ds (),
|
|
new OV.ImporterGltf ()
|
|
];
|
|
this.fileList = new OV.FileList (this.importers);
|
|
this.model = null;
|
|
this.usedFiles = [];
|
|
this.missingFiles = [];
|
|
}
|
|
|
|
LoadFilesFromUrls (fileList, onReady)
|
|
{
|
|
this.LoadFiles (fileList, OV.FileSource.Url, onReady);
|
|
}
|
|
|
|
LoadFilesFromFileObjects (fileList, onReady)
|
|
{
|
|
this.LoadFiles (fileList, OV.FileSource.File, onReady);
|
|
}
|
|
|
|
Import (settings, callbacks)
|
|
{
|
|
let mainFile = this.fileList.GetMainFile ();
|
|
if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
|
|
callbacks.error (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
|
|
return;
|
|
}
|
|
|
|
this.RevokeModelUrls ();
|
|
this.model = null;
|
|
this.usedFiles = [];
|
|
this.missingFiles = [];
|
|
this.usedFiles.push (mainFile.file.name);
|
|
|
|
let result = new OV.ImportResult ();
|
|
result.mainFile = mainFile.file.name;
|
|
|
|
let obj = this;
|
|
let importer = mainFile.importer;
|
|
let buffers = new OV.ImportBuffers (function (fileName) {
|
|
let fileBuffer = null;
|
|
let file = obj.fileList.FindFileByPath (fileName);
|
|
if (file === null || file.content === null) {
|
|
obj.missingFiles.push (fileName);
|
|
fileBuffer = null;
|
|
} else {
|
|
fileBuffer = file.content;
|
|
obj.usedFiles.push (fileName);
|
|
}
|
|
return fileBuffer;
|
|
});
|
|
|
|
importer.Import (mainFile.file.content, mainFile.file.extension, {
|
|
getDefaultMaterial : function () {
|
|
let material = new OV.Material ();
|
|
material.diffuse = settings.defaultColor;
|
|
return material;
|
|
},
|
|
getFileBuffer : function (filePath) {
|
|
return buffers.GetFileBuffer (filePath);
|
|
},
|
|
getTextureBuffer : function (filePath) {
|
|
return buffers.GetTextureBuffer (filePath);
|
|
}
|
|
});
|
|
|
|
if (importer.IsError ()) {
|
|
let message = importer.GetMessage ();
|
|
callbacks.error (new OV.ImportError (OV.ImportErrorCode.ImportFailed, message));
|
|
return;
|
|
}
|
|
|
|
this.model = importer.GetModel ();
|
|
this.model.SetName (mainFile.file.name);
|
|
|
|
result.model = this.model;
|
|
result.usedFiles = this.usedFiles;
|
|
result.missingFiles = this.missingFiles;
|
|
result.upVector = importer.GetUpDirection ();
|
|
callbacks.success (result);
|
|
}
|
|
|
|
LoadFiles (fileList, fileSource, onReady)
|
|
{
|
|
let newFileList = new OV.FileList (this.importers);
|
|
if (fileSource === OV.FileSource.Url) {
|
|
newFileList.FillFromFileUrls (fileList);
|
|
} else if (fileSource === OV.FileSource.File) {
|
|
newFileList.FillFromFileObjects (fileList);
|
|
}
|
|
let reset = false;
|
|
if (newFileList.HasMainFile ()) {
|
|
reset = true;
|
|
} else {
|
|
let foundMissingFile = false;
|
|
for (let i = 0; i < this.missingFiles.length; i++) {
|
|
let missingFile = this.missingFiles[i];
|
|
if (newFileList.ContainsFileByPath (missingFile)) {
|
|
foundMissingFile = true;
|
|
}
|
|
}
|
|
if (!foundMissingFile) {
|
|
reset = true;
|
|
} else {
|
|
let newFiles = newFileList.GetFiles ();
|
|
this.fileList.ExtendFromFileList (newFiles);
|
|
reset = false;
|
|
}
|
|
}
|
|
if (reset) {
|
|
this.fileList = newFileList;
|
|
}
|
|
this.fileList.GetContent (function () {
|
|
onReady ();
|
|
});
|
|
}
|
|
|
|
GetFileList ()
|
|
{
|
|
return this.fileList;
|
|
}
|
|
|
|
IsOnlyFileSource (source)
|
|
{
|
|
return this.fileList.IsOnlySource (source);
|
|
}
|
|
|
|
RevokeModelUrls ()
|
|
{
|
|
if (this.model === null) {
|
|
return;
|
|
}
|
|
for (let i = 0; i < this.model.MaterialCount (); i++) {
|
|
let material = this.model.GetMaterial (i);
|
|
material.EnumerateTextureMaps (function (texture) {
|
|
if (texture.url !== null) {
|
|
OV.RevokeObjectUrl (texture.url);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|