Select file to import when there are more importable files #176

This commit is contained in:
kovacsv 2021-11-29 19:48:12 +01:00
parent 7d3a454503
commit db57efeaf1
10 changed files with 130 additions and 38 deletions

View File

@ -22,7 +22,7 @@
src="../../website/embed.html#model=../test/testfiles/3ds/cube_four_instances.3ds,../test/testfiles/3ds/texture.png$camera=3.929421317669367,6.153966358575169,2.7076091223424714,1.5,1.5,0.5,0,0,1" src="../../website/embed.html#model=../test/testfiles/3ds/cube_four_instances.3ds,../test/testfiles/3ds/texture.png$camera=3.929421317669367,6.153966358575169,2.7076091223424714,1.5,1.5,0.5,0,0,1"
width=360 height=240 width=360 height=240
style="border:1px solid #eeeeee;"> style="border:1px solid #eeeeee;">
</iframe> </iframe>
<iframe <iframe
src="../../website/embed.html#model=../test/testfiles/obj/hundred_cubes.obj,../test/testfiles/obj/hundred_cubes.mtl$camera=1,1,1,0,0,0,0,0,1" src="../../website/embed.html#model=../test/testfiles/obj/hundred_cubes.obj,../test/testfiles/obj/hundred_cubes.mtl$camera=1,1,1,0,0,0,0,0,1"
width=360 height=240 width=360 height=240
@ -47,7 +47,7 @@
src="../../website/embed.html#model=wrong.3ds" src="../../website/embed.html#model=wrong.3ds"
width=360 height=240 width=360 height=240
style="border:1px solid #eeeeee;"> style="border:1px solid #eeeeee;">
</iframe> </iframe>
</body> </body>
</html> </html>

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>Online 3D Viewer</title>
</head>
<body>
<iframe
src="../../website/embed.html#model=../test/testfiles/3ds/cube_four_instances.3ds,../test/testfiles/3ds/texture.png,../test/testfiles/obj/hundred_cubes.obj,../test/testfiles/obj/hundred_cubes.mtl"
width=600 height=400
style="border:1px solid #eeeeee;">
</iframe>
</body>
</html>

View File

