Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require('./reaction_components/drag-droppable.js')
require('./reaction_components/draggable.js')
require('./reaction_components/droppable.js')
require('./reaction_components/clickable.js')
require('./reaction_components/activatable.js')

/**
* Super Hands component for A-Frame.
Expand Down Expand Up @@ -58,6 +59,18 @@ AFRAME.registerComponent('super-hands', {
'pointdown', 'thumbdown', 'pointingend', 'pistolend',
'thumbstickup', 'mouseup', 'touchend']
},
activateStartButtons: {
default: ['gripdown', 'trackpaddown', 'triggerdown', 'gripclose',
'abuttondown', 'bbuttondown', 'xbuttondown', 'ybuttondown',
'pointup', 'thumbup', 'pointingstart', 'pistolstart',
'thumbstickdown', 'mousedown', 'touchstart']
},
activateEndButtons: {
default: ['gripup', 'trackpadup', 'triggerup', 'gripopen',
'abuttonup', 'bbuttonup', 'xbuttonup', 'ybuttonup',
'pointdown', 'thumbdown', 'pointingend', 'pistolend',
'thumbstickup', 'mouseup', 'touchend']
},
interval: { default: 0 }
},

Expand All @@ -82,6 +95,8 @@ AFRAME.registerComponent('super-hands', {
this.DRAGOVER_EVENT = 'dragover-start'
this.UNDRAGOVER_EVENT = 'dragover-end'
this.DRAGDROP_EVENT = 'drag-drop'
this.ACTIVATE_EVENT = 'activate-start'
this.DEACTIVATE_EVENT = 'activate-end'

// links to other systems/components
this.otherSuperHand = null
Expand All @@ -106,6 +121,8 @@ AFRAME.registerComponent('super-hands', {
this.onStretchEndButton = this.onStretchEndButton.bind(this)
this.onDragDropStartButton = this.onDragDropStartButton.bind(this)
this.onDragDropEndButton = this.onDragDropEndButton.bind(this)
this.onActivateStartButton = this.onActivateStartButton.bind(this)
this.onActivateEndButton = this.onActivateEndButton.bind(this)
this.system.registerMe(this)
},

Expand Down Expand Up @@ -281,6 +298,30 @@ AFRAME.registerComponent('super-hands', {
}
}
},
onActivateStartButton: function (evt) {
const carried = this.state.get(this.GRAB_EVENT)
let activated = this.state.get(this.ACTIVATE_EVENT)
if (carried) {
if (!activated && !this.emitCancelable(carried, this.ACTIVATE_EVENT, {hand: this.el, buttonEvent: evt})) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would mean only an entity which is already the grabbed entity can be activated. In this respect, it wouldn't be much different from the drag gesture. What would you say to making this a more general gesture, just the act of pressing a button while targeting an entity? I'm thinking this way the activatable component would replace the clickable component and do a better job of what it has been trying to do without interfering with grabbing. When you do want an activation that is dependent on also being grabbed, that logic could be handled within the reaction component instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was definitely intended to be similar to draggable, but more generic and customizable (since you can specify exactly what state to set on the objects so you can have multiple). Also, given clickable exists, I didn't see the need to allow activatable to work on ungrabbed objects. I am not opposed to rolling all three of these together since they are pretty similar.

activated = this.state.get(this.ACTIVATE_EVENT)
}
if (activated) {
this.state.set(this.ACTIVATE_EVENT, activated)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is unreachable - I don't see another place where the activated state is set, so the condition would always be false

Copy link
Contributor Author

@InfiniteLee InfiniteLee Jul 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grabbing an object with two hands? nevermind

}
}
},
onActivateEndButton: function (evt) {
const carried = this.state.get(this.GRAB_EVENT)
let deactivated = this.state.get(this.DEACTIVATE_EVENT)
if (carried) {
if (!deactivated && !this.emitCancelable(carried, this.DEACTIVATE_EVENT, {hand: this.el, buttonEvent: evt})) {
deactivated = this.state.get(this.DEACTIVATE_EVENT)
}
if (deactivated) {
this.state.set(this.DEACTIVATE_EVENT, deactivated)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a need for storing the last activated entity on the state? So far, the gestures only track the current interaction.

}
}
},
processHitEl: function (hitEl, intersection) {
const dist = intersection && intersection.distance
const sects = this.hoverElsIntersections
Expand Down Expand Up @@ -434,6 +475,9 @@ AFRAME.registerComponent('super-hands', {
this.data.dragDropStartButtons.forEach(b => {
this.el.addEventListener(b, this.onDragDropStartButton)
})
this.data.activateStartButtons.forEach(b => {
this.el.addEventListener(b, this.onActivateStartButton)
})
this.data.dragDropEndButtons.forEach(b => {
this.el.addEventListener(b, this.onDragDropEndButton)
})
Expand All @@ -443,6 +487,9 @@ AFRAME.registerComponent('super-hands', {
this.data.grabEndButtons.forEach(b => {
this.el.addEventListener(b, this.onGrabEndButton)
})
this.data.activateEndButtons.forEach(b => {
this.el.addEventListener(b, this.onActivateEndButton)
})
},
unRegisterListeners: function (data) {
data = data || this.data
Expand All @@ -463,6 +510,9 @@ AFRAME.registerComponent('super-hands', {
data.stretchStartButtons.forEach(b => {
this.el.removeEventListener(b, this.onStretchStartButton)
})
data.activateStartButtons.forEach(b => {
this.el.removeEventListener(b, this.onActivateStartButton)
})
data.stretchEndButtons.forEach(b => {
this.el.removeEventListener(b, this.onStretchEndButton)
})
Expand All @@ -472,6 +522,9 @@ AFRAME.registerComponent('super-hands', {
data.dragDropEndButtons.forEach(b => {
this.el.removeEventListener(b, this.onDragDropEndButton)
})
data.activateEndButtons.forEach(b => {
this.el.removeEventListener(b, this.onActivateEndButton)
})
},
emitCancelable: function (target, name, detail) {
var data, evt
Expand Down
38 changes: 38 additions & 0 deletions reaction_components/activatable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* global AFRAME */
const inherit = AFRAME.utils.extendDeep
const buttonCore = require('./prototypes/buttons-proto.js')

AFRAME.registerComponent('activatable', inherit({}, buttonCore, {
multiple: true,
schema: {
buttonStartEvent: {default: ''},
buttonEndEvent: {default: ''},
activatedState: {default: 'activated'}
},
init: function () {
this.ACTIVATE_EVENT = 'activate-start'
this.DEACTIVATE_EVENT = 'activate-end'

this.activateStart = this.activateStart.bind(this)
this.activateEnd = this.activateEnd.bind(this)

this.el.addEventListener(this.ACTIVATE_EVENT, this.activateStart)
this.el.addEventListener(this.DEACTIVATE_EVENT, this.activateEnd)
},
remove: function () {
this.el.removeEventListener(this.ACTIVATE_EVENT, this.activateStart)
this.el.removeEventListener(this.DEACTIVATE_EVENT, this.activateEnd)
},
activateStart: function (evt) {
if (evt.defaultPrevented || !this.startButtonOk(evt)) { return }
if (evt.detail.buttonEvent.type !== this.data.buttonStartEvent) { return }
this.el.addState(this.data.activatedState)
if (evt.preventDefault) { evt.preventDefault() }
},
activateEnd: function (evt) {
if (evt.defaultPrevented || !this.endButtonOk(evt)) { return }
if (evt.detail.buttonEvent.type !== this.data.buttonEndEvent) { return }
this.el.removeState(this.data.activatedState)
if (evt.preventDefault) { evt.preventDefault() }
}
}))