nativescript-ar
Version:
NativeScript Augmented Reality plugin. ARKit on iOS and (with the help of Sceneform) ARCore on Android.
572 lines (571 loc) • 25.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var application = require("tns-core-modules/application");
var utils = require("tns-core-modules/utils/utils");
var ar_common_1 = require("./ar-common");
var imagefragment_android_1 = require("./imagefragment.android");
var arbox_1 = require("./nodes/android/arbox");
var argroup_1 = require("./nodes/android/argroup");
var arimage_1 = require("./nodes/android/arimage");
var armodel_1 = require("./nodes/android/armodel");
var arplane_1 = require("./nodes/android/arplane");
var arsphere_1 = require("./nodes/android/arsphere");
var artube_1 = require("./nodes/android/artube");
var aruiview_1 = require("./nodes/android/aruiview");
var arvideo_1 = require("./nodes/android/arvideo");
var screengrab_android_1 = require("./screengrab-android");
var videorecorder_android_1 = require("./videorecorder.android");
var _fragment, _origin, _videoRecorder;
var AppPackageName = useAndroidX() ? global.androidx.core.app : android.support.v4.app;
var ContentPackageName = useAndroidX() ? global.androidx.core.content : android.support.v4.content;
function useAndroidX() {
return global.androidx && global.androidx.appcompat;
}
var addNode = function (options, parentNode) {
return new Promise(function (resolve, reject) {
argroup_1.ARGroup.create(options, _fragment)
.then(function (group) {
group.android.setParent(parentNode);
resolve(group);
}).catch(reject);
});
};
var addVideo = function (options, parentNode) {
return new Promise(function (resolve, reject) {
arvideo_1.ARVideo.create(options, _fragment)
.then(function (video) {
video.android.setParent(parentNode);
resolve(video);
}).catch(reject);
});
};
var addImage = function (options, parentNode) {
return new Promise(function (resolve, reject) {
arimage_1.ARImage.create(options, _fragment)
.then(function (image) {
image.android.setParent(parentNode);
resolve(image);
}).catch(reject);
});
};
var addPlane = function (options, parentNode) {
return new Promise(function (resolve, reject) {
arplane_1.ARPlane.create(options, _fragment)
.then(function (plane) {
plane.android.setParent(parentNode);
resolve(plane);
}).catch(reject);
});
};
var addModel = function (options, parentNode) {
return new Promise(function (resolve, reject) {
armodel_1.ARModel.create(options, _fragment)
.then(function (model) {
if (parentNode) {
model.android.setParent(parentNode);
}
resolve(model);
}).catch(reject);
});
};
var addBox = function (options, parentNode) {
return new Promise(function (resolve, reject) {
arbox_1.ARBox.create(options, _fragment)
.then(function (box) {
box.android.setParent(parentNode);
if (parentNode && parentNode.getRenderable()) {
parentNode.getRenderable().setRenderPriority(Math.max(0, box.android.getRenderable().getRenderPriority() - 1));
}
resolve(box);
}).catch(reject);
});
};
var addSphere = function (options, parentNode) {
return new Promise(function (resolve, reject) {
arsphere_1.ARSphere.create(options, _fragment)
.then(function (sphere) {
sphere.android.setParent(parentNode);
if (parentNode && parentNode.getRenderable()) {
parentNode.getRenderable().setRenderPriority(Math.max(0, sphere.android.getRenderable().getRenderPriority() - 1));
}
resolve(sphere);
}).catch(reject);
});
};
var addUIView = function (options, parentNode) {
return new Promise(function (resolve, reject) {
aruiview_1.ARUIView.create(options, _fragment)
.then(function (view) {
view.android.setParent(parentNode);
resolve(view);
}).catch(reject);
});
};
var addTube = function (options, parentNode) {
return new Promise(function (resolve, reject) {
artube_1.ARTube.create(options, _fragment)
.then(function (tube) {
tube.android.setParent(parentNode);
resolve(tube);
}).catch(reject);
});
};
var resolveParentNode = function (options) {
if (options.parentNode && options.parentNode.android) {
return options.parentNode.android;
}
return getOriginAnchor();
};
var getOriginAnchor = function () {
if (!_origin) {
var session = _fragment.getArSceneView().getSession();
var pose = com.google.ar.core.Pose.IDENTITY;
var anchor = session.createAnchor(pose);
var anchorNode = new com.google.ar.sceneform.AnchorNode(anchor);
anchorNode.setParent(_fragment.getArSceneView().getScene());
_origin = anchorNode;
}
return _origin;
};
var TNSArFragmentForFaceDetection = (function (_super) {
__extends(TNSArFragmentForFaceDetection, _super);
function TNSArFragmentForFaceDetection() {
var _this = _super.call(this) || this;
return global.__native(_this);
}
TNSArFragmentForFaceDetection.prototype.getSessionConfiguration = function (session) {
var config = new com.google.ar.core.Config(session);
config.setAugmentedFaceMode(com.google.ar.core.Config.AugmentedFaceMode.MESH3D);
return config;
};
TNSArFragmentForFaceDetection.prototype.getSessionFeatures = function () {
return java.util.EnumSet.of(com.google.ar.core.Session.Feature.FRONT_CAMERA);
};
TNSArFragmentForFaceDetection.prototype.onCreateView = function (inflater, container, savedInstanceState) {
var frameLayout = _super.prototype.onCreateView.call(this, inflater, container, savedInstanceState);
_super.prototype.getPlaneDiscoveryController.call(this).hide();
_super.prototype.getPlaneDiscoveryController.call(this).setInstructionView(null);
return frameLayout;
};
return TNSArFragmentForFaceDetection;
}(com.google.ar.sceneform.ux.ArFragment));
var ARImageTrackingActionsImpl = (function () {
function ARImageTrackingActionsImpl(anchor, planeNode) {
this.anchor = anchor;
this.planeNode = planeNode;
this.video;
}
ARImageTrackingActionsImpl.prototype.playVideo = function (url, loop) {
var _this = this;
addVideo({
dimensions: {
x: this.anchor.getExtentX(),
y: this.anchor.getExtentZ()
},
position: { x: 0, y: 0, z: 0 },
scale: 1 / this.planeNode.getLocalScale().x,
video: url,
loop: loop
}, this.planeNode).then(function (video) { return _this.video = video; }).catch(console.error);
};
ARImageTrackingActionsImpl.prototype.stopVideoLoop = function () {
if (this.video) {
this.video.pause();
}
};
ARImageTrackingActionsImpl.prototype.addBox = function (options) {
return addBox(options, this.planeNode);
};
ARImageTrackingActionsImpl.prototype.addModel = function (options) {
return addModel(options, this.planeNode);
};
ARImageTrackingActionsImpl.prototype.addImage = function (options) {
return addImage(options, this.planeNode);
};
ARImageTrackingActionsImpl.prototype.addUIView = function (options) {
return addUIView(options, this.planeNode);
};
ARImageTrackingActionsImpl.prototype.addNode = function (options) {
return addNode(options, this.planeNode);
};
return ARImageTrackingActionsImpl;
}());
var ARFaceTrackingActionsImpl = (function () {
function ARFaceTrackingActionsImpl(faceNode) {
this.faceNode = faceNode;
}
ARFaceTrackingActionsImpl.prototype.addModel = function (options) {
var _this = this;
return new Promise(function (resolve, reject) {
addModel(options)
.then(function (model) {
_this.faceNode.setParent(_fragment.getArSceneView().getScene());
_this.faceNode.setFaceRegionsRenderable(model.android.getRenderable());
resolve(model);
})
.catch(function (err) { return reject; });
});
};
ARFaceTrackingActionsImpl.prototype.addText = function (options) {
return Promise.reject("addText not implemented for ARFaceTrackingActions");
};
ARFaceTrackingActionsImpl.prototype.addUIView = function (options) {
return Promise.reject("addUIView not implemented for ARFaceTrackingActions");
};
return ARFaceTrackingActionsImpl;
}());
var AR = (function (_super) {
__extends(AR, _super);
function AR() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.faceNodeMap = new Map();
return _this;
}
AR.prototype.initNativeView = function () {
_super.prototype.initNativeView.call(this);
this.initAR();
};
AR.prototype.disposeNativeView = function () {
_super.prototype.disposeNativeView.call(this);
if (_origin) {
_origin.setParent(null);
_origin = null;
}
var supportFragmentManager = (application.android.foregroundActivity || application.android.startActivity).getSupportFragmentManager();
supportFragmentManager.beginTransaction().remove(_fragment).commit();
};
AR.prototype.getCameraPosition = function () {
var p = Array.create("float", 3);
_fragment.getArSceneView().getArFrame().getCamera().getPose().getTranslation(p, 0);
return { x: p[0], y: p[1], z: p[2] };
};
AR.prototype.getCameraRotation = function () {
var q1 = Array.create("float", 4);
_fragment.getArSceneView().getArFrame().getCamera().getPose().getRotationQuaternion(q1, 0);
var q = {
x: q1[2],
y: q1[0],
z: q1[1],
w: q1[3]
};
var rot = {
z: 0,
x: 0,
y: 0
};
var sinr_cosp = +2.0 * (q.w * q.x + q.y * q.z);
var cosr_cosp = +1.0 - 2.0 * (q.x * q.x + q.y * q.y);
rot.z = -(Math.atan2(sinr_cosp, cosr_cosp) + Math.PI / 2);
var sinp = +2.0 * (q.w * q.y - q.z * q.x);
if (Math.abs(sinp) >= 1) {
rot.x = -(sinp / Math.abs(sinp)) * (Math.PI / 2);
}
else {
rot.x = -Math.asin(sinp);
}
var siny_cosp = +2.0 * (q.w * q.z + q.x * q.y);
var cosy_cosp = +1.0 - 2.0 * (q.y * q.y + q.z * q.z);
rot.y = Math.atan2(siny_cosp, cosy_cosp) + Math.PI;
var toDeg = function (rad) {
return ((rad * (180.0 / Math.PI)) + 360) % 360;
};
return { x: toDeg(rot.x), y: toDeg(rot.y), z: toDeg(rot.z) };
};
AR.prototype.initAR = function () {
var _this = this;
this.nativeView.setId(android.view.View.generateViewId());
if (this.trackingMode === "FACE") {
_fragment = new TNSArFragmentForFaceDetection();
}
else {
if (this.trackingMode === "IMAGE") {
_fragment = new imagefragment_android_1.TNSArFragmentForImageDetection();
_fragment.getImageDetectionSceneView().then(function (sceneView) {
if (_this.trackingImagesBundle) {
_fragment.addImagesInFolder(_this.trackingImagesBundle);
}
var scene = sceneView.getScene();
var augmentedImages = [];
scene.addOnUpdateListener(new com.google.ar.sceneform.Scene.OnUpdateListener({
onUpdate: function (frameTime) {
var frame = sceneView.getArFrame();
if (frame == null) {
return;
}
var updatedAugmentedImages = frame.getUpdatedTrackables(com.google.ar.core.AugmentedImage.class).toArray();
for (var i = 0; i < updatedAugmentedImages.length; i++) {
var augmentedImage = updatedAugmentedImages[i];
var state = augmentedImage.getTrackingState();
if (state === com.google.ar.core.TrackingState.PAUSED) {
}
else if (state === com.google.ar.core.TrackingState.TRACKING) {
if (augmentedImages.indexOf(augmentedImage.getName()) === -1) {
var anchor = new com.google.ar.sceneform.AnchorNode(augmentedImage.createAnchor(augmentedImage.getCenterPose()));
augmentedImages.push(augmentedImage.getName());
scene.addChild(anchor);
var planeNode = new com.google.ar.sceneform.Node();
anchor.addChild(planeNode);
planeNode.setLocalRotation(new com.google.ar.sceneform.math.Quaternion(new com.google.ar.sceneform.math.Vector3(-90, 0, 0)));
var eventData = {
eventName: ar_common_1.AR.trackingImageDetectedEvent,
object: _this,
size: {
width: augmentedImage.getExtentX(),
height: augmentedImage.getExtentZ()
},
position: {
x: augmentedImage.getCenterPose().tx(),
y: augmentedImage.getCenterPose().ty(),
z: augmentedImage.getCenterPose().tz()
},
imageName: augmentedImage.getName(),
imageTrackingActions: new ARImageTrackingActionsImpl(augmentedImage, planeNode)
};
_this.notify(eventData);
}
}
else if (state === com.google.ar.core.TrackingState.STOPPED) {
var i_1 = augmentedImages.indexOf(augmentedImage.getName());
augmentedImages.splice(i_1, 1);
}
}
}
}));
}).catch(console.log);
}
else {
_fragment = new com.google.ar.sceneform.ux.ArFragment();
}
}
var onCamPermissionGranted = function () {
if (_this.trackingMode === "FACE") {
setTimeout(function () {
var sceneView = _fragment.getArSceneView();
if (!sceneView) {
return;
}
sceneView.setCameraStreamRenderPriority(com.google.ar.sceneform.rendering.Renderable.RENDER_PRIORITY_FIRST);
var scene = sceneView.getScene();
scene.addOnUpdateListener(new com.google.ar.sceneform.Scene.OnUpdateListener({
onUpdate: function (frameTime) {
var faceList = sceneView.getSession().getAllTrackables(com.google.ar.core.AugmentedFace.class);
for (var i = 0; i < faceList.size(); i++) {
var face = faceList.get(i);
if (!_this.faceNodeMap.has(face)) {
var faceNode = new com.google.ar.sceneform.ux.AugmentedFaceNode(face);
_this.faceNodeMap.set(face, faceNode);
var eventData = {
eventType: "FOUND",
eventName: ar_common_1.AR.trackingFaceDetectedEvent,
object: _this,
faceTrackingActions: new ARFaceTrackingActionsImpl(faceNode)
};
_this.notify(eventData);
}
else {
}
}
_this.faceNodeMap.forEach(function (node, face) {
if (face.getTrackingState() === com.google.ar.core.TrackingState.STOPPED) {
node.setParent(null);
_this.faceNodeMap.delete(node);
var eventData = {
eventType: "LOST",
eventName: ar_common_1.AR.trackingFaceDetectedEvent,
object: _this
};
_this.notify(eventData);
}
});
}
}));
}, 1000);
}
var supportFragmentManager = (application.android.foregroundActivity || application.android.startActivity).getSupportFragmentManager();
supportFragmentManager.beginTransaction().add(_this.nativeView.getId(), _fragment).commit();
_fragment.setOnTapArPlaneListener(new com.google.ar.sceneform.ux.BaseArFragment.OnTapArPlaneListener({
onTapPlane: function (hitResult, plane, motionEvent) {
var eventData = {
eventName: ar_common_1.AR.planeTappedEvent,
object: _this,
position: {
x: hitResult.getHitPose().tx(),
y: hitResult.getHitPose().ty(),
z: hitResult.getHitPose().tz()
}
};
_this.notify(eventData);
}
}));
_this.fireArLoadedEvent(1000);
};
var cameraPermission = android.Manifest.permission.CAMERA;
if (this.wasPermissionGranted(cameraPermission)) {
setTimeout(function () { return onCamPermissionGranted(); }, 0);
}
else {
this._requestPermission(cameraPermission, function () { return onCamPermissionGranted(); });
}
};
AR.prototype.fireArLoadedEvent = function (attemptsLeft) {
var _this = this;
if (attemptsLeft-- <= 0) {
return;
}
setTimeout(function () {
if (_fragment.getArSceneView() &&
_fragment.getArSceneView().getSession() &&
_fragment.getArSceneView().getArFrame() &&
_fragment.getArSceneView().getArFrame().getCamera() &&
_fragment.getArSceneView().getArFrame().getCamera().getTrackingState() === com.google.ar.core.TrackingState.TRACKING) {
var eventData = {
eventName: ar_common_1.AR.arLoadedEvent,
object: _this,
android: _fragment
};
_this.notify(eventData);
}
else {
_this.fireArLoadedEvent(attemptsLeft);
}
}, 300);
};
AR.isSupported = function () {
return true;
};
AR.prototype.getFragment = function () {
return _fragment;
};
Object.defineProperty(AR.prototype, "android", {
get: function () {
return this.nativeView;
},
enumerable: true,
configurable: true
});
AR.prototype.togglePlaneVisibility = function (to) {
_fragment.getArSceneView().getPlaneRenderer().setVisible(to);
};
AR.prototype.setPlaneDetection = function (to) {
};
AR.prototype.toggleStatistics = function (on) {
console.log("Method not implemented: toggleStatistics");
};
AR.prototype.setDebugLevel = function (to) {
console.log("Method not implemented: setDebugLevel");
};
AR.prototype.grabScreenshot = function () {
return (new screengrab_android_1.FragmentScreenGrab()).grabScreenshot(_fragment);
};
AR.prototype.startRecordingVideo = function () {
var _this = this;
return new Promise(function (resolve, reject) {
if (!_videoRecorder) {
_videoRecorder = videorecorder_android_1.VideoRecorder.fromFragment(_fragment);
}
else if (_videoRecorder.isRecording()) {
reject("already recording");
return;
}
var record = function () {
_videoRecorder.setVideoQualityAuto();
_videoRecorder.startRecordingVideo();
};
var permission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
if (!_this.wasPermissionGranted(permission)) {
_this._requestPermission(permission, record, reject);
return;
}
record();
resolve(true);
});
};
AR.prototype.stopRecordingVideo = function () {
return new Promise(function (resolve, reject) {
if (!(_videoRecorder && _videoRecorder.isRecording())) {
reject("not recording");
}
_videoRecorder.stopRecordingVideo();
resolve(_videoRecorder.getVideoPath());
});
};
AR.prototype.reset = function () {
console.log("Method not implemented: reset");
return null;
};
AR.prototype.addNode = function (options) {
return addNode(options, resolveParentNode(options));
};
AR.prototype.addVideo = function (options) {
return addVideo(options, resolveParentNode(options));
};
AR.prototype.addImage = function (options) {
return addImage(options, resolveParentNode(options));
};
AR.prototype.addModel = function (options) {
return addModel(options, resolveParentNode(options));
};
AR.prototype.addPlane = function (options) {
return addPlane(options, resolveParentNode(options));
};
AR.prototype.addBox = function (options) {
return addBox(options, resolveParentNode(options));
};
AR.prototype.addSphere = function (options) {
return addSphere(options, resolveParentNode(options));
};
AR.prototype.addText = function (options) {
return new Promise(function (resolve, reject) {
reject("Method not implemented: addText");
});
};
AR.prototype.addTube = function (options) {
return addTube(options, resolveParentNode(options));
};
AR.prototype.addUIView = function (options) {
return addUIView(options, resolveParentNode(options));
};
AR.prototype.trackImage = function (options) {
if (!(_fragment instanceof imagefragment_android_1.TNSArFragmentForImageDetection)) {
throw "On Android, this is only supported in trackingMode: IMAGE";
}
var name = options.name || options.image.split('/').pop().split('.').slice(0, -1).join('.');
_fragment.addImage(options.image, name, options.width || -1);
if (!options.onDetectedImage) {
return;
}
this.on(ar_common_1.AR.trackingImageDetectedEvent, function (args) {
if (args.imageName === options.image.split('/').pop().split('.').slice(0, -1).join('.')) {
options.onDetectedImage(args);
}
});
};
AR.prototype.wasPermissionGranted = function (permission) {
var hasPermission = android.os.Build.VERSION.SDK_INT < 23;
if (!hasPermission) {
hasPermission = android.content.pm.PackageManager.PERMISSION_GRANTED ===
ContentPackageName.ContextCompat.checkSelfPermission(utils.ad.getApplicationContext(), permission);
}
return hasPermission;
};
AR.prototype._requestPermission = function (permission, onPermissionGranted, reject) {
var permissionRequestCode = 678;
var onPermissionEvent = function (args) {
if (args.requestCode === permissionRequestCode) {
for (var i = 0; i < args.permissions.length; i++) {
if (args.grantResults[i] === android.content.pm.PackageManager.PERMISSION_DENIED) {
application.off(application.AndroidApplication.activityRequestPermissionsEvent, onPermissionEvent);
reject && reject("Please allow access to external storage and try again.");
return;
}
}
application.off(application.AndroidApplication.activityRequestPermissionsEvent, onPermissionEvent);
onPermissionGranted();
}
};
application.android.on(application.AndroidApplication.activityRequestPermissionsEvent, onPermissionEvent);
AppPackageName.ActivityCompat.requestPermissions(application.android.foregroundActivity || application.android.startActivity, [permission], permissionRequestCode);
};
return AR;
}(ar_common_1.AR));
exports.AR = AR;