@plattar/plattar-ar-adapter
Version:
Plattar AR Adapter for interfacing with Google & Apple WebAR
214 lines (211 loc) • 10.7 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.ProductAR = void 0;
const plattar_api_1 = require("@plattar/plattar-api");
const plattar_analytics_1 = require("@plattar/plattar-analytics");
const util_1 = require("../util/util");
const quicklook_viewer_1 = __importDefault(require("../viewers/quicklook-viewer"));
const reality_viewer_1 = __importDefault(require("../viewers/reality-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 Products and Variation types
*/
class ProductAR extends launcher_ar_1.LauncherAR {
/*
constructor(productID: string | undefined | null = null, variationID: string | undefined | null = null, variationSKU: string | undefined | null = null) {
super();
if (!productID) {
throw new Error("ProductAR.constructor(productID, variationID) - productID must be defined");
}
this._productID = productID;
this._variationSKU = variationSKU;
this._variationID = variationID ? variationID : (variationSKU ? null : "default");
this._ar = null;
}
*/
constructor(options) {
super();
// analytics instance
this._analytics = null;
if (!options.productID) {
throw new Error("ProductAR.constructor(productID, variationID) - productID must be defined");
}
this._options = options;
this._ar = null;
}
get productID() {
return this._options.productID;
}
get variationID() {
return this._options.variationID;
}
get variationSKU() {
return this._options.variationSKU;
}
_SetupAnalytics(product, variation) {
let analytics = null;
const scene = product.relationships.find(plattar_api_1.Scene);
// 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", "product-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: product.attributes.title,
subtitle: variation.attributes.title,
button: 'Visit'
};
}
}
}
if (analytics) {
// set product stuff
analytics.data.push("productId", product.id);
analytics.data.push("productTitle", product.attributes.title);
analytics.data.push("productSKU", product.attributes.sku);
// set variation stuff
analytics.data.push("variationId", variation.id);
analytics.data.push("variationTitle", variation.attributes.title);
analytics.data.push("variationSKU", variation.attributes.sku);
}
}
/**
* Initialise the ProductAR 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("ProductAR.init() - cannot proceed as AR not available in context"));
}
const product = new plattar_api_1.Product(this.productID);
product.include(plattar_api_1.ProductVariation);
product.include(plattar_api_1.ProductVariation.include(plattar_api_1.FileModel));
product.include(plattar_api_1.Scene);
product.include(plattar_api_1.Scene.include(plattar_api_1.Project));
product.get().then((product) => {
// find the required variation from our product
const variationID = this.variationID ? (this.variationID === "default" ? product.attributes.product_variation_id : this.variationID) : null;
const variationSKU = this.variationSKU;
if (!variationID && !variationSKU) {
return reject(new Error("ProductAR.init() - cannot proceed as variation-id or variation-sku was not set correctly"));
}
let variation = undefined;
if (variationID) {
variation = product.relationships.find(plattar_api_1.ProductVariation, variationID);
}
// if no variation was found with variationID - try searching variation sku
if (!variation && variationSKU) {
const variations = product.relationships.filter(plattar_api_1.ProductVariation);
if (variations) {
variation = variations.find((element) => {
return element.attributes.sku === variationSKU;
});
}
}
// make sure our variation is actually available before moving forward
if (!variation) {
return reject(new Error("ProductAR.init() - cannot proceed as variation with id " + variationID + " or sku " + variationSKU + " cannot be found"));
}
// otherwise both the product and variation are available
// we need to figure out if we can actually do AR though
// check if variation has a model file defined
const modelID = variation.attributes.file_model_id;
if (!modelID) {
return reject(new Error("ProductAR.init() - cannot proceed as variation does not have a defined file"));
}
// find the actual FileModel from Variation
const model = variation.relationships.find(plattar_api_1.FileModel, modelID);
if (!model) {
return reject(new Error("ProductAR.init() - cannot proceed as ModelFile for selected variation is corrupt"));
}
this._SetupAnalytics(product, variation);
// we need to define our AR module here
// we are in Safari/Quicklook mode here
if (util_1.Util.isSafari() || util_1.Util.isChromeOnIOS()) {
// model needs to have either USDZ or REALITY files defined
// we load REALITY stuff first if available
if (model.attributes.reality_filename && util_1.Util.canRealityViewer()) {
this._ar = new reality_viewer_1.default();
this._ar.modelUrl = plattar_api_1.Server.location().cdn + model.attributes.path + model.attributes.reality_filename;
this._ar.banner = this.options.banner;
return accept(this);
}
// otherwise, load the USDZ stuff second if available
if (model.attributes.usdz_filename && util_1.Util.canQuicklook()) {
this._ar = new quicklook_viewer_1.default();
this._ar.modelUrl = plattar_api_1.Server.location().cdn + model.attributes.path + model.attributes.usdz_filename;
this._ar.banner = this.options.banner;
return accept(this);
}
return reject(new Error("ProductAR.init() - cannot proceed as ModelFile does not have a defined .usdz or .reality file"));
}
// check android
if (util_1.Util.canSceneViewer()) {
const arviewer = new scene_viewer_1.default();
arviewer.modelUrl = plattar_api_1.Server.location().cdn + model.attributes.path + model.attributes.original_filename;
arviewer.isVertical = this.options.anchor === "vertical" ? true : false;
arviewer.banner = this.options.banner;
const scene = product.relationships.find(plattar_api_1.Scene);
if (scene) {
const sceneOpt = scene.attributes.custom_json || {};
if (sceneOpt.anchor === "vertical") {
arviewer.isVertical = true;
}
}
this._ar = arviewer;
return accept(this);
}
// 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("ProductAR.init() - could not initialise AR correctly, check values"));
}).catch(reject);
});
}
/**
* Launches the internal AR instance using an appropriate version of AR Viewers
*/
start() {
if (!this._ar) {
throw new Error("ProductAR.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 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.ProductAR = ProductAR;