@plattar/plattar-ar-adapter
Version:
Plattar AR Adapter for interfacing with Google & Apple WebAR
160 lines (159 loc) • 6.94 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SceneGraphAR = void 0;
const plattar_analytics_1 = require("@plattar/plattar-analytics");
const plattar_api_1 = require("@plattar/plattar-api");
const util_1 = require("../util/util");
const quicklook_viewer_1 = __importDefault(require("../viewers/quicklook-viewer"));
const scene_viewer_1 = __importDefault(require("../viewers/scene-viewer"));
const launcher_ar_1 = require("./launcher-ar");
const version_1 = __importDefault(require("../version"));
/**
* Performs AR functionality related to Plattar Scenes
*/
class SceneGraphAR extends launcher_ar_1.LauncherAR {
constructor(options) {
super();
// analytics instance
this._analytics = null;
this._options = options;
this._ar = null;
}
async _SetupAnalytics() {
const scene = new plattar_api_1.Scene(this._options.sceneID);
scene.include(plattar_api_1.Project);
const fetchedScene = await scene.get();
let analytics = null;
analytics = new plattar_analytics_1.Analytics(fetchedScene.attributes.application_id);
analytics.origin = plattar_api_1.Server.location().type;
this._analytics = analytics;
analytics.data.push("type", "scene-graph-ar");
analytics.data.push("sdkVersion", version_1.default);
analytics.data.push("sceneId", fetchedScene.id);
analytics.data.push("sceneTitle", fetchedScene.attributes.title);
const application = fetchedScene.relationships.find(plattar_api_1.Project);
// setup application stuff (if any)
if (application) {
analytics.data.push("applicationId", application.id);
analytics.data.push("applicationTitle", application.attributes.title);
if (this._options.useARBanner) {
this.options.banner = {
title: application.attributes.title,
subtitle: fetchedScene.attributes.title,
button: 'Visit'
};
}
}
return fetchedScene;
}
/**
* Composes a Scene into an AR Model (remote operation) that can be used to launch
* an AR File
*/
async _Compose(output) {
const type = output === 'glb' ? "viewer" : "reality";
const url = `https://xrutils.plattar.com/v3/scene/${this._options.sceneID}/${type}/${this._options.id}`;
// grab our existing scene-graph from the saved API
try {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json"
}
});
if (!response.ok) {
throw new Error(`ARAdapter - Fetching Existing Graph Error - network response was not ok ${response.status}`);
}
const data = await response.json();
return data.data.attributes.url;
}
catch (error) {
throw new Error(`ARAdapter - Fetching Existing Graph Error - there was a request error to ${url}, error was ${error.message}`);
}
}
/**
* Initialise the SceneAR instance. This returns a Promise that resolves
* successfully if initialisation is successful, otherwise it will fail.
*
* filure can occur for a number of reasons but it generally means that AR
* cannot be performed.
*/
async init() {
if (!util_1.Util.canAugment()) {
throw new Error("SceneGraphAR.init() - cannot proceed as AR not available in context");
}
const scene = await this._SetupAnalytics();
const sceneOpt = scene.attributes.custom_json || {};
// we need to define our AR module here
// we are in Safari/Quicklook mode here
if (util_1.Util.isSafari() || util_1.Util.isChromeOnIOS()) {
// we need to launch a VTO experience here
// VTO requires Reality Support
if (sceneOpt.anchor === "face") {
if (util_1.Util.canRealityViewer()) {
const modelUrl = await this._Compose("vto");
this._ar = new quicklook_viewer_1.default();
this._ar.modelUrl = modelUrl;
this._ar.banner = this.options.banner;
return this;
}
else {
throw new Error("SceneGraphAR.init() - cannot proceed as VTO AR requires Reality Viewer support");
}
}
// otherwise, load the USDZ stuff second if available
if (util_1.Util.canQuicklook()) {
const modelUrl = await this._Compose("usdz");
this._ar = new quicklook_viewer_1.default();
this._ar.modelUrl = modelUrl;
this._ar.banner = this.options.banner;
return this;
}
throw new Error("SceneGraphAR.init() - cannot proceed as IOS device does not support AR Mode");
}
// check android
if (util_1.Util.canSceneViewer()) {
const modelUrl = await this._Compose("glb");
const arviewer = new scene_viewer_1.default();
arviewer.modelUrl = modelUrl;
arviewer.isVertical = this.options.anchor === "vertical" ? true : false;
arviewer.banner = this.options.banner;
if (sceneOpt.anchor === "vertical") {
arviewer.isVertical = true;
}
this._ar = arviewer;
return this;
}
// otherwise, we didn't have AR available - it should never really reach this stage as this should be caught
// earlier in the process
throw new Error("SceneGraphAR.init() - could not initialise AR correctly, check values");
}
start() {
if (!this._ar) {
throw new Error("SceneGraphAR.start() - cannot proceed as AR instance is null");
}
const analytics = this._analytics;
if (analytics) {
analytics.data.push("device", this._ar.device);
analytics.data.push("eventCategory", this._ar.nodeType);
analytics.data.push("eventAction", "Start Scene Augment");
analytics.write();
analytics.startRecordEngagement();
}
// this was initialised via the init() function
this._ar.start();
}
canQuicklook() {
return this._ar && this._ar.nodeType === "Quick Look" ? true : false;
}
canRealityViewer() {
return this._ar && this._ar.nodeType === "Reality Viewer" ? true : false;
}
canSceneViewer() {
return this._ar && this._ar.nodeType === "Scene Viewer" ? true : false;
}
}
exports.SceneGraphAR = SceneGraphAR;