working mechanism

in-situ-instructions
Fabien Benetou 8 months ago
parent 2e428b4134
commit 9154e17432
  1. 122
      index.html

@ -18,34 +18,46 @@ AFRAME.registerComponent('startfunctions', {
init: function(){ init: function(){
let newEl = document.createElement('a-entity') let newEl = document.createElement('a-entity')
newEl.setAttribute('instruction-coffee-machine', '') newEl.setAttribute('instruction-machine', '')
AFRAME.scenes[0].appendChild(newEl) AFRAME.scenes[0].appendChild(newEl)
} }
}) })
//___________________________________________________________________________________________________________________________________ //___________________________________________________________________________________________________________________________________
AFRAME.registerComponent('instruction-coffee-machine', { AFRAME.registerComponent('instruction-machine', {
// once done, equivalent for // other content next, ideally combinable
// tournevie metal workshop // tournevie metal workshop
// laser cutter at the EP // laser cutter at the EP
// todo // todo
// describe the target task, e.g "Make extra long coffee (on PicoBarista)" // visual timeline and where we are on it, e.g 1/4 steps
// 3D model of target object to align efficiently // a la Lego instruction, i.e horizontal bar with dot on current position
// list the steps then iterate over them : // could use a cylinder and a moving sphere
// highlight, e.g via arrow pointer, the next element to interact with // could be helpful to persist once position is ok, after step 1 then
// confirm that the instruction was properly conducted // https://aframe.io/docs/1.5.0/components/anchored.html
// optionally allow to // timeout for increasingly explicit feedback
// rollback 1 step // jump to specific step via hash to better discussion
// restart from scratch // port a text version, i.e no 6DoF or hand tracking, to Monocle/Frame
// adjust bounding box // adapt from wiki sequential instructions part, possibly with some images
// port a much simplified version, i.e no 6DoF or hand tracking, to Monocle/Frame // consider https://threejs.org/docs/?q=grid#api/en/helpers/GridHelper too
// probably text only then, so only the load from wiki sequential instructions part
init: function(){ init: function(){
// shortcut to navigate through steps, 2D only
onwheel = (event) => {
event.deltaY < 0 ?
document.querySelector("["+generatorName+"]").emit('previousStep')
// does not yet exist
: document.querySelector("["+generatorName+"]").emit('nextStep')
}
let generatorName = this.attrName let generatorName = this.attrName
const idSuffix = "_framing_box" const idSuffix = "_framing_box"
let el = this.el let el = this.el
this.scale = 1/10 this.scale = 1/10
this.steps = ["pick the grey box and align it with your coffee machine", "press button A", "press button B"] this.steps = ["pick the grey box and align it with your 3D printer", "press change filament button", "remove the filament spool"]
// symplistic, could instead be a directed graph of named nodes, each with optionally multiple outgoing edges
this.buttonSuffix = "_step_button"
this.endOfInstructions = "You have finished the instructions. Feel free to reset and try again."
const confirmationStep = "Done" // could also consider a "done" area, moving the text there const confirmationStep = "Done" // could also consider a "done" area, moving the text there
let newEl = document.createElement('a-box') let newEl = document.createElement('a-box')
newEl.setAttribute("scale", ""+this.scale+" "+this.scale+" "+this.scale) newEl.setAttribute("scale", ""+this.scale+" "+this.scale+" "+this.scale)
@ -62,9 +74,47 @@ AFRAME.registerComponent('instruction-coffee-machine', {
newEl.id = generatorName+idSuffix newEl.id = generatorName+idSuffix
el.appendChild(newEl) el.appendChild(newEl)
let timelinegEl = document.createElement('a-cylinder')
timelinegEl.setAttribute("height", "1")
timelinegEl.setAttribute("radius", ".1")
timelinegEl.setAttribute("color", "white")
timelinegEl.setAttribute("rotation", "90 0 0")
timelinegEl.setAttribute("position", "0.1 0.1 0.5")
timelinegEl.setAttribute("visible","false")
timelinegEl.classList.add( generatorName )
timelinegEl.id = generatorName+"_timeline"
//newEl.appendChild(timelinegEl)
let buttonEl = document.createElement('a-box')
buttonEl.setAttribute("scale", ".2 .1 .1")
buttonEl.setAttribute("wireframe", "true")
buttonEl.setAttribute("color", "red")
buttonEl.setAttribute("position", "0.1 0.1 0.5")
buttonEl.setAttribute("target","true")
buttonEl.setAttribute("visible","false")
buttonEl.classList.add( generatorName )
buttonEl.classList.add( generatorName+this.buttonSuffix)
buttonEl.id = generatorName+this.buttonSuffix+"_1"
newEl.appendChild(buttonEl)
this.addArrow([-4.5, 0, 0], buttonEl)
buttonEl = document.createElement('a-cylinder')
buttonEl.setAttribute("scale", ".5 .5 .5")
buttonEl.setAttribute("wireframe", "true")
buttonEl.setAttribute("color", "blue")
buttonEl.setAttribute("rotation", "90 0 0")
buttonEl.setAttribute("position", "0 0 -0.5")
buttonEl.setAttribute("target", "true")
buttonEl.setAttribute("visible","false")
buttonEl.classList.add( generatorName )
buttonEl.classList.add( generatorName+this.buttonSuffix)
buttonEl.id = generatorName+this.buttonSuffix+"_2"
newEl.appendChild(buttonEl)
this.addArrow([-4.5, 0, 0], buttonEl)
let n = addNewNote("jxr qs #"+newEl.id+" sa rotation 0", "0.5 0.9 -.5") let n = addNewNote("jxr qs #"+newEl.id+" sa rotation 0", "0.5 0.9 -.5")
n.setAttribute("rotation", "90 0 0") n.setAttribute("rotation", "90 0 0")
n.setAttribute("annotation", "content: snap") n.setAttribute("annotation", "content: snap")
let actions = [ let actions = [
"translateX(.1)", "translateX(-.1)", "translateY(.1)", "translateY(-.1)", "translateZ(.1)", "translateZ(-.1)", "translateX(.1)", "translateX(-.1)", "translateY(.1)", "translateY(-.1)", "translateZ(.1)", "translateZ(-.1)",
"rotateX(-.1)", "rotateX(.1)", "rotateY(.1)", "rotateY(-.1)", "rotateZ(.1)", "rotateZ(-.1)", "rotateX(-.1)", "rotateX(.1)", "rotateY(.1)", "rotateY(-.1)", "rotateZ(.1)", "rotateZ(-.1)",
@ -72,13 +122,21 @@ AFRAME.registerComponent('instruction-coffee-machine', {
actions.reverse().map( (a,i) => { actions.reverse().map( (a,i) => {
let n = addNewNote("jxr qs #"+newEl.id+" .object3D."+a, ".5 "+(1+i/20)+" -.5") let n = addNewNote("jxr qs #"+newEl.id+" .object3D."+a, ".5 "+(1+i/20)+" -.5")
n.setAttribute("rotation", "90 0 0") n.setAttribute("rotation", "90 0 0")
n.setAttribute("annotation", "content: "+a) n.setAttribute("annotation", "content: "+a.replace(/xxx/,''))
}) })
el.appendChild(newEl) el.appendChild(newEl)
n = addNewNote("jxr qs #"+newEl.id+" .emit('nextStep')" , "0 1.1 -.5") n = addNewNote("jxr qs #"+newEl.id+" .emit('nextStep')" , "0 1.1 -.5")
n.setAttribute("rotation", "90 0 0") n.setAttribute("rotation", "90 0 0")
n.setAttribute("annotation", "content: confirm/reset") n.setAttribute("annotation", "content: confirm")
n = addNewNote("jxr qs #"+newEl.id+" .emit('previousStep')" , "0 1.0 -.5")
n.setAttribute("rotation", "90 0 0")
n.setAttribute("annotation", "content: go backward")
n = addNewNote("jxr qs #"+newEl.id+" .emit('reset')" , "0 0.8 -.5")
n.setAttribute("rotation", "90 0 0")
n.setAttribute("annotation", "content: restart")
this.currentInstructionStep = 0 this.currentInstructionStep = 0
this.currentInstruction = addNewNote(this.steps[this.currentInstructionStep], "-.3 1.2 -.5") this.currentInstruction = addNewNote(this.steps[this.currentInstructionStep], "-.3 1.2 -.5")
@ -88,11 +146,41 @@ AFRAME.registerComponent('instruction-coffee-machine', {
reset: function (evt) { reset: function (evt) {
console.log(this.attrName, 'component was resetted!'); console.log(this.attrName, 'component was resetted!');
let generatorName = this.attrName let generatorName = this.attrName
this.currentInstructionStep=-1
document.querySelector("["+generatorName+"]").emit('nextStep')
}, },
nextStep: function (evt) { nextStep: function (evt) {
let generatorName = this.attrName
if (this.currentInstructionStep<this.steps.length-1){
this.currentInstruction.setAttribute("value",this.steps[++this.currentInstructionStep]) this.currentInstruction.setAttribute("value",this.steps[++this.currentInstructionStep])
Array.from( document.querySelectorAll( "."+generatorName+this.buttonSuffix) ).map( el => el.setAttribute("visible", "false" ) )
document.getElementById( generatorName+this.buttonSuffix +"_"+this.currentInstructionStep )?.setAttribute("visible", "true" )
} else {
this.currentInstruction.setAttribute("value", this.endOfInstructions)
}
},
previousStep: function (evt) {
let generatorName = this.attrName
if (this.currentInstructionStep>0){
this.currentInstruction.setAttribute("value",this.steps[--this.currentInstructionStep])
Array.from( document.querySelectorAll( "."+generatorName+this.buttonSuffix) ).map( el => el.setAttribute("visible", "false" ) )
document.getElementById( generatorName+this.buttonSuffix +"_"+this.currentInstructionStep )?.setAttribute("visible", "true" )
}
}, },
}, },
addArrow: function(relativePosition, parentEl, color=0xffff00){
const dir = new THREE.Vector3( 1, 0, 0 )
//normalize the direction vector (convert to vector of length 1)
dir.normalize()
const origin = new THREE.Vector3( ...relativePosition )
const length = 4
const hex = color
const arrowHelper = new THREE.ArrowHelper( dir, origin, length, hex )
parentEl.object3D.add( arrowHelper )
}
}) })
function cloneTarget(target){ function cloneTarget(target){

Loading…
Cancel
Save