diff --git a/assets/icons/measure.svg b/assets/icons/measure.svg new file mode 100644 index 0000000..df29db6 --- /dev/null +++ b/assets/icons/measure.svg @@ -0,0 +1,66 @@ + +image/svg+xml \ No newline at end of file diff --git a/sandbox/embed_edges.html b/sandbox/embed_edges.html index 1d4df26..c2040cc 100644 --- a/sandbox/embed_edges.html +++ b/sandbox/embed_edges.html @@ -71,6 +71,7 @@ + diff --git a/sandbox/embed_selfhost_errors.html b/sandbox/embed_selfhost_errors.html index dfee977..a74f59d 100644 --- a/sandbox/embed_selfhost_errors.html +++ b/sandbox/embed_selfhost_errors.html @@ -71,6 +71,7 @@ + diff --git a/sandbox/embed_selfhost_externallibs.html b/sandbox/embed_selfhost_externallibs.html index 3306850..f12633b 100644 --- a/sandbox/embed_selfhost_externallibs.html +++ b/sandbox/embed_selfhost_externallibs.html @@ -71,6 +71,7 @@ + diff --git a/sandbox/embed_selfhost_fullscreen.html b/sandbox/embed_selfhost_fullscreen.html index c5df813..061b8ac 100644 --- a/sandbox/embed_selfhost_fullscreen.html +++ b/sandbox/embed_selfhost_fullscreen.html @@ -70,6 +70,7 @@ + diff --git a/sandbox/embed_selfhost_manual.html b/sandbox/embed_selfhost_manual.html index 77260e5..110afed 100644 --- a/sandbox/embed_selfhost_manual.html +++ b/sandbox/embed_selfhost_manual.html @@ -71,6 +71,7 @@ + diff --git a/sandbox/embed_selfhost_multiple.html b/sandbox/embed_selfhost_multiple.html index cacbee9..dab88ab 100644 --- a/sandbox/embed_selfhost_multiple.html +++ b/sandbox/embed_selfhost_multiple.html @@ -71,6 +71,7 @@ + diff --git a/sandbox/embed_selfhost_single.html b/sandbox/embed_selfhost_single.html index 29ff348..be2c242 100644 --- a/sandbox/embed_selfhost_single.html +++ b/sandbox/embed_selfhost_single.html @@ -70,6 +70,7 @@ + + + @@ -115,6 +116,7 @@ + diff --git a/website/index.html b/website/index.html index 6570473..0ba7512 100644 --- a/website/index.html +++ b/website/index.html @@ -79,6 +79,7 @@ + @@ -117,6 +118,7 @@ + diff --git a/website/o3dv/css/O3DVIcons/O3DVIcons.woff b/website/o3dv/css/O3DVIcons/O3DVIcons.woff index 2046bcb..491c5b4 100644 Binary files a/website/o3dv/css/O3DVIcons/O3DVIcons.woff and b/website/o3dv/css/O3DVIcons/O3DVIcons.woff differ diff --git a/website/o3dv/css/icons.css b/website/o3dv/css/icons.css index 1b32aa5..c2c804a 100644 --- a/website/o3dv/css/icons.css +++ b/website/o3dv/css/icons.css @@ -1,6 +1,6 @@ @font-face { font-family: "O3DVIcons"; - src: url("O3DVIcons/O3DVIcons.woff?9f1e775b55726eccac0336790d9d9b2f") format("woff"); + src: url("O3DVIcons/O3DVIcons.woff?a94a3e222e39f4785c00ccb77bce301e") format("woff"); } i[class^="icon-"]:before, i[class*=" icon-"]:before { @@ -86,48 +86,51 @@ i[class^="icon-"]:before, i[class*=" icon-"]:before { .icon-materials:before { content: "\f118"; } -.icon-meshes:before { +.icon-measure:before { content: "\f119"; } -.icon-missing_files:before { +.icon-meshes:before { content: "\f11a"; } -.icon-model:before { +.icon-missing_files:before { content: "\f11b"; } -.icon-open_url:before { +.icon-model:before { content: "\f11c"; } -.icon-open:before { +.icon-open_url:before { content: "\f11d"; } -.icon-settings:before { +.icon-open:before { content: "\f11e"; } -.icon-share:before { +.icon-settings:before { content: "\f11f"; } -.icon-theme:before { +.icon-share:before { content: "\f120"; } -.icon-tree_mesh:before { +.icon-theme:before { content: "\f121"; } -.icon-tree_view:before { +.icon-tree_mesh:before { content: "\f122"; } -.icon-twitter:before { +.icon-tree_view:before { content: "\f123"; } -.icon-up_y:before { +.icon-twitter:before { content: "\f124"; } -.icon-up_z:before { +.icon-up_y:before { content: "\f125"; } -.icon-visible:before { +.icon-up_z:before { content: "\f126"; } -.icon-warning:before { +.icon-visible:before { content: "\f127"; } +.icon-warning:before { + content: "\f128"; +} diff --git a/website/o3dv/css/sidebar.css b/website/o3dv/css/sidebar.css index 57bc6ee..7ab7083 100644 --- a/website/o3dv/css/sidebar.css +++ b/website/o3dv/css/sidebar.css @@ -46,6 +46,12 @@ div.ov_sidebar_content overflow: auto; } +div.ov_sidebar_section +{ + margin: 10px 0px; + overflow: auto; +} + div.ov_sidebar_content div.ov_sidebar_settings_content { margin-bottom: 20px; @@ -83,6 +89,17 @@ div.ov_sidebar_content div.ov_sidebar_settings_padded overflow: hidden; } +div.ov_sidebar_content div.ov_sidebar_measure_name +{ + font-weight: bold; + margin-bottom: 5px; +} + +div.ov_sidebar_content div.ov_sidebar_measure_value +{ + margin-bottom: 10px; +} + div.ov_sidebar_content button.pcr-button { width: 30px; diff --git a/website/o3dv/js/featureset.js b/website/o3dv/js/featureset.js index 118c951..64ac4bf 100644 --- a/website/o3dv/js/featureset.js +++ b/website/o3dv/js/featureset.js @@ -1,3 +1,4 @@ OV.FeatureSet = { + MeasureTool : false }; diff --git a/website/o3dv/js/navigator.js b/website/o3dv/js/navigator.js index 801c0f0..cb3601e 100644 --- a/website/o3dv/js/navigator.js +++ b/website/o3dv/js/navigator.js @@ -64,11 +64,7 @@ OV.Navigator = class this.panelSet.Init ({ onResize : () => { - if (this.panelSet.IsPanelsVisible ()) { - OV.ShowDomElement (this.splitterDiv); - } else { - OV.HideDomElement (this.splitterDiv); - } + OV.ShowDomElement (this.splitterDiv, this.panelSet.IsPanelsVisible ()); this.callbacks.onResize (); }, onShowHidePanels : (show) => { diff --git a/website/o3dv/js/navigatormeshespanel.js b/website/o3dv/js/navigatormeshespanel.js index 6d1be07..b1126b1 100644 --- a/website/o3dv/js/navigatormeshespanel.js +++ b/website/o3dv/js/navigatormeshespanel.js @@ -157,15 +157,10 @@ OV.NavigatorMeshesPanel = class extends OV.NavigatorPanel buttons.flatList.iconDiv.classList.add ('selected'); buttons.treeView.iconDiv.classList.remove ('selected'); } - if (showTree && isHierarchical) { - OV.ShowDomElement (buttons.separator); - OV.ShowDomElement (buttons.expandAll.div); - OV.ShowDomElement (buttons.collapseAll.div); - } else { - OV.HideDomElement (buttons.separator); - OV.HideDomElement (buttons.expandAll.div); - OV.HideDomElement (buttons.collapseAll.div); - } + let showExpandButtons = showTree && isHierarchical; + OV.ShowDomElement (buttons.separator, showExpandButtons); + OV.ShowDomElement (buttons.expandAll.div, showExpandButtons); + OV.ShowDomElement (buttons.collapseAll.div, showExpandButtons); } function UpdateView (panel, importResult, isHierarchical) diff --git a/website/o3dv/js/panelset.js b/website/o3dv/js/panelset.js index 7b5ab84..8668eee 100644 --- a/website/o3dv/js/panelset.js +++ b/website/o3dv/js/panelset.js @@ -4,7 +4,7 @@ OV.Panel = class { this.parentDiv = parentDiv; this.panelDiv = OV.AddDiv (parentDiv); - OV.HideDomElement (this.panelDiv); + OV.ShowDomElement (this.panelDiv, false); this.visible = false; } @@ -25,11 +25,7 @@ OV.Panel = class } this.visible = show; - if (this.visible) { - OV.ShowDomElement (this.panelDiv); - } else { - OV.HideDomElement (this.panelDiv); - } + OV.ShowDomElement (this.panelDiv, this.visible); } Resize () @@ -101,7 +97,7 @@ OV.PanelSet = class this.panelsVisible = show; if (this.panelsVisible) { - OV.ShowDomElement (this.contentDiv); + OV.ShowDomElement (this.contentDiv, true); OV.SetDomElementWidth (this.parentDiv, this.menuDiv.offsetWidth + this.panelsPrevWidth); } else { for (let panelButton of this.panelButtons) { @@ -112,7 +108,7 @@ OV.PanelSet = class } this.panelsPrevWidth = this.contentDiv.offsetWidth; OV.SetDomElementWidth (this.parentDiv, this.menuDiv.offsetWidth); - OV.HideDomElement (this.contentDiv); + OV.ShowDomElement (this.contentDiv, false); } this.callbacks.onShowHidePanels (this.panelsVisible); diff --git a/website/o3dv/js/sidebar.js b/website/o3dv/js/sidebar.js index 64ef49d..5a995cb 100644 --- a/website/o3dv/js/sidebar.js +++ b/website/o3dv/js/sidebar.js @@ -8,9 +8,13 @@ OV.Sidebar = class this.detailsPanel = new OV.SidebarDetailsPanel (this.panelSet.GetContentDiv ()); this.settingsPanel = new OV.SidebarSettingsPanel (this.panelSet.GetContentDiv (), settings); + this.measurePanel = new OV.SidebarMeasurePanel (this.panelSet.GetContentDiv ()); this.panelSet.AddPanel (this.detailsPanel); this.panelSet.AddPanel (this.settingsPanel); + if (OV.FeatureSet.MeasureTool) { + this.panelSet.AddPanel (this.measurePanel); + } this.panelSet.ShowPanel (this.detailsPanel); } @@ -30,11 +34,7 @@ OV.Sidebar = class this.panelSet.Init ({ onResize : () => { - if (this.panelSet.IsPanelsVisible ()) { - OV.ShowDomElement (this.splitterDiv); - } else { - OV.HideDomElement (this.splitterDiv); - } + OV.ShowDomElement (this.splitterDiv, this.panelSet.IsPanelsVisible ()); this.callbacks.onResize (); }, onShowHidePanels : (show) => { @@ -57,6 +57,12 @@ OV.Sidebar = class } }); + this.measurePanel.Init ({ + onActivatedChange : (isActivated) => { + this.callbacks.onMeasureToolActivedChange (isActivated); + } + }); + OV.InstallVerticalSplitter (this.splitterDiv, this.mainDiv, true, () => { this.callbacks.onResize (); }); @@ -67,6 +73,11 @@ OV.Sidebar = class this.settingsPanel.UpdateSettings (hasDefaultMaterial); } + UpdateMeasureTool (measureTool) + { + this.measurePanel.UpdateMeasureTool (measureTool); + } + Resize (height) { OV.SetDomElementOuterHeight (this.mainDiv, height); diff --git a/website/o3dv/js/sidebarmeasurepanel.js b/website/o3dv/js/sidebarmeasurepanel.js new file mode 100644 index 0000000..64a6f0c --- /dev/null +++ b/website/o3dv/js/sidebarmeasurepanel.js @@ -0,0 +1,97 @@ +OV.SidebarMeasurePanel = class extends OV.SidebarPanel +{ + constructor (parentDiv) + { + super (parentDiv); + + this.helpSection = null; + this.resultSection = null; + } + + GetName () + { + return 'Measure'; + } + + GetIcon () + { + return 'measure'; + } + + Init (callbacks) + { + super.Init (callbacks); + + let isActive = false; + let activateButton = OV.AddDiv (this.contentDiv, 'ov_button ov_sidebar_button', 'Activate'); + activateButton.addEventListener ('click', () => { + isActive = !isActive; + if (isActive) { + activateButton.classList.add ('outline'); + activateButton.innerHTML = 'Deactivate'; + } else { + activateButton.classList.remove ('outline'); + activateButton.innerHTML = 'Activate'; + } + this.callbacks.onActivatedChange (isActive); + }); + + this.helpSection = OV.AddDiv (this.contentDiv, 'ov_sidebar_section'); + this.resultSection = OV.AddDiv (this.contentDiv, 'ov_sidebar_section'); + } + + UpdateMeasureTool (measureTool) + { + OV.ClearDomElement (this.helpSection); + OV.ClearDomElement (this.resultSection); + + OV.ShowDomElement (this.helpSection, true); + OV.ShowDomElement (this.resultSection, false); + + if (measureTool.IsActive ()) { + let markerCount = measureTool.GetMarkerCount (); + if (markerCount === 0) { + this.helpSection.innerHTML = 'Select a model point to start measure.'; + } else if (markerCount === 1) { + this.helpSection.innerHTML = 'Select another model point to start measure.'; + } else if (markerCount === 2) { + OV.ShowDomElement (this.helpSection, false); + OV.ShowDomElement (this.resultSection, true); + + let calculatedValues = measureTool.Calculate (); + + OV.AddDiv (this.resultSection, 'ov_sidebar_measure_name', 'Distance of points'); + let pointsDistanceStr = calculatedValues.pointsDistance.toLocaleString (undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 6 + }); + OV.AddDiv (this.resultSection, 'ov_sidebar_measure_value', pointsDistanceStr); + + OV.AddDiv (this.resultSection, 'ov_sidebar_measure_name', 'Distance of parallel faces'); + if (calculatedValues.parallelFacesDistance !== null) { + let facesDistanceStr = calculatedValues.parallelFacesDistance.toLocaleString (undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 6 + }); + OV.AddDiv (this.resultSection, 'ov_sidebar_measure_value', facesDistanceStr); + } else { + OV.AddDiv (this.resultSection, 'ov_sidebar_measure_value', 'Faces are not parallel'); + } + + OV.AddDiv (this.resultSection, 'ov_sidebar_measure_name', 'Angle of faces'); + let facesAngleDegree = calculatedValues.facesAngle * OV.RadDeg; + let facesAngleStr = facesAngleDegree.toLocaleString (undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 6 + }); + OV.AddDiv (this.resultSection, 'ov_sidebar_measure_value', facesAngleStr + '°'); + + } + } + } + + Clear () + { + + } +}; diff --git a/website/o3dv/js/sidebarsettingspanel.js b/website/o3dv/js/sidebarsettingspanel.js index 27ff8e2..6a10f85 100644 --- a/website/o3dv/js/sidebarsettingspanel.js +++ b/website/o3dv/js/sidebarsettingspanel.js @@ -58,11 +58,7 @@ OV.SettingsColorSection = class Show (show) { - if (show) { - OV.ShowDomElement (this.contentDiv); - } else { - OV.HideDomElement (this.contentDiv); - } + OV.ShowDomElement (this.contentDiv, show); } Update (color) @@ -139,11 +135,11 @@ OV.SettingsEdgeDisplaySection = class this.buttons = []; let offButton = AddRadioButton (buttonsDiv, 'off', 'Don\'t Show Edges', () => { - OV.HideDomElement (this.edgeSettingsDiv); + OV.ShowDomElement (this.edgeSettingsDiv, false); callbacks.onShowEdgesChange (false); }); let onButton = AddRadioButton (buttonsDiv, 'on', 'Show Edges', () => { - OV.ShowDomElement (this.edgeSettingsDiv); + OV.ShowDomElement (this.edgeSettingsDiv, true); callbacks.onShowEdgesChange (true); }); this.buttons.push (offButton); @@ -166,11 +162,7 @@ OV.SettingsEdgeDisplaySection = class ShowEdgeSettings (show) { - if (show) { - OV.ShowDomElement (this.edgeSettingsDiv); - } else { - OV.HideDomElement (this.edgeSettingsDiv); - } + OV.ShowDomElement (this.edgeSettingsDiv, show); } Clear () @@ -338,7 +330,7 @@ OV.SidebarSettingsPanel = class extends OV.SidebarPanel AddResetToDefaultsButton () { let defaultSettings = new OV.Settings (); - let resetToDefaultsButton = OV.AddDiv (this.contentDiv, 'ov_button outline ov_sidebar_button', 'Reset to Default'); + let resetToDefaultsButton = OV.AddDiv (this.contentDiv, 'ov_button ov_sidebar_button outline', 'Reset to Default'); resetToDefaultsButton.addEventListener ('click', () => { this.settings.backgroundColor = defaultSettings.backgroundColor; this.settings.defaultColor = defaultSettings.defaultColor; diff --git a/website/o3dv/js/toolbar.js b/website/o3dv/js/toolbar.js index 968caf1..4319446 100644 --- a/website/o3dv/js/toolbar.js +++ b/website/o3dv/js/toolbar.js @@ -41,6 +41,11 @@ OV.ToolbarButton = class this.buttonImg.classList.remove (className); } + IsSelected () + { + return this.selected; + } + SetSelected (selected) { this.selected = selected; @@ -66,6 +71,17 @@ OV.Toolbar = class return button; } + AddImagePushButton (image, imageTitle, isSelected, onClick) + { + let button = new OV.ToolbarButton (image, imageTitle, () => { + button.SetSelected (!button.IsSelected ()); + onClick (); + }); + button.AddDomElements (this.mainDiv); + button.SetSelected (isSelected); + return button; + } + AddImageRadioButton (buttonData, selectedIndex, onClick) { let buttons = []; diff --git a/website/o3dv/js/treeview.js b/website/o3dv/js/treeview.js index e30a22b..ff3a46c 100644 --- a/website/o3dv/js/treeview.js +++ b/website/o3dv/js/treeview.js @@ -154,10 +154,10 @@ OV.TreeViewGroupItem = class extends OV.TreeViewItem return; } if (this.isVisible) { - OV.ShowDomElement (this.mainElement); + OV.ShowDomElement (this.mainElement, true); this.childrenDiv.classList.add ('ov_tree_view_children'); } else { - OV.HideDomElement (this.mainElement); + OV.ShowDomElement (this.mainElement, false); this.childrenDiv.classList.remove ('ov_tree_view_children'); } } @@ -170,10 +170,10 @@ OV.TreeViewGroupItem = class extends OV.TreeViewItem } if (show) { OV.SetSvgIconImageElement (this.openCloseButton, this.openButtonIcon); - OV.ShowDomElement (this.childrenDiv); + OV.ShowDomElement (this.childrenDiv, true); } else { OV.SetSvgIconImageElement (this.openCloseButton, this.closeButtonIcon); - OV.HideDomElement (this.childrenDiv); + OV.ShowDomElement (this.childrenDiv, false); } } diff --git a/website/o3dv/js/website.js b/website/o3dv/js/website.js index c131bd7..d215fe4 100644 --- a/website/o3dv/js/website.js +++ b/website/o3dv/js/website.js @@ -13,6 +13,7 @@ OV.Website = class this.parameters = parameters; this.settings = new OV.Settings (); this.viewer = new OV.Viewer (); + this.measureTool = new OV.MeasureTool (); this.hashHandler = new OV.HashHandler (); this.cookieHandler = new OV.CookieHandler (); this.toolbar = new OV.Toolbar (this.parameters.toolbarDiv); @@ -33,6 +34,7 @@ OV.Website = class this.SwitchTheme (this.settings.themeId, false); this.InitViewer (); + this.InitMeasureTool (); this.InitToolbar (); this.InitDragAndDrop (); this.InitSidebar (); @@ -111,17 +113,17 @@ OV.Website = class this.uiState = uiState; if (this.uiState === OV.WebsiteUIState.Intro) { - OV.ShowDomElement (this.parameters.introDiv); - OV.HideDomElement (this.parameters.mainDiv); + OV.ShowDomElement (this.parameters.introDiv, true); + OV.ShowDomElement (this.parameters.mainDiv, false); ShowOnlyOnModelElements (false); } else if (this.uiState === OV.WebsiteUIState.Model) { - OV.HideDomElement (this.parameters.introDiv); - OV.ShowDomElement (this.parameters.mainDiv); + OV.ShowDomElement (this.parameters.introDiv, false); + OV.ShowDomElement (this.parameters.mainDiv, true); ShowOnlyOnModelElements (true); this.UpdatePanelsVisibility (); } else if (this.uiState === OV.WebsiteUIState.Loading) { - OV.HideDomElement (this.parameters.introDiv); - OV.HideDomElement (this.parameters.mainDiv); + OV.ShowDomElement (this.parameters.introDiv, false); + OV.ShowDomElement (this.parameters.mainDiv, false); ShowOnlyOnModelElements (false); } @@ -133,6 +135,7 @@ OV.Website = class this.HidePopups (); this.model = null; this.parameters.fileNameDiv.innerHTML = ''; + this.measureTool.Clear (); this.viewer.Clear (); this.navigator.Clear (); this.sidebar.Clear (); @@ -151,13 +154,21 @@ OV.Website = class OnModelClicked (button, mouseCoordinates) { - if (button === 1) { - let meshUserData = this.viewer.GetMeshUserDataUnderMouse (mouseCoordinates); - if (meshUserData === null) { - this.navigator.SetSelection (null); - } else { - this.navigator.SetSelection (new OV.Selection (OV.SelectionType.Mesh, meshUserData.originalMeshId)); - } + if (button !== 1) { + return; + } + + if (this.measureTool.IsActive ()) { + this.measureTool.Click (mouseCoordinates); + this.sidebar.UpdateMeasureTool (this.measureTool); + return; + } + + let meshUserData = this.viewer.GetMeshUserDataUnderMouse (mouseCoordinates); + if (meshUserData === null) { + this.navigator.SetSelection (null); + } else { + this.navigator.SetSelection (new OV.Selection (OV.SelectionType.Mesh, meshUserData.originalMeshId)); } } @@ -422,6 +433,11 @@ OV.Website = class ]); } + InitMeasureTool () + { + this.measureTool.Init (this.viewer, this.highlightColor); + } + InitToolbar () { function AddButton (toolbar, eventHandler, imageName, imageTitle, classNames, onClick) @@ -568,6 +584,15 @@ OV.Website = class onThemeChange : () => { this.SwitchTheme (this.settings.themeId, true); }, + onMeasureToolActivedChange : (isActivated) => { + if (isActivated) { + this.navigator.SetSelection (null); + this.measureTool.SetActive (true); + } else { + this.measureTool.SetActive (false); + } + this.sidebar.UpdateMeasureTool (this.measureTool); + }, onResize : () => { this.Resize (); },