export almost works

This commit is contained in:
Leon van Kammen 2024-03-12 16:42:18 +00:00
parent a456cd8264
commit 29ad07eabd
5 changed files with 129 additions and 17 deletions

View File

@ -11,6 +11,7 @@ import { MTLLoader } from 'super-three/examples/jsm/loaders/MTLLoader';
import * as BufferGeometryUtils from 'super-three/examples/jsm/utils/BufferGeometryUtils';
import { LightProbeGenerator } from 'super-three/examples/jsm/lights/LightProbeGenerator';
import { TransformControls } from 'super-three/examples/jsm/controls/TransformControls.js';
import { GLTFExporter } from 'super-three/examples/jsm/exporters/GLTFExporter.js';
var THREE = window.THREE = SUPER_THREE;
@ -28,6 +29,7 @@ THREE.OBB = OBB;
THREE.BufferGeometryUtils = BufferGeometryUtils;
THREE.LightProbeGenerator = LightProbeGenerator;
THREE.TransformControls = TransformControls;
THREE.GLTFExporter = GLTFExporter;
//THREE.Text = Text
export default THREE;

View File

@ -1,4 +1,62 @@
// reactive component for displaying the menu
$editorPopup = (el) => new Proxy({
html: (opts) => `
<div>
<b>#${$editor.selected.name}</b>
<table class="editorPopup">
<tbody>
<tr>
<td><b class="badge">href</a></td>
<td>
<input type="text" id="href" placeholder="https://foo.com" maxlength="255"
onkeyup="$editor.selected.edited = $editor.selected.userData.href = this.value"
value="${$editor.selected.userData.href||''}" />
</td>
</tr>
<tr>
<td><b class="badge">src</a></td>
<td>
<input type="text" id="src" placeholder="https://foo.com" maxlength="255"
onkeyup="$editor.selected.edited = $editor.selected.userData.src = this.value"
value="${$editor.selected.userData.src||''}" />
</td>
</tr>
<tr>
<td><b class="badge">tag</a></td>
<td>
<input type="text" id="tag" placeholder="foo bar" maxlength="255"
onkeyup="$editor.selected.edited = $editor.selected.userData.tag = this.value"
value="${$editor.selected.userData.tag||''}" />
</td>
</tr>
</tbody>
</table>
</div>
<style type="text/css">
table.editorPopup input{
min-width:200px;
}
</style>
`,
init(opts){
el.innerHTML = this.html(opts)
return el
},
},{
get(me,k,v){ return me[k] },
set(me,k,v){
me[k] = v
}
})
$editor = (el,opts) => new Proxy({
html: `
@ -13,6 +71,10 @@ $editor = (el,opts) => new Proxy({
width: 30px;
margin-top: 7px;
}
.edit-btn.enabled,
.edit-btn.enabled:hover{
background:black;
}
.edit-btn i.gg-pen{
margin-top: -26px;
margin-left: 4px;
@ -30,23 +92,26 @@ $editor = (el,opts) => new Proxy({
el.innerHTML = this.html
window.frontend.el.querySelector('#topbar').appendChild(el);
el.querySelector('.edit-btn').addEventListener('click', () => $editor.enabled = true )
document.addEventListener('download', (e) => this.updateOriginalScene(e.detail) )
return this
},
editNode(){
if( !this.enabled ) return console.log("not editing")
console.log("click!")
$editor.enabled = false // disable selections
$editor.enabled = false // disable selections
this.enableHref(this.selected,true) // re-enable hrefs
notify(`${this.selected.name}<br>${this.getMetaData(this.selected)}`)
notify(`<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)}`),{
notify( $editorPopup( document.createElement('div') ).init(this) , {
timeout:false,
onclose: () => xrf.scene.remove( this.helper )
})
},
initEdit(scene){
AFRAME.scenes[0].addEventListener('click', () => this.editNode() )
scene.traverse( (n) => {
let highlight = (n) => (e) => {
console.log(n.name)
if( this.selected ) this.enableHref(this.selected,true) // re-enable href of previous selection
if( this.helper){
if( this.helper.selected == n.uuid ) return // already selected
@ -62,17 +127,20 @@ $editor = (el,opts) => new Proxy({
xrf.scene.add(this.helper)
let div = document.createElement('div')
notify(`<b>XR Fragment:</b> #${n.name}<br><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.geometry ) n.addEventListener('mousemove', n.highlightOnMouseMove = highlight(n) )
if( n.material ) n.addEventListener('mousemove', n.highlightOnMouseMove = highlight(n) )
})
console.log("inited scene")
},
getMetaData(n){
return `href: ${n.userData.href}<br>src: ${n.userData.src}<br>tag: ${n.userData.tag}`
let html = `${n.userData.href ? `<b class="badge">href</b>${n.userData.href}<br>`:''}`
html += `${n.userData.src ? `<b class="badge">src</b>${n.userData.src}<br>` :''}`
html += `${n.userData.tag ? `<b class="badge">tag</b>${n.userData.tag}<br>` :''}`
return html
},
enableHref(n, state){
@ -86,6 +154,15 @@ $editor = (el,opts) => new Proxy({
n.userData.XRF.href.exec = exec.bak
}
}
},
updateOriginalScene(opts){
let {scene,ext} = opts
xrf.scene.traverse( (n) => {
if( n.edited && scene.getObjectByName(n.name) ){
scene.getObjectByName(n.name).userData = n.userData
}
})
}
},
@ -98,20 +175,25 @@ $editor = (el,opts) => new Proxy({
switch( k ){
case "enabled":{
lookctl = $('[look-controls]').components['look-controls']
if( v ){
lookctl.pause() // prevent click-conflict
notify("click an object to reveal XR Fragment metadata")
xrf.interactive.raycastAll = true
if( !xrf.scene.initEdit ) me.initEdit(xrf.scene)
lookctl.pause() // prevent click-conflict
el.querySelector('.edit-btn').classList.add(['enabled'])
}else{
console.log("idsabled")
lookctl.pause() // prevent click-conflict
xrf.scene.traverse( (n) => {
me.enableHref(n,true)
if( n.highlightOnMouseMove ){
n.removeEventListener( 'mousemove', n.highlightOnMouseMove )
}
})
me.helper.remove()
console.log("removed events")
lookctl.play() // prevent click-conflict (resume)
el.querySelector('.edit-btn').classList.remove(['enabled'])
}
break;
}

View File

@ -239,15 +239,38 @@ window.frontend = (opts) => new Proxy({
},
download(){
function fetchAndDownload(dataurl, filename) {
// setup exporters
let defaultExporter = THREE.GLTFExporter
xrf.loaders['gltf'].exporter = defaultExporter
xrf.loaders['glb'].exporter = defaultExporter
function download(dataurl, filename) {
var a = document.createElement("a");
a.href = dataurl;
a.setAttribute("download", filename);
a.click();
return false;
}
let file = document.location.search.replace(/\?/,'')
fetchAndDownload( file, file )
function exportScene(scene,ext){
const exporter = new (xrf.loaders[ext].exporter || defaultExporter)
document.dispatchEvent( new CustomEvent('download',{detail:{scene,ext}}) )
exporter.parse(
scene,
function ( glb ) { download(glb, `${file}.${ext}`) }, // ready
function ( error ) { console.error(error) }, // error
{binary:true}
);
}
// load original scene and overwrite with updates
let url = document.location.search.replace(/\?/,'')
let {urlObj,dir,file,hash,ext} = xrf.navigator.origin = xrf.parseUrl(url)
const Loader = xrf.loaders[ext]
loader = new Loader().setPath( dir )
loader.load(url, (model) => {
exportScene(model.scene,ext,file)
})
},
updateHashPosition(randomize){
@ -269,9 +292,11 @@ window.frontend = (opts) => new Proxy({
let lastPos = `pos=${camera.position.x.toFixed(2)},${camera.position.y.toFixed(2)},${camera.position.z.toFixed(2)}`
let newHash = document.location.hash.replace(/[&]?(pos|rot)=[0-9\.-]+,[0-9\.-]+,[0-9\.-]+/,'')
newHash += `&${lastPos}`
document.location.hash = newHash.replace(/&&/,'&')
.replace(/#&/,'')
if( lastPos != "pos=" ){
newHash += `&${lastPos}`
document.location.hash = newHash.replace(/&&/,'&')
.replace(/#&/,'')
}
this.copyToClipboard( window.location.href );
},

View File

@ -131,6 +131,8 @@ window.SnackBar = function(userOptions) {
_Container.removeChild(_Element);
} catch (e) { }
}, 1000);
if( _Options.onclose ) _Options.onclose()
};
_Options = { ..._OptionDefaults, ...userOptions }

View File

@ -95,6 +95,7 @@ class XRF {
guessType(this, value); // 1. extract the type
// validate
var ok:Bool = true;
if( value.length == 0 ) ok = false;
if( !is(T_FLOAT) && is(T_VECTOR2) && !(Std.isOfType(x,Float) && Std.isOfType(y,Float)) ) ok = false;
if( !(is(T_VECTOR2) || is(T_STRING)) && is(T_VECTOR3) && !(Std.isOfType(x,Float) && Std.isOfType(y,Float) && Std.isOfType(z,Float)) ) ok = false;
return ok;