work in progress [might break]
This commit is contained in:
parent
7e0d7ca7c1
commit
a456cd8264
|
@ -18,13 +18,13 @@
|
|||
light="defaultLightsEnabled: false">
|
||||
<a-entity id="player" movement-controls touch-controls wasd-controls="fly:false" look-controls>
|
||||
<a-entity camera="fov:90" position="0 1.6 0" id="camera"></a-entity>
|
||||
<a-entity id="left-hand" hand-tracking-controls="hand:left" laser-controls="hand: left" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">
|
||||
<a-entity id="left-hand" hand-tracking-controls="hand:left;modelColor:#cccccc" laser-controls="hand: left" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">
|
||||
<a-entity rotation="-35 0 0" position="0 0.1 0" id="navigator">
|
||||
<a-entity id="back" xrf-button="label: <; width:0.05; action: history.back()" position="-0.025 0 0" class="ray"></a-entity>
|
||||
<a-entity id="next" xrf-button="label: >; width:0.05; action: history.forward()" position=" 0.025 0 0" class="ray"></a-entity>
|
||||
</a-entity>
|
||||
</a-entity>
|
||||
<a-entity id="right-hand" hand-tracking-controls="hand:right" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor" xrf-pinchmove="rig: #player"></a-entity>
|
||||
<a-entity id="right-hand" hand-tracking-controls="hand:right;modelColor:#cccccc" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor" xrf-pinchmove="rig: #player"></a-entity>
|
||||
</a-entity>
|
||||
|
||||
<a-entity id="home" xrf="index.glb" xrf-menu></a-entity>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { ColladaLoader } from 'super-three/examples/jsm/loaders/ColladaLoader';
|
|||
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 {Text} from 'troika-three-text'
|
||||
import { TransformControls } from 'super-three/examples/jsm/controls/TransformControls.js';
|
||||
|
||||
var THREE = window.THREE = SUPER_THREE;
|
||||
|
||||
|
@ -27,6 +27,7 @@ THREE.ColladaLoader = ColladaLoader;
|
|||
THREE.OBB = OBB;
|
||||
THREE.BufferGeometryUtils = BufferGeometryUtils;
|
||||
THREE.LightProbeGenerator = LightProbeGenerator;
|
||||
THREE.TransformControls = TransformControls;
|
||||
//THREE.Text = Text
|
||||
|
||||
export default THREE;
|
||||
|
|
|
@ -100,7 +100,7 @@ window.AFRAME.registerComponent('xrf', {
|
|||
}
|
||||
|
||||
// give headset users way to debug without a cumbersome usb-tapdance
|
||||
if( xrf.debug || document.location.hostname.match(/^(localhost|[1-9])/) && !aScene.getAttribute("vconsole") ){
|
||||
if( document.location.hostname.match(/^(localhost|[1-9])/) && !aScene.getAttribute("vconsole") ){
|
||||
aScene.setAttribute('vconsole','')
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,6 @@ window.AFRAME.registerComponent('xrf', {
|
|||
el.addEventListener("click", clickHandler )
|
||||
el.addEventListener("mouseenter", mesh.userData.XRF.href.selected(true) )
|
||||
el.addEventListener("mouseleave", mesh.userData.XRF.href.selected(false) )
|
||||
el.addEventListener("pressedstarted", clickHandler )
|
||||
$('a-scene').appendChild(el)
|
||||
}
|
||||
createEl(mesh)
|
||||
|
|
|
@ -45,7 +45,7 @@ AFRAME.registerComponent('pressable', {
|
|||
handEl.object3D.getWorldPosition( this.fingerWorldPosition )
|
||||
this.fingerWorldPosition.add( indexTipPosition )
|
||||
|
||||
this.raycaster.far = 0.05
|
||||
this.raycaster.far = this.data.pressDistance
|
||||
// Create a direction vector (doesnt matter because it is supershort for 'touch' purposes)
|
||||
const direction = new THREE.Vector3(1.0,0,0);
|
||||
this.raycaster.set(this.fingerWorldPosition, direction)
|
||||
|
@ -59,6 +59,7 @@ AFRAME.registerComponent('pressable', {
|
|||
if (intersects.length ){
|
||||
if( !this.pressed ){
|
||||
this.el.emit('pressedstarted');
|
||||
this.el.emit('click');
|
||||
this.pressed = setTimeout( () => {
|
||||
this.el.emit('pressedended');
|
||||
this.pressed = null
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
// reactive component for displaying the menu
|
||||
$editor = (el,opts) => new Proxy({
|
||||
|
||||
html: `
|
||||
<div style="position:absolute; width:100%; text-align:right; right:166px;">
|
||||
<button class="btn edit-btn">
|
||||
<i class="gg-pen"></i>
|
||||
</button>
|
||||
</div>
|
||||
<style type="text/css">
|
||||
.xrf button.edit-btn{
|
||||
height: 32px;
|
||||
width: 30px;
|
||||
margin-top: 7px;
|
||||
}
|
||||
.edit-btn i.gg-pen{
|
||||
margin-top: -26px;
|
||||
margin-left: 4px;
|
||||
width: 10px;
|
||||
color: var(--xrf-white);
|
||||
}
|
||||
</style>
|
||||
`,
|
||||
|
||||
enabled: false,
|
||||
helper: null,
|
||||
selected: null,
|
||||
|
||||
init(opts){
|
||||
el.innerHTML = this.html
|
||||
window.frontend.el.querySelector('#topbar').appendChild(el);
|
||||
el.querySelector('.edit-btn').addEventListener('click', () => $editor.enabled = true )
|
||||
return this
|
||||
},
|
||||
|
||||
editNode(){
|
||||
if( !this.enabled ) return console.log("not editing")
|
||||
console.log("click!")
|
||||
$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)}`)
|
||||
},
|
||||
|
||||
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
|
||||
xrf.scene.remove(this.helper)
|
||||
}
|
||||
if( !this.enabled ) return // do nothing
|
||||
|
||||
this.selected = n
|
||||
this.helper = new THREE.BoxHelper( n, 0xFF00FF )
|
||||
this.helper.material.linewidth = 5
|
||||
this.helper.material.color = xrf.focusLine.material.color
|
||||
this.helper.selected = n.uuid
|
||||
xrf.scene.add(this.helper)
|
||||
|
||||
let div = document.createElement('div')
|
||||
notify(`<b>XR Fragment:</b> #${n.name}<br><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) )
|
||||
})
|
||||
console.log("inited scene")
|
||||
},
|
||||
|
||||
getMetaData(n){
|
||||
return `href: ${n.userData.href}<br>src: ${n.userData.src}<br>tag: ${n.userData.tag}`
|
||||
},
|
||||
|
||||
enableHref(n, state){
|
||||
if( n.userData.XRF && n.userData.XRF.href && n.userData.XRF.href.exec ){
|
||||
let exec = n.userData.XRF.href.exec
|
||||
if( !state && !exec.bak ){
|
||||
exec.bak = exec
|
||||
n.userData.XRF.href.exec = function(){}
|
||||
}
|
||||
if( state && exec.bak ){
|
||||
n.userData.XRF.href.exec = exec.bak
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
|
||||
get(me,k,v){ return me[k] },
|
||||
|
||||
set(me,k,v){
|
||||
me[k] = v
|
||||
switch( k ){
|
||||
|
||||
case "enabled":{
|
||||
if( v ){
|
||||
notify("click an object to reveal XR Fragment metadata")
|
||||
xrf.interactive.raycastAll = true
|
||||
if( !xrf.scene.initEdit ) me.initEdit(xrf.scene)
|
||||
}else{
|
||||
console.log("idsabled")
|
||||
xrf.scene.traverse( (n) => {
|
||||
me.enableHref(n,true)
|
||||
if( n.highlightOnMouseMove ){
|
||||
n.removeEventListener( 'mousemove', n.highlightOnMouseMove )
|
||||
}
|
||||
})
|
||||
me.helper.remove()
|
||||
console.log("removed events")
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
// reactify component!
|
||||
document.addEventListener('frontend:ready', (e) => {
|
||||
window.$editor = $editor( document.createElement('div') ).init(e.detail)
|
||||
})
|
|
@ -0,0 +1,40 @@
|
|||
window.$editor = (opts) => new Proxy({
|
||||
opts,
|
||||
html: `
|
||||
<div class="xrf footer">
|
||||
<div class="menu">
|
||||
<div id="buttons"></div>
|
||||
<a class="btn" id="more" aria-title="menu button"><i id="icon" class="gg-menu"></i></a><br>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
enabled: false,
|
||||
|
||||
toggle(){ this.enabled = !this.enabled },
|
||||
|
||||
init(){
|
||||
el.innerHTML = this.html
|
||||
document.body.appendChild(el);
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
// auto-trigger events on changes
|
||||
get(data,k,receiver){ return data[k] },
|
||||
set(data,k,v){
|
||||
data[k] = v
|
||||
switch( k ){
|
||||
case "enabled": {
|
||||
data.enabled = v
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
document.addEventListener('$menu:ready', (e) => {
|
||||
return
|
||||
try{
|
||||
$editor = $editor( document.createElement('div'), {} )
|
||||
$editor.init()
|
||||
}catch(e){console.error(e)}
|
||||
})
|
|
@ -781,5 +781,46 @@ document.head.innerHTML += `
|
|||
bottom: 8px;
|
||||
background: currentColor
|
||||
}
|
||||
|
||||
.gg-pen {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: block;
|
||||
transform: rotate(-45deg) scale(var(--ggs,1));
|
||||
width: 14px;
|
||||
height: 4px;
|
||||
border-right: 2px solid transparent;
|
||||
box-shadow:
|
||||
0 0 0 2px,
|
||||
inset -2px 0 0;
|
||||
border-top-right-radius: 1px;
|
||||
border-bottom-right-radius: 1px;
|
||||
margin-right: -2px
|
||||
}
|
||||
.gg-pen::after,
|
||||
.gg-pen::before {
|
||||
content: "";
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
position: absolute
|
||||
}
|
||||
.gg-pen::before {
|
||||
background: currentColor;
|
||||
border-left: 0;
|
||||
right: -6px;
|
||||
width: 3px;
|
||||
height: 4px;
|
||||
border-radius: 1px;
|
||||
top: 0
|
||||
}
|
||||
.gg-pen::after {
|
||||
width: 8px;
|
||||
height: 7px;
|
||||
border-top: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
border-right: 7px solid;
|
||||
left: -11px;
|
||||
top: -2px
|
||||
}
|
||||
</style>
|
||||
`
|
||||
|
|
|
@ -178,9 +178,14 @@ window.frontend = (opts) => new Proxy({
|
|||
let isChatMsg = e.target.closest('.msg')
|
||||
let isChatLine = e.target.id == 'chatline'
|
||||
let isChatEmptySpace = e.target.id == 'messages'
|
||||
let isUI = e.target.closest('.ui')
|
||||
let isUI = e.target.closest('.ui') ||
|
||||
e.target.closest('.btn') ||
|
||||
e.target.closest('button') ||
|
||||
e.target.closest('textarea') ||
|
||||
e.target.closest('input') ||
|
||||
e.target.closest('a')
|
||||
//console.dir({class: e.target.className, id: e.target.id, isChatMsg,isChatLine,isChatEmptySpace,isUI, tagName: e.target.tagName})
|
||||
if( isUI || e.target.tagName.match(/^(BUTTON|TEXTAREA|INPUT|A)/) || e.target.className.match(/(btn)/) ) return
|
||||
if( isUI ) return
|
||||
if( show ){
|
||||
$chat.visible = true
|
||||
}else{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// wrapper to survive in/outside modules
|
||||
// wrapper to collect interactive raycastable objects
|
||||
|
||||
xrf.interactiveGroup = function(THREE,renderer,camera){
|
||||
|
||||
|
@ -26,6 +26,8 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const scope = this;
|
||||
scope.objects = []
|
||||
scope.raycastAll = false
|
||||
|
||||
|
||||
const raycaster = new Raycaster();
|
||||
const tempMatrix = new Matrix4();
|
||||
|
@ -44,7 +46,8 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
raycaster.setFromCamera( _pointer, camera );
|
||||
|
||||
const intersects = raycaster.intersectObjects( scope.objects, false );
|
||||
let objects = scope.raycastAll ? xrf.scene.children : scope.objects
|
||||
const intersects = raycaster.intersectObjects( objects, scope.raycastAll );
|
||||
|
||||
if ( intersects.length > 0 ) {
|
||||
|
||||
|
@ -54,7 +57,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
|
|||
const uv = intersection.uv;
|
||||
|
||||
_event.type = event.type;
|
||||
_event.data.set( uv.x, 1 - uv.y );
|
||||
if( uv ) _event.data.set( uv.x, 1 - uv.y );
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else{
|
||||
|
@ -93,7 +96,8 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
|
|||
raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld );
|
||||
raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix );
|
||||
|
||||
const intersections = raycaster.intersectObjects( scope.objects, false );
|
||||
let objects = scope.raycastAll ? xrf.scene.children : scope.objects
|
||||
const intersections = raycaster.intersectObjects( objects, scope.raycastAll );
|
||||
|
||||
if ( intersections.length > 0 ) {
|
||||
|
||||
|
@ -105,7 +109,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
|
|||
const uv = intersection.uv;
|
||||
|
||||
_event.type = eventsMapper[ event.type ];
|
||||
_event.data.set( uv.x, 1 - uv.y );
|
||||
if( uv ) _event.data.set( uv.x, 1 - uv.y );
|
||||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
|
@ -132,6 +136,8 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
}
|
||||
|
||||
// we create our own add to avoid unnecessary unparenting of buffergeometries from
|
||||
// their 3D model (which breaks animations)
|
||||
add(obj, unparent){
|
||||
if( unparent ) Group.prototype.add.call( this, obj )
|
||||
this.objects.push(obj)
|
||||
|
|
Loading…
Reference in New Issue