|
|
|
@ -149,95 +149,62 @@ AFRAME.registerComponent('pinchsecondary', { |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// grouping and distance between last two pinches should be rewritten, simplified and more reliable
|
|
|
|
|
AFRAME.registerComponent('pinchprimary', { // currently only 1 hand, the right one, should be switchable
|
|
|
|
|
|
|
|
|
|
// consider instead https://github.com/AdaRoseCannon/handy-work/blob/main/README-AFRAME.md for specific poses
|
|
|
|
|
// or https://aframe.io/aframe/examples/showcase/hand-tracking/pinchable.js
|
|
|
|
|
|
|
|
|
|
init: function () { |
|
|
|
|
var el = this.el |
|
|
|
|
this.el.addEventListener('pinchended', function (event) {
|
|
|
|
|
// if positioned close enough to a target zone, trigger action
|
|
|
|
|
// see own trigger-box component. Could use dedicated threejs helpers instead.
|
|
|
|
|
// https://github.com/Utopiah/aframe-triggerbox-component/blob/master/aframe-triggerbox-component.js#L66
|
|
|
|
|
// could make trigger zones visible as debug mode
|
|
|
|
|
var closests = getClosestTargetElements( event.detail.position ) |
|
|
|
|
//if (closests && closests.length > 0) // avoiding self reference
|
|
|
|
|
// setFeedbackHUD("close enough, could stack with "+ closests[1].el.getAttribute("value") )
|
|
|
|
|
/* |
|
|
|
|
somehow #box MUST exist, otherwise craches?! |
|
|
|
|
*/ |
|
|
|
|
let dist = 100 |
|
|
|
|
if ( document.querySelector("#box") ) |
|
|
|
|
dist = event.detail.position.distanceTo( document.querySelector("#box").object3D.position ) |
|
|
|
|
if (dist < .1){ |
|
|
|
|
setFeedbackHUD("close enough, replaced shortcut with "+ selectedElement.getAttribute("value") ) |
|
|
|
|
wristShortcut = selectedElement.getAttribute("value") |
|
|
|
|
} |
|
|
|
|
if (selectedElement){ |
|
|
|
|
let content = selectedElement.getAttribute("value") |
|
|
|
|
selectedElement.emit('released', {element:selectedElement, timestamp:Date.now(), primary:true}) |
|
|
|
|
} |
|
|
|
|
// unselect current target if any
|
|
|
|
|
selectedElement = null; |
|
|
|
|
if ( groupingMode ) addToGroup( event.detail.position ) |
|
|
|
|
selectionPinchMode = false |
|
|
|
|
/* |
|
|
|
|
setHUD( AFRAME.utils.coordinates.stringify( bbox.min ), |
|
|
|
|
AFRAME.utils.coordinates.stringify( bbox.max ) ) |
|
|
|
|
bbox.min.copy( zeroVector3 ) |
|
|
|
|
bbox.man.copy( zeroVector3 ) |
|
|
|
|
*/ |
|
|
|
|
setTimeout( _ => primaryPinchStarted = false, 200) // delay otherwise still activate on release
|
|
|
|
|
|
|
|
|
|
var newPinchPos = new THREE.Vector3() |
|
|
|
|
newPinchPos.copy(event.detail.position ) |
|
|
|
|
pinches.push({position:newPinchPos, timestamp:Date.now(), primary:true}) |
|
|
|
|
dl2p = distanceLastTwoPinches() |
|
|
|
|
|
|
|
|
|
}); |
|
|
|
|
this.el.addEventListener('pinchmoved', function (event) {
|
|
|
|
|
// move current target if any
|
|
|
|
|
if (selectionPinchMode){ |
|
|
|
|
bbox.max.copy( event.detail.position ) |
|
|
|
|
if (!bbox.min.equal(zeroVector3)) |
|
|
|
|
selectionBox.update(); |
|
|
|
|
} |
|
|
|
|
if (selectedElement && !groupingMode) { |
|
|
|
|
selectedElement.setAttribute("position", event.detail.position) |
|
|
|
|
document.querySelector("#rightHand").object3D.traverse( e => { |
|
|
|
|
if (e.name == "ring-finger-tip"){ |
|
|
|
|
selectedElement.object3D.rotation.copy( e.rotation ) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
// rotation isn't ideal with the wrist as tend not have wrist flat as we pinch
|
|
|
|
|
} |
|
|
|
|
if (selectedElement) selectedElement.emit("moved") |
|
|
|
|
}); |
|
|
|
|
this.el.addEventListener('pinchstarted', function (event) { |
|
|
|
|
primaryPinchStarted = true |
|
|
|
|
if (!selectionPinchMode) bbox.max.copy( zeroVector3 ) |
|
|
|
|
|
|
|
|
|
//var clone = getClosestTargetElement( event.detail.position ).cloneNode()
|
|
|
|
|
// might want to limit cloning to unmoved element and otherwise move the cloned one
|
|
|
|
|
//AFRAME.scenes[0].appendChild( clone )
|
|
|
|
|
//targets.push( clone )
|
|
|
|
|
//selectedElement = clone
|
|
|
|
|
|
|
|
|
|
selectedElement = getClosestTargetElement( event.detail.position ) |
|
|
|
|
if (selectedElement) { |
|
|
|
|
selectedElements.push({element:selectedElement, timestamp:Date.now(), primary:true}) |
|
|
|
|
selectedElement.emit("picked") |
|
|
|
|
events: { |
|
|
|
|
pinchended: function (event) { |
|
|
|
|
let closests = getClosestTargetElements( event.detail.position ) |
|
|
|
|
let dist = 100 |
|
|
|
|
if ( document.querySelector("#box") ) |
|
|
|
|
dist = event.detail.position.distanceTo( document.querySelector("#box").object3D.position ) |
|
|
|
|
if (dist < .1){ |
|
|
|
|
setFeedbackHUD("close enough, replaced shortcut with "+ selectedElement.getAttribute("value") ) |
|
|
|
|
wristShortcut = selectedElement.getAttribute("value") |
|
|
|
|
} |
|
|
|
|
if (selectedElement){ |
|
|
|
|
let content = selectedElement.getAttribute("value") |
|
|
|
|
selectedElement.emit('released', {element:selectedElement, timestamp:Date.now(), primary:true}) |
|
|
|
|
} |
|
|
|
|
// unselect current target if any
|
|
|
|
|
selectedElement = null; |
|
|
|
|
if ( groupingMode ) addToGroup( event.detail.position ) |
|
|
|
|
selectionPinchMode = false |
|
|
|
|
setTimeout( _ => primaryPinchStarted = false, 200) // delay otherwise still activate on release
|
|
|
|
|
var newPinchPos = new THREE.Vector3() |
|
|
|
|
newPinchPos.copy(event.detail.position ) |
|
|
|
|
pinches.push({position:newPinchPos, timestamp:Date.now(), primary:true}) |
|
|
|
|
dl2p = distanceLastTwoPinches() |
|
|
|
|
}, |
|
|
|
|
pinchmoved: function (event) { |
|
|
|
|
if (selectionPinchMode){ |
|
|
|
|
bbox.max.copy( event.detail.position ) |
|
|
|
|
if (!bbox.min.equal(zeroVector3)) |
|
|
|
|
selectionBox.update(); |
|
|
|
|
} |
|
|
|
|
if (selectedElement && !groupingMode) { |
|
|
|
|
selectedElement.setAttribute("position", event.detail.position) |
|
|
|
|
document.querySelector("#rightHand").object3D.traverse( e => { |
|
|
|
|
if (e.name == "ring-finger-tip"){ |
|
|
|
|
selectedElement.object3D.rotation.copy( e.rotation ) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
// rotation isn't ideal with the wrist as tend not have wrist flat as we pinch
|
|
|
|
|
} |
|
|
|
|
if (selectedElement) selectedElement.emit("moved") // consider adding as data selectedElement
|
|
|
|
|
}, |
|
|
|
|
pinchstarted: function (event) { |
|
|
|
|
primaryPinchStarted = true |
|
|
|
|
if (!selectionPinchMode) bbox.max.copy( zeroVector3 ) |
|
|
|
|
|
|
|
|
|
selectedElement = getClosestTargetElement( event.detail.position ) |
|
|
|
|
if (selectedElement) { |
|
|
|
|
selectedElements.push({element:selectedElement, timestamp:Date.now(), primary:true}) |
|
|
|
|
selectedElement.emit("picked") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// is it truly world position? See https://github.com/aframevr/aframe/issues/5182
|
|
|
|
|
// setFeedbackHUD( AFRAME.utils.coordinates.stringify( event.detail.position ) )
|
|
|
|
|
// if close enough to a target among a list of potential targets, unselect previous target then select new
|
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
remove: function() { |
|
|
|
|
// should remove event listeners here. Requires naming them.
|
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
// should remove event listeners
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// avoiding setOnDropFromAttribute() as it is not idiosyncratic and creates timing issues
|
|
|
|
|
AFRAME.registerComponent('onreleased', { // changed from ondrop to be coherent with event name
|
|
|
|
|