(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jiboAnimDb = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o matchingNoDupes.push(elm)); res.matching = matchingNoDupes; let nonMatchingNoDupes = []; new Set(res.nonMatching).forEach(elm => nonMatchingNoDupes.push(elm)); res.nonMatching = nonMatchingNoDupes; return res; } _search(term, res) { let catByName = this._categoriesByName.get(term); if (catByName) { res.category = catByName; } let animByName = this._animationsByName.get(term); if (animByName) { res.name = animByName; } this.animations.forEach(anim => { anim.meta.metaTerms.forEach(meta => { if (meta === term) { res.meta.push(anim); } }); }); } _query(query, res) { if (query.categories.length) { query.categories.forEach(catName => { let category = this._categoriesByName.get(catName); if (category) { category._query(query, res); } }); } else { Utils_1.Utils.getAnimationsByQuery(this.animations, res, query); } } } exports.AnimCollection = AnimCollection; },{"./AnimUtils":4,"./Classes":7,"./Utils":10}],2:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Classes_1 = require("./Classes"); const AnimUtils_1 = require("./AnimUtils"); class AnimDB { constructor(jibo) { this.collections = []; this.jibo = jibo; } push(animCollection) { this.collections.push(animCollection); } pop() { return this.collections.pop(); } getAnimByName(animName) { let anim; for (let i = 0; i < this.collections.length; i++) { let animDB = this.collections[i]; let a = animDB.getAnimByName(animName); if (a) { anim = a; break; } } return anim; } getAnimationNames() { let names = []; for (let i = 0; i < this.collections.length; i++) { names = names.concat(this.collections[i].getAnimationNames()); } return names; } getAnimationCategories() { let names = []; for (let i = 0; i < this.collections.length; i++) { names = names.concat(this.collections[i].getAnimationCategories()); } return names; } search(searchTerm) { let term = searchTerm.toLowerCase(); let res = new Classes_1.SearchResults(); this.collections.forEach(animColl => { animColl._search(term, res); }); return res; } query(query) { AnimUtils_1.AnimUtils.insertDefaultAnimQueryParams(query); let res = new Classes_1.AnimResults(); this.collections.forEach(animColl => { animColl._query(query, res); }); let matchingNoDupes = []; new Set(res.matching).forEach(elm => matchingNoDupes.push(elm)); res.matching = matchingNoDupes; let nonMatchingNoDupes = []; new Set(res.nonMatching).forEach(elm => nonMatchingNoDupes.push(elm)); res.nonMatching = nonMatchingNoDupes; return res; } } exports.AnimDB = AnimDB; },{"./AnimUtils":4,"./Classes":7}],3:[function(require,module,exports){ "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); const fs = require("fs"); const jibo_cai_utils_1 = require("jibo-cai-utils"); const AnimDB_1 = require("./AnimDB"); const AnimCollection_1 = require("./AnimCollection"); const Animation_1 = require("./Animation"); const Category_1 = require("./Category"); const AnimUtils_1 = require("./AnimUtils"); const Utils_1 = require("./Utils"); const Classes_1 = require("./Classes"); const Range_1 = require("./Range"); const stringify = require('json-stable-stringify'); class AnimDBParser { static readAnimDB(jibo, animDBPath, ...moreAnimDBPaths) { moreAnimDBPaths.unshift(animDBPath); let animDB = new AnimDB_1.AnimDB(jibo); let promises = moreAnimDBPaths.map((rootDir) => { return AnimDBParser.readAndAddAnimCollection(animDB, rootDir); }); return Promise.all(promises) .then(() => animDB); } static readAndAddAnimCollection(animDB, animDBPath) { const rootDir = path.dirname(animDBPath); return jibo_cai_utils_1.FileUtils.readFile(animDBPath) .then(animStr => { const animMetaMap = JSON.parse(animStr); AnimDBParser.addAnimCollection(animDB, rootDir, animMetaMap); }); } static addAnimCollection(animDB, rootDir, animMetaMap) { let collection = new AnimCollection_1.AnimCollection(animDB); AnimDBParser.addToAnimCollection(collection, rootDir, animMetaMap); animDB.push(collection); } static addToAnimCollection(collection, rootDir, animMetadataCollection) { let kvAnimMetaArray; if (animMetadataCollection instanceof Array) { kvAnimMetaArray = animMetadataCollection; } else { kvAnimMetaArray = []; Object.keys(animMetadataCollection).forEach(key => { kvAnimMetaArray.push([key, animMetadataCollection[key]]); }); } for (let [animName, animMeta] of kvAnimMetaArray) { if (!animMeta.name) { throw new Error(`Missing anim name: ${animName}`); } animName = animMeta.name.toLowerCase(); const anim = new Animation_1.Animation(collection, animMeta, rootDir); let existingAnim = collection.getAnimByName(anim.name); if (existingAnim) { const paths = [existingAnim.meta.path, animMeta.path]; throw new Error(`Duplicate animation name: '${animName}' at paths: ${paths}`); } collection.addAnimation(anim); anim.meta.categories.forEach(categoryName => { let cat = collection.getCategoryByName(categoryName); if (!cat) { cat = new Category_1.Category(categoryName); collection.addCategory(cat); } cat.addAnimation(anim); }); } } static createAndWriteAnimMetaData(jibo, rootDir, outName) { return AnimDBParser.createAnimMetaData(jibo, rootDir) .then(allAnimData => { const outPath = path.join(rootDir, outName + '.json'); const outData = stringify(allAnimData, { space: ' ' }); return jibo_cai_utils_1.PromiseUtils.promisify(h => fs.writeFile(outPath, outData, 'utf8', h)); }); } static createAnimMetaData(jibo, rootDir) { const animsDir = path.join(rootDir, 'animations'); return jibo_cai_utils_1.FileUtils.findAllFilesWithExt(animsDir, 'keys') .then((filePaths) => { const goodPaths = filePaths.filter(filePath => { const relFilePath = path.relative(animsDir, filePath); const pathElements = relFilePath.split(path.sep); return !pathElements.some(el => el.startsWith('_')); }); return AnimDBParser._createAnimMetaData(jibo, rootDir, goodPaths); }); } static _createAnimMetaData(jibo, rootDir, paths) { return __awaiter(this, void 0, void 0, function* () { let cachedAnimDB = jibo.animDB._animDB; jibo.animDB._animDB = new AnimDB_1.AnimDB(jibo); let collection = new AnimCollection_1.AnimCollection(jibo.animDB._animDB); jibo.animDB.push(collection); let completeMetadata = {}; let unparsed = []; let parsed = []; while (paths.length > 0) { const unparsedCount = paths.length; for (const path of paths) { try { const meta = yield AnimDBParser.parseAnimation(jibo, path, rootDir); parsed.push(meta); } catch (err) { if (err instanceof ReferenceError) { unparsed.push(path); } else { throw err; } } } if (unparsedCount === unparsed.length) { throw new Error(`Could not resolve ${unparsedCount} animations: ${unparsed}`); } else { paths = unparsed; } const rootDirResolved = path.resolve(rootDir); let kvAnimMetaArray = []; parsed.forEach(animData => { const firstPart = animData.path.substring(0, rootDirResolved.length); if (firstPart !== rootDirResolved) { throw new Error(`Animation doesn't have the expected root path: ${[animData.path, rootDirResolved]}`); } animData.path = animData.path.substring(rootDirResolved.length + path.sep.length); kvAnimMetaArray.push([animData.name, animData]); }); AnimDBParser.addToAnimCollection(collection, rootDir, kvAnimMetaArray); let tempAnimMetaMap = {}; kvAnimMetaArray.forEach(([key, value]) => { tempAnimMetaMap[key] = value; }); Object.assign(completeMetadata, tempAnimMetaMap); parsed = []; unparsed = []; } jibo.animDB._animDB = cachedAnimDB; return completeMetadata; }); } static parseAnimation(jibo, filePath, rootDir) { return __awaiter(this, void 0, void 0, function* () { const animData = yield AnimDBParser.loadKeys(jibo, filePath, rootDir); return AnimDBParser.parseAnimationFromAnim(animData, filePath); }); } static loadKeys(jibo, keysPath, rootDir) { return __awaiter(this, void 0, void 0, function* () { return new jibo.rendering.animation.KeysLoader(keysPath, rootDir).load(); }); } static parseAnimationFromAnim(animData, filePath) { let animdbTag; let scale, speed, name; try { const defaultName = filePath ? path.basename(filePath, path.extname(filePath)) : 'UNKNOWN_ANIM'; animdbTag = animData.animdb || {}; name = Utils_1.Utils.parseString(animdbTag.name, defaultName); scale = [ Utils_1.Utils.parseNumber(animdbTag.scaleMin, 1), Utils_1.Utils.parseNumber(animdbTag.scaleMax, 1) ]; speed = [ Utils_1.Utils.parseNumber(animdbTag.speedMin, 1), Utils_1.Utils.parseNumber(animdbTag.speedMax, 1) ]; } catch (error) { throw new Error(`Error parsing animation at path '${filePath}': '${error}'`); } if ((speed[0] <= 0) || (speed[0] > speed[1])) { throw new Error(`Invalid speed bounds '${JSON.stringify(speed)}' for animation '${filePath}'`); } if (scale[0] > scale[1]) { throw new Error(`Invalid scale bounds '${JSON.stringify(scale)}' for animation '${filePath}'`); } const categoryString = animdbTag.categories || ''; let categories = []; categoryString.split(',').forEach(category => { let catName = category.trim().toLowerCase(); if (catName.length) { categories.push(catName); } }); const metaString = animdbTag.meta || ''; let metaTerms = []; metaString.split(',').forEach(_metaTerm => { let metaName = _metaTerm.trim().toLowerCase(); if (metaName.length) { metaTerms.push(metaName); } }); const holdSafeKF = AnimUtils_1.AnimUtils.hasHoldSafe(animData, name); let durationRange = [ speed[0] * animData.duration, speed[1] * animData.duration ]; if (holdSafeKF !== -1) { durationRange[1] = Range_1.INFINITE_DURATION; } let layers = AnimUtils_1.AnimUtils.checkLayers(animData); if (metaTerms.indexOf(AnimUtils_1.AUDIO_ONLY_META) !== -1) { Object.keys(layers).forEach(layer => { if (layers[layer] && (layer !== Classes_1.LayerName.AudioEvent.short)) { layers[layer] = false; } }); } const animMetadata = { name, scale, speed, durationRange, categories, metaTerms, holdSafeKF, path: filePath, duration: animData.duration, startsNeutral: AnimUtils_1.AnimUtils.startsNeutral(animData), endsNeutral: AnimUtils_1.AnimUtils.endsNeutral(animData), hasAudio: AnimUtils_1.AnimUtils.hasAudio(animData), orientation: AnimUtils_1.AnimUtils.calculateOrientation(animData), layers }; return animMetadata; } } exports.AnimDBParser = AnimDBParser; },{"./AnimCollection":1,"./AnimDB":2,"./AnimUtils":4,"./Animation":5,"./Category":6,"./Classes":7,"./Range":9,"./Utils":10,"fs":undefined,"jibo-cai-utils":undefined,"json-stable-stringify":undefined,"path":undefined}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Classes_1 = require("./Classes"); const LayerMocks_1 = require("./animation_formats/LayerMocks"); const BODY_ANGLE_EPSILON = 3; const HOLD_SAFE_EVENT_NAME = 'HOLD_SAFE'; exports.AUDIO_ONLY_META = "audio-only"; class AnimUtils { static _addMockLayer(animData, type) { animData.layers.push(LayerMocks_1.LayerTemplate.generateLayer(type, type)); } static scaleTimeInPlace(animData, scale) { animData.layers.forEach((layer) => { layer.keyframes.forEach(kf => { kf.time = Math.round(kf.time * scale); }); }); animData.duration = Math.round(animData.duration * scale); } static scaleBodyInPlace(animData, scale) { AnimUtils.forEachLayerType(animData, Classes_1.LayerName.Body, (layer) => { layer.keyframes.forEach(kf => { kf.value.Head *= scale; kf.value.Pelvis *= scale; kf.value.Torso *= scale; }); }); } static flipScreenLeftRight(animData) { let handler = (layer) => { layer.keyframes.forEach(kf => { kf.value.Translate.x *= -1; }); }; AnimUtils.forEachLayerType(animData, Classes_1.LayerName.Eye, handler); AnimUtils.forEachLayerType(animData, Classes_1.LayerName.Overlay, handler); } static startsNeutral(animData) { let ret = true; let earliestFrame = animData.duration; AnimUtils.forEachLayerType(animData, Classes_1.LayerName.Body, (layer) => { if (layer.keyframes.length) { let kf = layer.keyframes[0]; if (kf.time < earliestFrame) { earliestFrame = kf.time; if (Math.abs(kf.value.Pelvis) > BODY_ANGLE_EPSILON || Math.abs(kf.value.Head) > BODY_ANGLE_EPSILON || Math.abs(kf.value.Torso) > BODY_ANGLE_EPSILON) { ret = false; } } } }); return ret; } static endsNeutral(animData) { let ret = true; let latestTime = -1; AnimUtils.forEachLayerType(animData, Classes_1.LayerName.Body, (layer) => { if (layer.keyframes.length) { let kf = layer.keyframes[layer.keyframes.length - 1]; if (kf.time > latestTime) { latestTime = kf.time; if (Math.abs(kf.value.Pelvis) > BODY_ANGLE_EPSILON || Math.abs(kf.value.Head) > BODY_ANGLE_EPSILON || Math.abs(kf.value.Torso) > BODY_ANGLE_EPSILON) { ret = false; } } } }); return ret; } static checkLayers(animData, strict = true) { let layerPresence = {}; Classes_1.LayerName.Layers.forEach(layerName => { if (AnimUtils.hasLayer(animData, layerName, strict)) { layerPresence[layerName.short] = true; } }); return layerPresence; } static hasAudio(animData) { return AnimUtils.hasLayer(animData, Classes_1.LayerName.AudioEvent); } static hasLayer(animData, layerName, strict = true) { let layerCheck = []; AnimUtils.forEachLayerType(animData, layerName, (layer) => { if (strict) { layerCheck.push(layer.visible && (layer.keyframes.length !== 0)); } else { layerCheck.push(true); } }); return layerCheck.some(hasContent => hasContent); } static hasHoldSafe(animData, name) { let kf = -1; AnimUtils.forEachLayerType(animData, Classes_1.LayerName.Event, (layer) => { layer.keyframes.forEach(layerKF => { if (layerKF.value.Event.name === HOLD_SAFE_EVENT_NAME) { if (kf !== -1) { throw new Error(`Two HOLD_SAFE keyframes defined in animation` + ` '${name}' at frames ${kf} and ${layerKF.time}`); } kf = layerKF.time; } }); }); return kf; } static calculateOrientation(animData) { let headSum = 0; let pelvisSum = 0; let torsoSum = 0; let numFrames = 0; AnimUtils.forEachLayerType(animData, Classes_1.LayerName.Body, (layer) => { layer.keyframes.forEach(layerKF => { numFrames++; headSum += layerKF.value.Head; pelvisSum += layerKF.value.Pelvis; torsoSum += layerKF.value.Torso; }); }); headSum /= numFrames; pelvisSum /= numFrames; torsoSum /= numFrames; let bodySum = (torsoSum + pelvisSum) / 2; if (Math.abs(bodySum) > 10) { return (bodySum > 0) ? Classes_1.Orientation.LEFT : Classes_1.Orientation.RIGHT; } else { return (headSum > 0) ? Classes_1.Orientation.LEFT : Classes_1.Orientation.RIGHT; } } static forEachLayerType(animData, layerTypeName, handler) { let name = layerTypeName.long || layerTypeName.short; animData.layers.forEach(layer => { if (layer.type === name) { handler(layer); } }); } static insertDefaultAnimQueryParams(query) { if (!query.categories) { query.categories = []; } if (query.category) { query.categories.push(query.category); } for (let i = 0; i < query.categories.length; i++) { query.categories[i] = query.categories[i].toLowerCase(); } query.includeCat = query.includeCat || []; query.includeSomeCat = query.includeSomeCat || []; query.excludeCat = query.excludeCat || []; query.includeMeta = query.includeMeta || []; query.includeSomeMeta = query.includeSomeMeta || []; query.excludeMeta = query.excludeMeta || []; const filters = [query.includeCat, query.includeSomeCat, query.excludeCat, query.includeMeta, query.includeSomeMeta, query.excludeMeta]; filters.forEach(array => { for (let i = 0; i < array.length; i++) { array[i] = array[i].toLowerCase(); } }); if (!query.durationError) { query.durationError = 0; } if (!query.duration) { query.duration = -1; } if (typeof query.hasAudio === 'undefined') { query.hasAudio = Classes_1.HasAudio.DONT_CARE; } } } exports.AnimUtils = AnimUtils; },{"./Classes":7,"./animation_formats/LayerMocks":12}],5:[function(require,module,exports){ "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const Range_1 = require("./Range"); const Utils_1 = require("./Utils"); const Playback_1 = require("./Playback"); const Classes_1 = require("./Classes"); const log_1 = require("./log"); const log = log_1.default.createChild("Animation"); class Animation { constructor(parent, meta, resourceRoot, animData) { this.parent = parent; this.meta = meta; this.resourceRoot = resourceRoot; this.animData = animData; this.animDataCache = {}; this.name = meta.name; this.durationRange = new Range_1.Range(meta.durationRange[0], meta.durationRange[1]); } createFromConfig(config = { cache: null }) { return __awaiter(this, void 0, void 0, function* () { log.debug(`Configuring Animation ${this.name} for configuration: `, config); let transformation = this._getTransformation(config); const playback = new Playback_1.Playback(transformation, config.cache, this); return playback.init(config); }); } play(config = { cache: null }, options) { log.debug(`Configuring Animation ${this.name} with config: `, config, ` for immediate playback with options: `, options); let transformation = this._getTransformation(config); const playback = new Playback_1.Playback(transformation, config.cache, this); return { playback: playback, result: playback.initAndPlay(config, options) }; } _getTransformation(options) { let trans = new Classes_1.Transform(); if (options) { if (options.orientation) { let reqOrientation = options.orientation; if (reqOrientation !== this.meta.orientation) { trans.shouldFlipLeftRight = true; } } if (options.speed) { trans.speed = Utils_1.Utils.limitToRange(options.speed, this.meta.speed); } if (options.exaggerate) { trans.exaggerate = Utils_1.Utils.limitToRange(options.exaggerate, this.meta.scale); } if (options.duration) { if (options.duration < this.meta.durationRange[0]) { trans.speed = this.meta.speed[0]; } else if (options.duration < trans.speed * this.meta.duration) { trans.speed = options.duration / this.meta.duration; trans.speed = Utils_1.Utils.limitToRange(trans.speed, this.meta.speed); } else if (this.meta.holdSafeKF !== -1) { trans.framesToHold = options.duration - trans.speed * this.meta.duration; } else if (options.duration > trans.speed * this.meta.duration) { if (typeof options.speed !== 'number') { trans.speed = options.duration / this.meta.duration; trans.speed = Utils_1.Utils.limitToRange(trans.speed, this.meta.speed); } } } } return trans; } } exports.Animation = Animation; },{"./Classes":7,"./Playback":8,"./Range":9,"./Utils":10,"./log":15}],6:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Utils_1 = require("./Utils"); const AnimUtils_1 = require("./AnimUtils"); const Classes_1 = require("./Classes"); class Category { constructor(name) { this.name = name; this.animations = []; this.animationsByName = new Map(); } addAnimation(anim) { this.animations.push(anim); this.animationsByName.set(anim.name, anim); } query(query) { AnimUtils_1.AnimUtils.insertDefaultAnimQueryParams(query); let res = new Classes_1.AnimResults(); this._query(query, res); return res; } _query(query, res) { Utils_1.Utils.getAnimationsByQuery(this.animations, res, query); } } exports.Category = Category; },{"./AnimUtils":4,"./Classes":7,"./Utils":10}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class Transform { constructor() { this.framesToHold = -1; this.speed = 1; this.exaggerate = 1; this.shouldFlipLeftRight = false; } } exports.Transform = Transform; var Orientation; (function (Orientation) { Orientation["LEFT"] = "LEFT"; Orientation["RIGHT"] = "RIGHT"; })(Orientation = exports.Orientation || (exports.Orientation = {})); var HasAudio; (function (HasAudio) { HasAudio["YES"] = "YES"; HasAudio["NO"] = "NO"; HasAudio["DONT_CARE"] = "DONT_CARE"; })(HasAudio = exports.HasAudio || (exports.HasAudio = {})); class AnimResults { constructor() { this.matching = []; this.nonMatching = []; } } exports.AnimResults = AnimResults; class SearchResults { constructor() { this.meta = []; } } exports.SearchResults = SearchResults; class LayerName { constructor(short, long) { this.short = short; this.long = long; } } LayerName.Body = new LayerName('Body'); LayerName.Eye = new LayerName('Eye'); LayerName.EyeTexture = new LayerName('EyeTexture', 'Eye Texture'); LayerName.Overlay = new LayerName('Overlay'); LayerName.OverlayTexture = new LayerName('OverlayTexture', 'Overlay Texture'); LayerName.AudioEvent = new LayerName('AudioEvent', 'Audio Event'); LayerName.Event = new LayerName('Event'); LayerName.Pixi = new LayerName('Pixi'); LayerName.BackgroundTexture = new LayerName('BackgroundTexture', 'Background Texture'); LayerName.LED = new LayerName('LED'); LayerName.Layers = [ LayerName.Body, LayerName.Eye, LayerName.EyeTexture, LayerName.Overlay, LayerName.OverlayTexture, LayerName.AudioEvent, LayerName.Event, LayerName.Pixi, LayerName.BackgroundTexture, LayerName.LED ]; exports.LayerName = LayerName; var BuilderLayer; (function (BuilderLayer) { BuilderLayer["BEAT"] = "beat"; BuilderLayer["DEFAULT"] = "default"; BuilderLayer["POSTURE"] = "posture"; })(BuilderLayer = exports.BuilderLayer || (exports.BuilderLayer = {})); },{}],8:[function(require,module,exports){ "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const uuid = require("uuid"); const path = require("path"); const events = require("events"); const jibo_cai_utils_1 = require("jibo-cai-utils"); const jibo_expression_client_1 = require("jibo-expression-client"); const Classes_1 = require("./Classes"); const AnimUtils_1 = require("./AnimUtils"); const log_1 = require("./log"); const log = log_1.default.createChild("Playback"); const FRAMERATE = 30; const defaultOptions = { ownerInformation: 'AnimDB', disableSetFaceAnim: false, screenCenterOverride: true }; class ExtPromise { constructor() { this.promise = new Promise((res, rej) => { this.resolve = res; this.reject = rej; }); } } class Playback extends events.EventEmitter { constructor(transform, cacheName, animation) { super(); this.transform = transform; this.cacheName = cacheName; this.animation = animation; this.runtimeKeys = false; this.holdSafeDuration = 0; this.runtimeKeys = !this.animation.meta.path; this.jibo = this.animation.parent.parent.jibo; } init(config) { return __awaiter(this, void 0, void 0, function* () { this._init(config); this.keysAnimation = yield this.loadAnimation(); this.instance = this.keysAnimation.instance; log.debug(`Initialized playback ${this.animation.name}`); return this; }); } initAndPlay(config, options) { return __awaiter(this, void 0, void 0, function* () { this.playExtPr = new ExtPromise(); this._init(config); this.resolvePlaybackOptions(options); this.keysAnimation = yield this.loadAnimation(true); this.instance = this.keysAnimation.instance; this.registerEventsAndHandlers(); const state = yield this.playExtPr.promise; yield this.handlePlaybackCompletion(state); return state; }); } play(options) { return __awaiter(this, void 0, void 0, function* () { this.playExtPr = new ExtPromise(); this.resolvePlaybackOptions(options); this.registerEventsAndHandlers(); if ((this.options.screenCenterOverride === false) && this.hasScreenDOFs) { try { yield this.jibo.expression.centerRobot({ requestor: this.options.ownerInformation, centerGlobally: false, dofs: this.jibo.expression.dofs.SCREEN }); } catch (err) { this.playExtPr.reject(err); } } try { if (!this.hasBeenStopped) { log.debug(`Playback ${this.animation.name} playing with these options: `, this.options); yield this.keysAnimation.instance.play(this.options.ownerInformation); } } catch (err) { this.playExtPr.reject(err); } const state = yield this.playExtPr.promise; yield this.handlePlaybackCompletion(state); return state; }); } stop() { return __awaiter(this, void 0, void 0, function* () { if (this.keysAnimation) { try { yield this.keysAnimation.instance.stop(); } catch (error) { log.warn(`Could not stop instance that no longer exists: `, error); } } if (this.assetToken) { this.assetToken.unload(); this.assetToken = null; } }); } _init(config) { if (!config) { config = { cache: this.jibo.loader.activeCache }; } log.debug(`Initializing playback ${this.animation.name} with config: `, config); if (this.runtimeKeys) { this.filePath = this.animation.resourceRoot; } else { this.filePath = path.join(this.animation.resourceRoot, this.animation.meta.path); } if (this.animation.meta.metaTerms.indexOf(AnimUtils_1.AUDIO_ONLY_META) !== -1) { config.layer = Classes_1.BuilderLayer.BEAT; } if (this.transform.shouldFlipLeftRight || this.transform.exaggerate) { let flipMult = this.transform.shouldFlipLeftRight ? -1 : 1; let flipAndExagMult = flipMult * (this.transform.exaggerate || 1); if ((flipMult !== 1) || (flipAndExagMult !== 1)) { let dofs = { bottomSection_r: 1, middleSection_r: 1, topSection_r: 1, eyeSubRootBn_t: 1 }; Object.keys(dofs).forEach(dof => { if (dof === "eyeSubRootBn_t_2") { dofs[dof] *= flipMult; } else { dofs[dof] *= flipAndExagMult; } }); config.scale = dofs; } } if (this.transform.framesToHold !== -1) { this.holdSafeDuration = ((this.transform.framesToHold / FRAMERATE) * 1000); } if (this.transform.speed !== 1) { config.speed = this.transform.speed; } this.duration = this.animation.meta.duration; if (this.transform.speed !== -1) { this.duration *= this.transform.speed; } if (this.transform.framesToHold !== -1) { this.duration += this.transform.framesToHold; } this.config = config; } resolvePlaybackOptions(options) { const playOptions = Object.assign({}, defaultOptions, options); this.options = playOptions; } registerEventsAndHandlers() { const dofsInScreen = this.jibo.expression.dofs.SCREEN; const dofsInAnim = this.keysAnimation.instance.dofs; const dofsNotInAnim = dofsInScreen.minus(dofsInAnim); this.hasScreenDOFs = (dofsNotInAnim.getDOFs().length !== dofsInScreen.getDOFs().length); if (this.hasScreenDOFs && !this.options.disableSetFaceAnim) { this.jibo.face.eye.addAnimation(this.keysAnimation); } const stopHandler = (state) => { this.hasBeenStopped = true; log.debug(`Playback ${this.animation.name} was stopped with state ${state}`); this._cleanup(); this.playExtPr.resolve(state); }; const holdSafeHandler = () => __awaiter(this, void 0, void 0, function* () { try { if (this.keysAnimation) { yield this.keysAnimation.instance.pause(); yield jibo_cai_utils_1.TimeUtils.wait(this.holdSafeDuration); } if (this.keysAnimation) { yield this.keysAnimation.instance.resume(); } } catch (error) { log.warn(`Error in hold-safe logic for animation ${this.animation.name}: `, error); } }); this.keysAnimation.instance.events.stopped.on(() => stopHandler(jibo_expression_client_1.AnimationState.STOPPED)); this.keysAnimation.instance.events.cancelled.on(() => stopHandler(jibo_expression_client_1.AnimationState.CANCELLED)); this.keysAnimation.instance.events.rejected.on(() => stopHandler(jibo_expression_client_1.AnimationState.REJECTED)); if (this.holdSafeDuration > 0) { this.keysAnimation.instance.events.holdSafe.on(holdSafeHandler); } } handlePlaybackCompletion(state) { return __awaiter(this, void 0, void 0, function* () { if (state === jibo_expression_client_1.AnimationState.REJECTED) { log.warn(`Playback ${this.animation.name} was rejected! (See DOFArbiter debug for more details)`); } else if (this.options.forceReturnToIdle) { log.debug(`Returning playback ${this.animation.name} to idle pose.`); if (!Playback.DOFS_TO_CENTER) { const dofs = this.jibo.expression.dofs; Playback.DOFS_TO_CENTER = dofs.ALL.minus(dofs.BASE).minus(dofs.EYE_TRANSLATE); } yield this.jibo.expression.centerRobot({ requestor: this.options.ownerInformation, dofs: Playback.DOFS_TO_CENTER, centerGlobally: false }); } }); } _cleanup() { if (this.keysAnimation) { if (this.hasScreenDOFs && !this.options.disableSetFaceAnim) { this.jibo.face.eye.removeAnimation(this.keysAnimation); } else { this.keysAnimation.destroy(); } this.keysAnimation = null; if (this.assetToken) { this.assetToken.unload(); this.assetToken = null; } } this.instance = null; } loadAnimation(andPlay = false) { return __awaiter(this, void 0, void 0, function* () { const id = this.filePath; if (this.runtimeKeys) { this.filePath = path.join(id, uuid.v4()); } return new Promise((resolve, reject) => { const load = this.jibo.loader.load({ id: id, cache: this.cacheName, options: this.config, data: this.runtimeKeys ? this.animation.animData : null, src: this.filePath, upload: true, root: this.animation.resourceRoot, type: 'keys', }, (error, keysData) => { if (error) { reject(error); } else { if (!this.assetToken) { return; } if (andPlay && this.options) { resolve(keysData.getAndPlayAnim(Object.assign({ src: this.filePath }, this.config), this.options.ownerInformation)); } else { resolve(keysData.getAnim(Object.assign({ src: this.filePath }, this.config))); } } }); this.assetToken = load.tokens[0]; }); }); } } exports.Playback = Playback; },{"./AnimUtils":4,"./Classes":7,"./log":15,"events":undefined,"jibo-cai-utils":undefined,"jibo-expression-client":undefined,"path":undefined,"uuid":undefined}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.INFINITE_DURATION = 1e6; class Range { constructor(min, max) { this.min = min; this.max = max; if (min > max) { throw new Error(`Invalid bounds ${this.toString()}`); } } toString() { return `[${this.min}, ${this.max}]`; } limit(num) { if (num < this.min) { return this.min; } else if (num > this.max) { return this.max; } else { return num; } } isUpperInfinite() { return (this.max === exports.INFINITE_DURATION); } distanceFrom(num) { if (num < this.min) { return this.min - num; } else if (num > this.max) { return num - this.max; } else { return 0; } } } exports.Range = Range; },{}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Classes_1 = require("./Classes"); let SemverUtils = require('semver-utils'); class Utils { static parseString(input, defaultVal) { if (!input || !(input.length)) { return defaultVal; } return input; } static parseNumber(input, defaultVal) { if (typeof input === 'number') { return input; } if (!input || !(input.length)) { return defaultVal; } try { let num = parseFloat(input); return num; } catch (e) { return defaultVal; } } static parseSemVer(input) { let parse = SemverUtils.parse(input); return { semver: parse.semver, version: parse.version, major: parseInt(parse.major), minor: parseInt(parse.minor), patch: parseInt(parse.patch), release: parse.release }; } static getAnimationsByQuery(animations, interimResults, query) { animations.forEach(anim => { if (Utils.audioMatch(anim, query.hasAudio) && Utils.catMatch(anim, query.includeCat, query.includeSomeCat, query.excludeCat) && Utils.metaMatch(anim, query.includeMeta, query.includeSomeMeta, query.excludeMeta)) { Utils.addIfDurationMatch(anim, query.duration, query.durationError, interimResults); } }); } static audioMatch(animation, shouldHaveAudio) { return (shouldHaveAudio === Classes_1.HasAudio.DONT_CARE) || (shouldHaveAudio === Classes_1.HasAudio.YES && animation.meta.hasAudio) || (shouldHaveAudio === Classes_1.HasAudio.NO && !animation.meta.hasAudio); } static catMatch(animation, allOfCat, someOfCat, noneOfCat) { const categories = animation.meta.categories; const allOfMatch = (allOfCat.length > 0) ? allOfCat.every(cat => categories.indexOf(cat) !== -1) : true; const someOfMatch = (someOfCat.length > 0) ? someOfCat.some(cat => categories.indexOf(cat) !== -1) : true; const noneOfMatch = (noneOfCat.length > 0) ? noneOfCat.every(cat => categories.indexOf(cat) === -1) : true; return (allOfMatch && someOfMatch && noneOfMatch); } static metaMatch(animation, allOfMeta, someOfMeta, noneOfMeta) { const metas = animation.meta.metaTerms; const allOfMatch = (allOfMeta.length > 0) ? allOfMeta.every(meta => metas.indexOf(meta) !== -1) : true; const someOfMatch = (someOfMeta.length > 0) ? someOfMeta.some(meta => metas.indexOf(meta) !== -1) : true; const noneOfMatch = (noneOfMeta.length > 0) ? noneOfMeta.every(meta => metas.indexOf(meta) === -1) : true; return (allOfMatch && someOfMatch && noneOfMatch); } static addIfDurationMatch(animation, duration, durationError, res) { if (duration === -1) { res.matching.push(animation); } else { let dist = Utils.distanceFromRange(duration, animation.meta.durationRange); if (dist === 0) { res.matching.push(animation); } else if (dist <= durationError) { res.nonMatching.push(animation); } } } static limitToRange(num, range) { if (num < range[0]) { return range[0]; } else if (num > range[1]) { return range[1]; } else { return num; } } static distanceFromRange(num, range) { if (num < range[0]) { return range[0] - num; } else if (num > range[1]) { return num - range[1]; } else { return 0; } } } exports.Utils = Utils; },{"./Classes":7,"semver-utils":undefined}],11:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); },{}],12:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); let generateId = require('jibo-keyframes').generateId; class LayerTemplate { static generateLayer(name, type) { let layer = {}; layer.id = generateId(); layer.name = name; layer.type = type; layer.visible = true; layer.locked = false; layer.keyframes = []; return layer; } } exports.LayerTemplate = LayerTemplate; },{"jibo-keyframes":undefined}],13:[function(require,module,exports){ "use strict"; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } Object.defineProperty(exports, "__esModule", { value: true }); __export(require("./LayerMocks")); const format_0_6_x = require("./0_6_X"); exports.format_0_6_x = format_0_6_x; },{"./0_6_X":11,"./LayerMocks":12}],14:[function(require,module,exports){ "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); const fs = require("fs"); const AnimDBParser_1 = require("./AnimDBParser"); exports.AnimDBParser = AnimDBParser_1.AnimDBParser; const AnimCollection_1 = require("./AnimCollection"); exports.AnimCollection = AnimCollection_1.AnimCollection; const Animation_1 = require("./Animation"); exports.Animation = Animation_1.Animation; const AnimDB_1 = require("./AnimDB"); exports.AnimDB = AnimDB_1.AnimDB; const Playback_1 = require("./Playback"); exports.Playback = Playback_1.Playback; __export(require("./animation_formats")); __export(require("./Classes")); function init(jibo, animDBPath, ...moreAnimDBPaths) { return __awaiter(this, void 0, void 0, function* () { if (!animDBPath) { exports._animDB = new AnimDB_1.AnimDB(jibo); } else { exports._animDB = yield AnimDBParser_1.AnimDBParser.readAnimDB(jibo, animDBPath, ...moreAnimDBPaths); } }); } exports.init = init; function isInitialized() { return !!exports._animDB; } exports.isInitialized = isInitialized; function resolveAnimDB(jibo, dir) { let animDBPath; let packjson; if (!dir) { const adaPath = jibo.utils.PathUtils.resolve('jibo-anim-db-animations'); dir = adaPath ? path.dirname(adaPath) : undefined; } try { packjson = require(path.resolve(dir, 'package.json')); } catch (error) { return undefined; } if (packjson && packjson.jibo) { if (packjson.jibo.animdb && (path.extname(packjson.jibo.animdb).toLowerCase() === '.json')) { animDBPath = path.resolve(dir, packjson.jibo.animdb); } else { animDBPath = path.resolve(dir, 'animdb.json'); } } if (fs.existsSync(animDBPath)) { return animDBPath; } return undefined; } exports.resolveAnimDB = resolveAnimDB; function getAnimByName(animName) { return exports._animDB.getAnimByName(animName); } exports.getAnimByName = getAnimByName; function getAnimationNames() { return exports._animDB.getAnimationNames(); } exports.getAnimationNames = getAnimationNames; function getAnimationCategories() { return exports._animDB.getAnimationCategories(); } exports.getAnimationCategories = getAnimationCategories; function search(searchTerm) { return exports._animDB.search(searchTerm); } exports.search = search; function query(query) { return exports._animDB.query(query); } exports.query = query; function push(animCollection) { exports._animDB.push(animCollection); } exports.push = push; function pop() { return exports._animDB.pop(); } exports.pop = pop; },{"./AnimCollection":1,"./AnimDB":2,"./AnimDBParser":3,"./Animation":5,"./Classes":7,"./Playback":8,"./animation_formats":13,"fs":undefined,"path":undefined}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_log_1 = require("jibo-log"); exports.default = new jibo_log_1.Log('Jibo.AnimDB'); },{"jibo-log":undefined}],16:[function(require,module,exports){ "use strict"; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } Object.defineProperty(exports, "__esModule", { value: true }); __export(require("./AnimDB")); __export(require("./Range")); __export(require("./AnimDBParser")); __export(require("./AnimUtils")); __export(require("./AnimCollection")); __export(require("./Playback")); __export(require("./Animation")); __export(require("./Classes")); __export(require("./AnimUtils")); __export(require("./Utils")); const api = require("./api"); exports.api = api; const animation_formats = require("./animation_formats"); exports.animation_formats = animation_formats; },{"./AnimCollection":1,"./AnimDB":2,"./AnimDBParser":3,"./AnimUtils":4,"./Animation":5,"./Classes":7,"./Playback":8,"./Range":9,"./Utils":10,"./animation_formats":13,"./api":14}],17:[function(require,module,exports){ "use strict"; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } Object.defineProperty(exports, "__esModule", { value: true }); __export(require("./main")); },{"./main":16}]},{},[17])(17) }); //# sourceMappingURL=jibo-anim-db.js.map