@ -54,7 +54,7 @@ global.FileReader = class
}; };
let settings = new OV.ImportSettings (); let settings = new OV.ImportSettings ();
importer.ImportFilesFromFileObjects (files, settings, { importer.ImportFiles (files, OV.FileSource.File, settings, {
onFilesLoaded : function () { onFilesLoaded : function () {
}, },

View File

@ -103,16 +103,6 @@ OV.Importer = class
this.importers.push (importer); this.importers.push (importer);
} }
ImportFilesFromUrls (urlList, settings, callbacks)
{
this.ImportFiles (urlList, OV.FileSource.Url, settings, callbacks);
}
ImportFilesFromFileObjects (fileList, settings, callbacks)
{
this.ImportFiles (fileList, OV.FileSource.File, settings, callbacks);
}
ImportFiles (fileList, fileSource, settings, callbacks) ImportFiles (fileList, fileSource, settings, callbacks)
{ {
this.LoadFiles (fileList, fileSource, () => { this.LoadFiles (fileList, fileSource, () => {
@ -132,7 +122,7 @@ OV.Importer = class
newFileList.FillFromFileObjects (fileList); newFileList.FillFromFileObjects (fileList);
} }
let reset = false; let reset = false;
if (this.HasMainFile (newFileList)) { if (this.HasImportableFile (newFileList)) {
reset = true; reset = true;
} else { } else {
let foundMissingFile = false; let foundMissingFile = false;
@ -162,7 +152,29 @@ OV.Importer = class
ImportLoadedFiles (settings, callbacks) ImportLoadedFiles (settings, callbacks)
{ {
let mainFile = this.GetMainFile (this.fileList); let importableFiles = this.GetImportableFiles (this.fileList);
if (importableFiles.length === 0) {
callbacks.onImportError (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
return;
}
if (importableFiles.length === 1 || !callbacks.onSelectMainFile) {
let mainFile = importableFiles[0];
this.ImportLoadedMainFile (mainFile, settings, callbacks);
} else {
callbacks.onSelectMainFile (importableFiles, (mainFileIndex) => {
if (mainFileIndex === null) {
callbacks.onImportError (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
return;
}
let mainFile = importableFiles[mainFileIndex];
this.ImportLoadedMainFile (mainFile, settings, callbacks);
});
}
}
ImportLoadedMainFile (mainFile, settings, callbacks)
{
if (mainFile === null || mainFile.file === null || mainFile.file.content === null) { if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
callbacks.onImportError (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null)); callbacks.onImportError (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
return; return;
@ -256,12 +268,13 @@ OV.Importer = class
return this.fileList; return this.fileList;
} }
HasMainFile (fileList) HasImportableFile (fileList)
{ {
return this.GetMainFile (fileList) !== null; let importableFiles = this.GetImportableFiles (fileList);
return importableFiles.length > 0;
} }
GetMainFile (fileList) GetImportableFiles (fileList)
{ {
function FindImporter (file, importers) function FindImporter (file, importers)
{ {
@ -274,18 +287,19 @@ OV.Importer = class
return null; return null;
} }
let importableFiles = [];
let files = fileList.GetFiles (); let files = fileList.GetFiles ();
for (let fileIndex = 0; fileIndex < files.length; fileIndex++) { for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
let file = files[fileIndex]; let file = files[fileIndex];
let importer = FindImporter (file, this.importers); let importer = FindImporter (file, this.importers);
if (importer !== null) { if (importer !== null) {
return { importableFiles.push ({
file : file, file : file,
importer : importer importer : importer
}; });
} }
} }
return null; return importableFiles;
} }
RevokeModelUrls () RevokeModelUrls ()

View File

@ -36,6 +36,13 @@ OV.ThreeModelLoader = class
onFilesLoaded : () => { onFilesLoaded : () => {
this.callbacks.onImportStart (); this.callbacks.onImportStart ();
}, },
onSelectMainFile : (files, selectFile) => {
if (!this.callbacks.onSelectMainFile) {
selectFile (0);
} else {
this.callbacks.onSelectMainFile (files, selectFile);
}
},
onImportSuccess : (importResult) => { onImportSuccess : (importResult) => {
this.OnModelImported (importResult); this.OnModelImported (importResult);
}, },

View File

@ -12,7 +12,7 @@ function ExportImport (model, format, extension, onReady)
} }
let importer = new OV.Importer (); let importer = new OV.Importer ();
let settings = new OV.ImportSettings (); let settings = new OV.ImportSettings ();
importer.ImportFilesFromFileObjects (fileObjects, settings, { importer.ImportFiles (fileObjects, OV.FileSource.File, settings, {
onFilesLoaded : function () { onFilesLoaded : function () {
}, },

View File

@ -4,7 +4,7 @@ var path = require ('path');
function ImportFilesWithImporter (importer, files, callbacks) function ImportFilesWithImporter (importer, files, callbacks)
{ {
let settings = new OV.ImportSettings (); let settings = new OV.ImportSettings ();
importer.ImportFilesFromFileObjects (files, settings, { importer.ImportFiles (files, OV.FileSource.File, settings, {
onFilesLoaded : function () { onFilesLoaded : function () {
}, },
@ -254,7 +254,7 @@ describe ('Importer Test', function () {
let theImporter = new OV.Importer (); let theImporter = new OV.Importer ();
let settings = new OV.ImportSettings (); let settings = new OV.ImportSettings ();
settings.defaultColor = new OV.Color (200, 0, 0); settings.defaultColor = new OV.Color (200, 0, 0);
theImporter.ImportFilesFromFileObjects (files, settings, { theImporter.ImportFiles (files, OV.FileSource.File, settings, {
onFilesLoaded : function () { onFilesLoaded : function () {
}, },

View File

@ -116,22 +116,31 @@ div.ov_dialog div.ov_dialog_file_list
overflow: auto; overflow: auto;
} }
div.ov_dialog a.ov_dialog_file_link div.ov_dialog div.ov_dialog_import_file_list
{ {
max-height: 300px;
overflow: auto;
}
div.ov_dialog div.ov_dialog_file_link
{
color: var(--ov_button_color);
padding: 5px; padding: 5px;
display: block; display: block;
overflow: auto; overflow: auto;
border-radius: 5px; border-radius: 5px;
cursor: pointer;
} }
div.ov_dialog a.ov_dialog_file_link div.ov_file_link_img div.ov_dialog div.ov_dialog_file_link div.ov_file_link_img
{ {
color: var(--ov_button_color); color: var(--ov_button_color);
margin-top: 2px;
margin-right: 10px; margin-right: 10px;
float: left; float: left;
} }
div.ov_dialog a.ov_dialog_file_link div.ov_dialog_file_link_text div.ov_dialog div.ov_dialog_file_link div.ov_dialog_file_link_text
{ {
float: left; float: left;
} }
@ -234,13 +243,13 @@ div.ov_progress div.ov_progress_text
@media (hover) @media (hover)
{ {
div.ov_dialog a.ov_dialog_file_link:hover div.ov_dialog div.ov_dialog_file_link:hover
{ {
color: var(--ov_hover_text_color); color: var(--ov_hover_text_color);
background: var(--ov_hover_color); background: var(--ov_hover_color);
} }
div.ov_dialog a.ov_dialog_file_link:hover div.ov_file_link_img div.ov_dialog div.ov_dialog_file_link:hover div.ov_file_link_img
{ {
color: var(--ov_hover_text_color); color: var(--ov_hover_text_color);
} }

View File

@ -212,14 +212,13 @@ OV.ExportDialog = class
let fileListSection = OV.AddDiv (contentDiv, 'ov_dialog_section'); let fileListSection = OV.AddDiv (contentDiv, 'ov_dialog_section');
let fileList = OV.AddDiv (fileListSection, 'ov_dialog_file_list ov_thin_scrollbar'); let fileList = OV.AddDiv (fileListSection, 'ov_dialog_file_list ov_thin_scrollbar');
for (let i = 0; i < files.length; i++) { for (let file of files) {
let file = files[i]; let fileLink = OV.AddDiv (fileList, 'ov_dialog_file_link');
let url = OV.CreateObjectUrl (file.GetBufferContent ());
let fileLink = OV.AddDomElement (fileList, 'a', 'ov_dialog_file_link');
fileLink.setAttribute ('href', url);
fileLink.setAttribute ('download', file.GetName ());
OV.AddSvgIconElement (fileLink, 'file_download', 'ov_file_link_img'); OV.AddSvgIconElement (fileLink, 'file_download', 'ov_file_link_img');
OV.AddDiv (fileLink, 'ov_dialog_file_link_text', file.GetName ()); OV.AddDiv (fileLink, 'ov_dialog_file_link_text', file.GetName ());
fileLink.addEventListener ('click', () => {
OV.DownloadArrayBufferAsFile (file.GetBufferContent (), file.GetName ());
});
} }
dialog.Show (); dialog.Show ();

View File

@ -23,6 +23,44 @@ OV.InitModelLoader = function (modelLoader, callbacks)
} }
} }
function ShowFileSelectorDialog (files, onSelect)
{
let dialog = new OV.ButtonDialog ();
let contentDiv = dialog.Init ('Select Model', [
{
name : 'Cancel',
subClass : 'outline',
onClick () {
dialog.Hide ();
}
}
]);
dialog.SetCloseHandler (() => {
onSelect (null);
});
let text = 'Multiple importable models found. Select the model you would like to import from the list below.';
OV.AddDiv (contentDiv, 'ov_dialog_message', text);
let fileListSection = OV.AddDiv (contentDiv, 'ov_dialog_section');
let fileList = OV.AddDiv (fileListSection, 'ov_dialog_import_file_list ov_thin_scrollbar');
for (let i = 0; i < files.length; i++) {
let file = files[i];
let fileLink = OV.AddDiv (fileList, 'ov_dialog_file_link');
OV.AddSvgIconElement (fileLink, 'meshes', 'ov_file_link_img');
OV.AddDiv (fileLink, 'ov_dialog_file_link_text', file.file.name);
fileLink.addEventListener ('click', () => {
dialog.SetCloseHandler (null);
dialog.Hide ();
onSelect (i);
});
}
dialog.Show ();
return dialog;
}
function CloseDialogIfOpen (dialog) function CloseDialogIfOpen (dialog)
{ {
if (dialog !== null) { if (dialog !== null) {
@ -31,16 +69,23 @@ OV.InitModelLoader = function (modelLoader, callbacks)
} }
} }
let errorDialog = null; let modalDialog = null;
let progressDialog = null; let progressDialog = null;
modelLoader.Init ({ modelLoader.Init ({
onLoadStart : () => { onLoadStart : () => {
CloseDialogIfOpen (errorDialog); CloseDialogIfOpen (modalDialog);
callbacks.onStart (); callbacks.onStart ();
progressDialog = new OV.ProgressDialog (); progressDialog = new OV.ProgressDialog ();
progressDialog.Init ('Loading Model'); progressDialog.Init ('Loading Model');
progressDialog.Show (); progressDialog.Show ();
}, },
onSelectMainFile : (files, selectFile) => {
progressDialog.Hide ();
modalDialog = ShowFileSelectorDialog (files, (index) => {
progressDialog.Show ();
selectFile (index);
});
},
onImportStart : () => { onImportStart : () => {
progressDialog.SetText ('Importing Model'); progressDialog.SetText ('Importing Model');
}, },
@ -57,7 +102,7 @@ OV.InitModelLoader = function (modelLoader, callbacks)
onLoadError : (importError) => { onLoadError : (importError) => {
progressDialog.Hide (); progressDialog.Hide ();
callbacks.onError (importError); callbacks.onError (importError);
errorDialog = OpenErrorDialog (importError); modalDialog = OpenErrorDialog (importError);
}, },
}); });
}; };