diff --git a/website/index.html b/website/index.html index 25b049b..4f28ef9 100644 --- a/website/index.html +++ b/website/index.html @@ -2,213 +2,221 @@ - - - + + + - Online 3D Viewer + Online 3D Viewer - - - - - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + + - + - - + + - - -
- - -
-
-
-
-
-
- -
-
- Drag and drop your 3D models here.
- obj, 3ds, stl, ply, gltf, glb, off, 3dm, fbx, and more -
-
- Or you can use the browse button above. -
-
-
Example models:
-
- logo - | - solids - | - helmet -
-
-
+ + +
+ + +
+
+
+
+
+
+ +
+
+ Drag and drop your 3D models here.
+ obj, 3ds, stl, ply, gltf, glb, off, 3dm, fbx, and more +
+
+ Or you can use the browse button above. +
+
+
Example models:
+
+ logo + | + solids + | + helmet +
+
+
diff --git a/website/o3dv/js/eventhandler.js b/website/o3dv/js/eventhandler.js index 32dd7e0..874fc0a 100644 --- a/website/o3dv/js/eventhandler.js +++ b/website/o3dv/js/eventhandler.js @@ -5,11 +5,11 @@ OV.EventHandler = class this.eventHandler = eventHandler; } - HandleEvent (name, parameters) + HandleEvent (eventName, eventData) { if (this.eventHandler === undefined || this.eventHandler === null) { return; } - this.eventHandler (name, parameters); + this.eventHandler (eventName, eventData); } }; diff --git a/website/o3dv/js/exportdialog.js b/website/o3dv/js/exportdialog.js index 7508fee..c9f79e4 100644 --- a/website/o3dv/js/exportdialog.js +++ b/website/o3dv/js/exportdialog.js @@ -169,9 +169,10 @@ OV.ImageExporterUI = class extends OV.ExporterUI OV.ExportDialog = class { - constructor (callbacks) + constructor (callbacks, eventHandler) { this.callbacks = callbacks; + this.eventHandler = eventHandler; this.selectedExporter = null; this.parametersDiv = null; @@ -243,6 +244,7 @@ OV.ExportDialog = class this.callbacks.onDialog (filesDialog); } }); + this.eventHandler.HandleEvent ('model_exported', this.selectedExporter.GetName ()); } else if (this.selectedExporter.GetType () === OV.ExportType.Image) { this.selectedExporter.ExportImage (viewer); } diff --git a/website/o3dv/js/sharingdialog.js b/website/o3dv/js/sharingdialog.js index 50a5a08..b6e2c28 100644 --- a/website/o3dv/js/sharingdialog.js +++ b/website/o3dv/js/sharingdialog.js @@ -1,4 +1,4 @@ -OV.ShowSharingDialog = function (importer, settings, camera) +OV.ShowSharingDialog = function (fileList, settings, camera, eventHandler) { function AddCheckboxLine (parentDiv, text, id, onChange) { @@ -53,23 +53,25 @@ OV.ShowSharingDialog = function (importer, settings, camera) return input; } - function AddSharingLinkTab (parentDiv, sharingLinkParams) + function AddSharingLinkTab (parentDiv, sharingLinkParams, eventHandler) { let section = OV.AddDiv (parentDiv, 'ov_dialog_section'); OV.AddDiv (section, 'ov_dialog_inner_title', 'Sharing Link'); let sharingLinkInput = AddCopyableTextInput (section, () => { + eventHandler.HandleEvent ('model_shared', 'sharing_link'); return GetSharingLink (sharingLinkParams); }); sharingLinkInput.value = GetSharingLink (sharingLinkParams); } - function AddEmbeddingCodeTab (parentDiv, settings, embeddingCodeParams) + function AddEmbeddingCodeTab (parentDiv, settings, embeddingCodeParams, eventHandler) { let section = OV.AddDiv (parentDiv, 'ov_dialog_section'); section.style.marginTop = '20px'; OV.AddDiv (section, 'ov_dialog_inner_title', 'Embedding Code'); let optionsSection = OV.AddDiv (section, 'ov_dialog_section'); let embeddingCodeInput = AddCopyableTextInput (section, () => { + eventHandler.HandleEvent ('model_shared', 'embedding_code'); return GetEmbeddingCode (embeddingCodeParams); }); AddCheckboxLine (optionsSection, 'Use current camera position', 'embed_camera', (checked) => { @@ -96,7 +98,7 @@ OV.ShowSharingDialog = function (importer, settings, camera) embeddingCodeInput.value = GetEmbeddingCode (embeddingCodeParams); } - if (!importer.GetFileList ().IsOnlyUrlSource ()) { + if (!fileList.IsOnlyUrlSource ()) { return OV.ShowMessageDialog ( 'Sharing Failed', 'Sharing works only if you load files by url. Please upload your model files to a web server, open them by url, and try embedding again.', @@ -104,7 +106,7 @@ OV.ShowSharingDialog = function (importer, settings, camera) ); } - let files = importer.GetFileList ().GetFiles (); + let files = fileList.GetFiles (); let modelFiles = []; for (let fileIndex = 0; fileIndex < files.length; fileIndex++) { let file = files[fileIndex]; @@ -139,8 +141,8 @@ OV.ShowSharingDialog = function (importer, settings, camera) } ]); - AddSharingLinkTab (contentDiv, sharingLinkParams); - AddEmbeddingCodeTab (contentDiv, settings, embeddingCodeParams); + AddSharingLinkTab (contentDiv, sharingLinkParams, eventHandler); + AddEmbeddingCodeTab (contentDiv, settings, embeddingCodeParams, eventHandler); dialog.Show (); return dialog; diff --git a/website/o3dv/js/website.js b/website/o3dv/js/website.js index 8d0a861..e7b8b33 100644 --- a/website/o3dv/js/website.js +++ b/website/o3dv/js/website.js @@ -32,6 +32,7 @@ OV.Website = class { this.settings.LoadFromCookies (this.cookieHandler); this.SwitchTheme (this.settings.themeId, false); + this.eventHandler.HandleEvent ('theme_on_load', this.settings.themeId === OV.Theme.Light ? 'light' : 'dark'); this.InitViewer (); this.InitMeasureTool (); @@ -260,7 +261,7 @@ OV.Website = class if (defaultColor !== null) { importSettings.defaultColor = defaultColor; } - this.eventHandler.HandleEvent ('model_load_started', { source : 'hash' }); + this.eventHandler.HandleEvent ('model_load_started', 'hash'); this.LoadModelFromUrlList (urls, importSettings); } else { this.ClearModel (); @@ -364,7 +365,7 @@ OV.Website = class this.SetUIState (OV.WebsiteUIState.Model); this.OnModelLoaded (importResult, threeObject); let importedExtension = OV.GetFileExtension (importResult.mainFile); - this.eventHandler.HandleEvent ('model_loaded', { extension : importedExtension }); + this.eventHandler.HandleEvent ('model_loaded', importedExtension); }, onRender : () => { @@ -373,24 +374,20 @@ OV.Website = class onError : (importError) => { this.SetUIState (OV.WebsiteUIState.Intro); - let reason = 'unknown'; - if (importError.code === OV.ImportErrorCode.NoImportableFile) { - reason = 'no_importable_file'; - } else if (importError.code === OV.ImportErrorCode.FailedToLoadFile) { - reason = 'failed_to_load_file'; - } else if (importError.code === OV.ImportErrorCode.ImportFailed) { - reason = 'import_failed'; - } let extensions = []; let importer = this.modelLoaderUI.GetImporter (); let fileList = importer.GetFileList ().GetFiles (); for (let i = 0; i < fileList.length; i++) { extensions.push (fileList[i].extension); } - this.eventHandler.HandleEvent ('model_load_failed', { - reason : reason, - extensions : extensions - }); + let extensionsStr = extensions.join (','); + if (importError.code === OV.ImportErrorCode.NoImportableFile) { + this.eventHandler.HandleEvent ('no_importable_file', extensionsStr); + } else if (importError.code === OV.ImportErrorCode.FailedToLoadFile) { + this.eventHandler.HandleEvent ('failed_to_load_file', extensionsStr); + } else if (importError.code === OV.ImportErrorCode.ImportFailed) { + this.eventHandler.HandleEvent ('import_failed', extensionsStr); + } } }); } @@ -457,10 +454,9 @@ OV.Website = class InitToolbar () { - function AddButton (toolbar, eventHandler, imageName, imageTitle, classNames, onClick) + function AddButton (toolbar, imageName, imageTitle, classNames, onClick) { let button = toolbar.AddImageButton (imageName, imageTitle, () => { - eventHandler.HandleEvent ('toolbar_clicked', { item : imageName }); onClick (); }); for (let className of classNames) { @@ -469,7 +465,7 @@ OV.Website = class return button; } - function AddRadioButton (toolbar, eventHandler, imageNames, imageTitles, selectedIndex, classNames, onClick) + function AddRadioButton (toolbar, imageNames, imageTitles, selectedIndex, classNames, onClick) { let imageData = []; for (let i = 0; i < imageNames.length; i++) { @@ -481,7 +477,6 @@ OV.Website = class }); } let buttons = toolbar.AddImageRadioButton (imageData, selectedIndex, (buttonIndex) => { - eventHandler.HandleEvent ('toolbar_clicked', { item : imageNames[buttonIndex] }); onClick (buttonIndex); }); for (let className of classNames) { @@ -503,10 +498,10 @@ OV.Website = class let importer = this.modelLoaderUI.GetImporter (); - AddButton (this.toolbar, this.eventHandler, 'open', 'Open model from your device', [], () => { + AddButton (this.toolbar, 'open', 'Open model from your device', [], () => { this.OpenFileBrowserDialog (); }); - AddButton (this.toolbar, this.eventHandler, 'open_url', 'Open model from a url', [], () => { + AddButton (this.toolbar, 'open_url', 'Open model from a url', [], () => { this.dialog = OV.ShowOpenUrlDialog ((urls) => { if (urls.length > 0) { this.hashHandler.SetModelFilesToHash (urls); @@ -514,20 +509,20 @@ OV.Website = class }); }); AddSeparator (this.toolbar, ['only_on_model']); - AddButton (this.toolbar, this.eventHandler, 'fit', 'Fit model to window', ['only_on_model'], () => { + AddButton (this.toolbar, 'fit', 'Fit model to window', ['only_on_model'], () => { this.FitModelToWindow (false); }); - AddButton (this.toolbar, this.eventHandler, 'up_y', 'Set Y axis as up vector', ['only_on_model'], () => { + AddButton (this.toolbar, 'up_y', 'Set Y axis as up vector', ['only_on_model'], () => { this.viewer.SetUpVector (OV.Direction.Y, true); }); - AddButton (this.toolbar, this.eventHandler, 'up_z', 'Set Z axis as up vector', ['only_on_model'], () => { + AddButton (this.toolbar, 'up_z', 'Set Z axis as up vector', ['only_on_model'], () => { this.viewer.SetUpVector (OV.Direction.Z, true); }); - AddButton (this.toolbar, this.eventHandler, 'flip', 'Flip up vector', ['only_on_model'], () => { + AddButton (this.toolbar, 'flip', 'Flip up vector', ['only_on_model'], () => { this.viewer.FlipUpVector (); }); AddSeparator (this.toolbar, ['only_on_model']); - AddRadioButton (this.toolbar, this.eventHandler, ['fix_up_on', 'fix_up_off'], ['Fixed up vector', 'Free orbit'], 0, ['only_on_model'], (buttonIndex) => { + AddRadioButton (this.toolbar, ['fix_up_on', 'fix_up_off'], ['Fixed up vector', 'Free orbit'], 0, ['only_on_model'], (buttonIndex) => { if (buttonIndex === 0) { this.viewer.SetFixUpVector (true); } else if (buttonIndex === 1) { @@ -535,7 +530,7 @@ OV.Website = class } }); AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']); - AddButton (this.toolbar, this.eventHandler, 'export', 'Export model', ['only_full_width', 'only_on_model'], () => { + AddButton (this.toolbar, 'export', 'Export model', ['only_full_width', 'only_on_model'], () => { let exportDialog = new OV.ExportDialog ({ isMeshVisible : (meshInstanceId) => { return this.navigator.IsMeshVisible (meshInstanceId); @@ -543,16 +538,16 @@ OV.Website = class onDialog : (dialog) => { this.dialog = dialog; } - }); + }, this.eventHandler); exportDialog.Show (this.model, this.viewer); }); - AddButton (this.toolbar, this.eventHandler, 'share', 'Share model', ['only_full_width', 'only_on_model'], () => { - this.dialog = OV.ShowSharingDialog (importer, this.settings, this.viewer.GetCamera ()); + AddButton (this.toolbar, 'share', 'Share model', ['only_full_width', 'only_on_model'], () => { + this.dialog = OV.ShowSharingDialog (importer.GetFileList (), this.settings, this.viewer.GetCamera (), this.eventHandler); }); this.parameters.fileInput.addEventListener ('change', (ev) => { if (ev.target.files.length > 0) { - this.eventHandler.HandleEvent ('model_load_started', { source : 'open_file' }); + this.eventHandler.HandleEvent ('model_load_started', 'open_file'); this.LoadModelFromFileList (ev.target.files); } }); @@ -575,7 +570,7 @@ OV.Website = class ev.preventDefault (); OV.GetFilesFromDataTransfer (ev.dataTransfer, (files) => { if (files.length > 0) { - this.eventHandler.HandleEvent ('model_load_started', { source : 'drop' }); + this.eventHandler.HandleEvent ('model_load_started', 'drop'); this.LoadModelFromFileList (files); } }); @@ -602,9 +597,11 @@ OV.Website = class this.UpdateGridDisplay (); }, onEdgeDisplayChange : () => { + this.eventHandler.HandleEvent ('edge_display_changed', this.settings.showEdges ? 'on' : 'off'); this.UpdateEdgeDisplay (); }, onThemeChange : () => { + this.eventHandler.HandleEvent ('theme_changed', this.settings.themeId === OV.Theme.Light ? 'light' : 'dark'); this.SwitchTheme (this.settings.themeId, true); }, onMeasureToolActivedChange : (isActivated) => {