@@ -80,6 +80,7 @@ AFRAME.registerComponent('super-hands', {
8080
8181 // state tracking - reaction components
8282 this . hoverEls = [ ] ;
83+ this . hoverElsDist = [ ] ;
8384 this . state = new Map ( ) ;
8485 this . dragging = false ;
8586
@@ -185,9 +186,9 @@ AFRAME.registerComponent('super-hands', {
185186 } ,
186187 onStretchEndButton : function ( evt ) {
187188 const stretched = this . state . get ( this . STRETCH_EVENT ) ;
188- const endEvt = { hand : this . el , buttonEvent : evt
189- // check if end event accepted
190- } ; if ( stretched && ! this . emitCancelable ( stretched , this . UNSTRETCH_EVENT , endEvt ) ) {
189+ const endEvt = { hand : this . el , buttonEvent : evt } ;
190+ // check if end event accepted
191+ if ( stretched && ! this . emitCancelable ( stretched , this . UNSTRETCH_EVENT , endEvt ) ) {
191192 this . promoteHoveredEl ( stretched ) ;
192193 this . state . delete ( this . STRETCH_EVENT ) ;
193194 this . hover ( ) ;
@@ -253,11 +254,23 @@ AFRAME.registerComponent('super-hands', {
253254 } ,
254255 onHit : function ( evt ) {
255256 const hitEl = evt . detail [ this . data . colliderEventProperty ] ;
256- var processHitEl = hitEl => {
257+ var processHitEl = ( hitEl , distance ) => {
257258 let hitElIndex ;
258259 hitElIndex = this . hoverEls . indexOf ( hitEl ) ;
259260 if ( hitElIndex === - 1 ) {
260- this . hoverEls . push ( hitEl ) ;
261+ // insert in order of distance when available
262+ if ( distance ) {
263+ let i = 0 ;
264+ const dists = this . hoverElsDist ;
265+ while ( distance < dists [ i ] && i < dists . length ) {
266+ i ++ ;
267+ }
268+ this . hoverEls . splice ( i , 0 , hitEl ) ;
269+ this . hoverElsDist . splice ( i , 0 , distance ) ;
270+ } else {
271+ this . hoverEls . push ( hitEl ) ;
272+ this . hoverElsDist . push ( null ) ;
273+ }
261274 // later loss of collision will remove from hoverEls
262275 hitEl . addEventListener ( 'stateremoved' , this . unWatch ) ;
263276 this . dispatchMouseEvent ( hitEl , 'mouseover' , this . el ) ;
@@ -274,9 +287,13 @@ AFRAME.registerComponent('super-hands', {
274287 return ;
275288 }
276289 if ( Array . isArray ( hitEl ) ) {
290+ for ( let i = 0 , dist ; i < hitEl . length ; i ++ ) {
291+ dist = evt . detail . intersections && evt . detail . intersections [ i ] . distance ;
292+ processHitEl ( hitEl [ i ] , dist ) ;
293+ }
277294 hitEl . forEach ( processHitEl ) ;
278295 } else {
279- processHitEl ( hitEl ) ;
296+ processHitEl ( hitEl , null ) ;
280297 }
281298 } ,
282299 /* search collided entities for target to hover/dragover */
@@ -372,6 +389,7 @@ AFRAME.registerComponent('super-hands', {
372389 target . removeEventListener ( 'stateremoved' , this . unWatch ) ;
373390 if ( hoverIndex !== - 1 ) {
374391 this . hoverEls . splice ( hoverIndex , 1 ) ;
392+ this . hoverElsDist . splice ( hoverIndex , 1 ) ;
375393 }
376394 this . gehDragged . forEach ( dragged => {
377395 this . dispatchMouseEvent ( target , 'dragleave' , dragged ) ;
@@ -384,24 +402,26 @@ AFRAME.registerComponent('super-hands', {
384402 this . el . addEventListener ( this . data . colliderEndEvent , this . unWatch ) ;
385403 this . el . addEventListener ( this . data . colliderEndEvent , this . unHover ) ;
386404
405+ // binding order to keep grabEnd from triggering dragover
406+ // again before dragDropEnd can delete its carried state
387407 this . data . grabStartButtons . forEach ( b => {
388408 this . el . addEventListener ( b , this . onGrabStartButton ) ;
389409 } ) ;
390- this . data . grabEndButtons . forEach ( b => {
391- this . el . addEventListener ( b , this . onGrabEndButton ) ;
392- } ) ;
393410 this . data . stretchStartButtons . forEach ( b => {
394411 this . el . addEventListener ( b , this . onStretchStartButton ) ;
395412 } ) ;
396- this . data . stretchEndButtons . forEach ( b => {
397- this . el . addEventListener ( b , this . onStretchEndButton ) ;
398- } ) ;
399413 this . data . dragDropStartButtons . forEach ( b => {
400414 this . el . addEventListener ( b , this . onDragDropStartButton ) ;
401415 } ) ;
402416 this . data . dragDropEndButtons . forEach ( b => {
403417 this . el . addEventListener ( b , this . onDragDropEndButton ) ;
404418 } ) ;
419+ this . data . stretchEndButtons . forEach ( b => {
420+ this . el . addEventListener ( b , this . onStretchEndButton ) ;
421+ } ) ;
422+ this . data . grabEndButtons . forEach ( b => {
423+ this . el . addEventListener ( b , this . onGrabEndButton ) ;
424+ } ) ;
405425 } ,
406426 unRegisterListeners : function ( data ) {
407427 data = data || this . data ;
@@ -473,16 +493,20 @@ AFRAME.registerComponent('super-hands', {
473493 }
474494 return null ;
475495 } ,
496+ // Helper to ensure dropping and regrabbing finds the same target for
497+ // for order-sorted hoverEls (grabbing; no-op for distance-sorted (pointing)
476498 promoteHoveredEl : function ( el ) {
477499 var hoverIndex = this . hoverEls . indexOf ( el ) ;
478- if ( hoverIndex !== - 1 ) {
500+ if ( hoverIndex !== - 1 && this . hoverElsDist [ hoverIndex ] == null ) {
479501 this . hoverEls . splice ( hoverIndex , 1 ) ;
502+ this . hoverElsDist . splice ( hoverIndex , 1 ) ;
480503 this . hoverEls . push ( el ) ;
504+ this . hoverElsDist . push ( null ) ;
481505 }
482506 }
483507} ) ;
484508
485- } , { "./misc_components/locomotor-auto-config.js" :2 , "./misc_components/progressive-controls.js" :3 , "./primitives/a-locomotor.js" :4 , "./reaction_components/clickable.js" :5 , "./reaction_components/drag-droppable.js" :6 , "./reaction_components/draggable.js" :7 , "./reaction_components/droppable.js" :8 , "./reaction_components/grabbable.js" :9 , "./reaction_components/hoverable.js" :10 , "./reaction_components/stretchable.js" :13 , "./systems/super-hands-system.js" :14 } ] , 2 :[ function ( require , module , exports ) {
509+ } , { "./misc_components/locomotor-auto-config.js" :2 , "./misc_components/progressive-controls.js" :3 , "./primitives/a-locomotor.js" :4 , "./reaction_components/clickable.js" :5 , "./reaction_components/drag-droppable.js" :6 , "./reaction_components/draggable.js" :7 , "./reaction_components/droppable.js" :8 , "./reaction_components/grabbable.js" :9 , "./reaction_components/hoverable.js" :10 , "./reaction_components/stretchable.js" :14 , "./systems/super-hands-system.js" :15 } ] , 2 :[ function ( require , module , exports ) {
486510'use strict' ;
487511
488512/* global AFRAME */
@@ -498,6 +522,7 @@ AFRAME.registerComponent('locomotor-auto-config', {
498522 if ( this . data . camera ) {
499523 if ( ! document . querySelector ( 'a-camera, [camera]' ) ) {
500524 let cam = document . createElement ( 'a-camera' ) ;
525+ cam . setAttribute ( 'position' , '0 1.6 0' ) ;
501526 this . el . appendChild ( cam ) ;
502527 }
503528 }
@@ -523,7 +548,14 @@ AFRAME.registerComponent('locomotor-auto-config', {
523548 }
524549 } ,
525550 remove : function ( ) {
526- this . el . removeState ( this . colliderState ) ;
551+ this . el . getChildEntities ( ) . forEach ( el => {
552+ let sh = el . getAttribute ( 'super-hands' ) ;
553+ if ( sh ) {
554+ let evtDetails = { } ;
555+ evtDetails [ sh . colliderEndEventProperty ] = this . el ;
556+ el . emit ( sh . colliderEndEvent , evtDetails ) ;
557+ }
558+ } ) ;
527559 this . el . removeEventListener ( 'controllerconnected' , this . fakeCollisionsB ) ;
528560 } ,
529561 announceReady : function ( ) {
@@ -543,8 +575,8 @@ AFRAME.registerComponent('locomotor-auto-config', {
543575 this . colliderState = sh . colliderState ;
544576 this . el . addState ( this . colliderState ) ;
545577 }
546- this . announceReady ( ) ;
547578 } ) ;
579+ this . announceReady ( ) ;
548580 }
549581} ) ;
550582
@@ -609,7 +641,11 @@ AFRAME.registerComponent('progressive-controls', {
609641 assets . appendChild ( pointDefault ) ;
610642 assets . appendChild ( touchDefault ) ;
611643
612- this . camera = this . el . querySelector ( 'a-camera,[camera]' ) || this . el . appendChild ( document . createElement ( 'a-camera' ) ) ;
644+ this . camera = this . el . querySelector ( 'a-camera,[camera]' ) ;
645+ if ( ! this . camera ) {
646+ this . camera = this . el . appendChild ( document . createElement ( 'a-camera' ) ) ;
647+ this . camera . setAttribute ( 'position' , '0 1.6 0' ) ;
648+ }
613649 this . caster = this . camera . querySelector ( '.gazecaster' ) || this . camera . appendChild ( document . createElement ( 'a-entity' ) ) ;
614650 [ 'left' , 'right' ] . forEach ( hand => {
615651 // find controller by left-controller/right-controller class or create one
@@ -1067,7 +1103,10 @@ AFRAME.registerComponent('droppable', {
10671103const inherit = AFRAME . utils . extendDeep ;
10681104const physicsCore = require ( './prototypes/physics-grab-proto.js' ) ;
10691105const buttonsCore = require ( './prototypes/buttons-proto.js' ) ;
1070- AFRAME . registerComponent ( 'grabbable' , inherit ( { } , physicsCore , buttonsCore , {
1106+ const networkedCore = require ( './prototypes/networked-proto.js' ) ;
1107+ // new object with all core modules
1108+ const base = inherit ( { } , physicsCore , buttonsCore , networkedCore ) ;
1109+ AFRAME . registerComponent ( 'grabbable' , inherit ( base , {
10711110 schema : {
10721111 maxGrabbers : { type : 'int' , default : NaN } ,
10731112 invert : { default : false } ,
@@ -1083,9 +1122,9 @@ AFRAME.registerComponent('grabbable', inherit({}, physicsCore, buttonsCore, {
10831122 this . deltaPositionIsValid = false ;
10841123 this . grabDistance = undefined ;
10851124 this . grabDirection = { x : 0 , y : 0 , z : - 1 } ;
1086- this . grabOffset = { x : 0 , y : 0 , z : 0
1087- // persistent object speeds up repeat setAttribute calls
1088- } ; this . destPosition = { x : 0 , y : 0 , z : 0 } ;
1125+ this . grabOffset = { x : 0 , y : 0 , z : 0 } ;
1126+ // persistent object speeds up repeat setAttribute calls
1127+ this . destPosition = { x : 0 , y : 0 , z : 0 } ;
10891128 this . deltaPosition = new THREE . Vector3 ( ) ;
10901129 this . targetPosition = new THREE . Vector3 ( ) ;
10911130 this . physicsInit ( ) ;
@@ -1132,7 +1171,7 @@ AFRAME.registerComponent('grabbable', inherit({}, physicsCore, buttonsCore, {
11321171 // room for more grabbers?
11331172 const grabAvailable = ! Number . isFinite ( this . data . maxGrabbers ) || this . grabbers . length < this . data . maxGrabbers ;
11341173
1135- if ( this . grabbers . indexOf ( evt . detail . hand ) === - 1 && grabAvailable ) {
1174+ if ( this . grabbers . indexOf ( evt . detail . hand ) === - 1 && grabAvailable && this . networkedOk ( ) ) {
11361175 if ( ! evt . detail . hand . object3D ) {
11371176 console . warn ( 'grabbable entities must have an object3D' ) ;
11381177 return ;
@@ -1192,7 +1231,7 @@ AFRAME.registerComponent('grabbable', inherit({}, physicsCore, buttonsCore, {
11921231 }
11931232} ) ) ;
11941233
1195- } , { "./prototypes/buttons-proto.js" :11 , "./prototypes/physics-grab-proto.js" :12 } ] , 10 :[ function ( require , module , exports ) {
1234+ } , { "./prototypes/buttons-proto.js" :11 , "./prototypes/networked-proto.js" : 12 , "./prototypes/ physics-grab-proto.js" :13 } ] , 10 :[ function ( require , module , exports ) {
11961235'use strict' ;
11971236
11981237/* global AFRAME */
@@ -1263,6 +1302,25 @@ module.exports = function () {
12631302} ( ) ;
12641303
12651304} , { } ] , 12 :[ function ( require , module , exports ) {
1305+ "use strict" ;
1306+
1307+ // integration with networked-aframe
1308+ module . exports = {
1309+ schema : {
1310+ takeOwnership : { default : false }
1311+ } ,
1312+ networkedOk : function ( ) {
1313+ if ( ! window . NAF || window . NAF . utils . isMine ( this . el ) ) {
1314+ return true ;
1315+ }
1316+ if ( this . data . takeOwnership ) {
1317+ return window . NAF . utils . takeOwnership ( this . el ) ;
1318+ }
1319+ return false ;
1320+ }
1321+ } ;
1322+
1323+ } , { } ] , 13 :[ function ( require , module , exports ) {
12661324'use strict' ;
12671325
12681326// base code used by grabbable for physics interactions
@@ -1320,13 +1378,16 @@ module.exports = {
13201378 }
13211379} ;
13221380
1323- } , { } ] , 13 :[ function ( require , module , exports ) {
1381+ } , { } ] , 14 :[ function ( require , module , exports ) {
13241382'use strict' ;
13251383
13261384/* global AFRAME, THREE */
13271385const inherit = AFRAME . utils . extendDeep ;
1328- const buttonCore = require ( './prototypes/buttons-proto.js' ) ;
1329- AFRAME . registerComponent ( 'stretchable' , inherit ( { } , buttonCore , {
1386+ const buttonsCore = require ( './prototypes/buttons-proto.js' ) ;
1387+ const networkedCore = require ( './prototypes/networked-proto.js' ) ;
1388+ // new object with all core modules
1389+ const base = inherit ( { } , buttonsCore , networkedCore ) ;
1390+ AFRAME . registerComponent ( 'stretchable' , inherit ( base , {
13301391 schema : {
13311392 usePhysics : { default : 'ifavailable' } ,
13321393 invert : { default : false } ,
@@ -1379,7 +1440,7 @@ AFRAME.registerComponent('stretchable', inherit({}, buttonCore, {
13791440 this . el . removeEventListener ( this . UNSTRETCH_EVENT , this . end ) ;
13801441 } ,
13811442 start : function ( evt ) {
1382- if ( this . stretched || this . stretchers . includes ( evt . detail . hand ) || ! this . startButtonOk ( evt ) || evt . defaultPrevented ) {
1443+ if ( this . stretched || this . stretchers . includes ( evt . detail . hand ) || ! this . startButtonOk ( evt ) || evt . defaultPrevented || ! this . networkedOk ( ) ) {
13831444 return ;
13841445 } // already stretched or already captured this hand or wrong button
13851446 this . stretchers . push ( evt . detail . hand ) ;
@@ -1453,7 +1514,7 @@ AFRAME.registerComponent('stretchable', inherit({}, buttonCore, {
14531514 }
14541515} ) ) ;
14551516
1456- } , { "./prototypes/buttons-proto.js" :11 } ] , 14 :[ function ( require , module , exports ) {
1517+ } , { "./prototypes/buttons-proto.js" :11 , "./prototypes/networked-proto.js" : 12 } ] , 15 :[ function ( require , module , exports ) {
14571518'use strict' ;
14581519
14591520/* global AFRAME */
0 commit comments