Merge pull request #23 from andyps/master

Refactor ARKitWrapper to promises
This commit is contained in:
Trevor F. Smith 2017-09-22 16:17:56 -07:00 коммит произвёл GitHub
Родитель 21c3b6c962 c62e275401
Коммит f267fd78db
3 изменённых файлов: 71 добавлений и 68 удалений

Просмотреть файл

@ -148,9 +148,7 @@ export default class FlatDisplay extends XRDisplay {
location: true,
camera: true,
objects: true,
debug: false,
h_plane: false,
hit_test_result: 'hit_test_plane'
light_intensity: true
})
}, 1000)
}

Просмотреть файл

@ -36,7 +36,7 @@ export default class ARKitWrapper extends EventHandlerBase {
this._globalCallbacksMap = {} // Used to map a window.arkitCallback method name to an ARKitWrapper.on* method name
// Set up the window.arkitCallback methods that the ARKit bridge depends on
let callbackNames = ['onInit', 'onWatch', 'onStop', 'onHitTest', 'onAddAnchor']
let callbackNames = ['onInit', 'onWatch']
for(let i=0; i < callbackNames.length; i++){
this._generateGlobalCallback(callbackNames[i], i)
}
@ -100,7 +100,7 @@ export default class ARKitWrapper extends EventHandlerBase {
resolve()
return
}
let callback = () => {
const callback = () => {
this.removeEventListener(ARKitWrapper.INIT_EVENT, callback, false)
resolve()
}
@ -149,42 +149,69 @@ export default class ARKitWrapper extends EventHandlerBase {
Sends a hitTest message to ARKit to get hit testing results
x, y - screen coordinates normalized to 0..1
types - bit mask of hit testing types
Returns a promise that returns an array of hit results:
[
{
type: hitTestType,
world_transform: matrix4x4 - specifies the position and orientation relative to WCS,
local_transform: matrix4x4 - the position and orientation of the hit test result relative to the nearest anchor or feature point,
distance: distance to the detected plane,
anchor: {uuid, transform, ...} - the anchor representing the detected surface, if any
},
...
]
@see https://developer.apple.com/documentation/arkit/arframe/2875718-hittest
*/
hitTest(x, y, types = ARKitWrapper.HIT_TEST_TYPE_ALL) {
if (!this._isInitialized) {
return false
}
window.webkit.messageHandlers.hitTest.postMessage({
x: x,
y: y,
type: types,
callback: this._globalCallbacksMap.onHitTest
return new Promise((resolve, reject) => {
if (!this._isInitialized) {
reject(new Error('ARKit is not initialized'));
return;
}
window.webkit.messageHandlers.hitTest.postMessage({
x: x,
y: y,
type: types,
callback: this._createPromiseCallback('hitTest', resolve)
})
})
}
/*
Sends an addAnchor message to ARKit
Returns a promise that returns:
{
uuid - the anchor's uuid,
transform - anchor transformation matrix
}
*/
addAnchor(uuid, transform) {
if (!this._isInitialized) {
return false
}
window.webkit.messageHandlers.addAnchor.postMessage({
uuid: uuid,
transform: transform,
callback: this._globalCallbacksMap.onAddAnchor
return new Promise((resolve, reject) => {
if (!this._isInitialized) {
reject(new Error('ARKit is not initialized'));
return;
}
window.webkit.messageHandlers.addAnchor.postMessage({
uuid: uuid,
transform: transform,
callback: this._createPromiseCallback('addAnchor', resolve)
})
})
}
/*
If this instance is currently watching, send the stopAR message to ARKit to request that it stop sending data on onWatch
*/
stop() {
if (!this._isWatching) {
return
}
window.webkit.messageHandlers.stopAR.postMessage({
callback: this._globalCallbacksMap.onStop
return new Promise((resolve, reject) => {
if (!this._isWatching) {
resolve();
return;
}
window.webkit.messageHandlers.stopAR.postMessage({
callback: this._createPromiseCallback('stop', resolve)
})
})
}
@ -318,45 +345,25 @@ export default class ARKitWrapper extends EventHandlerBase {
*/
_onStop() {
this._isWatching = false
this.dispatchEvent(new CustomEvent(ARKitWrapper.STOP_EVENT, {
source: this
}))
}
/*
Callback from ARKit for when it does the work initiated by sending the addAnchor message from JS
data: {
uuid - the anchor's uuid,
transform - anchor transformation matrix
}
*/
_onAddAnchor(data) {
this.dispatchEvent(new CustomEvent(ARKitWrapper.ADD_ANCHOR_EVENT, {
source: this,
detail: data
}))
_createPromiseCallback(action, resolve) {
const callbackName = this._generateCallbackUID(action);
window[callbackName] = (data) => {
delete window[callbackName]
const wrapperCallbackName = '_on' + action[0].toUpperCase() +
action.slice(1);
if (typeof(this[wrapperCallbackName]) == 'function') {
this[wrapperCallbackName](data);
}
resolve(data)
}
return callbackName;
}
/*
Callback from ARKit for when it does the work initiated by sending the hitTest message from JS
ARKit returns an array of hit results
data: [
{
type: hitTestType,
world_transform: matrix4x4 - specifies the position and orientation relative to WCS,
local_transform: matrix4x4 - the position and orientation of the hit test result relative to the nearest anchor or feature point,
distance: distance to the detected plane,
anchor: {uuid, transform, ...} - the anchor representing the detected surface, if any
},
...
]
@see https://developer.apple.com/documentation/arkit/arframe/2875718-hittest
*/
_onHitTest(data) {
this.dispatchEvent(new CustomEvent(ARKitWrapper.HIT_TEST_EVENT, {
source: this,
detail: data
}))
_generateCallbackUID(prefix) {
return 'arkitCallback_' + prefix + '_' + new Date().getTime() +
'_' + Math.floor((Math.random() * Number.MAX_SAFE_INTEGER))
}
/*
@ -377,15 +384,12 @@ export default class ARKitWrapper extends EventHandlerBase {
// ARKitWrapper event names:
ARKitWrapper.INIT_EVENT = 'arkit-init'
ARKitWrapper.WATCH_EVENT = 'arkit-watch'
ARKitWrapper.STOP_EVENT = 'arkit-stop'
ARKitWrapper.ADD_ANCHOR_EVENT = 'arkit-add-anchor'
ARKitWrapper.RECORD_START_EVENT = 'arkit-record-start'
ARKitWrapper.RECORD_STOP_EVENT = 'arkit-record-stop'
ARKitWrapper.DID_MOVE_BACKGROUND_EVENT = 'arkit-did-move-background'
ARKitWrapper.WILL_ENTER_FOREGROUND_EVENT = 'arkit-will-enter-foreground'
ARKitWrapper.INTERRUPTED_EVENT = 'arkit-interrupted'
ARKitWrapper.INTERRUPTION_ENDED_EVENT = 'arkit-interruption-ended'
ARKitWrapper.HIT_TEST_EVENT = 'arkit-hit-test'
ARKitWrapper.SHOW_DEBUG_EVENT = 'arkit-show-debug'
// hit test types

Просмотреть файл

@ -83,7 +83,6 @@ export default class CameraReality extends Reality {
if(this._initialized === false){
this._initialized = true
this._arKitWrapper = ARKitWrapper.GetOrCreate()
this._arKitWrapper.addEventListener(ARKitWrapper.ADD_ANCHOR_EVENT, this._handleARKitAddObject.bind(this))
this._arKitWrapper.addEventListener(ARKitWrapper.WATCH_EVENT, this._handleARKitWatch.bind(this))
this._arKitWrapper.waitForInit().then(() => {
this._arKitWrapper.watch()
@ -138,8 +137,8 @@ export default class CameraReality extends Reality {
}
}
_handleARKitAddObject(ev){
this._updateAnchorFromARKitUpdate(ev.detail.uuid, ev.detail)
_handleARKitAddObject(anchorInfo){
this._updateAnchorFromARKitUpdate(anchorInfo.uuid, anchorInfo)
}
_updateAnchorFromARKitUpdate(uuid, anchorInfo){
@ -156,7 +155,9 @@ export default class CameraReality extends Reality {
// Convert coordinates to the stage coordinate system so that updating from ARKit transforms is simple
anchor.coordinates = anchor.coordinates.getTransformedCoordinates(display._stageCoordinateSystem)
if(this._arKitWrapper !== null){
this._arKitWrapper.addAnchor(anchor.uid, anchor.coordinates.poseMatrix)
this._arKitWrapper.addAnchor(anchor.uid, anchor.coordinates.poseMatrix).then(
detail => this._handleARKitAddObject(detail)
)
}
// ARCore as implemented in the browser does not offer anchors except on a surface, so we just use untracked anchors
this._anchors.set(anchor.uid, anchor)