Skip to content

Instantly share code, notes, and snippets.

@oggy83
Last active Jul 5, 2021
Embed
What would you like to do?
pixi-live2d-display
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("@pixi/math"), require("@pixi/utils"), require("@pixi/core"), require("@pixi/text"), require("@pixi/display"), require("@pixi/graphics"));
else if(typeof define === 'function' && define.amd)
define(["@pixi/math", "@pixi/utils", "@pixi/core", "@pixi/text", "@pixi/display", "@pixi/graphics"], factory);
else if(typeof exports === 'object')
exports["live2d"] = factory(require("@pixi/math"), require("@pixi/utils"), require("@pixi/core"), require("@pixi/text"), require("@pixi/display"), require("@pixi/graphics"));
else
root["PIXI"] = root["PIXI"] || {}, root["PIXI"]["live2d"] = factory(root["PIXI"], root["PIXI"]["utils"], root["PIXI"], root["PIXI"], root["PIXI"], root["PIXI"]);
})(window, function(__WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__3__, __WEBPACK_EXTERNAL_MODULE__20__, __WEBPACK_EXTERNAL_MODULE__24__, __WEBPACK_EXTERNAL_MODULE__34__, __WEBPACK_EXTERNAL_MODULE__35__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 167);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
// EXPORTS
__webpack_require__.d(__webpack_exports__, "f", function() { return /* reexport */ log_logger; });
__webpack_require__.d(__webpack_exports__, "b", function() { return /* reexport */ clamp; });
__webpack_require__.d(__webpack_exports__, "g", function() { return /* reexport */ rand; });
__webpack_require__.d(__webpack_exports__, "d", function() { return /* reexport */ copyProperty; });
__webpack_require__.d(__webpack_exports__, "c", function() { return /* reexport */ copyArray; });
__webpack_require__.d(__webpack_exports__, "a", function() { return /* reexport */ applyMixins; });
__webpack_require__.d(__webpack_exports__, "e", function() { return /* reexport */ folderName; });
// EXTERNAL MODULE: ./src/config.ts
var config = __webpack_require__(1);
// CONCATENATED MODULE: ./src/utils/log.ts
/**
* A simple tagged logger.
*
* You can replace the methods with your own ones.
*
* ```js
* import { logger } from 'pixi-live2d-display';
*
* logger.log = (tag, ...messages) => {
* console.log(tag, 'says:', ...messages);
* };
* ```
*/
var log_logger;
(function (logger) {
function log(tag, ...messages) {
if (config["b" /* config */].logLevel <= config["b" /* config */].LOG_LEVEL_VERBOSE) {
console.log(`[${tag}]`, ...messages);
}
}
logger.log = log;
function warn(tag, ...messages) {
if (config["b" /* config */].logLevel <= config["b" /* config */].LOG_LEVEL_WARNING) {
console.warn(`[${tag}]`, ...messages);
}
}
logger.warn = warn;
function error(tag, ...messages) {
if (config["b" /* config */].logLevel <= config["b" /* config */].LOG_LEVEL_ERROR) {
console.error(`[${tag}]`, ...messages);
}
}
logger.error = error;
})(log_logger || (log_logger = {}));
// CONCATENATED MODULE: ./src/utils/math.ts
/**
* These functions can be slightly faster than the ones in Lodash.
* @packageDocumentation
*/
function clamp(num, lower, upper) {
return num < lower ? lower : num > upper ? upper : num;
}
function rand(min, max) {
return Math.random() * (max - min) + min;
}
// CONCATENATED MODULE: ./src/utils/obj.ts
/**
* Copies a property at only if it matches the `type`.
* @param type - Type expected to match `typeof` on the property.
* @param from - Source object.
* @param to - Destination object.
* @param fromKey - Key of the property in source object.
* @param toKey - Key of the property in destination object.
*/
// TODO: lint and fix the formatting!
function copyProperty(type, from, to, fromKey, toKey) {
const value = from[fromKey];
if (value !== null && typeof value === type) {
// a type error will occur here, have no idea
to[toKey] = value;
}
}
/**
* Copies an array at `key`, filtering the items that match the `type`.
* @param type - Type expected to match `typeof` on the items.
* @param from - Source object.
* @param to - Destination object.
* @param fromKey - Key of the array property in source object.
* @param toKey - Key of the array property in destination object.
*/
function copyArray(type, from, to, fromKey, toKey) {
const array = from[fromKey];
if (Array.isArray(array)) {
to[toKey] = array.filter(item => item !== null && typeof item === type);
}
}
/**
* @see {@link https://www.typescriptlang.org/docs/handbook/mixins.html}
*/
function applyMixins(derivedCtor, baseCtors) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype, name));
}
});
});
}
// CONCATENATED MODULE: ./src/utils/string.ts
/**
* Gets the name of parent folder in a url.
* @param url - URL of a file.
* @return Name of the parent folder, or the file itself if it has no parent folder.
*/
function folderName(url) {
let lastSlashIndex = url.lastIndexOf('/');
if (lastSlashIndex != -1) {
url = url.slice(0, lastSlashIndex);
}
lastSlashIndex = url.lastIndexOf('/');
if (lastSlashIndex !== -1) {
url = url.slice(lastSlashIndex + 1);
}
return url;
}
// CONCATENATED MODULE: ./src/utils/index.ts
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return config; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return VERSION; });
/**
* Global configs.
*/
var config;
(function (config) {
config.LOG_LEVEL_VERBOSE = 0;
config.LOG_LEVEL_WARNING = 1;
config.LOG_LEVEL_ERROR = 2;
config.LOG_LEVEL_NONE = 999;
/**
* Global log level.
* @default {@link LOG_LEVEL_WARNING}
*/
config.logLevel = true ? config.LOG_LEVEL_WARNING : undefined;
/**
* Enabling sound for motions.
*/
config.sound = true;
/**
* Deferring motion and corresponding sound until both are loaded.
*/
config.motionSync = true;
/**
* Default fading duration for motions without such value specified.
*/
config.motionFadingDuration = 500;
/**
* Default fading duration for idle motions without such value specified.
*/
config.idleMotionFadingDuration = 2000;
/**
* Default fading duration for expressions without such value specified.
*/
config.expressionFadingDuration = 500;
})(config || (config = {}));
/**
* Consistent with the `version` in package.json.
*/
const VERSION = "0.3.0";
/***/ }),
/* 2 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__2__;
/***/ }),
/* 3 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__3__;
/***/ }),
/* 4 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Live2DLoader; });
/* harmony import */ var _factory_XHRLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18);
/* harmony import */ var _utils_middleware__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19);
class Live2DLoader {
/**
* Loads a resource.
* @return Promise that resolves with the loaded data in a format that's consistent with the specified `type`.
*/
static load(context) {
return Object(_utils_middleware__WEBPACK_IMPORTED_MODULE_1__[/* runMiddlewares */ "a"])(this.middlewares, context).then(() => context.result);
}
}
Live2DLoader.middlewares = [_factory_XHRLoader__WEBPACK_IMPORTED_MODULE_0__[/* XHRLoader */ "a"].loader];
/***/ }),
/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
// EXPORTS
__webpack_require__.d(__webpack_exports__, "a", function() { return /* binding */ Live2DFactory_Live2DFactory; });
// EXTERNAL MODULE: ./src/cubism-common/index.ts
var cubism_common = __webpack_require__(6);
// EXTERNAL MODULE: ./src/factory/Live2DLoader.ts
var Live2DLoader = __webpack_require__(4);
// EXTERNAL MODULE: ./src/utils/index.ts + 4 modules
var utils = __webpack_require__(0);
// EXTERNAL MODULE: ./src/utils/middleware.ts
var middleware = __webpack_require__(19);
// EXTERNAL MODULE: external {"commonjs":"@pixi/core","commonjs2":"@pixi/core","amd":"@pixi/core","root":"PIXI"}
var core_root_PIXI_ = __webpack_require__(20);
// CONCATENATED MODULE: ./src/factory/texture.ts
function createTexture(url, options = {}) {
var _a;
const textureOptions = { resourceOptions: { crossorigin: options.crossOrigin } };
// there's already such a method since Pixi v5.3.0
if (core_root_PIXI_["Texture"].fromURL) {
return core_root_PIXI_["Texture"].fromURL(url, textureOptions).catch(e => {
if (e instanceof Error) {
throw e;
}
// assume e is an ErrorEvent, let's convert it to an Error
const err = new Error('Texture loading error');
err.event = e;
throw err;
});
}
// and in order to provide backward compatibility for older Pixi versions,
// we have to manually implement this method
// see https://github.com/pixijs/pixi.js/pull/6687/files
textureOptions.resourceOptions.autoLoad = false;
const texture = core_root_PIXI_["Texture"].from(url, textureOptions);
if (texture.baseTexture.valid) {
return Promise.resolve(texture);
}
const resource = texture.baseTexture.resource;
// before Pixi v5.2.2, the Promise will not be rejected when loading has failed,
// we have to manually handle the "error" event
// see https://github.com/pixijs/pixi.js/pull/6374
(_a = resource._live2d_load) !== null && _a !== void 0 ? _a : (resource._live2d_load = new Promise((resolve, reject) => {
const errorHandler = (event) => {
resource.source.removeEventListener('error', errorHandler);
// convert the ErrorEvent to an Error
const err = new Error('Texture loading error');
err.event = event;
reject(err);
};
resource.source.addEventListener('error', errorHandler);
resource.load().then(() => resolve(texture)).catch(errorHandler);
}));
return resource._live2d_load;
}
// CONCATENATED MODULE: ./src/factory/model-middlewares.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
const TAG = 'Live2DFactory';
/**
* A middleware that converts the source from a URL to a settings JSON object.
*/
const urlToJSON = (context, next) => __awaiter(void 0, void 0, void 0, function* () {
if (typeof context.source === 'string') {
const data = yield Live2DLoader["a" /* Live2DLoader */].load({
url: context.source,
type: 'json',
target: context.live2dModel,
});
data.url = context.source;
context.source = data;
context.live2dModel.emit('settingsJSONLoaded', data);
}
return next();
});
/**
* A middleware that converts the source from a settings JSON object to a ModelSettings instance.
*/
const jsonToSettings = (context, next) => __awaiter(void 0, void 0, void 0, function* () {
if (context.source instanceof cubism_common["f" /* ModelSettings */]) {
context.settings = context.source;
return next();
}
else if (typeof context.source === 'object') {
const runtime = Live2DFactory_Live2DFactory.findRuntime(context.source);
if (runtime) {
const settings = runtime.createModelSettings(context.source);
context.settings = settings;
context.live2dModel.emit('settingsLoaded', settings);
return next();
}
}
throw new TypeError('Unknown settings format.');
});
const waitUntilReady = (context, next) => {
if (context.settings) {
const runtime = Live2DFactory_Live2DFactory.findRuntime(context.settings);
if (runtime) {
return runtime.ready().then(next);
}
}
return next();
};
/**
* A middleware that populates the Live2DModel with optional resources.
* Requires InternalModel in context when all the subsequent middlewares have finished.
*/
const setupOptionals = (context, next) => __awaiter(void 0, void 0, void 0, function* () {
// wait until all has finished
yield next();
const internalModel = context.internalModel;
if (internalModel) {
const settings = context.settings;
const runtime = Live2DFactory_Live2DFactory.findRuntime(settings);
if (runtime) {
const tasks = [];
if (settings.pose) {
tasks.push(Live2DLoader["a" /* Live2DLoader */].load({
settings,
url: settings.pose,
type: 'json',
target: internalModel,
})
.then((data) => {
internalModel.pose = runtime.createPose(internalModel.coreModel, data);
context.live2dModel.emit('poseLoaded', internalModel.pose);
})
.catch((e) => utils["f" /* logger */].warn(TAG, 'Failed to load pose.\n', e)));
}
if (settings.physics) {
tasks.push(Live2DLoader["a" /* Live2DLoader */].load({
settings,
url: settings.physics,
type: 'json',
target: internalModel,
})
.then((data) => {
internalModel.physics = runtime.createPhysics(internalModel.coreModel, data);
context.live2dModel.emit('physicsLoaded', internalModel.physics);
})
.catch((e) => utils["f" /* logger */].warn(TAG, 'Failed to load physics.\n', e)));
}
if (tasks.length) {
yield Promise.all(tasks);
}
}
}
});
/**
* A middleware that populates the Live2DModel with essential resources.
* Requires ModelSettings in context immediately, and InternalModel in context
* when all the subsequent middlewares have finished.
*/
const setupEssentials = (context, next) => __awaiter(void 0, void 0, void 0, function* () {
if (context.settings) {
const live2DModel = context.live2dModel;
const textureLoadings = context.settings.textures.map(tex => {
const url = context.settings.resolveURL(tex);
return createTexture(url, { crossOrigin: context.options.crossOrigin });
});
// wait for the internal model to be created
yield next();
if (context.internalModel) {
live2DModel.internalModel = context.internalModel;
live2DModel.emit('modelLoaded', context.internalModel);
}
else {
throw new TypeError('Missing internal model.');
}
live2DModel.textures = yield Promise.all(textureLoadings);
live2DModel.emit('textureLoaded', live2DModel.textures);
}
else {
throw new TypeError('Missing settings.');
}
});
/**
* A middleware that creates the InternalModel. Requires ModelSettings in context.
*/
const createInternalModel = (context, next) => __awaiter(void 0, void 0, void 0, function* () {
const settings = context.settings;
if (settings instanceof cubism_common["f" /* ModelSettings */]) {
const runtime = Live2DFactory_Live2DFactory.findRuntime(settings);
if (!runtime) {
throw new TypeError('Unknown model settings.');
}
const modelData = yield Live2DLoader["a" /* Live2DLoader */].load({
settings,
url: settings.moc,
type: 'arraybuffer',
target: context.live2dModel,
});
if (!runtime.isValidMoc(modelData)) {
throw new Error('Invalid moc data');
}
const coreModel = runtime.createCoreModel(modelData);
context.internalModel = runtime.createInternalModel(coreModel, settings, context.options);
return next();
}
throw new TypeError('Missing settings.');
});
// CONCATENATED MODULE: ./src/factory/Live2DFactory.ts
var Live2DFactory_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/**
* Handles all the network load tasks.
*
* - Model creation: requested by {@link Live2DModel.from}.
* - Motion loading: implements the load method of MotionManager.
* - Expression loading: implements the load method of ExpressionManager.
*/
class Live2DFactory_Live2DFactory {
/**
* Registers a Live2DRuntime.
*/
static registerRuntime(runtime) {
Live2DFactory_Live2DFactory.runtimes.push(runtime);
// higher version as higher priority
Live2DFactory_Live2DFactory.runtimes.sort((a, b) => b.version - a.version);
}
/**
* Finds a runtime that matches given source.
* @param source - Either a settings JSON object or a ModelSettings instance.
* @return The Live2DRuntime, or undefined if not found.
*/
static findRuntime(source) {
for (const runtime of Live2DFactory_Live2DFactory.runtimes) {
if (runtime.test(source)) {
return runtime;
}
}
}
/**
* Sets up a Live2DModel, populating it with all defined resources.
* @param live2dModel - The Live2DModel instance.
* @param source - Can be one of: settings file URL, settings JSON object, ModelSettings instance.
* @param options - Options for the process.
* @return Promise that resolves when all resources have been loaded, rejects when error occurs.
*/
static setupLive2DModel(live2dModel, source, options) {
return Live2DFactory_awaiter(this, void 0, void 0, function* () {
const textureLoaded = new Promise(resolve => live2dModel.once('textureLoaded', resolve));
const modelLoaded = new Promise(resolve => live2dModel.once('modelLoaded', resolve));
// because the "ready" event is supposed to be emitted after
// both the internal model and textures have been loaded,
// we should here wrap the emit() in a then() so it'll
// be executed after all the handlers of "modelLoaded" and "textureLoaded"
const readyEventEmitted = Promise.all([textureLoaded, modelLoaded]).then(() => live2dModel.emit('ready'));
yield Object(middleware["a" /* runMiddlewares */])(Live2DFactory_Live2DFactory.live2DModelMiddlewares, {
live2dModel,
source,
options: options || {},
});
// the "load" event should never be emitted before "ready"
yield readyEventEmitted;
live2dModel.emit('load');
});
}
/**
* Loads a Motion and registers the task to {@link motionTasksMap}. The task will be automatically
* canceled when its owner - the MotionManager instance - has been destroyed.
* @param motionManager - MotionManager that owns this Motion.
* @param group - The motion group.
* @param index - Index in the motion group.
* @return Promise that resolves with the Motion, or with undefined if it can't be loaded.
*/
static loadMotion(motionManager, group, index) {
var _a, _b;
// errors in this method are always handled
const handleError = (e) => motionManager.emit('motionLoadError', group, index, e);
try {
const definition = (_a = motionManager.definitions[group]) === null || _a === void 0 ? void 0 : _a[index];
if (!definition) {
return Promise.resolve(undefined);
}
if (!motionManager.listeners('destroy').includes(Live2DFactory_Live2DFactory.releaseTasks)) {
motionManager.once('destroy', Live2DFactory_Live2DFactory.releaseTasks);
}
let tasks = Live2DFactory_Live2DFactory.motionTasksMap.get(motionManager);
if (!tasks) {
tasks = {};
Live2DFactory_Live2DFactory.motionTasksMap.set(motionManager, tasks);
}
let taskGroup = tasks[group];
if (!taskGroup) {
taskGroup = [];
tasks[group] = taskGroup;
}
const path = motionManager.getMotionFile(definition);
(_b = taskGroup[index]) !== null && _b !== void 0 ? _b : (taskGroup[index] = Live2DLoader["a" /* Live2DLoader */].load({
url: path,
settings: motionManager.settings,
type: motionManager.motionDataType,
target: motionManager,
})
.then(data => {
var _a;
const taskGroup = (_a = Live2DFactory_Live2DFactory.motionTasksMap.get(motionManager)) === null || _a === void 0 ? void 0 : _a[group];
if (taskGroup) {
delete taskGroup[index];
}
const motion = motionManager.createMotion(data, group, definition);
motionManager.emit('motionLoaded', group, index, motion);
return motion;
})
.catch(e => {
utils["f" /* logger */].warn(motionManager.tag, `Failed to load motion: ${path}\n`, e);
handleError(e);
}));
return taskGroup[index];
}
catch (e) {
utils["f" /* logger */].warn(motionManager.tag, `Failed to load motion at "${group}"[${index}]\n`, e);
handleError(e);
}
return Promise.resolve(undefined);
}
/**
* Loads an Expression and registers the task to {@link expressionTasksMap}. The task will be automatically
* canceled when its owner - the ExpressionManager instance - has been destroyed.
* @param expressionManager - ExpressionManager that owns this Expression.
* @param index - Index of the Expression.
* @return Promise that resolves with the Expression, or with undefined if it can't be loaded.
*/
static loadExpression(expressionManager, index) {
var _a;
// errors in this method are always handled
const handleError = (e) => expressionManager.emit('expressionLoadError', index, e);
try {
const definition = expressionManager.definitions[index];
if (!definition) {
return Promise.resolve(undefined);
}
if (!expressionManager.listeners('destroy').includes(Live2DFactory_Live2DFactory.releaseTasks)) {
expressionManager.once('destroy', Live2DFactory_Live2DFactory.releaseTasks);
}
let tasks = Live2DFactory_Live2DFactory.expressionTasksMap.get(expressionManager);
if (!tasks) {
tasks = [];
Live2DFactory_Live2DFactory.expressionTasksMap.set(expressionManager, tasks);
}
const path = expressionManager.getExpressionFile(definition);
(_a = tasks[index]) !== null && _a !== void 0 ? _a : (tasks[index] = Live2DLoader["a" /* Live2DLoader */].load({
url: path,
settings: expressionManager.settings,
type: 'json',
target: expressionManager,
})
.then(data => {
const tasks = Live2DFactory_Live2DFactory.expressionTasksMap.get(expressionManager);
if (tasks) {
delete tasks[index];
}
const expression = expressionManager.createExpression(data, definition);
expressionManager.emit('expressionLoaded', index, expression);
return expression;
})
.catch(e => {
utils["f" /* logger */].warn(expressionManager.tag, `Failed to load expression: ${path}\n`, e);
handleError(e);
}));
return tasks[index];
}
catch (e) {
utils["f" /* logger */].warn(expressionManager.tag, `Failed to load expression at [${index}]\n`, e);
handleError(e);
}
return Promise.resolve(undefined);
}
static releaseTasks() {
if (this instanceof cubism_common["g" /* MotionManager */]) {
Live2DFactory_Live2DFactory.motionTasksMap.delete(this);
}
else {
Live2DFactory_Live2DFactory.expressionTasksMap.delete(this);
}
}
}
/**
* All registered runtimes, sorted by versions in descending order.
*/
Live2DFactory_Live2DFactory.runtimes = [];
Live2DFactory_Live2DFactory.urlToJSON = urlToJSON;
Live2DFactory_Live2DFactory.jsonToSettings = jsonToSettings;
Live2DFactory_Live2DFactory.waitUntilReady = waitUntilReady;
Live2DFactory_Live2DFactory.setupOptionals = setupOptionals;
Live2DFactory_Live2DFactory.setupEssentials = setupEssentials;
Live2DFactory_Live2DFactory.createInternalModel = createInternalModel;
/**
* Middlewares to run through when setting up a Live2DModel.
*/
Live2DFactory_Live2DFactory.live2DModelMiddlewares = [
urlToJSON, jsonToSettings, waitUntilReady, setupOptionals, setupEssentials, createInternalModel,
];
/**
* load tasks of each motion. The structure of each value in this map
* is the same as respective {@link MotionManager.definitions}.
*/
Live2DFactory_Live2DFactory.motionTasksMap = new WeakMap();
/**
* Load tasks of each expression.
*/
Live2DFactory_Live2DFactory.expressionTasksMap = new WeakMap();
cubism_common["g" /* MotionManager */].prototype._loadMotion = function (group, index) {
return Live2DFactory_Live2DFactory.loadMotion(this, group, index);
};
cubism_common["a" /* ExpressionManager */].prototype._loadExpression = function (index) {
return Live2DFactory_Live2DFactory.loadExpression(this, index);
};
/***/ }),
/* 6 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "d", function() { return _constants__WEBPACK_IMPORTED_MODULE_0__["a"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "e", function() { return _constants__WEBPACK_IMPORTED_MODULE_0__["b"]; });
/* harmony import */ var _ExpressionManager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _ExpressionManager__WEBPACK_IMPORTED_MODULE_1__["a"]; });
/* harmony import */ var _FocusController__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(17);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "b", function() { return _FocusController__WEBPACK_IMPORTED_MODULE_2__["a"]; });
/* harmony import */ var _ModelSettings__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "f", function() { return _ModelSettings__WEBPACK_IMPORTED_MODULE_3__["a"]; });
/* harmony import */ var _MotionState__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(10);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "i", function() { return _MotionState__WEBPACK_IMPORTED_MODULE_4__["a"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "j", function() { return _MotionState__WEBPACK_IMPORTED_MODULE_4__["b"]; });
/* harmony import */ var _MotionManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(15);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "g", function() { return _MotionManager__WEBPACK_IMPORTED_MODULE_5__["a"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "h", function() { return _MotionManager__WEBPACK_IMPORTED_MODULE_5__["b"]; });
/* harmony import */ var _SoundManager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "k", function() { return _SoundManager__WEBPACK_IMPORTED_MODULE_6__["a"]; });
/* harmony import */ var _InternalModel__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(16);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "c", function() { return _InternalModel__WEBPACK_IMPORTED_MODULE_7__["a"]; });
/***/ }),
/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SoundManager; });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
/* harmony import */ var lodash_pull__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33);
/* harmony import */ var lodash_pull__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(lodash_pull__WEBPACK_IMPORTED_MODULE_1__);
const TAG = 'SoundManager';
const VOLUME = 0.5;
/**
* Manages all the sounds.
*/
class SoundManager {
/**
* Global volume that applies to all the sounds.
*/
static get volume() {
return this._volume;
}
static set volume(value) {
this._volume = (value > 1 ? 1 : value < 0 ? 0 : value) || 0;
this.audios.forEach(audio => (audio.volume = this._volume));
}
// TODO: return an ID?
/**
* Creates an audio element and adds it to the {@link audios}.
* @param file - URL of the sound file.
* @param onFinish - Callback invoked when the playback has finished.
* @param onError - Callback invoked when error occurs.
* @return Created audio element.
*/
static add(file, onFinish, onError) {
const audio = new Audio(file);
audio.volume = this._volume;
audio.preload = 'auto';
audio.addEventListener('ended', () => {
this.dispose(audio);
onFinish === null || onFinish === void 0 ? void 0 : onFinish();
});
audio.addEventListener('error', (e) => {
this.dispose(audio);
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].warn(TAG, `Error occurred on "${file}"`, e.error);
onError === null || onError === void 0 ? void 0 : onError(e.error);
});
this.audios.push(audio);
return audio;
}
/**
* Plays the sound.
* @param audio - An audio element.
* @return Promise that resolves when the audio is ready to play, rejects when error occurs.
*/
static play(audio) {
return new Promise((resolve, reject) => {
var _a;
// see https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
(_a = audio.play()) === null || _a === void 0 ? void 0 : _a.catch(e => {
audio.dispatchEvent(new ErrorEvent('error', { error: e }));
reject(e);
});
if (audio.readyState === audio.HAVE_ENOUGH_DATA) {
resolve();
}
else {
audio.addEventListener('canplaythrough', resolve);
}
});
}
/**
* Disposes an audio element and removes it from {@link audios}.
* @param audio - An audio element.
*/
static dispose(audio) {
audio.pause();
audio.removeAttribute('src');
lodash_pull__WEBPACK_IMPORTED_MODULE_1___default()(this.audios, audio);
}
/**
* Destroys all managed audios.
*/
static destroy() {
// dispose() removes given audio from the array, so the loop must be backward
for (let i = this.audios.length - 1; i >= 0; i--) {
this.dispose(this.audios[i]);
}
}
}
/**
* Audio elements playing or pending to play. Finished audios will be removed automatically.
*/
SoundManager.audios = [];
SoundManager._volume = VOLUME;
/***/ }),
/* 8 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return LOGICAL_WIDTH; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return LOGICAL_HEIGHT; });
const LOGICAL_WIDTH = 2;
const LOGICAL_HEIGHT = 2;
/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {
var freeGlobal = __webpack_require__(38);
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
module.exports = root;
/***/ }),
/* 10 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MotionPriority; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return MotionState; });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
/**
* Indicates the motion priority.
*/
var MotionPriority;
(function (MotionPriority) {
/** States that the model is currently not playing any motion. This priority cannot be applied to a motion. */
MotionPriority[MotionPriority["NONE"] = 0] = "NONE";
/** Low priority, used when starting idle motions automatically. */
MotionPriority[MotionPriority["IDLE"] = 1] = "IDLE";
/** Medium priority. */
MotionPriority[MotionPriority["NORMAL"] = 2] = "NORMAL";
/** High priority. Motions as this priority will always be played regardless of the current priority. */
MotionPriority[MotionPriority["FORCE"] = 3] = "FORCE";
})(MotionPriority || (MotionPriority = {}));
/**
* Handles the state of a MotionManager.
*/
class MotionState {
constructor() {
/**
* When enabled, the states will be dumped to the logger when an exception occurs.
*/
this.debug = false;
/**
* Priority of the current motion. Will be `MotionPriority.NONE` if there's no playing motion.
*/
this.currentPriority = MotionPriority.NONE;
/**
* Priority of the reserved motion, which is still in loading and will be played once loaded.
* Will be `MotionPriority.NONE` if there's no reserved motion.
*/
this.reservePriority = MotionPriority.NONE;
}
/**
* Reserves the playback for a motion.
* @param group - The motion group.
* @param index - Index in the motion group.
* @param priority - The priority to be applied.
* @return True if the reserving has succeeded.
*/
reserve(group, index, priority) {
if (priority <= MotionPriority.NONE) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, `Cannot start a motion with MotionPriority.NONE.`);
return false;
}
if (group === this.currentGroup && index === this.currentIndex) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, `Motion is already playing.`, this.dump(group, index));
return false;
}
if ((group === this.reservedGroup && index === this.reservedIndex) || (group === this.reservedIdleGroup && index === this.reservedIdleIndex)) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, `Motion is already reserved.`, this.dump(group, index));
return false;
}
if (priority === MotionPriority.IDLE) {
if (this.currentPriority !== MotionPriority.NONE) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, `Cannot start idle motion because another motion is playing.`, this.dump(group, index));
return false;
}
if (this.reservedIdleGroup !== undefined) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, `Cannot start idle motion because another idle motion has reserved.`, this.dump(group, index));
return false;
}
this.setReservedIdle(group, index);
}
else {
if (priority < MotionPriority.FORCE) {
if (priority <= this.currentPriority) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, 'Cannot start motion because another motion is playing as an equivalent or higher priority.', this.dump(group, index));
return false;
}
if (priority <= this.reservePriority) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, 'Cannot start motion because another motion has reserved as an equivalent or higher priority.', this.dump(group, index));
return false;
}
}
this.setReserved(group, index, priority);
}
return true;
}
/**
* Requests the playback for a motion.
* @param motion - The Motion, can be undefined.
* @param group - The motion group.
* @param index - Index in the motion group.
* @param priority - The priority to be applied.
* @return True if the request has been approved, i.e. the motion is allowed to play.
*/
start(motion, group, index, priority) {
if (priority === MotionPriority.IDLE) {
this.setReservedIdle(undefined, undefined);
if (this.currentPriority !== MotionPriority.NONE) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, 'Cannot start idle motion because another motion is playing.', this.dump(group, index));
return false;
}
}
else {
if (group !== this.reservedGroup || index !== this.reservedIndex) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].log(this.tag, 'Cannot start motion because another motion has taken the place.', this.dump(group, index));
return false;
}
this.setReserved(undefined, undefined, MotionPriority.NONE);
}
if (!motion) {
return false;
}
this.setCurrent(group, index, priority);
return true;
}
/**
* Notifies the motion playback has finished.
*/
complete() {
this.setCurrent(undefined, undefined, MotionPriority.NONE);
}
/**
* Sets the current motion.
*/
setCurrent(group, index, priority) {
this.currentPriority = priority;
this.currentGroup = group;
this.currentIndex = index;
}
/**
* Sets the reserved motion.
*/
setReserved(group, index, priority) {
this.reservePriority = priority;
this.reservedGroup = group;
this.reservedIndex = index;
}
/**
* Sets the reserved idle motion.
*/
setReservedIdle(group, index) {
this.reservedIdleGroup = group;
this.reservedIdleIndex = index;
}
/**
* Checks if a Motion is currently playing or has reserved.
* @return True if active.
*/
isActive(group, index) {
return (group === this.currentGroup && index === this.currentIndex)
|| (group === this.reservedGroup && index === this.reservedIndex)
|| (group === this.reservedIdleGroup && index === this.reservedIdleIndex);
}
/**
* Resets the state.
*/
reset() {
this.setCurrent(undefined, undefined, MotionPriority.NONE);
// make sure the reserved motions (if existing) won't start when they are loaded
this.setReserved(undefined, undefined, MotionPriority.NONE);
this.setReservedIdle(undefined, undefined);
}
/**
* Checks if an idle motion should be requests to play.
*/
shouldRequestIdleMotion() {
return this.currentGroup === undefined && this.reservedIdleGroup === undefined;
}
/**
* Checks if the model's expression should be overridden by the motion.
*/
shouldOverrideExpression() {
return this.currentPriority > MotionPriority.IDLE;
}
/**
* Dumps the state for debugging.
*/
dump(requestedGroup, requestedIndex) {
if (this.debug) {
const keys = [
'currentPriority',
'reservePriority',
'currentGroup',
'currentIndex',
'reservedGroup',
'reservedIndex',
'reservedIdleGroup',
'reservedIdleIndex',
];
return `\n<Requested> group = "${requestedGroup}", index = ${requestedIndex}\n` + keys.map(key => '[' + key + '] ' + this[key]).join('\n');
}
return '';
}
}
/***/ }),
/* 11 */
/***/ (function(module, exports, __webpack_require__) {
var baseIsNative = __webpack_require__(54),
getValue = __webpack_require__(60);
/**
* Gets the native function at `key` of `object`.
*
* @private
* @param {Object} object The object to query.
* @param {string} key The key of the method to get.
* @returns {*} Returns the function if it's native, else `undefined`.
*/
function getNative(object, key) {
var value = getValue(object, key);
return baseIsNative(value) ? value : undefined;
}
module.exports = getNative;
/***/ }),
/* 12 */
/***/ (function(module, exports) {
/**
* Checks if `value` is classified as an `Array` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array, else `false`.
* @example
*
* _.isArray([1, 2, 3]);
* // => true
*
* _.isArray(document.body.children);
* // => false
*
* _.isArray('abc');
* // => false
*
* _.isArray(_.noop);
* // => false
*/
var isArray = Array.isArray;
module.exports = isArray;
/***/ }),
/* 13 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ExpressionManager; });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_pixi_utils__WEBPACK_IMPORTED_MODULE_1__);
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/**
* Abstract expression manager.
*/
class ExpressionManager extends _pixi_utils__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"] {
constructor(settings, options) {
super();
/**
* The Expressions. The structure is the same as {@link definitions}, initially there's only
* an empty array, which means all expressions will be `undefined`. When an Expression has
* been loaded, it'll fill the place in which it should be; when it fails to load,
* the place will be filled with `null`.
*/
this.expressions = [];
/**
* The pending Expression.
*/
this.reserveExpressionIndex = -1;
/**
* Flags the instance has been destroyed.
*/
this.destroyed = false;
this.settings = settings;
this.tag = `ExpressionManager(${settings.name})`;
}
/**
* Should be called in the constructor of derived class.
*/
init() {
this.defaultExpression = this.createExpression({}, undefined);
this.currentExpression = this.defaultExpression;
this.stopAllExpressions();
}
/**
* Loads an Expression. Errors in this method will not be thrown,
* but be emitted with an "expressionLoadError" event.
* @param index - Index of the expression in definitions.
* @return Promise that resolves with the Expression, or with undefined if it can't be loaded.
* @emits {@link ExpressionManagerEvents.expressionLoaded}
* @emits {@link ExpressionManagerEvents.expressionLoadError}
*/
loadExpression(index) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.definitions[index]) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].warn(this.tag, `Undefined expression at [${index}]`);
return undefined;
}
if (this.expressions[index] === null) {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].warn(this.tag, `Cannot set expression at [${index}] because it's already failed in loading.`);
return undefined;
}
if (this.expressions[index]) {
return this.expressions[index];
}
const expression = yield this._loadExpression(index);
this.expressions[index] = expression;
return expression;
});
}
/**
* Loads the Expression. Will be implemented by Live2DFactory.
* @ignore
*/
_loadExpression(index) {
throw new Error('Not implemented.');
}
/**
* Sets a random Expression that differs from current one.
* @return Promise that resolves with true if succeeded, with false otherwise.
*/
setRandomExpression() {
return __awaiter(this, void 0, void 0, function* () {
if (this.definitions.length) {
const availableIndices = [];
for (let i = 0; i < this.definitions.length; i++) {
if (this.expressions[i] !== null
&& this.expressions[i] !== this.currentExpression
&& i !== this.reserveExpressionIndex) {
availableIndices.push(i);
}
}
if (availableIndices.length) {
const index = Math.floor(Math.random() * availableIndices.length);
return this.setExpression(index);
}
}
return false;
});
}
/**
* Resets model's expression using {@link defaultExpression}.
*/
resetExpression() {
this._setExpression(this.defaultExpression);
}
/**
* Restores model's expression to {@link currentExpression}.
*/
restoreExpression() {
this._setExpression(this.currentExpression);
}
/**
* Sets an Expression.
* @param index - Either the index, or the name of the expression.
* @return Promise that resolves with true if succeeded, with false otherwise.
*/
setExpression(index) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof index !== 'number') {
index = this.getExpressionIndex(index);
}
if (!(index > -1 && index < this.definitions.length)) {
return false;
}
if (index === this.expressions.indexOf(this.currentExpression)) {
return false;
}
this.reserveExpressionIndex = index;
const expression = yield this.loadExpression(index);
if (!expression || this.reserveExpressionIndex !== index) {
return false;
}
this.reserveExpressionIndex = -1;
this.currentExpression = expression;
this._setExpression(expression);
return true;
});
}
/**
* Updates parameters of the core model.
* @return True if the parameters are actually updated.
*/
update(model, now) {
if (!this.isFinished()) {
return this.updateParameters(model, now);
}
return false;
}
/**
* Destroys the instance.
* @emits {@link ExpressionManagerEvents.destroy}
*/
destroy() {
this.destroyed = true;
this.emit('destroy');
const self = this;
self.definitions = undefined;
self.expressions = undefined;
}
}
/***/ }),
/* 14 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ModelSettings; });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_pixi_utils__WEBPACK_IMPORTED_MODULE_1__);
/**
* Parses, and provides access to the settings JSON.
*/
class ModelSettings {
/**
* @param json - The settings JSON object.
* @param json.url - The `url` field must be defined to specify the settings file's URL.
*/
constructor(json) {
this.json = json;
let url = json.url;
if (typeof url !== 'string') {
// this is not allowed because it'll typically result in errors, including a
// fatal error - an OOM that crashes the browser while initializing this cubism2 model,
// I'm not kidding!
throw new TypeError('The `url` field in settings JSON must be defined as a string.');
}
this.url = url;
// set default name to folder's name
this.name = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[/* folderName */ "e"])(this.url);
}
/**
* Resolves a relative path using the {@link url}. This is used to resolve the resource files
* defined in the settings.
* @param path - Relative path.
* @return Resolved path.
*/
resolveURL(path) {
return _pixi_utils__WEBPACK_IMPORTED_MODULE_1__["url"].resolve(this.url, path);
}
/**
* Replaces the resource files by running each file through the `replacer`.
* @param replacer - Invoked with two arguments: `(file, path)`, where `file` is the file definition,
* and `path` is its property path in the ModelSettings instance. A string must be returned to be the replacement.
*
* ```js
* modelSettings.replaceFiles((file, path) => {
* // file = "foo.moc", path = "moc"
* // file = "foo.png", path = "textures[0]"
* // file = "foo.mtn", path = "motions.idle[0].file"
* // file = "foo.motion3.json", path = "motions.idle[0].File"
*
* return "bar/" + file;
* });
* ```
*/
replaceFiles(replacer) {
this.moc = replacer(this.moc, 'moc');
if (this.pose !== undefined) {
(this.pose = replacer(this.pose, 'pose'));
}
if (this.physics !== undefined) {
(this.physics = replacer(this.physics, 'physics'));
}
for (let i = 0; i < this.textures.length; i++) {
this.textures[i] = replacer(this.textures[i], `textures[${i}]`);
}
}
;
/**
* Retrieves all resource files defined in the settings.
* @return A flat array of the paths of all resource files.
*
* ```js
* modelSettings.getDefinedFiles();
* // returns: ["foo.moc", "foo.png", ...]
* ```
*/
getDefinedFiles() {
const files = [];
this.replaceFiles((file) => {
files.push(file);
return file;
});
return files;
}
/**
* Validates that the files defined in the settings exist in given files. Each file will be
* resolved by {@link resolveURL} before comparison.
* @param files - A flat array of file paths.
* @return All the files which are defined in the settings and also exist in given files,
* *including the optional files*.
* @throws Error if any *essential* file is defined in settings but not included in given files.
*/
validateFiles(files) {
const assertFileExists = (expectedFile, shouldThrow) => {
const actualPath = this.resolveURL(expectedFile);
if (!files.includes(actualPath)) {
if (shouldThrow) {
throw new Error(`File "${expectedFile}" is defined in settings, but doesn't exist in given files`);
}
return false;
}
return true;
};
const essentialFiles = [this.moc, ...this.textures];
essentialFiles.forEach(texture => assertFileExists(texture, true));
const definedFiles = this.getDefinedFiles();
return definedFiles.filter(file => assertFileExists(file, false));
}
}
/***/ }),
/* 15 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return MotionPreloadStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MotionManager; });
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var _cubism_common_MotionState__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10);
/* harmony import */ var _cubism_common_SoundManager__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(0);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_pixi_utils__WEBPACK_IMPORTED_MODULE_4__);
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/**
* Indicates how the motions will be preloaded.
*/
var MotionPreloadStrategy;
(function (MotionPreloadStrategy) {
/** Preload all the motions. */
MotionPreloadStrategy["ALL"] = "ALL";
/** Preload only the idle motions. */
MotionPreloadStrategy["IDLE"] = "IDLE";
/** No preload. */
MotionPreloadStrategy["NONE"] = "NONE";
})(MotionPreloadStrategy || (MotionPreloadStrategy = {}));
/**
* Handles the motion playback.
*/
class MotionManager extends _pixi_utils__WEBPACK_IMPORTED_MODULE_4__["EventEmitter"] {
constructor(settings, options) {
super();
/**
* The Motions. The structure is the same as {@link definitions}, initially each group contains
* an empty array, which means all motions will be `undefined`. When a Motion has been loaded,
* it'll fill the place in which it should be; when it fails to load, the place will be filled
* with `null`.
*/
this.motionGroups = {};
/**
* Maintains the state of this MotionManager.
*/
this.state = new _cubism_common_MotionState__WEBPACK_IMPORTED_MODULE_1__[/* MotionState */ "b"]();
/**
* Flags there's a motion playing.
*/
this.playing = false;
/**
* Flags the instances has been destroyed.
*/
this.destroyed = false;
this.settings = settings;
this.tag = `MotionManager(${settings.name})`;
this.state.tag = this.tag;
}
/**
* Should be called in the constructor of derived class.
*/
init(options) {
if (options === null || options === void 0 ? void 0 : options.idleMotionGroup) {
this.groups.idle = options.idleMotionGroup;
}
this.setupMotions(options);
this.stopAllMotions();
}
/**
* Sets up motions from the definitions, and preloads them according to the preload strategy.
*/
setupMotions(options) {
for (const group of Object.keys(this.definitions)) {
// init with the same structure of definitions
this.motionGroups[group] = [];
}
// preload motions
let groups;
switch (options === null || options === void 0 ? void 0 : options.motionPreload) {
case MotionPreloadStrategy.NONE:
return;
case MotionPreloadStrategy.ALL:
groups = Object.keys(this.definitions);
break;
case MotionPreloadStrategy.IDLE:
default:
groups = [this.groups.idle];
break;
}
for (const group of groups) {
if (this.definitions[group]) {
for (let i = 0; i < this.definitions[group].length; i++) {
this.loadMotion(group, i).then();
}
}
}
}
/**
* Loads a Motion in a motion group. Errors in this method will not be thrown,
* but be emitted with a "motionLoadError" event.
* @param group - The motion group.
* @param index - Index in the motion group.
* @return Promise that resolves with the Motion, or with undefined if it can't be loaded.
* @emits {@link MotionManagerEvents.motionLoaded}
* @emits {@link MotionManagerEvents.motionLoadError}
*/
loadMotion(group, index) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (!((_a = this.definitions[group]) === null || _a === void 0 ? void 0 : _a[index])) {
_utils__WEBPACK_IMPORTED_MODULE_3__[/* logger */ "f"].warn(this.tag, `Undefined motion at "${group}"[${index}]`);
return undefined;
}
if (this.motionGroups[group][index] === null) {
_utils__WEBPACK_IMPORTED_MODULE_3__[/* logger */ "f"].warn(this.tag, `Cannot start motion at "${group}"[${index}] because it's already failed in loading.`);
return undefined;
}
if (this.motionGroups[group][index]) {
return this.motionGroups[group][index];
}
const motion = yield this._loadMotion(group, index);
if (this.destroyed) {
return;
}
this.motionGroups[group][index] = motion !== null && motion !== void 0 ? motion : null;
return motion;
});
}
// TODO: remove
/**
* Loads the Motion. Will be implemented by Live2DFactory.
* @ignore
*/
_loadMotion(group, index) {
throw new Error('Not implemented.');
}
/**
* Starts a motion as given priority.
* @param group - The motion group.
* @param index - Index in the motion group.
* @param priority - The priority to be applied.
* @return Promise that resolves with true if the motion is successfully started, with false otherwise.
*/
startMotion(group, index, priority = _cubism_common_MotionState__WEBPACK_IMPORTED_MODULE_1__[/* MotionPriority */ "a"].NORMAL) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (!this.state.reserve(group, index, priority)) {
return false;
}
const definition = (_a = this.definitions[group]) === null || _a === void 0 ? void 0 : _a[index];
if (!definition) {
return false;
}
if (this.currentAudio) {
// TODO: reuse the audio?
_cubism_common_SoundManager__WEBPACK_IMPORTED_MODULE_2__[/* SoundManager */ "a"].dispose(this.currentAudio);
}
let audio;
if (_config__WEBPACK_IMPORTED_MODULE_0__[/* config */ "b"].sound) {
const soundURL = this.getSoundFile(definition);
if (soundURL) {
try {
// start to load the audio
audio = _cubism_common_SoundManager__WEBPACK_IMPORTED_MODULE_2__[/* SoundManager */ "a"].add(this.settings.resolveURL(soundURL), () => this.currentAudio = undefined, () => this.currentAudio = undefined);
this.currentAudio = audio;
}
catch (e) {
_utils__WEBPACK_IMPORTED_MODULE_3__[/* logger */ "f"].warn(this.tag, 'Failed to create audio', soundURL, e);
}
}
}
const motion = yield this.loadMotion(group, index);
if (audio) {
const readyToPlay = _cubism_common_SoundManager__WEBPACK_IMPORTED_MODULE_2__[/* SoundManager */ "a"].play(audio)
.catch(e => _utils__WEBPACK_IMPORTED_MODULE_3__[/* logger */ "f"].warn(this.tag, 'Failed to play audio', audio.src, e));
if (_config__WEBPACK_IMPORTED_MODULE_0__[/* config */ "b"].motionSync) {
// wait until the audio is ready
yield readyToPlay;
}
}
if (!this.state.start(motion, group, index, priority)) {
if (audio) {
_cubism_common_SoundManager__WEBPACK_IMPORTED_MODULE_2__[/* SoundManager */ "a"].dispose(audio);
this.currentAudio = undefined;
}
return false;
}
_utils__WEBPACK_IMPORTED_MODULE_3__[/* logger */ "f"].log(this.tag, 'Start motion:', this.getMotionName(definition));
this.emit('motionStart', group, index, audio);
if (this.state.shouldOverrideExpression()) {
this.expressionManager && this.expressionManager.resetExpression();
}
this.playing = true;
this._startMotion(motion);
return true;
});
}
/**
* Starts a random Motion as given priority.
* @param group - The motion group.
* @param priority - The priority to be applied.
* @return Promise that resolves with true if the motion is successfully started, with false otherwise.
*/
startRandomMotion(group, priority) {
return __awaiter(this, void 0, void 0, function* () {
const groupDefs = this.definitions[group];
if (groupDefs === null || groupDefs === void 0 ? void 0 : groupDefs.length) {
const availableIndices = [];
for (let i = 0; i < groupDefs.length; i++) {
if (this.motionGroups[group][i] !== null && !this.state.isActive(group, i)) {
availableIndices.push(i);
}
}
if (availableIndices.length) {
const index = Math.floor(Math.random() * availableIndices.length);
return this.startMotion(group, availableIndices[index], priority);
}
}
return false;
});
}
/**
* Stops all playing motions as well as the sound.
*/
stopAllMotions() {
this._stopAllMotions();
this.state.reset();
if (this.currentAudio) {
_cubism_common_SoundManager__WEBPACK_IMPORTED_MODULE_2__[/* SoundManager */ "a"].dispose(this.currentAudio);
this.currentAudio = undefined;
}
}
/**
* Updates parameters of the core model.
* @param model - The core model.
* @param now - Current time in milliseconds.
* @return True if the parameters have been actually updated.
*/
update(model, now) {
var _a, _b;
if (this.isFinished()) {
if (this.playing) {
this.playing = false;
this.emit('motionFinish');
}
if (this.state.shouldOverrideExpression()) {
(_a = this.expressionManager) === null || _a === void 0 ? void 0 : _a.restoreExpression();
}
this.state.complete();
if (this.state.shouldRequestIdleMotion()) {
// noinspection JSIgnoredPromiseFromCall
this.startRandomMotion(this.groups.idle, _cubism_common_MotionState__WEBPACK_IMPORTED_MODULE_1__[/* MotionPriority */ "a"].IDLE);
}
}
let updated = this.updateParameters(model, now);
updated = ((_b = this.expressionManager) === null || _b === void 0 ? void 0 : _b.update(model, now)) || updated;
return updated;
}
/**
* Destroys the instance.
* @emits {@link MotionManagerEvents.destroy}
*/
destroy() {
var _a;
this.destroyed = true;
this.emit('destroy');
this.stopAllMotions();
(_a = this.expressionManager) === null || _a === void 0 ? void 0 : _a.destroy();
const self = this;
self.definitions = undefined;
self.motionGroups = undefined;
}
}
/***/ }),
/* 16 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return InternalModel; });
/* harmony import */ var _cubism_common_constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8);
/* harmony import */ var _cubism_common_FocusController__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(17);
/* harmony import */ var _pixi_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
/* harmony import */ var _pixi_math__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_pixi_math__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3);
/* harmony import */ var _pixi_utils__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_pixi_utils__WEBPACK_IMPORTED_MODULE_3__);
const tempBounds = { x: 0, y: 0, width: 0, height: 0 };
/**
* A wrapper that manages the states of a Live2D core model, and delegates all operations to it.
* @emits {@link InternalModelEvents}
*/
class InternalModel extends _pixi_utils__WEBPACK_IMPORTED_MODULE_3__["EventEmitter"] {
constructor() {
super(...arguments);
this.focusController = new _cubism_common_FocusController__WEBPACK_IMPORTED_MODULE_1__[/* FocusController */ "a"]();
/**
* Original canvas width of the model. Note this doesn't represent the model's real size,
* as the model can overflow from its canvas.
*/
this.originalWidth = 0;
/**
* Original canvas height of the model. Note this doesn't represent the model's real size,
* as the model can overflow from its canvas.
*/
this.originalHeight = 0;
/**
* Canvas width of the model, scaled by the `width` of the model's layout.
*/
this.width = 0;
/**
* Canvas height of the model, scaled by the `height` of the model's layout.
*/
this.height = 0;
/**
* Local transformation, calculated from the model's layout.
*/
this.localTransform = new _pixi_math__WEBPACK_IMPORTED_MODULE_2__["Matrix"]();
/**
* The final matrix to draw the model.
*/
this.drawingMatrix = new _pixi_math__WEBPACK_IMPORTED_MODULE_2__["Matrix"]();
// TODO: change structure
/**
* The hit area definitions, keyed by their names.
*/
this.hitAreas = {};
/**
* Flags whether `gl.UNPACK_FLIP_Y_WEBGL` should be enabled when binding the textures.
*/
this.textureFlipY = false;
/**
* WebGL viewport when drawing the model. The format is `[x, y, width, height]`.
*/
this.viewport = [0, 0, 0, 0];
/**
* Flags this instance has been destroyed.
*/
this.destroyed = false;
}
/**
* Should be called in the constructor of derived class.
*/
init() {
this.setupLayout();
this.setupHitAreas();
}
/**
* Sets up the model's size and local transform by the model's layout.
*/
setupLayout() {
// cast `this` to be mutable
const self = this;
const size = this.getSize();
self.originalWidth = size[0];
self.originalHeight = size[1];
const layout = Object.assign({
width: _cubism_common_constants__WEBPACK_IMPORTED_MODULE_0__[/* LOGICAL_WIDTH */ "b"],
height: _cubism_common_constants__WEBPACK_IMPORTED_MODULE_0__[/* LOGICAL_HEIGHT */ "a"],
}, this.getLayout());
this.localTransform.scale(layout.width / _cubism_common_constants__WEBPACK_IMPORTED_MODULE_0__[/* LOGICAL_WIDTH */ "b"], layout.height / _cubism_common_constants__WEBPACK_IMPORTED_MODULE_0__[/* LOGICAL_HEIGHT */ "a"]);
self.width = this.originalWidth * this.localTransform.a;
self.height = this.originalHeight * this.localTransform.d;
// this calculation differs from Live2D SDK...
const offsetX = (layout.x !== undefined && layout.x - layout.width / 2)
|| (layout.centerX !== undefined && layout.centerX)
|| (layout.left !== undefined && layout.left - layout.width / 2)
|| (layout.right !== undefined && layout.right + layout.width / 2)
|| 0;
const offsetY = (layout.y !== undefined && layout.y - layout.height / 2)
|| (layout.centerY !== undefined && layout.centerY)
|| (layout.top !== undefined && layout.top - layout.height / 2)
|| (layout.bottom !== undefined && layout.bottom + layout.height / 2)
|| 0;
this.localTransform.translate(this.width * offsetX, -this.height * offsetY);
}
/**
* Sets up the hit areas by their definitions in settings.
*/
setupHitAreas() {
const definitions = this.getHitAreaDefs().filter(hitArea => hitArea.index >= 0);
for (const def of definitions) {
this.hitAreas[def.name] = def;
}
}
/**
* Hit-test on the model.
* @param x - Position in model canvas.
* @param y - Position in model canvas.
* @return The names of the *hit* hit areas. Can be empty if none is hit.
*/
hitTest(x, y) {
return Object.keys(this.hitAreas).filter(hitAreaName => this.isHit(hitAreaName, x, y));
}
/**
* Hit-test for a single hit area.
* @param hitAreaName - The hit area's name.
* @param x - Position in model canvas.
* @param y - Position in model canvas.
* @return True if hit.
*/
isHit(hitAreaName, x, y) {
if (!this.hitAreas[hitAreaName]) {
return false;
}
const drawIndex = this.hitAreas[hitAreaName].index;
const bounds = this.getDrawableBounds(drawIndex, tempBounds);
return bounds.x <= x && x <= bounds.x + bounds.width && bounds.y <= y && y <= bounds.y + bounds.height;
}
/**
* Gets a drawable's bounds.
* @param index - Index of the drawable.
* @param bounds - Object to store the output values.
* @return The bounds in model canvas space.
*/
getDrawableBounds(index, bounds) {
const vertices = this.getDrawableVertices(index);
let left = vertices[0];
let right = vertices[0];
let top = vertices[1];
let bottom = vertices[1];
for (let i = 0; i < vertices.length; i += 2) {
const vx = vertices[i];
const vy = vertices[i + 1];
left = Math.min(vx, left);
right = Math.max(vx, right);
top = Math.min(vy, top);
bottom = Math.max(vy, bottom);
}
bounds !== null && bounds !== void 0 ? bounds : (bounds = {});
bounds.x = left;
bounds.y = top;
bounds.width = right - left;
bounds.height = bottom - top;
return bounds;
}
/**
* Updates the model's transform.
* @param transform - The world transform.
*/
updateTransform(transform) {
this.drawingMatrix.copyFrom(transform).append(this.localTransform);
}
/**
* Updates the model's parameters.
* @param dt - Elapsed time in milliseconds from last frame.
* @param now - Current time in milliseconds.
*/
update(dt, now) {
this.focusController.update(dt);
}
;
/**
* Destroys the model and all related resources.
* @emits {@link InternalModelEvents.destroy | destroy}
*/
destroy() {
this.destroyed = true;
this.emit('destroy');
this.motionManager.destroy();
this.motionManager = undefined;
}
}
/***/ }),
/* 17 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return FocusController; });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
// Minimum distance to respond
const EPSILON = 0.01;
const MAX_SPEED = 40 / 7.5;
// the time to accelerate to max speed
const ACCELERATION_TIME = 1 / (0.15 * 1000);
/**
* Interpolates the transition of focus position.
*/
class FocusController {
constructor() {
/** The focus position. */
this.targetX = 0;
/** The focus position. */
this.targetY = 0;
/** Current position. */
this.x = 0;
/** Current position. */
this.y = 0;
/** Current velocity. */
this.vx = 0;
/** Current velocity. */
this.vy = 0;
}
/**
* Sets the focus position.
* @param x - X position in range `[-1, 1]`.
* @param y - Y position in range `[-1, 1]`.
* @param instant - Should the focus position be instantly applied.
*/
focus(x, y, instant = false) {
this.targetX = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[/* clamp */ "b"])(x, -1, 1);
this.targetY = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[/* clamp */ "b"])(y, -1, 1);
if (instant) {
this.x = this.targetX;
this.y = this.targetY;
}
}
/**
* Updates the interpolation.
* @param dt - Delta time in milliseconds.
*/
update(dt) {
const dx = this.targetX - this.x;
const dy = this.targetY - this.y;
if (Math.abs(dx) < EPSILON && Math.abs(dy) < EPSILON)
return;
const d = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
const maxSpeed = MAX_SPEED / (1000 / dt);
let ax = maxSpeed * (dx / d) - this.vx;
let ay = maxSpeed * (dy / d) - this.vy;
const a = Math.sqrt(Math.pow(ax, 2) + Math.pow(ay, 2));
const maxA = maxSpeed * ACCELERATION_TIME * dt;
if (a > maxA) {
ax *= maxA / a;
ay *= maxA / a;
}
this.vx += ax;
this.vy += ay;
const v = Math.sqrt(Math.pow(this.vx, 2) + Math.pow(this.vy, 2));
const maxV = 0.5 * (Math.sqrt(Math.pow(maxA, 2) + 8 * maxA * d) - maxA);
if (v > maxV) {
this.vx *= maxV / v;
this.vy *= maxV / v;
}
this.x += this.vx;
this.y += this.vy;
}
}
/***/ }),
/* 18 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return XHRLoader; });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
const TAG = 'XHRLoader';
class NetworkError extends Error {
constructor(message, url, status, aborted = false) {
super(message);
this.url = url;
this.status = status;
this.aborted = aborted;
}
}
/**
* The basic XHR loader.
*
* A network error will be thrown with the following properties:
* - `url` - The request URL.
* - `status` - The HTTP status.
* - `aborted` - True if the error is caused by aborting the XHR.
*/
class XHRLoader {
/**
* Creates a managed XHR.
* @param target - If provided, the XHR will be canceled when receiving an "destroy" event from the target.
* @param url - The URL.
* @param type - The XHR response type.
* @param onload - Load listener.
* @param onerror - Error handler.
*/
static createXHR(target, url, type, onload, onerror) {
const xhr = new XMLHttpRequest();
XHRLoader.allXhrSet.add(xhr);
if (target) {
let xhrSet = XHRLoader.xhrMap.get(target);
if (!xhrSet) {
xhrSet = new Set([xhr]);
XHRLoader.xhrMap.set(target, xhrSet);
}
else {
xhrSet.add(xhr);
}
if (!target.listeners('destroy').includes(XHRLoader.cancelXHRs)) {
target.once('destroy', XHRLoader.cancelXHRs);
}
}
xhr.open('GET', url);
xhr.responseType = type;
xhr.onload = () => {
if ((xhr.status === 200 || xhr.status === 0) && xhr.response) {
onload(xhr.response);
}
else {
xhr.onerror();
}
};
xhr.onerror = () => {
_utils__WEBPACK_IMPORTED_MODULE_0__[/* logger */ "f"].warn(TAG, `Failed to load resource as ${xhr.responseType} (Status ${xhr.status}): ${url}`);
onerror(new NetworkError('Network error.', url, xhr.status));
};
xhr.onabort = () => onerror(new NetworkError('Aborted.', url, xhr.status, true));
xhr.onloadend = () => {
var _a;
XHRLoader.allXhrSet.delete(xhr);
if (target) {
(_a = XHRLoader.xhrMap.get(target)) === null || _a === void 0 ? void 0 : _a.delete(xhr);
}
};
return xhr;
}
/**
* Cancels all XHRs related to this target.
*/
static cancelXHRs() {
var _a;
(_a = XHRLoader.xhrMap.get(this)) === null || _a === void 0 ? void 0 : _a.forEach(xhr => {
xhr.abort();
XHRLoader.allXhrSet.delete(xhr);
});
XHRLoader.xhrMap.delete(this);
}
/**
* Release all XHRs.
*/
static release() {
XHRLoader.allXhrSet.forEach(xhr => xhr.abort());
XHRLoader.allXhrSet.clear();
XHRLoader.xhrMap = new WeakMap();
}
}
/**
* All the created XHRs, keyed by their owners respectively.
*/
XHRLoader.xhrMap = new WeakMap();
/**
* All the created XHRs as a flat array.
*/
XHRLoader.allXhrSet = new Set();
/**
* Middleware for Live2DLoader.
*/
XHRLoader.loader = (context, next) => {
return new Promise((resolve, reject) => {
const xhr = XHRLoader.createXHR(context.target, context.settings ? context.settings.resolveURL(context.url) : context.url, context.type, data => {
context.result = data;
resolve();
}, reject);
xhr.send();
});
};
/***/ }),
/* 19 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return runMiddlewares; });
/**
* Run middlewares with given context.
* @see https://github.com/koajs/compose/blob/master/index.js
*
* @param middleware
* @param context
*/
function runMiddlewares(middleware, context) {
// last called middleware #
let index = -1;
return dispatch(0);
function dispatch(i, err) {
if (err)
return Promise.reject(err);
if (i <= index)
return Promise.reject(new Error('next() called multiple times'));
index = i;
const fn = middleware[i];
if (!fn)
return Promise.resolve();
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
}
catch (err) {
return Promise.reject(err);
}
}
}
/***/ }),
/* 20 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__20__;
/***/ }),
/* 21 */
/***/ (function(module, exports, __webpack_require__) {
var Symbol = __webpack_require__(22),
getRawTag = __webpack_require__(56),
objectToString = __webpack_require__(57);
/** `Object#toString` result references. */
var nullTag = '[object Null]',
undefinedTag = '[object Undefined]';
/** Built-in value references. */
var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
/**
* The base implementation of `getTag` without fallbacks for buggy environments.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function baseGetTag(value) {
if (value == null) {
return value === undefined ? undefinedTag : nullTag;
}
return (symToStringTag && symToStringTag in Object(value))
? getRawTag(value)
: objectToString(value);
}
module.exports = baseGetTag;
/***/ }),
/* 22 */
/***/ (function(module, exports, __webpack_require__) {
var root = __webpack_require__(9);
/** Built-in value references. */
var Symbol = root.Symbol;
module.exports = Symbol;
/***/ }),
/* 23 */
/***/ (function(module, exports) {
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike(value) {
return value != null && typeof value == 'object';
}
module.exports = isObjectLike;
/***/ }),
/* 24 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__24__;
/***/ }),
/* 25 */
/***/ (function(module, exports) {
/**
* This method returns the first argument it receives.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {*} value Any value.
* @returns {*} Returns `value`.
* @example
*
* var object = { 'a': 1 };
*
* console.log(_.identity(object) === object);
* // => true
*/
function identity(value) {
return value;
}
module.exports = identity;
/***/ }),
/* 26 */
/***/ (function(module, exports) {
/**
* Checks if `value` is the
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static