editor improvements
This commit is contained in:
parent
85d25386c7
commit
24f1336c41
4 changed files with 84 additions and 44 deletions
|
|
@ -2,6 +2,7 @@ AFRAME.registerComponent('vconsole', {
|
||||||
init: function () {
|
init: function () {
|
||||||
//AFRAME.XRF.navigator.to("https://coderofsalvation.github.io/xrsh-media/assets/background.glb")
|
//AFRAME.XRF.navigator.to("https://coderofsalvation.github.io/xrsh-media/assets/background.glb")
|
||||||
let aScene = AFRAME.scenes[0]
|
let aScene = AFRAME.scenes[0]
|
||||||
|
return
|
||||||
|
|
||||||
// return
|
// return
|
||||||
document.head.innerHTML += `
|
document.head.innerHTML += `
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ $editorPopup = (el) => new Proxy({
|
||||||
<td><b class="badge">href</a></td>
|
<td><b class="badge">href</a></td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" id="href" placeholder="https://foo.com" maxlength="255"
|
<input type="text" id="href" placeholder="https://foo.com" maxlength="255"
|
||||||
|
onkeydown="document.querySelector('#editActions').classList.add('show')"
|
||||||
onkeyup="$editor.selected.edited = $editor.selected.userData.href = this.value"
|
onkeyup="$editor.selected.edited = $editor.selected.userData.href = this.value"
|
||||||
value="${$editor.selected.userData.href||''}" />
|
value="${$editor.selected.userData.href||''}" />
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -19,6 +20,7 @@ $editorPopup = (el) => new Proxy({
|
||||||
<td><b class="badge">src</a></td>
|
<td><b class="badge">src</a></td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" id="src" placeholder="https://foo.com" maxlength="255"
|
<input type="text" id="src" placeholder="https://foo.com" maxlength="255"
|
||||||
|
onkeydown="document.querySelector('#editActions').classList.add('show')"
|
||||||
onkeyup="$editor.selected.edited = $editor.selected.userData.src = this.value"
|
onkeyup="$editor.selected.edited = $editor.selected.userData.src = this.value"
|
||||||
value="${$editor.selected.userData.src||''}" />
|
value="${$editor.selected.userData.src||''}" />
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -27,23 +29,38 @@ $editorPopup = (el) => new Proxy({
|
||||||
<td><b class="badge">tag</a></td>
|
<td><b class="badge">tag</a></td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" id="tag" placeholder="foo bar" maxlength="255"
|
<input type="text" id="tag" placeholder="foo bar" maxlength="255"
|
||||||
|
onkeydown="document.querySelector('#editActions').classList.add('show')"
|
||||||
onkeyup="$editor.selected.edited = $editor.selected.userData.tag = this.value"
|
onkeyup="$editor.selected.edited = $editor.selected.userData.tag = this.value"
|
||||||
value="${$editor.selected.userData.tag||''}" />
|
value="${$editor.selected.userData.tag||''}" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<br>
|
||||||
|
<div id="editActions">
|
||||||
|
<button class="download" onclick="$editor.export()"><i class="gg-software-download"></i> download scene file</button>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
table.editorPopup input{
|
table.editorPopup input{
|
||||||
min-width:200px;
|
min-width:200px;
|
||||||
}
|
}
|
||||||
|
table.editorPopup tr td:nth-child(1){
|
||||||
|
text-align:left;
|
||||||
|
}
|
||||||
|
#editActions{
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
#editActions.show{
|
||||||
|
visibility:visible;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
`,
|
`,
|
||||||
|
|
||||||
init(opts){
|
init(opts){
|
||||||
el.innerHTML = this.html(opts)
|
el.innerHTML = this.html(opts)
|
||||||
return el
|
return (this.el = el)
|
||||||
},
|
},
|
||||||
|
|
||||||
},{
|
},{
|
||||||
|
|
@ -84,52 +101,76 @@ $editor = (el,opts) => new Proxy({
|
||||||
</style>
|
</style>
|
||||||
`,
|
`,
|
||||||
|
|
||||||
enabled: false,
|
selecting: false,
|
||||||
|
editing: false,
|
||||||
helper: null,
|
helper: null,
|
||||||
selected: null,
|
selected: null,
|
||||||
|
|
||||||
init(opts){
|
init(opts){
|
||||||
el.innerHTML = this.html
|
el.innerHTML = this.html
|
||||||
window.frontend.el.querySelector('#topbar').appendChild(el);
|
window.frontend.el.querySelector('#topbar').appendChild(el);
|
||||||
el.querySelector('.edit-btn').addEventListener('click', () => $editor.enabled = true )
|
el.querySelector('.edit-btn').addEventListener('click', () => {
|
||||||
|
if( $editor.selecting || $editor.editing ) this.reset()
|
||||||
|
else{
|
||||||
|
$editor.selecting = true
|
||||||
|
$editor.editing = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
document.addEventListener('download', (e) => this.updateOriginalScene(e.detail) )
|
document.addEventListener('frontend.export', (e) => this.updateOriginalScene(e.detail) )
|
||||||
|
xrf.addEventListener('href', (opts) => {
|
||||||
|
if( this.selecting || this.editing ) return opts.promise().reject("$editor should block hrefs while editing") // never resolve (block hrefs from interfering)
|
||||||
|
})
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
reset(){
|
||||||
|
if( this.helper) xrf.scene.remove(this.helper)
|
||||||
|
this.selecting = false
|
||||||
|
this.editing = false
|
||||||
|
},
|
||||||
|
|
||||||
|
export(){
|
||||||
|
window.frontend.download()
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
|
||||||
editNode(){
|
editNode(){
|
||||||
if( !this.enabled ) return console.log("not editing")
|
if( !this.selecting ) return console.log("not editing")
|
||||||
$editor.enabled = false // disable selections
|
$editor.editing = true
|
||||||
this.enableHref(this.selected,true) // re-enable hrefs
|
|
||||||
//`<b>XR Fragment:</b> #${this.selected.name}<br><br>${this.getMetaData(this.selected)}`),{
|
//`<b>XR Fragment:</b> #${this.selected.name}<br><br>${this.getMetaData(this.selected)}`),{
|
||||||
|
setTimeout( () => this.reset(), 4000 )
|
||||||
notify( $editorPopup( document.createElement('div') ).init(this) , {
|
notify( $editorPopup( document.createElement('div') ).init(this) , {
|
||||||
timeout:false,
|
timeout:false,
|
||||||
onclose: () => xrf.scene.remove( this.helper )
|
onclose: () => this.reset()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
initEdit(scene){
|
initEdit(scene){
|
||||||
AFRAME.scenes[0].addEventListener('click', () => this.editNode() )
|
if( !this.listenersInstalled ){
|
||||||
|
AFRAME.scenes[0].addEventListener('click', () => this.editNode() )
|
||||||
|
this.listenersInstalled = true
|
||||||
|
}
|
||||||
scene.traverse( (n) => {
|
scene.traverse( (n) => {
|
||||||
let highlight = (n) => (e) => {
|
let highlight = (n) => (e) => {
|
||||||
if( this.selected ) this.enableHref(this.selected,true) // re-enable href of previous selection
|
if( !this.selecting || this.editing ) return // do nothing
|
||||||
if( this.helper){
|
if( this.helper){
|
||||||
if( this.helper.selected == n.uuid ) return // already selected
|
if( this.helper.selected == n.uuid ) return // already selected
|
||||||
xrf.scene.remove(this.helper)
|
xrf.scene.remove(this.helper)
|
||||||
}
|
}
|
||||||
if( !this.enabled ) return // do nothing
|
|
||||||
|
|
||||||
this.selected = n
|
this.selected = n
|
||||||
this.helper = new THREE.BoxHelper( n, 0xFF00FF )
|
this.helper = new THREE.BoxHelper( n, 0xFF00FF )
|
||||||
this.helper.material.linewidth = 5
|
this.helper.material.linewidth = 4
|
||||||
this.helper.material.color = xrf.focusLine.material.color
|
this.helper.material.color = xrf.focusLine.material.color
|
||||||
|
this.helper.material.dashSize = xrf.focusLine.material.dashSize
|
||||||
|
this.helper.material.gapSize = xrf.focusLine.material.gapSize
|
||||||
this.helper.selected = n.uuid
|
this.helper.selected = n.uuid
|
||||||
xrf.scene.add(this.helper)
|
xrf.scene.add(this.helper)
|
||||||
|
|
||||||
let div = document.createElement('div')
|
let div = document.createElement('div')
|
||||||
notify(`<b>#${n.name}</b><br>${this.getMetaData(this.selected)}`)
|
notify(`<b>#${n.name}</b><br>${this.getMetaData(this.selected)}`)
|
||||||
|
|
||||||
this.enableHref(n,false) // prevent clicks from doing their usual teleporting/executions
|
|
||||||
}
|
}
|
||||||
if( n.material ) n.addEventListener('mousemove', n.highlightOnMouseMove = highlight(n) )
|
if( n.material ) n.addEventListener('mousemove', n.highlightOnMouseMove = highlight(n) )
|
||||||
})
|
})
|
||||||
|
|
@ -143,24 +184,15 @@ $editor = (el,opts) => new Proxy({
|
||||||
return html
|
return html
|
||||||
},
|
},
|
||||||
|
|
||||||
enableHref(n, state){
|
updateOriginalScene(e){
|
||||||
if( n.userData.XRF && n.userData.XRF.href && n.userData.XRF.href.exec ){
|
const {scene,ext} = e
|
||||||
let exec = n.userData.XRF.href.exec
|
scene.traverse( (n) => {
|
||||||
if( !state && !exec.bak ){
|
if( !n.name ) return
|
||||||
exec.bak = exec
|
// overwrite node with modified userData from scene
|
||||||
n.userData.XRF.href.exec = function(){}
|
let o = xrf.scene.getObjectByName(n.name)
|
||||||
}
|
if( o && o.edited ){
|
||||||
if( state && exec.bak ){
|
for( let i in o.userData ) n.userData[i] = o.userData[i]
|
||||||
n.userData.XRF.href.exec = exec.bak
|
console.log("updating export")
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
updateOriginalScene(opts){
|
|
||||||
let {scene,ext} = opts
|
|
||||||
xrf.scene.traverse( (n) => {
|
|
||||||
if( n.edited && scene.getObjectByName(n.name) ){
|
|
||||||
scene.getObjectByName(n.name).userData = n.userData
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -174,20 +206,18 @@ $editor = (el,opts) => new Proxy({
|
||||||
me[k] = v
|
me[k] = v
|
||||||
switch( k ){
|
switch( k ){
|
||||||
|
|
||||||
case "enabled":{
|
case "selecting":{
|
||||||
lookctl = $('[look-controls]').components['look-controls']
|
lookctl = $('[look-controls]').components['look-controls']
|
||||||
if( v ){
|
if( v ){
|
||||||
lookctl.pause() // prevent click-conflict
|
lookctl.pause() // prevent click-conflict
|
||||||
notify("click an object to reveal XR Fragment metadata")
|
notify("click an object to reveal XR Fragment metadata")
|
||||||
xrf.interactive.raycastAll = true
|
xrf.interactive.raycastAll = true
|
||||||
if( !xrf.scene.initEdit ) me.initEdit(xrf.scene)
|
me.initEdit(xrf.scene)
|
||||||
|
|
||||||
lookctl.pause() // prevent click-conflict
|
lookctl.pause() // prevent click-conflict
|
||||||
el.querySelector('.edit-btn').classList.add(['enabled'])
|
el.querySelector('.edit-btn').classList.add(['enabled'])
|
||||||
}else{
|
}else{
|
||||||
lookctl.pause() // prevent click-conflict
|
lookctl.pause() // prevent click-conflict
|
||||||
xrf.scene.traverse( (n) => {
|
xrf.scene.traverse( (n) => {
|
||||||
me.enableHref(n,true)
|
|
||||||
if( n.highlightOnMouseMove ){
|
if( n.highlightOnMouseMove ){
|
||||||
n.removeEventListener( 'mousemove', n.highlightOnMouseMove )
|
n.removeEventListener( 'mousemove', n.highlightOnMouseMove )
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -252,14 +252,20 @@ window.frontend = (opts) => new Proxy({
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportScene(scene,ext){
|
function exportScene(model,ext){
|
||||||
const exporter = new (xrf.loaders[ext].exporter || defaultExporter)
|
const exporter = new (xrf.loaders[ext].exporter || defaultExporter)
|
||||||
document.dispatchEvent( new CustomEvent('download',{detail:{scene,ext}}) )
|
document.dispatchEvent( new CustomEvent('frontend.export',{detail:{ scene: model.scene,ext}}) )
|
||||||
exporter.parse(
|
exporter.parse(
|
||||||
scene,
|
model.scene,
|
||||||
function ( glb ) { download(glb, `${file}.${ext}`) }, // ready
|
function ( glb ) { download(glb, `${file}`) }, // ready
|
||||||
function ( error ) { console.error(error) }, // error
|
function ( error ) { console.error(error) }, // error
|
||||||
{binary:true}
|
{
|
||||||
|
binary:true,
|
||||||
|
onlyVisible: false,
|
||||||
|
animations: model.animations,
|
||||||
|
includeCustomExtensions: true,
|
||||||
|
trs:true
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,8 +274,9 @@ window.frontend = (opts) => new Proxy({
|
||||||
let {urlObj,dir,file,hash,ext} = xrf.navigator.origin = xrf.parseUrl(url)
|
let {urlObj,dir,file,hash,ext} = xrf.navigator.origin = xrf.parseUrl(url)
|
||||||
const Loader = xrf.loaders[ext]
|
const Loader = xrf.loaders[ext]
|
||||||
loader = new Loader().setPath( dir )
|
loader = new Loader().setPath( dir )
|
||||||
|
notify('exporting scene<br><br>please wait..')
|
||||||
loader.load(url, (model) => {
|
loader.load(url, (model) => {
|
||||||
exportScene(model.scene,ext,file)
|
exportScene(model,ext,file)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -315,7 +322,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
if( network.meetingLink && !document.location.hash.match(/meet=/) ){
|
if( network.meetingLink && !document.location.hash.match(/meet=/) ){
|
||||||
document.location.hash += `&meet=${network.meetingLink}`
|
document.location.hash += `&meet=${network.meetingLink}`
|
||||||
}
|
}
|
||||||
if( !document.location.hash.match(/pos=/) ){
|
if( !document.location.hash.match(/pos=/) && (network.posName || network.pos) ){
|
||||||
document.location.hash += `&pos=${ network.posName || network.pos }`
|
document.location.hash += `&pos=${ network.posName || network.pos }`
|
||||||
}
|
}
|
||||||
let url = window.location.href
|
let url = window.location.href
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ xrf.frag.defaultPredefinedViews = (opts) => {
|
||||||
let {scene,model} = opts;
|
let {scene,model} = opts;
|
||||||
scene.traverse( (n) => {
|
scene.traverse( (n) => {
|
||||||
if( n.userData && n.userData['#'] ){
|
if( n.userData && n.userData['#'] ){
|
||||||
xrf.hashbus.pub( n.userData['#'], n ) // evaluate default XR fragments without affecting URL
|
if( !n.parent ){
|
||||||
|
xrf.navigator.to( n.userData['#'] )
|
||||||
|
}else xrf.hashbus.pub( n.userData['#'], n ) // evaluate default XR fragments without affecting URL
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue