Compare commits
9 Commits
a2246015c9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8294edc1d1 | |||
| 846106a1a8 | |||
| 717ef152f1 | |||
| 859183fe2e | |||
| 9953dff4a0 | |||
| 8ed4e1f679 | |||
| 7e353bee24 | |||
| 383818b6f8 | |||
| 88cd5e4727 |
@@ -183,10 +183,10 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
$attrModelView = array_merge(['src' => $srcUrl, 'class' => 'mv-model', 'interpolation-decay' => '100', 'interaction-prompt' => 'none'], $attrModelView);
|
$attrModelView = array_merge(['src' => $srcUrl, 'class' => 'mv-model', 'interpolation-decay' => '100', 'interaction-prompt' => 'none'], $attrModelView);
|
||||||
$attrModelView['style'] = 'width: 100%; height: 100%;';
|
$attrModelView['style'] = 'width: 100%; height: 100%;';
|
||||||
$attrModelView['onload'] = 'modelLoaded(event)';
|
$attrModelView['onload'] = 'modelLoaded(event)';
|
||||||
$hotspotHtml = (isset($hotspots)) ? implode($hotspots) : '';
|
$hotspotHtml = (!empty($hotspots)) ? implode($hotspots) : '';
|
||||||
|
|
||||||
$elModel = Html::rawElement('model-viewer', $attrModelView, $hotspotHtml);
|
$elModel = Html::rawElement('model-viewer', $attrModelView, $hotspotHtml);
|
||||||
$elMenu = self::buildViewMenu();
|
$elMenu = self::buildViewMenu(!empty($hotspots));
|
||||||
|
|
||||||
$elFileLink = '';
|
$elFileLink = '';
|
||||||
if (!isset($viewParams['preview']) && $context->getTitle() != $this->file->getTitle()) {
|
if (!isset($viewParams['preview']) && $context->getTitle() != $this->file->getTitle()) {
|
||||||
@@ -213,9 +213,10 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
/**
|
/**
|
||||||
* Build the button menu used for viewer actions
|
* Build the button menu used for viewer actions
|
||||||
*
|
*
|
||||||
|
* @param bool $annotsDrawn true to enable the annotation buttons
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function buildViewMenu() {
|
private static function buildViewMenu($annotsDrawn) {
|
||||||
$attrMenu = array(
|
$attrMenu = array(
|
||||||
'class' => 'glmv-menu awaiting-model',
|
'class' => 'glmv-menu awaiting-model',
|
||||||
'style' => 'display: none;'
|
'style' => 'display: none;'
|
||||||
@@ -230,13 +231,15 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
|
|
||||||
$gotoUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/goto_hs.svg';
|
$gotoUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/goto_hs.svg';
|
||||||
$attrMenuButtonPrev = array (
|
$attrMenuButtonPrev = array (
|
||||||
'class' => 'glmv-menu-button prev-hs disable-on-hide',
|
'class' => 'glmv-menu-button prev-hs disable-on-hide disable-on-none',
|
||||||
|
'disabled' => !$annotsDrawn,
|
||||||
'onclick' => 'prevAnnotation(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
'onclick' => 'prevAnnotation(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
'onmousedown' => 'event.stopPropagation()',
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
'ontouchstart' => 'event.stopPropagation()'
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
);
|
);
|
||||||
$attrMenuButtonNext = array (
|
$attrMenuButtonNext = array (
|
||||||
'class' => 'glmv-menu-button next-hs disable-on-hide',
|
'class' => 'glmv-menu-button next-hs disable-on-hide disable-on-none',
|
||||||
|
'disabled' => !$annotsDrawn,
|
||||||
'onclick' => 'nextAnnotation(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
'onclick' => 'nextAnnotation(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
'onmousedown' => 'event.stopPropagation()',
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
'ontouchstart' => 'event.stopPropagation()'
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
@@ -244,7 +247,8 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
|
|
||||||
$slideUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/hs_slideshow.svg';
|
$slideUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/hs_slideshow.svg';
|
||||||
$attrMenuButtonSlides = array (
|
$attrMenuButtonSlides = array (
|
||||||
'class' => 'glmv-menu-button disable-on-hide',
|
'class' => 'glmv-menu-button disable-on-hide disable-on-none',
|
||||||
|
'disabled' => !$annotsDrawn,
|
||||||
'onclick' => 'event.target.toggleAttribute("toggled"); slideshowAnnotations(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
'onclick' => 'event.target.toggleAttribute("toggled"); slideshowAnnotations(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
'onmousedown' => 'event.stopPropagation()',
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
'ontouchstart' => 'event.stopPropagation()'
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
@@ -252,7 +256,8 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
|
|
||||||
$hideUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/hs_hide.svg';
|
$hideUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/hs_hide.svg';
|
||||||
$attrMenuButtonHide = array (
|
$attrMenuButtonHide = array (
|
||||||
'class' => 'glmv-menu-button',
|
'class' => 'glmv-menu-button disable-on-none',
|
||||||
|
'disabled' => !$annotsDrawn,
|
||||||
'onclick' => 'event.target.toggleAttribute("toggled"); toggleAnnotations(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
'onclick' => 'event.target.toggleAttribute("toggled"); toggleAnnotations(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
'onmousedown' => 'event.stopPropagation()',
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
'ontouchstart' => 'event.stopPropagation()'
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
@@ -267,12 +272,21 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
'ontouchstart' => 'event.stopPropagation()'
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$resetUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/reset.svg';
|
||||||
|
$attrMenuButtonReset = array (
|
||||||
|
'class' => 'glmv-menu-button',
|
||||||
|
'onclick' => 'resetView(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
|
);
|
||||||
|
|
||||||
$menuButtons = array(
|
$menuButtons = array(
|
||||||
Html::rawElement('div', $attrMenuButtonPrev, '<img class="awaiting-model" src="' . $gotoUrl . '"></image>'),
|
Html::rawElement('div', $attrMenuButtonPrev, '<img class="awaiting-model" src="' . $gotoUrl . '"></image>'),
|
||||||
Html::rawElement('div', $attrMenuButtonSlides, '<img class="awaiting-model" src="' . $slideUrl . '"></image>'),
|
Html::rawElement('div', $attrMenuButtonSlides, '<img class="awaiting-model" src="' . $slideUrl . '"></image>'),
|
||||||
Html::rawElement('div', $attrMenuButtonNext, '<img class="awaiting-model" src="' . $gotoUrl . '"></image>'),
|
Html::rawElement('div', $attrMenuButtonNext, '<img class="awaiting-model" src="' . $gotoUrl . '"></image>'),
|
||||||
Html::rawElement('div', $attrMenuButtonHide, '<img class="awaiting-model" src="' . $hideUrl . '"></image>'),
|
Html::rawElement('div', $attrMenuButtonHide, '<img class="awaiting-model" src="' . $hideUrl . '"></image>'),
|
||||||
Html::rawElement('div', $attrMenuButtonScreen, '<img class="awaiting-model full-hide" src="' . $screenUpUrl . '"></image><img class="awaiting-model full-show" src="' . $screenDownUrl . '"></image>')
|
Html::rawElement('div', $attrMenuButtonScreen, '<img class="awaiting-model full-hide" src="' . $screenUpUrl . '"></image><img class="awaiting-model full-show" src="' . $screenDownUrl . '"></image>'),
|
||||||
|
Html::rawElement('div', $attrMenuButtonReset, '<img class="awaiting-model" src="' . $resetUrl . '"></image>')
|
||||||
);
|
);
|
||||||
|
|
||||||
return Html::rawElement('div', $attrMenu, $menuImg . implode($menuButtons));
|
return Html::rawElement('div', $attrMenu, $menuImg . implode($menuButtons));
|
||||||
|
|||||||
@@ -69,13 +69,15 @@ clickDeleteHotspot = function (hs) {
|
|||||||
deleteHotspot = null
|
deleteHotspot = null
|
||||||
enableViewer()
|
enableViewer()
|
||||||
const anName = hs.target.childNodes[0].innerText
|
const anName = hs.target.childNodes[0].innerText
|
||||||
let purgeAnnotation = new RegExp('(?<="annotationSets"[\\S\\s]*?)(^.*?' + anName + '.*\n)','gm')
|
|
||||||
hs.target.remove()
|
hs.target.remove()
|
||||||
const editText = $('#wpTextbox1').val()
|
let currentText = $('#wpTextbox1').val()
|
||||||
const newText = editText.replace(purgeAnnotation,'')
|
let [_, mvconfig] = extractMvconfig(currentText)
|
||||||
const finalText = newText.replace(/(,)(\n\s+])/gm,'$2')
|
delete mvconfig.annotations[anName]
|
||||||
$('#wpTextbox1').val(finalText)
|
for (anSet in mvconfig.annotationSets) {
|
||||||
writeMvconfig()
|
mvconfig.annotationSets[anSet]=mvconfig.annotationSets[anSet].filter( x => x !== anName )
|
||||||
|
}
|
||||||
|
let newText = currentText.replace(/(.*?<mvconfig>)[\S\s]*?(<\/mvconfig>.*)/,`$1\n${TOML.stringify(mvconfig, null, 2)}\n$2`)
|
||||||
|
$('#wpTextbox1').val(newText)
|
||||||
readMvconfig()
|
readMvconfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +95,7 @@ isDeleting = function() {
|
|||||||
*/
|
*/
|
||||||
grabAnnotation = function(e) {
|
grabAnnotation = function(e) {
|
||||||
if (e.ctrlKey) {
|
if (e.ctrlKey) {
|
||||||
grabHotspot = {x: e.x, y: e.y}
|
grabHotspot = {x: e.x, y: e.y, target: e.target}
|
||||||
const contEl = $('.glmv-container')[0]
|
const contEl = $('.glmv-container')[0]
|
||||||
contEl.addEventListener('mousemove', moveAnnotation)
|
contEl.addEventListener('mousemove', moveAnnotation)
|
||||||
const mvEl = $('model-viewer')[0]
|
const mvEl = $('model-viewer')[0]
|
||||||
@@ -110,7 +112,7 @@ grabAnnotation = function(e) {
|
|||||||
moveAnnotation = function(e) {
|
moveAnnotation = function(e) {
|
||||||
if (grabHotspot) {
|
if (grabHotspot) {
|
||||||
grabHotspot.move = true
|
grabHotspot.move = true
|
||||||
e.target.style['transform'] = `translate(${e.x - grabHotspot.x}px, ${e.y - grabHotspot.y}px) scale(1.1,1.1)`
|
grabHotspot.target.style['transform'] = `translate(${e.x - grabHotspot.x}px, ${e.y - grabHotspot.y}px) scale(1.1,1.1)`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ extractMvconfig = function() {
|
|||||||
if (mvconfig.annotations === undefined) {
|
if (mvconfig.annotations === undefined) {
|
||||||
mvconfig.annotations = {}
|
mvconfig.annotations = {}
|
||||||
}
|
}
|
||||||
|
const mView = $('model-viewer')[0]
|
||||||
|
const hsButtons = [...mView.parentElement.querySelectorAll('.disable-on-none')]
|
||||||
|
hsButtons.forEach( mb => {
|
||||||
|
mb.toggleAttribute('disabled',$.isEmptyObject(mvconfig.annotations))
|
||||||
|
})
|
||||||
|
|
||||||
if (mvconfig.annotationSets === undefined) {
|
if (mvconfig.annotationSets === undefined) {
|
||||||
mvconfig.annotationSets = {}
|
mvconfig.annotationSets = {}
|
||||||
}
|
}
|
||||||
@@ -36,7 +42,7 @@ readMvconfig = function() {
|
|||||||
let mvconfig
|
let mvconfig
|
||||||
let slotNum = 1
|
let slotNum = 1
|
||||||
|
|
||||||
createHotspot = function(hsLabel, hsSlot, hsTag) {
|
createHotspot = function(hsLabel, hsSlot, hsTag, hsSkip) {
|
||||||
let newHs = document.createElement('button')
|
let newHs = document.createElement('button')
|
||||||
newHs.classList.add('Hotspot')
|
newHs.classList.add('Hotspot')
|
||||||
newHs.setAttribute('slot',`hotspot-${hsSlot}`)
|
newHs.setAttribute('slot',`hotspot-${hsSlot}`)
|
||||||
@@ -44,6 +50,7 @@ readMvconfig = function() {
|
|||||||
newHs.setAttribute('onclick', 'onAnnotation(event)')
|
newHs.setAttribute('onclick', 'onAnnotation(event)')
|
||||||
newHs.setAttribute('onmousedown', 'grabAnnotation(event)')
|
newHs.setAttribute('onmousedown', 'grabAnnotation(event)')
|
||||||
newHs.setAttribute('onmouseup', 'releaseAnnotation(event)')
|
newHs.setAttribute('onmouseup', 'releaseAnnotation(event)')
|
||||||
|
newHs.toggleAttribute('seq-skip', !!hsSkip)
|
||||||
Object.keys(mvconfig.annotations[hsLabel]).forEach((prop) => {
|
Object.keys(mvconfig.annotations[hsLabel]).forEach((prop) => {
|
||||||
newHs.setAttribute(prop, mvconfig.annotations[hsLabel][prop])
|
newHs.setAttribute(prop, mvconfig.annotations[hsLabel][prop])
|
||||||
})
|
})
|
||||||
@@ -75,7 +82,7 @@ readMvconfig = function() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let label = (currentSet != 'default' && mvconfig.annotationSets[currentSet]) ? '-' : null
|
let label = (currentSet != 'default' && mvconfig.annotationSets[currentSet]) ? '-' : null
|
||||||
createHotspot(hs, slotNum, label)
|
createHotspot(hs, slotNum, label, true)
|
||||||
slotNum += 1
|
slotNum += 1
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -238,6 +245,7 @@ selectViewConfig = function(view) {
|
|||||||
mView.removeAttribute(s)
|
mView.removeAttribute(s)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
mView.setAttribute('current-view',selectView)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,6 +254,7 @@ selectViewConfig = function(view) {
|
|||||||
*/
|
*/
|
||||||
writeCameraOrbit = function() {
|
writeCameraOrbit = function() {
|
||||||
const mView = $('model-viewer')[0]
|
const mView = $('model-viewer')[0]
|
||||||
|
const currentView = mView.getAttribute('current-view') ? mView.getAttribute('current-view') : 'default'
|
||||||
const newOrbit = orb2degree(mView.getCameraOrbit().toString(),[2,2,5])
|
const newOrbit = orb2degree(mView.getCameraOrbit().toString(),[2,2,5])
|
||||||
mView.setAttribute('camera-orbit', newOrbit)
|
mView.setAttribute('camera-orbit', newOrbit)
|
||||||
const targetObj = mView.getCameraTarget()
|
const targetObj = mView.getCameraTarget()
|
||||||
@@ -254,9 +263,9 @@ writeCameraOrbit = function() {
|
|||||||
const newField = mView.getFieldOfView().toFixed(5) + 'deg'
|
const newField = mView.getFieldOfView().toFixed(5) + 'deg'
|
||||||
mView.setAttribute('field-of-view',newField)
|
mView.setAttribute('field-of-view',newField)
|
||||||
let [currentText, mvconfig] = extractMvconfig()
|
let [currentText, mvconfig] = extractMvconfig()
|
||||||
mvconfig.viewerConfig.default['camera-orbit'] = newOrbit
|
mvconfig.viewerConfig[currentView]['camera-orbit'] = newOrbit
|
||||||
mvconfig.viewerConfig.default['camera-target'] = newTarget
|
mvconfig.viewerConfig[currentView]['camera-target'] = newTarget
|
||||||
mvconfig.viewerConfig.default['field-of-view'] = newField
|
mvconfig.viewerConfig[currentView]['field-of-view'] = newField
|
||||||
const textUpdate = currentText.replace(/(?<=<mvconfig>)([\S\s]*?)(?=<\/mvconfig>)/gm,`\n${TOML.stringify(mvconfig, null, 2)}\n`)
|
const textUpdate = currentText.replace(/(?<=<mvconfig>)([\S\s]*?)(?=<\/mvconfig>)/gm,`\n${TOML.stringify(mvconfig, null, 2)}\n`)
|
||||||
$('#wpTextbox1').val(textUpdate)
|
$('#wpTextbox1').val(textUpdate)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
width: 196px;
|
width: 232px;
|
||||||
|
|
||||||
& .glmv-menu-image {
|
& .glmv-menu-image {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
@@ -209,7 +209,7 @@
|
|||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
width: 294px;
|
width: 342px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ selectAnnotation = function(mView, annotId) {
|
|||||||
*/
|
*/
|
||||||
nextAnnotation = function(mView) {
|
nextAnnotation = function(mView) {
|
||||||
let incrAnnotation = 0
|
let incrAnnotation = 0
|
||||||
const numSpots = [...mView.querySelectorAll('Button')].length
|
const numSpots = [...mView.querySelectorAll('Button:not([seq-skip])')].length
|
||||||
const currentAnnotation = mView.querySelectorAll('Button:has(.HotspotAnnotation:not(.HiddenAnnotation))')[0]
|
const currentAnnotation = mView.querySelectorAll('Button:has(.HotspotAnnotation:not(.HiddenAnnotation))')[0]
|
||||||
if (!currentAnnotation) {
|
if (!currentAnnotation) {
|
||||||
incrAnnotation = 1
|
incrAnnotation = 1
|
||||||
@@ -95,7 +95,7 @@ nextAnnotation = function(mView) {
|
|||||||
*/
|
*/
|
||||||
prevAnnotation = function(mView) {
|
prevAnnotation = function(mView) {
|
||||||
let decrAnnotation = 0
|
let decrAnnotation = 0
|
||||||
const numSpots = [...mView.querySelectorAll('Button')].length
|
const numSpots = [...mView.querySelectorAll('Button:not([seq-skip])')].length
|
||||||
const currentAnnotation = mView.querySelectorAll('Button:has(.HotspotAnnotation:not(.HiddenAnnotation))')[0]
|
const currentAnnotation = mView.querySelectorAll('Button:has(.HotspotAnnotation:not(.HiddenAnnotation))')[0]
|
||||||
if (!currentAnnotation) {
|
if (!currentAnnotation) {
|
||||||
decrAnnotation = numSpots
|
decrAnnotation = numSpots
|
||||||
@@ -159,3 +159,17 @@ toggleFullScreen = function(glCont) {
|
|||||||
glCont.requestFullscreen()
|
glCont.requestFullscreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset view to initial position
|
||||||
|
*
|
||||||
|
* @param {ModelViewer} mView
|
||||||
|
*/
|
||||||
|
resetView = function(mView) {
|
||||||
|
const resetOrb = mView.getAttribute('camera-orbit') || 'auto auto auto'
|
||||||
|
const resetTarg = mView.getAttribute('camera-target') || 'auto auto auto'
|
||||||
|
const resetFov = mView.getAttribute('field-of-view') || 'auto'
|
||||||
|
mView.cameraOrbit = resetOrb
|
||||||
|
mView.cameraTarget = resetTarg
|
||||||
|
mView.fieldOfView = resetFov
|
||||||
|
}
|
||||||
1
resources/reset.svg
Normal file
1
resources/reset.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M320-280q-33 0-56.5-23.5T240-360v-240q0-33 23.5-56.5T320-680h40l40-40h160l40 40h40q33 0 56.5 23.5T720-600v240q0 33-23.5 56.5T640-280H320Zm0-80h320v-240H320v240Zm160-40q33 0 56.5-23.5T560-480q0-33-23.5-56.5T480-560q-33 0-56.5 23.5T400-480q0 33 23.5 56.5T480-400ZM342-940q34-11 68.5-15.5T480-960q94 0 177.5 33.5t148 93Q870-774 911-693.5T960-520h-80q-7-72-38-134.5t-79.5-110Q714-812 651-842t-135-36l62 62-56 56-180-180ZM618-20Q584-9 549.5-4.5T480 0q-94 0-177.5-33.5t-148-93Q90-186 49-266.5T0-440h80q8 72 38.5 134.5t79 110Q246-148 309-118t135 36l-62-62 56-56L618-20ZM480-480Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 696 B |
Reference in New Issue
Block a user