diff --git a/modules/glmv-hs.js b/modules/glmv-hs.js index b0e9a18..3582ccb 100644 --- a/modules/glmv-hs.js +++ b/modules/glmv-hs.js @@ -147,4 +147,14 @@ releaseAnnotation = function(e) { $('#wpTextbox1').val(newText) } grabHotspot = null +} + +/** + * Change the currently selected annotation set + * + * @param {string} newSet name of annotation set to select + */ +selectAnnotationSet = function(newSet) { + $('model-viewer').attr('currentSet',newSet) + readMvconfig() } \ No newline at end of file diff --git a/modules/glmv-mvconfig.js b/modules/glmv-mvconfig.js index 5765104..5d5315c 100644 --- a/modules/glmv-mvconfig.js +++ b/modules/glmv-mvconfig.js @@ -1,5 +1,3 @@ -let currentSet = 'default' - /** * Convert text in the preview text editor to js object * @@ -27,9 +25,9 @@ extractMvconfig = function() { /** * Reads the json string in the edit panel - * and updates hotspot elements + * and updates hotspot elements and menu settings * - * @return {bool} true on successful read and update + * @return {bool|object} arrays of view and set names on successful read and update false on failure */ readMvconfig = function() { let hotspotsObj = [] @@ -63,6 +61,7 @@ readMvconfig = function() { console.warn('Failed to read model config:' + err.message) return false } + const currentSet = $('model-viewer').attr('currentSet') || 'default' if (currentSet != 'default' && mvconfig.annotationSets[currentSet]) { mvconfig.annotationSets[currentSet].forEach(hs => { createHotspot(hs, slotNum) @@ -84,7 +83,10 @@ readMvconfig = function() { mView.appendChild(hs) }) - return true + return { + set: Object.keys(mvconfig.annotationSets), + view: Object.keys(mvconfig.viewerConfig) + } } /** @@ -160,6 +162,40 @@ toggleCameraControl = function(view) { return newControl } +/** + * Add a new annoation set object to annotatsionSets array + * + * @param {string} newSet name of new view config + */ +addAnnotationSet = function(newSet) { + const mView = $('model-viewer')[0] + let [currentText, mvconfig] = extractMvconfig() + mvconfig.annotationSets[newSet] = [] + const textUpdate = currentText.replace(/(?<=)([\S\s]*?)(?=<\/mvconfig>)/gm,`\n${JSON.stringify(mvconfig, null, 2)}\n`) + $('#wpTextbox1').val(textUpdate) + selectAnnotationSet(newSet) +} + +/** + * Add a new set of view configurations to viewerConfig + * + * @param {string} newView name of new view config + */ +addViewConfig = function(newView) { + const mView = $('model-viewer')[0] + let [currentText, mvconfig] = extractMvconfig() + mvconfig.viewerConfig[newView] = { "camera-controls": true } + const textUpdate = currentText.replace(/(?<=)([\S\s]*?)(?=<\/mvconfig>)/gm,`\n${JSON.stringify(mvconfig, null, 2)}\n`) + $('#wpTextbox1').val(textUpdate) + selectViewConfig(newView) +} + +/** + * Switch the current model-viewer attributes to a different + * set of configurations in the mvconfig data + * + * @param {string} view the view name (viewerConfig object key) + */ selectViewConfig = function(view) { const mView = $('model-viewer')[0] let [_, mvconfig] = extractMvconfig() @@ -242,28 +278,4 @@ writeCameraLimit = function(axis, limit) { mView.setAttribute(`${limit}-camera-orbit`, oldOrbitVals.join(' ')) const textUpdate = currentText.replace(/(?<=)([\S\s]*?)(?=<\/mvconfig>)/gm,`\n${JSON.stringify(mvconfig, null, 2)}\n`) $('#wpTextbox1').val(textUpdate) -} - -/** - * Change the currently selected annotation set - * - * @param {string} newSet name of annotation set to select - */ -selectAnnotationSet = function(newSet) { - currentSet = newSet - readMvconfig() -} - -/* -export default { - extractMvconfig, - readMvconfig, - writeMvconfig, - orb2degree, - toggleCameraControl, - selectViewConfig, - writeCameraOrbit, - writeCameraLimit, - selectAnnotationSet -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/modules/glmv-prev.js b/modules/glmv-prev.js index d6af30c..c706dbc 100644 --- a/modules/glmv-prev.js +++ b/modules/glmv-prev.js @@ -20,14 +20,6 @@ buildPreviewMenu = function() { addHS.on('click', readyAddHotspot) addHS.setDisabled(true) - const updateHS = new OO.ui.ButtonWidget({ - icon: 'reload', - label: 'Update annotations', - invisibleLabel: true - }) - updateHS.on('click', readMvconfig) - updateHS.setDisabled(true) - const deleteHS = new OO.ui.ButtonWidget({ icon: 'cancel', label: 'Delete annotation', @@ -36,7 +28,7 @@ buildPreviewMenu = function() { deleteHS.on('click', readyDelHotspot) deleteHS.setDisabled(true) - const setOptions = ['default', ...Object.keys(origMetadata.annotationSets)] + const setOptions = ['default', ...Object.keys(origMetadata.annotationSets), 'Add new'] let setOptionItems = [] setOptions.forEach(opt => { setOptionItems.push(new OO.ui.MenuOptionWidget({data: opt, label: opt})) @@ -53,25 +45,15 @@ buildPreviewMenu = function() { $overlay: $('#bodyContent') }) setSelectHS.getMenu().on( 'choose', selSet => { - selectAnnotationSet(selSet.data) + onSetMenu(selSet.data) }) setSelectHS.setDisabled(true) const hotspotButtons = new OO.ui.ButtonGroupWidget({ - items: [ addHS, updateHS, deleteHS, setSelectHS ] + items: [ addHS, deleteHS, setSelectHS ] }) //View Edit Controls - const downloadViewerImage = new OO.ui.ButtonWidget({ - icon: 'imageAdd', - label: 'Download current image', - invisibleLabel: true - }) - downloadViewerImage.on('click', () => { - downloadImage(mw.config.values.wgTitle) - }) - downloadViewerImage.setDisabled(true) - const setView = new OO.ui.ButtonWidget({ icon: 'camera', label: 'Set Initial View', @@ -162,7 +144,7 @@ buildPreviewMenu = function() { }) setLims.setDisabled(true) - const setViewConfig = [...Object.keys(origMetadata.viewerConfig)] + const setViewConfig = [...Object.keys(origMetadata.viewerConfig), 'Add new'] let setViewItems = [] setViewConfig.forEach(opt => { setViewItems.push(new OO.ui.MenuOptionWidget({data: opt, label: opt})) @@ -179,26 +161,50 @@ buildPreviewMenu = function() { $overlay: $('#bodyContent') }) selectVC.getMenu().on( 'choose', selSet => { - selectViewConfig(selSet.data) + onViewMenu(selSet.data) }) selectVC.setDisabled(true) const cameraButtons = new OO.ui.ButtonGroupWidget({ - items: [ downloadViewerImage, setControl, setView, setLims, selectVC ] + items: [ setControl, setView, setLims, selectVC ] + }) + + //General controls + const downloadViewerImage = new OO.ui.ButtonWidget({ + icon: 'imageAdd', + label: 'Download current image', + invisibleLabel: true + }) + downloadViewerImage.on('click', () => { + downloadImage(mw.config.values.wgTitle) + }) + downloadViewerImage.setDisabled(true) + + const updateViewer = new OO.ui.ButtonWidget({ + icon: 'reload', + label: 'Update from text', + invisibleLabel: true + }) + updateViewer.on('click', refreshConfigs) + updateViewer.setDisabled(true) + + const generalButtons = new OO.ui.ButtonGroupWidget({ + items: [ downloadViewerImage, updateViewer ] }) //Main Menu const modelMenu = new OO.ui.HorizontalLayout({ items: [ hotspotButtons, - cameraButtons + cameraButtons, + generalButtons ], id: 'edit-model-menu' }) $('#wikiPreview').after(modelMenu.$element) - return [modelMenu, selectVC] + return [modelMenu, selectVC, setSelectHS] } /** @@ -211,15 +217,6 @@ enableMenu = function() { }); } -/** - * Add a selection option to a ButtonMenuSelectWidget - * - * @param {ButtonMenuSelectWidget} menuWidget - */ -addMenuOption = function(menuWidget) { - menuWidget.menu.addItems([new OO.ui.MenuOptionWidget({data: 'New option', label: 'New option'})]) -} - /** * Disable general interaction with model * viewer for specific additional function @@ -278,5 +275,76 @@ downloadImage = function(defName) { }) } +/** + * Process view selection menu select event + * + * @param {string} selectData data associated with the selected menu label + */ +onViewMenu = function(selectData) { + if (selectData == 'Add new') { + const newSelectIdx = viewSelector.menu.items.length + const newView = `View${newSelectIdx}` + viewSelector.menu.addItems([new OO.ui.MenuOptionWidget({data: newView, label: newView})], newSelectIdx - 1) + addViewConfig(newView) + } else { + selectViewConfig(selectData) + } +} + +/** + * Process annotation set menu select event + * + * @param {string} selectData data associated with the selected menu label + */ +onSetMenu = function(selectData) { + if (selectData == 'Add new') { + const newSelectIdx = setSelector.menu.items.length + const newSet = `Set${newSelectIdx - 1}` + setSelector.menu.addItems([new OO.ui.MenuOptionWidget({data: newSet, label: newSet})], newSelectIdx - 1) + addAnnotationSet(newSet) + } else { + selectAnnotationSet(selectData) + } +} + +/** + * Update the available menu options in the given menu + * from an array + * + * @param {string} menuTYpe 'set'|'view' to determine which menu to update + * @param {array} newOpts array of strings containing new menu options + */ +updateMenu = function(menuType, newOpts) { + let menuObj + switch (menuType) { + case 'set': + menuObj = setSelector + menuOpts = ['default', ...newOpts, 'Add new'] + break + case 'view': + menuObj = viewSelector + menuOpts = [...newOpts, 'Add new'] + break + } + menuObj.menu.clearItems() + menuOpts.forEach(opt => { + menuObj.menu.addItems([new OO.ui.MenuOptionWidget({data: opt, label: opt})]) + }) +} + +/** + * Refresh all viewer settings and menus from the edit input text + */ +refreshConfigs = function() { + const newLists = readMvconfig() + if (newLists) { + for (let lst in newLists) { + updateMenu(lst, newLists[lst]) + } + } +} + //Initialize the menu and get required global objects -const [modelMenu, viewSelector] = buildPreviewMenu() \ No newline at end of file +const [modelMenu, + viewSelector, + setSelector] = buildPreviewMenu() \ No newline at end of file