UNPKG

@plattar/plattar-ar-adapter

Version:

Plattar AR Adapter for interfacing with Google & Apple WebAR

210 lines (209 loc) 10.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SceneAR = void 0; const plattar_analytics_1 = require("@plattar/plattar-analytics"); const plattar_api_1 = require("@plattar/plattar-api"); const plattar_services_1 = require("@plattar/plattar-services"); 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 SceneAR extends launcher_ar_1.LauncherAR { constructor(options) { super(); // analytics instance this._analytics = null; if (!options.sceneID) { throw new Error("SceneAR.constructor(sceneID) - sceneID must be defined"); } this._options = options; this._ar = null; } get sceneID() { return this._options.sceneID; } _SetupAnalytics(scene) { let analytics = null; // setup scene stuff (if any) if (scene) { analytics = new plattar_analytics_1.Analytics(scene.attributes.application_id); analytics.origin = plattar_api_1.Server.location().type; this._analytics = analytics; analytics.data.push("type", "scene-ar"); analytics.data.push("sdkVersion", version_1.default); analytics.data.push("sceneId", scene.id); analytics.data.push("sceneTitle", scene.attributes.title); const application = scene.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: scene.attributes.title, button: 'Visit' }; } } } } /** * Composes a Scene into an AR Model (remote operation) that can be used to launch * an AR File */ _ComposeScene(scene, output) { return new Promise((accept, reject) => { const sceneProducts = scene.relationships.filter(plattar_api_1.SceneProduct); const sceneModels = scene.relationships.filter(plattar_api_1.SceneModel); // nothing to do if no AR components can be found if ((sceneProducts.length + sceneModels.length) <= 0) { return reject(new Error("SceneAR.ComposeScene() - cannot proceed as scene does not contain AR components")); } // define our configurator const configurator = new plattar_services_1.Configurator(); configurator.server = plattar_api_1.Server.location().type; configurator.output = output; let totalARObjectCount = 0; // add our scene products sceneProducts.forEach((sceneProduct) => { const product = sceneProduct.relationships.find(plattar_api_1.Product); const selection = this._options.variationSelection; // we have a specific product selection if (sceneProduct.attributes.include_in_augment) { // check if this product is the one we want (from selection optionally) if (product && (product.id === selection.productID) && selection.variationID) { configurator.addSceneProduct(sceneProduct.id, selection.variationID); totalARObjectCount++; } else if (product) { // check if this scene-product is the one we want (from selection) if ((sceneProduct.id === selection.sceneProductID) && selection.variationID) { configurator.addSceneProduct(sceneProduct.id, selection.variationID); totalARObjectCount++; } else if (product.attributes.product_variation_id) { configurator.addSceneProduct(sceneProduct.id, product.attributes.product_variation_id); totalARObjectCount++; } } } }); // add our scene models sceneModels.forEach((sceneModel) => { if (sceneModel.attributes.include_in_augment) { configurator.addModel(sceneModel.id); totalARObjectCount++; } }); // ensure we have actually added AR objects if (totalARObjectCount <= 0) { return reject(new Error("SceneAR.ComposeScene() - cannot proceed as scene does not contain any enabled AR components")); } return configurator.get().then((result) => { accept(result.filename); }).catch(reject); }); } /** * 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. */ init() { return new Promise((accept, reject) => { if (!util_1.Util.canAugment()) { return reject(new Error("SceneAR.init() - cannot proceed as AR not available in context")); } const scene = new plattar_api_1.Scene(this.sceneID); scene.include(plattar_api_1.Project); scene.include(plattar_api_1.SceneProduct); scene.include(plattar_api_1.SceneProduct.include(plattar_api_1.Product)); scene.include(plattar_api_1.SceneModel); scene.get().then((scene) => { this._SetupAnalytics(scene); 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()) { return this._ComposeScene(scene, "vto").then((modelUrl) => { this._ar = new quicklook_viewer_1.default(); this._ar.modelUrl = modelUrl; this._ar.banner = this.options.banner; return accept(this); }).catch(reject); } else { return reject(new Error("SceneAR.init() - cannot proceed as VTO AR requires Reality Viewer support")); } } // otherwise, load the USDZ stuff second if available if (util_1.Util.canQuicklook()) { return this._ComposeScene(scene, "usdz").then((modelUrl) => { this._ar = new quicklook_viewer_1.default(); this._ar.modelUrl = modelUrl; this._ar.banner = this.options.banner; return accept(this); }).catch(reject); } return reject(new Error("SceneAR.init() - cannot proceed as IOS device does not support AR Mode")); } // check android if (util_1.Util.canSceneViewer()) { return this._ComposeScene(scene, "glb").then((modelUrl) => { 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 accept(this); }).catch(reject); } // otherwise, we didn't have AR available - it should never really reach this stage as this should be caught // earlier in the process return reject(new Error("SceneAR.init() - could not initialise AR correctly, check values")); }).catch(reject); }); } start() { if (!this._ar) { throw new Error("SceneAR.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.SceneAR = SceneAR;