diff --git a/source/website/exportdialog.js b/source/website/exportdialog.js index 4af5734..db91e5d 100644 --- a/source/website/exportdialog.js +++ b/source/website/exportdialog.js @@ -13,22 +13,15 @@ import { DownloadArrayBufferAsFile, DownloadUrlAsFile } from './utils.js'; import { CookieGetStringVal, CookieSetStringVal } from './cookiehandler.js'; import { HandleEvent } from './eventhandler.js'; -const ExportType = +class ModelExporterUI { - Model : 0, - Image : 1 -}; - -class ExporterUI -{ - constructor (name) + constructor (name, format, extension) { this.name = name; - } - - GetType () - { - return null; + this.format = format; + this.extension = extension; + this.visibleOnlySelect = null; + this.rotationSelect = null; } GetName () @@ -38,38 +31,16 @@ class ExporterUI GenerateParametersUI (parametersDiv) { + function AddSelectItem (parametersDiv, name, values, defaultIndex) + { + let parameterRow = AddDiv (parametersDiv, 'ov_dialog_row'); + AddDiv (parameterRow, 'ov_dialog_row_name', name); + let parameterValueDiv = AddDiv (parameterRow, 'ov_dialog_row_value'); + return AddSelect (parameterValueDiv, values, defaultIndex); + } - } - - AddSelectItem (parametersDiv, name, values, defaultIndex) - { - let parameterRow = AddDiv (parametersDiv, 'ov_dialog_row'); - AddDiv (parameterRow, 'ov_dialog_row_name', name); - let parameterValueDiv = AddDiv (parameterRow, 'ov_dialog_row_value'); - return AddSelect (parameterValueDiv, values, defaultIndex); - } -} - -class ModelExporterUI extends ExporterUI -{ - constructor (name, format, extension) - { - super (name); - this.format = format; - this.extension = extension; - this.visibleOnlySelect = null; - this.rotationSelect = null; - } - - GetType () - { - return ExportType.Model; - } - - GenerateParametersUI (parametersDiv) - { - this.visibleOnlySelect = this.AddSelectItem (parametersDiv, 'Scope', ['Entire Model', 'Visible Only'], 1); - this.rotationSelect = this.AddSelectItem (parametersDiv, 'Rotation', ['No Rotation', '-90 Degrees', '90 Degrees'], 0); + this.visibleOnlySelect = AddSelectItem (parametersDiv, 'Scope', ['Entire Model', 'Visible Only'], 1); + this.rotationSelect = AddSelectItem (parametersDiv, 'Rotation', ['No Rotation', '-90 Degrees', '90 Degrees'], 0); } ExportModel (model, callbacks) @@ -136,45 +107,6 @@ class ModelExporterUI extends ExporterUI } } -class ImageExporterUI extends ExporterUI -{ - constructor (name, extension) - { - super (name); - this.extension = extension; - this.sizeSelect = null; - this.sizes = [ - { name : 'Current size', value : null }, - { name : '1280 x 720', value : [1280, 720] }, - { name : '1920 x 1080', value : [1920, 1080] } - ]; - } - - GetType () - { - return ExportType.Image; - } - - GenerateParametersUI (parametersDiv) - { - let sizeNames = this.sizes.map (size => size.name); - this.sizeSelect = this.AddSelectItem (parametersDiv, 'Image size', sizeNames, 1); - } - - ExportImage (viewer) - { - let selectedSize = this.sizes[this.sizeSelect.selectedIndex]; - let url = null; - if (selectedSize.value === null) { - let size = viewer.GetImageSize (); - url = viewer.GetImageAsDataUrl (size.width, size.height); - } else { - url = viewer.GetImageAsDataUrl (selectedSize.value[0], selectedSize.value[1]); - } - DownloadUrlAsFile (url, 'model.' + this.extension); - } -} - class ExportDialog { constructor (callbacks) @@ -192,8 +124,7 @@ class ExportDialog new ModelExporterUI ('glTF Text (.gltf)', FileFormat.Text, 'gltf'), new ModelExporterUI ('glTF Binary (.glb)', FileFormat.Binary, 'glb'), new ModelExporterUI ('Object File Format Text (.off)', FileFormat.Text, 'off'), - new ModelExporterUI ('Rhinoceros 3D (.3dm)', FileFormat.Binary, '3dm'), - new ImageExporterUI ('PNG Image (.png)', 'png') + new ModelExporterUI ('Rhinoceros 3D (.3dm)', FileFormat.Binary, '3dm') ]; } @@ -246,16 +177,12 @@ class ExportDialog ExportFormat (model, viewer) { - if (this.selectedExporter.GetType () === ExportType.Model) { - this.selectedExporter.ExportModel (model, { - isMeshVisible : (meshInstanceId) => { - return this.callbacks.isMeshVisible (meshInstanceId); - } - }); - HandleEvent ('model_exported', this.selectedExporter.GetName ()); - } else if (this.selectedExporter.GetType () === ExportType.Image) { - this.selectedExporter.ExportImage (viewer); - } + this.selectedExporter.ExportModel (model, { + isMeshVisible : (meshInstanceId) => { + return this.callbacks.isMeshVisible (meshInstanceId); + } + }); + HandleEvent ('model_exported', this.selectedExporter.GetName ()); } } @@ -318,6 +245,7 @@ export function ShowSnapshotDialog (viewer) name : 'Create', onClick () { dialog.Close (); + HandleEvent ('snapshot_created', sizes[selectedIndex].name); let url = GetImageUrl (viewer, sizes[selectedIndex]); DownloadUrlAsFile (url, 'model.png'); } @@ -327,7 +255,7 @@ export function ShowSnapshotDialog (viewer) let optionsDiv = AddDiv (contentDiv, 'ov_snapshot_dialog_left'); let previewImage = CreateDomElement ('img', 'ov_snapshot_dialog_preview'); - let lastSnapshotSizeName = CookieGetStringVal ('ov_last_snapshot_size', sizes[0].name); + let lastSnapshotSizeName = CookieGetStringVal ('ov_last_snapshot_size', sizes[1].name); for (let i = 0; i < sizes.length; i++) { if (lastSnapshotSizeName === sizes[i].name) { selectedIndex = i; diff --git a/source/website/website.js b/source/website/website.js index ef6d60f..774dc29 100644 --- a/source/website/website.js +++ b/source/website/website.js @@ -11,7 +11,7 @@ import { Sidebar } from './sidebar.js'; import { ThemeHandler } from './themehandler.js'; import { ThreeModelLoaderUI } from './threemodelloaderui.js'; import { Toolbar } from './toolbar.js'; -import { ShowExportDialog } from './exportdialog.js'; +import { ShowExportDialog, ShowSnapshotDialog } from './exportdialog.js'; import { AddSmallWidthChangeEventListener, GetFilesFromDataTransfer, IsSmallWidth } from './utils.js'; import { ShowOpenUrlDialog } from './openurldialog.js'; import { ShowSharingDialog } from './sharingdialog.js'; @@ -565,6 +565,9 @@ export class Website }); this.measureTool.SetButton (measureToolButton); AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']); + AddButton (this.toolbar, 'snapshot', 'Create snapshot', ['only_full_width', 'only_on_model'], () => { + ShowSnapshotDialog (this.viewer); + }); AddButton (this.toolbar, 'export', 'Export model', ['only_full_width', 'only_on_model'], () => { ShowExportDialog (this.model, this.viewer, { isMeshVisible : (meshInstanceId) => { diff --git a/website/css/O3DVIcons/O3DVIcons.woff b/website/css/O3DVIcons/O3DVIcons.woff index 4758d1a..ae17c39 100644 Binary files a/website/css/O3DVIcons/O3DVIcons.woff and b/website/css/O3DVIcons/O3DVIcons.woff differ diff --git a/website/css/dialogs.css b/website/css/dialogs.css index 9bb5a6d..2e43567 100644 --- a/website/css/dialogs.css +++ b/website/css/dialogs.css @@ -258,8 +258,9 @@ div.ov_snapshot_dialog_left img.ov_snapshot_dialog_preview { background: var(--ov_border_color); - width: 250px; - height: 140px; + border: 1px solid var(--ov_border_color); + width: 240px; + height: 135px; object-fit: contain; float: right; } diff --git a/website/css/icons.css b/website/css/icons.css index 6794363..2f07294 100644 --- a/website/css/icons.css +++ b/website/css/icons.css @@ -1,6 +1,6 @@ @font-face { font-family: "O3DVIcons"; - src: url("O3DVIcons/O3DVIcons.woff?8e8ff80e3f2f51d21873c070a35e0f3c") format("woff"); + src: url("O3DVIcons/O3DVIcons.woff?3aa6f39e888e50c0858037b7381ba7ac") format("woff"); } i[class^="icon-"]:before, i[class*=" icon-"]:before { @@ -119,24 +119,27 @@ i[class^="icon-"]:before, i[class*=" icon-"]:before { .icon-share:before { content: "\f123"; } -.icon-tree_mesh:before { +.icon-snapshot:before { content: "\f124"; } -.icon-tree_view:before { +.icon-tree_mesh:before { content: "\f125"; } -.icon-twitter:before { +.icon-tree_view:before { content: "\f126"; } -.icon-up_y:before { +.icon-twitter:before { content: "\f127"; } -.icon-up_z:before { +.icon-up_y:before { content: "\f128"; } -.icon-visible:before { +.icon-up_z:before { content: "\f129"; } -.icon-warning:before { +.icon-visible:before { content: "\f12a"; } +.icon-warning:before { + content: "\f12b"; +} diff --git a/website/info/O3DVIcons.woff b/website/info/O3DVIcons.woff index 4758d1a..ae17c39 100644 Binary files a/website/info/O3DVIcons.woff and b/website/info/O3DVIcons.woff differ diff --git a/website/info/icons.css b/website/info/icons.css index a76f10d..d819fc1 100644 --- a/website/info/icons.css +++ b/website/info/icons.css @@ -1,6 +1,6 @@ @font-face { font-family: "O3DVIcons"; - src: url("./O3DVIcons.woff?8e8ff80e3f2f51d21873c070a35e0f3c") format("woff"); + src: url("./O3DVIcons.woff?3aa6f39e888e50c0858037b7381ba7ac") format("woff"); } i[class^="icon-"]:before, i[class*=" icon-"]:before { @@ -119,24 +119,27 @@ i[class^="icon-"]:before, i[class*=" icon-"]:before { .icon-share:before { content: "\f123"; } -.icon-tree_mesh:before { +.icon-snapshot:before { content: "\f124"; } -.icon-tree_view:before { +.icon-tree_mesh:before { content: "\f125"; } -.icon-twitter:before { +.icon-tree_view:before { content: "\f126"; } -.icon-up_y:before { +.icon-twitter:before { content: "\f127"; } -.icon-up_z:before { +.icon-up_y:before { content: "\f128"; } -.icon-visible:before { +.icon-up_z:before { content: "\f129"; } -.icon-warning:before { +.icon-visible:before { content: "\f12a"; } +.icon-warning:before { + content: "\f12b"; +}