| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122 |
- var __pow = Math.pow;
- var __async = (__this, __arguments, generator) => {
- return new Promise((resolve, reject) => {
- var fulfilled = (value) => {
- try {
- step(generator.next(value));
- } catch (e) {
- reject(e);
- }
- };
- var rejected = (value) => {
- try {
- step(generator.throw(value));
- } catch (e) {
- reject(e);
- }
- };
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
- step((generator = generator.apply(__this, __arguments)).next());
- });
- };
- import { EventEmitter, url } from "@pixi/utils";
- import { Matrix, Transform, Point, ObservablePoint } from "@pixi/math";
- import { Texture } from "@pixi/core";
- import { Container } from "@pixi/display";
- const LOGICAL_WIDTH = 2;
- const LOGICAL_HEIGHT = 2;
- var CubismConfig;
- ((CubismConfig2) => {
- CubismConfig2.supportMoreMaskDivisions = true;
- CubismConfig2.setOpacityFromMotion = false;
- })(CubismConfig || (CubismConfig = {}));
- var config;
- ((config2) => {
- config2.LOG_LEVEL_VERBOSE = 0;
- config2.LOG_LEVEL_WARNING = 1;
- config2.LOG_LEVEL_ERROR = 2;
- config2.LOG_LEVEL_NONE = 999;
- config2.logLevel = config2.LOG_LEVEL_WARNING;
- config2.sound = true;
- config2.motionSync = true;
- config2.motionFadingDuration = 500;
- config2.idleMotionFadingDuration = 2e3;
- config2.expressionFadingDuration = 500;
- config2.preserveExpressionOnMotion = true;
- config2.cubism4 = CubismConfig;
- })(config || (config = {}));
- const VERSION = "0.4.0";
- const logger = {
- log(tag, ...messages) {
- if (config.logLevel <= config.LOG_LEVEL_VERBOSE) {
- console.log(`[${tag}]`, ...messages);
- }
- },
- warn(tag, ...messages) {
- if (config.logLevel <= config.LOG_LEVEL_WARNING) {
- console.warn(`[${tag}]`, ...messages);
- }
- },
- error(tag, ...messages) {
- if (config.logLevel <= config.LOG_LEVEL_ERROR) {
- console.error(`[${tag}]`, ...messages);
- }
- }
- };
- function clamp(num, lower, upper) {
- return num < lower ? lower : num > upper ? upper : num;
- }
- function rand(min, max) {
- return Math.random() * (max - min) + min;
- }
- function copyProperty(type, from, to, fromKey, toKey) {
- const value = from[fromKey];
- if (value !== null && typeof value === type) {
- to[toKey] = value;
- }
- }
- 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);
- }
- }
- 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));
- }
- });
- });
- }
- function folderName(url2) {
- let lastSlashIndex = url2.lastIndexOf("/");
- if (lastSlashIndex != -1) {
- url2 = url2.slice(0, lastSlashIndex);
- }
- lastSlashIndex = url2.lastIndexOf("/");
- if (lastSlashIndex !== -1) {
- url2 = url2.slice(lastSlashIndex + 1);
- }
- return url2;
- }
- function remove(array, item) {
- const index = array.indexOf(item);
- if (index !== -1) {
- array.splice(index, 1);
- }
- }
- class ExpressionManager extends EventEmitter {
- constructor(settings, options) {
- super();
- this.expressions = [];
- this.reserveExpressionIndex = -1;
- this.destroyed = false;
- this.settings = settings;
- this.tag = `ExpressionManager(${settings.name})`;
- }
- init() {
- this.defaultExpression = this.createExpression({}, void 0);
- this.currentExpression = this.defaultExpression;
- this.stopAllExpressions();
- }
- loadExpression(index) {
- return __async(this, null, function* () {
- if (!this.definitions[index]) {
- logger.warn(this.tag, `Undefined expression at [${index}]`);
- return void 0;
- }
- if (this.expressions[index] === null) {
- logger.warn(this.tag, `Cannot set expression at [${index}] because it's already failed in loading.`);
- return void 0;
- }
- if (this.expressions[index]) {
- return this.expressions[index];
- }
- const expression = yield this._loadExpression(index);
- this.expressions[index] = expression;
- return expression;
- });
- }
- _loadExpression(index) {
- throw new Error("Not implemented.");
- }
- setRandomExpression() {
- return __async(this, null, 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;
- });
- }
- resetExpression() {
- this._setExpression(this.defaultExpression);
- }
- restoreExpression() {
- this._setExpression(this.currentExpression);
- }
- setExpression(index) {
- return __async(this, null, 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;
- });
- }
- update(model, now) {
- if (!this.isFinished()) {
- return this.updateParameters(model, now);
- }
- return false;
- }
- destroy() {
- this.destroyed = true;
- this.emit("destroy");
- const self = this;
- self.definitions = void 0;
- self.expressions = void 0;
- }
- }
- const EPSILON = 0.01;
- const MAX_SPEED = 40 / 7.5;
- const ACCELERATION_TIME = 1 / (0.15 * 1e3);
- class FocusController {
- constructor() {
- this.targetX = 0;
- this.targetY = 0;
- this.x = 0;
- this.y = 0;
- this.vx = 0;
- this.vy = 0;
- }
- focus(x, y, instant = false) {
- this.targetX = clamp(x, -1, 1);
- this.targetY = clamp(y, -1, 1);
- if (instant) {
- this.x = this.targetX;
- this.y = this.targetY;
- }
- }
- 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(__pow(dx, 2) + __pow(dy, 2));
- const maxSpeed = MAX_SPEED / (1e3 / dt);
- let ax = maxSpeed * (dx / d) - this.vx;
- let ay = maxSpeed * (dy / d) - this.vy;
- const a = Math.sqrt(__pow(ax, 2) + __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(__pow(this.vx, 2) + __pow(this.vy, 2));
- const maxV = 0.5 * (Math.sqrt(__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;
- }
- }
- class ModelSettings {
- constructor(json) {
- this.json = json;
- let url2 = json.url;
- if (typeof url2 !== "string") {
- throw new TypeError("The `url` field in settings JSON must be defined as a string.");
- }
- this.url = url2;
- this.name = folderName(this.url);
- }
- resolveURL(path) {
- return url.resolve(this.url, path);
- }
- replaceFiles(replacer) {
- this.moc = replacer(this.moc, "moc");
- if (this.pose !== void 0) {
- this.pose = replacer(this.pose, "pose");
- }
- if (this.physics !== void 0) {
- this.physics = replacer(this.physics, "physics");
- }
- for (let i = 0; i < this.textures.length; i++) {
- this.textures[i] = replacer(this.textures[i], `textures[${i}]`);
- }
- }
- getDefinedFiles() {
- const files = [];
- this.replaceFiles((file) => {
- files.push(file);
- return file;
- });
- return 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));
- }
- }
- var MotionPriority = /* @__PURE__ */ ((MotionPriority2) => {
- MotionPriority2[MotionPriority2["NONE"] = 0] = "NONE";
- MotionPriority2[MotionPriority2["IDLE"] = 1] = "IDLE";
- MotionPriority2[MotionPriority2["NORMAL"] = 2] = "NORMAL";
- MotionPriority2[MotionPriority2["FORCE"] = 3] = "FORCE";
- return MotionPriority2;
- })(MotionPriority || {});
- class MotionState {
- constructor() {
- this.debug = false;
- this.currentPriority = 0;
- this.reservePriority = 0;
- }
- reserve(group, index, priority) {
- if (priority <= 0) {
- logger.log(this.tag, `Cannot start a motion with MotionPriority.NONE.`);
- return false;
- }
- if (group === this.currentGroup && index === this.currentIndex) {
- logger.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) {
- logger.log(this.tag, `Motion is already reserved.`, this.dump(group, index));
- return false;
- }
- if (priority === 1) {
- if (this.currentPriority !== 0) {
- logger.log(this.tag, `Cannot start idle motion because another motion is playing.`, this.dump(group, index));
- return false;
- }
- if (this.reservedIdleGroup !== void 0) {
- logger.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 < 3) {
- if (priority <= this.currentPriority) {
- logger.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) {
- logger.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;
- }
- start(motion, group, index, priority) {
- if (priority === 1) {
- this.setReservedIdle(void 0, void 0);
- if (this.currentPriority !== 0) {
- logger.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) {
- logger.log(this.tag, "Cannot start motion because another motion has taken the place.", this.dump(group, index));
- return false;
- }
- this.setReserved(void 0, void 0, 0);
- }
- if (!motion) {
- return false;
- }
- this.setCurrent(group, index, priority);
- return true;
- }
- complete() {
- this.setCurrent(void 0, void 0, 0);
- }
- setCurrent(group, index, priority) {
- this.currentPriority = priority;
- this.currentGroup = group;
- this.currentIndex = index;
- }
- setReserved(group, index, priority) {
- this.reservePriority = priority;
- this.reservedGroup = group;
- this.reservedIndex = index;
- }
- setReservedIdle(group, index) {
- this.reservedIdleGroup = group;
- this.reservedIdleIndex = index;
- }
- isActive(group, index) {
- return group === this.currentGroup && index === this.currentIndex || group === this.reservedGroup && index === this.reservedIndex || group === this.reservedIdleGroup && index === this.reservedIdleIndex;
- }
- reset() {
- this.setCurrent(void 0, void 0, 0);
- this.setReserved(void 0, void 0, 0);
- this.setReservedIdle(void 0, void 0);
- }
- shouldRequestIdleMotion() {
- return this.currentGroup === void 0 && this.reservedIdleGroup === void 0;
- }
- shouldOverrideExpression() {
- return !config.preserveExpressionOnMotion && this.currentPriority > 1;
- }
- dump(requestedGroup, requestedIndex) {
- if (this.debug) {
- const keys = [
- "currentPriority",
- "reservePriority",
- "currentGroup",
- "currentIndex",
- "reservedGroup",
- "reservedIndex",
- "reservedIdleGroup",
- "reservedIdleIndex"
- ];
- return `
- <Requested> group = "${requestedGroup}", index = ${requestedIndex}
- ` + keys.map((key) => "[" + key + "] " + this[key]).join("\n");
- }
- return "";
- }
- }
- const TAG$2 = "SoundManager";
- const VOLUME = 0.5;
- class SoundManager {
- 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);
- }
- 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 ? void 0 : onFinish();
- });
- audio.addEventListener("error", (e) => {
- this.dispose(audio);
- logger.warn(TAG$2, `Error occurred on "${file}"`, e.error);
- onError == null ? void 0 : onError(e.error);
- });
- this.audios.push(audio);
- return audio;
- }
- static play(audio) {
- return new Promise((resolve, reject) => {
- var _a;
- (_a = audio.play()) == null ? 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);
- }
- });
- }
- static dispose(audio) {
- audio.pause();
- audio.removeAttribute("src");
- remove(this.audios, audio);
- }
- static destroy() {
- for (let i = this.audios.length - 1; i >= 0; i--) {
- this.dispose(this.audios[i]);
- }
- }
- }
- SoundManager.audios = [];
- SoundManager._volume = VOLUME;
- var MotionPreloadStrategy = /* @__PURE__ */ ((MotionPreloadStrategy2) => {
- MotionPreloadStrategy2["ALL"] = "ALL";
- MotionPreloadStrategy2["IDLE"] = "IDLE";
- MotionPreloadStrategy2["NONE"] = "NONE";
- return MotionPreloadStrategy2;
- })(MotionPreloadStrategy || {});
- class MotionManager extends EventEmitter {
- constructor(settings, options) {
- super();
- this.motionGroups = {};
- this.state = new MotionState();
- this.playing = false;
- this.destroyed = false;
- this.settings = settings;
- this.tag = `MotionManager(${settings.name})`;
- this.state.tag = this.tag;
- }
- init(options) {
- if (options == null ? void 0 : options.idleMotionGroup) {
- this.groups.idle = options.idleMotionGroup;
- }
- this.setupMotions(options);
- this.stopAllMotions();
- }
- setupMotions(options) {
- for (const group of Object.keys(this.definitions)) {
- this.motionGroups[group] = [];
- }
- let groups;
- switch (options == null ? void 0 : options.motionPreload) {
- case "NONE":
- return;
- case "ALL":
- groups = Object.keys(this.definitions);
- break;
- case "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();
- }
- }
- }
- }
- loadMotion(group, index) {
- return __async(this, null, function* () {
- var _a;
- if (!((_a = this.definitions[group]) == null ? void 0 : _a[index])) {
- logger.warn(this.tag, `Undefined motion at "${group}"[${index}]`);
- return void 0;
- }
- if (this.motionGroups[group][index] === null) {
- logger.warn(this.tag, `Cannot start motion at "${group}"[${index}] because it's already failed in loading.`);
- return void 0;
- }
- 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 : null;
- return motion;
- });
- }
- _loadMotion(group, index) {
- throw new Error("Not implemented.");
- }
- startMotion(_0, _1) {
- return __async(this, arguments, function* (group, index, priority = MotionPriority.NORMAL) {
- var _a;
- if (!this.state.reserve(group, index, priority)) {
- return false;
- }
- const definition = (_a = this.definitions[group]) == null ? void 0 : _a[index];
- if (!definition) {
- return false;
- }
- if (this.currentAudio) {
- SoundManager.dispose(this.currentAudio);
- }
- let audio;
- if (config.sound) {
- const soundURL = this.getSoundFile(definition);
- if (soundURL) {
- try {
- audio = SoundManager.add(this.settings.resolveURL(soundURL), () => this.currentAudio = void 0, () => this.currentAudio = void 0);
- this.currentAudio = audio;
- } catch (e) {
- logger.warn(this.tag, "Failed to create audio", soundURL, e);
- }
- }
- }
- const motion = yield this.loadMotion(group, index);
- if (audio) {
- const readyToPlay = SoundManager.play(audio).catch((e) => logger.warn(this.tag, "Failed to play audio", audio.src, e));
- if (config.motionSync) {
- yield readyToPlay;
- }
- }
- if (!this.state.start(motion, group, index, priority)) {
- if (audio) {
- SoundManager.dispose(audio);
- this.currentAudio = void 0;
- }
- return false;
- }
- logger.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;
- });
- }
- startRandomMotion(group, priority) {
- return __async(this, null, function* () {
- const groupDefs = this.definitions[group];
- if (groupDefs == null ? 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;
- });
- }
- stopAllMotions() {
- this._stopAllMotions();
- this.state.reset();
- if (this.currentAudio) {
- SoundManager.dispose(this.currentAudio);
- this.currentAudio = void 0;
- }
- }
- update(model, now) {
- var _a;
- if (this.isFinished()) {
- if (this.playing) {
- this.playing = false;
- this.emit("motionFinish");
- }
- if (this.state.shouldOverrideExpression()) {
- (_a = this.expressionManager) == null ? void 0 : _a.restoreExpression();
- }
- this.state.complete();
- if (this.state.shouldRequestIdleMotion()) {
- this.startRandomMotion(this.groups.idle, MotionPriority.IDLE);
- }
- }
- return this.updateParameters(model, now);
- }
- destroy() {
- var _a;
- this.destroyed = true;
- this.emit("destroy");
- this.stopAllMotions();
- (_a = this.expressionManager) == null ? void 0 : _a.destroy();
- const self = this;
- self.definitions = void 0;
- self.motionGroups = void 0;
- }
- }
- const tempBounds = { x: 0, y: 0, width: 0, height: 0 };
- class InternalModel extends EventEmitter {
- constructor() {
- super(...arguments);
- this.focusController = new FocusController();
- this.originalWidth = 0;
- this.originalHeight = 0;
- this.width = 0;
- this.height = 0;
- this.localTransform = new Matrix();
- this.drawingMatrix = new Matrix();
- this.hitAreas = {};
- this.textureFlipY = false;
- this.viewport = [0, 0, 0, 0];
- this.destroyed = false;
- }
- init() {
- this.setupLayout();
- this.setupHitAreas();
- }
- setupLayout() {
- const self = this;
- const size = this.getSize();
- self.originalWidth = size[0];
- self.originalHeight = size[1];
- const layout = Object.assign({
- width: LOGICAL_WIDTH,
- height: LOGICAL_HEIGHT
- }, this.getLayout());
- this.localTransform.scale(layout.width / LOGICAL_WIDTH, layout.height / LOGICAL_HEIGHT);
- self.width = this.originalWidth * this.localTransform.a;
- self.height = this.originalHeight * this.localTransform.d;
- const offsetX = layout.x !== void 0 && layout.x - layout.width / 2 || layout.centerX !== void 0 && layout.centerX || layout.left !== void 0 && layout.left - layout.width / 2 || layout.right !== void 0 && layout.right + layout.width / 2 || 0;
- const offsetY = layout.y !== void 0 && layout.y - layout.height / 2 || layout.centerY !== void 0 && layout.centerY || layout.top !== void 0 && layout.top - layout.height / 2 || layout.bottom !== void 0 && layout.bottom + layout.height / 2 || 0;
- this.localTransform.translate(this.width * offsetX, -this.height * offsetY);
- }
- setupHitAreas() {
- const definitions = this.getHitAreaDefs().filter((hitArea) => hitArea.index >= 0);
- for (const def of definitions) {
- this.hitAreas[def.name] = def;
- }
- }
- hitTest(x, y) {
- return Object.keys(this.hitAreas).filter((hitAreaName) => this.isHit(hitAreaName, x, y));
- }
- 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;
- }
- 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 : bounds = {};
- bounds.x = left;
- bounds.y = top;
- bounds.width = right - left;
- bounds.height = bottom - top;
- return bounds;
- }
- updateTransform(transform) {
- this.drawingMatrix.copyFrom(transform).append(this.localTransform);
- }
- update(dt, now) {
- this.focusController.update(dt);
- }
- destroy() {
- this.destroyed = true;
- this.emit("destroy");
- this.motionManager.destroy();
- this.motionManager = void 0;
- }
- }
- const TAG$1 = "XHRLoader";
- class NetworkError extends Error {
- constructor(message, url2, status, aborted = false) {
- super(message);
- this.url = url2;
- this.status = status;
- this.aborted = aborted;
- }
- }
- const _XHRLoader = class {
- static createXHR(target, url2, type, onload, onerror) {
- const xhr = new XMLHttpRequest();
- _XHRLoader.allXhrSet.add(xhr);
- if (target) {
- let xhrSet = _XHRLoader.xhrMap.get(target);
- if (!xhrSet) {
- xhrSet = /* @__PURE__ */ 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", url2);
- xhr.responseType = type;
- xhr.onload = () => {
- if ((xhr.status === 200 || xhr.status === 0) && xhr.response) {
- onload(xhr.response);
- } else {
- xhr.onerror();
- }
- };
- xhr.onerror = () => {
- logger.warn(TAG$1, `Failed to load resource as ${xhr.responseType} (Status ${xhr.status}): ${url2}`);
- onerror(new NetworkError("Network error.", url2, xhr.status));
- };
- xhr.onabort = () => onerror(new NetworkError("Aborted.", url2, xhr.status, true));
- xhr.onloadend = () => {
- var _a;
- _XHRLoader.allXhrSet.delete(xhr);
- if (target) {
- (_a = _XHRLoader.xhrMap.get(target)) == null ? void 0 : _a.delete(xhr);
- }
- };
- return xhr;
- }
- static cancelXHRs() {
- var _a;
- (_a = _XHRLoader.xhrMap.get(this)) == null ? void 0 : _a.forEach((xhr) => {
- xhr.abort();
- _XHRLoader.allXhrSet.delete(xhr);
- });
- _XHRLoader.xhrMap.delete(this);
- }
- static release() {
- _XHRLoader.allXhrSet.forEach((xhr) => xhr.abort());
- _XHRLoader.allXhrSet.clear();
- _XHRLoader.xhrMap = /* @__PURE__ */ new WeakMap();
- }
- };
- let XHRLoader = _XHRLoader;
- XHRLoader.xhrMap = /* @__PURE__ */ new WeakMap();
- XHRLoader.allXhrSet = /* @__PURE__ */ new Set();
- 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();
- });
- };
- function runMiddlewares(middleware, context) {
- 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 (err2) {
- return Promise.reject(err2);
- }
- }
- }
- class Live2DLoader {
- static load(context) {
- return runMiddlewares(this.middlewares, context).then(() => context.result);
- }
- }
- Live2DLoader.middlewares = [XHRLoader.loader];
- function createTexture(url2, options = {}) {
- var _a;
- const textureOptions = { resourceOptions: { crossorigin: options.crossOrigin } };
- if (Texture.fromURL) {
- return Texture.fromURL(url2, textureOptions).catch((e) => {
- if (e instanceof Error) {
- throw e;
- }
- const err = new Error("Texture loading error");
- err.event = e;
- throw err;
- });
- }
- textureOptions.resourceOptions.autoLoad = false;
- const texture = Texture.from(url2, textureOptions);
- if (texture.baseTexture.valid) {
- return Promise.resolve(texture);
- }
- const resource = texture.baseTexture.resource;
- (_a = resource._live2d_load) != null ? _a : resource._live2d_load = new Promise((resolve, reject) => {
- const errorHandler = (event) => {
- resource.source.removeEventListener("error", errorHandler);
- 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;
- }
- const TAG = "Live2DFactory";
- const urlToJSON = (context, next) => __async(void 0, null, function* () {
- if (typeof context.source === "string") {
- const data = yield Live2DLoader.load({
- url: context.source,
- type: "json",
- target: context.live2dModel
- });
- data.url = context.source;
- context.source = data;
- context.live2dModel.emit("settingsJSONLoaded", data);
- }
- return next();
- });
- const jsonToSettings = (context, next) => __async(void 0, null, function* () {
- if (context.source instanceof ModelSettings) {
- context.settings = context.source;
- return next();
- } else if (typeof context.source === "object") {
- const runtime = 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.findRuntime(context.settings);
- if (runtime) {
- return runtime.ready().then(next);
- }
- }
- return next();
- };
- const setupOptionals = (context, next) => __async(void 0, null, function* () {
- yield next();
- const internalModel = context.internalModel;
- if (internalModel) {
- const settings = context.settings;
- const runtime = Live2DFactory.findRuntime(settings);
- if (runtime) {
- const tasks = [];
- if (settings.pose) {
- tasks.push(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) => {
- context.live2dModel.emit("poseLoadError", e);
- logger.warn(TAG, "Failed to load pose.", e);
- }));
- }
- if (settings.physics) {
- tasks.push(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) => {
- context.live2dModel.emit("physicsLoadError", e);
- logger.warn(TAG, "Failed to load physics.", e);
- }));
- }
- if (tasks.length) {
- yield Promise.all(tasks);
- }
- }
- }
- });
- const setupEssentials = (context, next) => __async(void 0, null, function* () {
- if (context.settings) {
- const live2DModel = context.live2dModel;
- const textureLoadings = context.settings.textures.map((tex) => {
- const url2 = context.settings.resolveURL(tex);
- return createTexture(url2, { crossOrigin: context.options.crossOrigin });
- });
- 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.");
- }
- });
- const createInternalModel = (context, next) => __async(void 0, null, function* () {
- const settings = context.settings;
- if (settings instanceof ModelSettings) {
- const runtime = Live2DFactory.findRuntime(settings);
- if (!runtime) {
- throw new TypeError("Unknown model settings.");
- }
- const modelData = yield 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.");
- });
- const _Live2DFactory = class {
- static registerRuntime(runtime) {
- _Live2DFactory.runtimes.push(runtime);
- _Live2DFactory.runtimes.sort((a, b) => b.version - a.version);
- }
- static findRuntime(source) {
- for (const runtime of _Live2DFactory.runtimes) {
- if (runtime.test(source)) {
- return runtime;
- }
- }
- }
- static setupLive2DModel(live2dModel, source, options) {
- return __async(this, null, function* () {
- const textureLoaded = new Promise((resolve) => live2dModel.once("textureLoaded", resolve));
- const modelLoaded = new Promise((resolve) => live2dModel.once("modelLoaded", resolve));
- const readyEventEmitted = Promise.all([textureLoaded, modelLoaded]).then(() => live2dModel.emit("ready"));
- yield runMiddlewares(_Live2DFactory.live2DModelMiddlewares, {
- live2dModel,
- source,
- options: options || {}
- });
- yield readyEventEmitted;
- live2dModel.emit("load");
- });
- }
- static loadMotion(motionManager, group, index) {
- var _a, _b;
- const handleError = (e) => motionManager.emit("motionLoadError", group, index, e);
- try {
- const definition = (_a = motionManager.definitions[group]) == null ? void 0 : _a[index];
- if (!definition) {
- return Promise.resolve(void 0);
- }
- if (!motionManager.listeners("destroy").includes(_Live2DFactory.releaseTasks)) {
- motionManager.once("destroy", _Live2DFactory.releaseTasks);
- }
- let tasks = _Live2DFactory.motionTasksMap.get(motionManager);
- if (!tasks) {
- tasks = {};
- _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 : taskGroup[index] = Live2DLoader.load({
- url: path,
- settings: motionManager.settings,
- type: motionManager.motionDataType,
- target: motionManager
- }).then((data) => {
- var _a2;
- const taskGroup2 = (_a2 = _Live2DFactory.motionTasksMap.get(motionManager)) == null ? void 0 : _a2[group];
- if (taskGroup2) {
- delete taskGroup2[index];
- }
- const motion = motionManager.createMotion(data, group, definition);
- motionManager.emit("motionLoaded", group, index, motion);
- return motion;
- }).catch((e) => {
- logger.warn(motionManager.tag, `Failed to load motion: ${path}
- `, e);
- handleError(e);
- });
- return taskGroup[index];
- } catch (e) {
- logger.warn(motionManager.tag, `Failed to load motion at "${group}"[${index}]
- `, e);
- handleError(e);
- }
- return Promise.resolve(void 0);
- }
- static loadExpression(expressionManager, index) {
- var _a;
- const handleError = (e) => expressionManager.emit("expressionLoadError", index, e);
- try {
- const definition = expressionManager.definitions[index];
- if (!definition) {
- return Promise.resolve(void 0);
- }
- if (!expressionManager.listeners("destroy").includes(_Live2DFactory.releaseTasks)) {
- expressionManager.once("destroy", _Live2DFactory.releaseTasks);
- }
- let tasks = _Live2DFactory.expressionTasksMap.get(expressionManager);
- if (!tasks) {
- tasks = [];
- _Live2DFactory.expressionTasksMap.set(expressionManager, tasks);
- }
- const path = expressionManager.getExpressionFile(definition);
- (_a = tasks[index]) != null ? _a : tasks[index] = Live2DLoader.load({
- url: path,
- settings: expressionManager.settings,
- type: "json",
- target: expressionManager
- }).then((data) => {
- const tasks2 = _Live2DFactory.expressionTasksMap.get(expressionManager);
- if (tasks2) {
- delete tasks2[index];
- }
- const expression = expressionManager.createExpression(data, definition);
- expressionManager.emit("expressionLoaded", index, expression);
- return expression;
- }).catch((e) => {
- logger.warn(expressionManager.tag, `Failed to load expression: ${path}
- `, e);
- handleError(e);
- });
- return tasks[index];
- } catch (e) {
- logger.warn(expressionManager.tag, `Failed to load expression at [${index}]
- `, e);
- handleError(e);
- }
- return Promise.resolve(void 0);
- }
- static releaseTasks() {
- if (this instanceof MotionManager) {
- _Live2DFactory.motionTasksMap.delete(this);
- } else {
- _Live2DFactory.expressionTasksMap.delete(this);
- }
- }
- };
- let Live2DFactory = _Live2DFactory;
- Live2DFactory.runtimes = [];
- Live2DFactory.urlToJSON = urlToJSON;
- Live2DFactory.jsonToSettings = jsonToSettings;
- Live2DFactory.waitUntilReady = waitUntilReady;
- Live2DFactory.setupOptionals = setupOptionals;
- Live2DFactory.setupEssentials = setupEssentials;
- Live2DFactory.createInternalModel = createInternalModel;
- Live2DFactory.live2DModelMiddlewares = [
- urlToJSON,
- jsonToSettings,
- waitUntilReady,
- setupOptionals,
- setupEssentials,
- createInternalModel
- ];
- Live2DFactory.motionTasksMap = /* @__PURE__ */ new WeakMap();
- Live2DFactory.expressionTasksMap = /* @__PURE__ */ new WeakMap();
- MotionManager.prototype["_loadMotion"] = function(group, index) {
- return Live2DFactory.loadMotion(this, group, index);
- };
- ExpressionManager.prototype["_loadExpression"] = function(index) {
- return Live2DFactory.loadExpression(this, index);
- };
- class InteractionMixin {
- constructor() {
- this._autoInteract = false;
- }
- get autoInteract() {
- return this._autoInteract;
- }
- set autoInteract(autoInteract) {
- if (autoInteract !== this._autoInteract) {
- if (autoInteract) {
- this.on("pointertap", onTap, this);
- } else {
- this.off("pointertap", onTap, this);
- }
- this._autoInteract = autoInteract;
- }
- }
- registerInteraction(manager) {
- if (manager !== this.interactionManager) {
- this.unregisterInteraction();
- if (this._autoInteract && manager) {
- this.interactionManager = manager;
- manager.on("pointermove", onPointerMove, this);
- }
- }
- }
- unregisterInteraction() {
- var _a;
- if (this.interactionManager) {
- (_a = this.interactionManager) == null ? void 0 : _a.off("pointermove", onPointerMove, this);
- this.interactionManager = void 0;
- }
- }
- }
- function onTap(event) {
- this.tap(event.data.global.x, event.data.global.y);
- }
- function onPointerMove(event) {
- this.focus(event.data.global.x, event.data.global.y);
- }
- class Live2DTransform extends Transform {
- }
- const tempPoint = new Point();
- const tempMatrix = new Matrix();
- let tickerRef;
- class Live2DModel extends Container {
- constructor(options) {
- super();
- this.tag = "Live2DModel(uninitialized)";
- this.textures = [];
- this.transform = new Live2DTransform();
- this.anchor = new ObservablePoint(this.onAnchorChange, this, 0, 0);
- this.glContextID = -1;
- this.elapsedTime = performance.now();
- this.deltaTime = 0;
- this._autoUpdate = false;
- this.once("modelLoaded", () => this.init(options));
- }
- static from(source, options) {
- const model = new this(options);
- return Live2DFactory.setupLive2DModel(model, source, options).then(() => model);
- }
- static fromSync(source, options) {
- const model = new this(options);
- Live2DFactory.setupLive2DModel(model, source, options).then(options == null ? void 0 : options.onLoad).catch(options == null ? void 0 : options.onError);
- return model;
- }
- static registerTicker(tickerClass) {
- tickerRef = tickerClass;
- }
- get autoUpdate() {
- return this._autoUpdate;
- }
- set autoUpdate(autoUpdate) {
- var _a;
- tickerRef || (tickerRef = (_a = window.PIXI) == null ? void 0 : _a.Ticker);
- if (autoUpdate) {
- if (!this._destroyed) {
- if (tickerRef) {
- tickerRef.shared.add(this.onTickerUpdate, this);
- this._autoUpdate = true;
- } else {
- logger.warn(this.tag, "No Ticker registered, please call Live2DModel.registerTicker(Ticker).");
- }
- }
- } else {
- tickerRef == null ? void 0 : tickerRef.shared.remove(this.onTickerUpdate, this);
- this._autoUpdate = false;
- }
- }
- init(options) {
- this.tag = `Live2DModel(${this.internalModel.settings.name})`;
- const _options = Object.assign({
- autoUpdate: true,
- autoInteract: true
- }, options);
- if (_options.autoInteract) {
- this.interactive = true;
- }
- this.autoInteract = _options.autoInteract;
- this.autoUpdate = _options.autoUpdate;
- }
- onAnchorChange() {
- this.pivot.set(this.anchor.x * this.internalModel.width, this.anchor.y * this.internalModel.height);
- }
- motion(group, index, priority) {
- return index === void 0 ? this.internalModel.motionManager.startRandomMotion(group, priority) : this.internalModel.motionManager.startMotion(group, index, priority);
- }
- expression(id) {
- if (this.internalModel.motionManager.expressionManager) {
- return id === void 0 ? this.internalModel.motionManager.expressionManager.setRandomExpression() : this.internalModel.motionManager.expressionManager.setExpression(id);
- }
- return Promise.resolve(false);
- }
- focus(x, y, instant = false) {
- tempPoint.x = x;
- tempPoint.y = y;
- this.toModelPosition(tempPoint, tempPoint, true);
- let tx = tempPoint.x / this.internalModel.originalWidth * 2 - 1;
- let ty = tempPoint.y / this.internalModel.originalHeight * 2 - 1;
- let radian = Math.atan2(ty, tx);
- this.internalModel.focusController.focus(Math.cos(radian), -Math.sin(radian), instant);
- }
- tap(x, y) {
- const hitAreaNames = this.hitTest(x, y);
- if (hitAreaNames.length) {
- logger.log(this.tag, `Hit`, hitAreaNames);
- this.emit("hit", hitAreaNames);
- }
- }
- hitTest(x, y) {
- tempPoint.x = x;
- tempPoint.y = y;
- this.toModelPosition(tempPoint, tempPoint);
- return this.internalModel.hitTest(tempPoint.x, tempPoint.y);
- }
- toModelPosition(position, result = position.clone(), skipUpdate) {
- if (!skipUpdate) {
- this._recursivePostUpdateTransform();
- if (!this.parent) {
- this.parent = this._tempDisplayObjectParent;
- this.displayObjectUpdateTransform();
- this.parent = null;
- } else {
- this.displayObjectUpdateTransform();
- }
- }
- this.transform.worldTransform.applyInverse(position, result);
- this.internalModel.localTransform.applyInverse(result, result);
- return result;
- }
- containsPoint(point) {
- return this.getBounds(true).contains(point.x, point.y);
- }
- _calculateBounds() {
- this._bounds.addFrame(this.transform, 0, 0, this.internalModel.width, this.internalModel.height);
- }
- onTickerUpdate() {
- this.update(tickerRef.shared.deltaMS);
- }
- update(dt) {
- this.deltaTime += dt;
- this.elapsedTime += dt;
- }
- _render(renderer) {
- this.registerInteraction(renderer.plugins.interaction);
- renderer.batch.reset();
- renderer.geometry.reset();
- renderer.shader.reset();
- renderer.state.reset();
- let shouldUpdateTexture = false;
- if (this.glContextID !== renderer.CONTEXT_UID) {
- this.glContextID = renderer.CONTEXT_UID;
- this.internalModel.updateWebGLContext(renderer.gl, this.glContextID);
- shouldUpdateTexture = true;
- }
- for (let i = 0; i < this.textures.length; i++) {
- const texture = this.textures[i];
- if (!texture.valid) {
- continue;
- }
- if (shouldUpdateTexture || !texture.baseTexture._glTextures[this.glContextID]) {
- renderer.gl.pixelStorei(WebGLRenderingContext.UNPACK_FLIP_Y_WEBGL, this.internalModel.textureFlipY);
- renderer.texture.bind(texture.baseTexture, 0);
- }
- this.internalModel.bindTexture(i, texture.baseTexture._glTextures[this.glContextID].texture);
- texture.baseTexture.touched = renderer.textureGC.count;
- }
- const viewport = renderer.framebuffer.viewport;
- this.internalModel.viewport = [viewport.x, viewport.y, viewport.width, viewport.height];
- if (this.deltaTime) {
- this.internalModel.update(this.deltaTime, this.elapsedTime);
- this.deltaTime = 0;
- }
- const internalTransform = tempMatrix.copyFrom(renderer.globalUniforms.uniforms.projectionMatrix).append(this.worldTransform);
- this.internalModel.updateTransform(internalTransform);
- this.internalModel.draw(renderer.gl);
- renderer.state.reset();
- renderer.texture.reset();
- }
- destroy(options) {
- this.emit("destroy");
- this.autoUpdate = false;
- this.unregisterInteraction();
- if (options == null ? void 0 : options.texture) {
- this.textures.forEach((texture) => texture.destroy(options.baseTexture));
- }
- this.internalModel.destroy();
- super.destroy(options);
- }
- }
- applyMixins(Live2DModel, [InteractionMixin]);
- const _FileLoader = class {
- static resolveURL(settingsURL, filePath) {
- var _a;
- const resolved = (_a = _FileLoader.filesMap[settingsURL]) == null ? void 0 : _a[filePath];
- if (resolved === void 0) {
- throw new Error("Cannot find this file from uploaded files: " + filePath);
- }
- return resolved;
- }
- static upload(files, settings) {
- return __async(this, null, function* () {
- const fileMap = {};
- for (const definedFile of settings.getDefinedFiles()) {
- const actualPath = decodeURI(url.resolve(settings.url, definedFile));
- const actualFile = files.find((file) => file.webkitRelativePath === actualPath);
- if (actualFile) {
- fileMap[definedFile] = URL.createObjectURL(actualFile);
- }
- }
- _FileLoader.filesMap[settings._objectURL] = fileMap;
- });
- }
- static createSettings(files) {
- return __async(this, null, function* () {
- const settingsFile = files.find((file) => file.name.endsWith("model.json") || file.name.endsWith("model3.json"));
- if (!settingsFile) {
- throw new TypeError("Settings file not found");
- }
- const settingsText = yield _FileLoader.readText(settingsFile);
- const settingsJSON = JSON.parse(settingsText);
- settingsJSON.url = settingsFile.webkitRelativePath;
- const runtime = Live2DFactory.findRuntime(settingsJSON);
- if (!runtime) {
- throw new Error("Unknown settings JSON");
- }
- const settings = runtime.createModelSettings(settingsJSON);
- settings._objectURL = URL.createObjectURL(settingsFile);
- return settings;
- });
- }
- static readText(file) {
- return __async(this, null, function* () {
- return new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onload = () => resolve(reader.result);
- reader.onerror = reject;
- reader.readAsText(file, "utf8");
- });
- });
- }
- };
- let FileLoader = _FileLoader;
- FileLoader.filesMap = {};
- FileLoader.factory = (context, next) => __async(void 0, null, function* () {
- if (Array.isArray(context.source) && context.source[0] instanceof File) {
- const files = context.source;
- let settings = files.settings;
- if (!settings) {
- settings = yield _FileLoader.createSettings(files);
- } else if (!settings._objectURL) {
- throw new Error('"_objectURL" must be specified in ModelSettings');
- }
- settings.validateFiles(files.map((file) => encodeURI(file.webkitRelativePath)));
- yield _FileLoader.upload(files, settings);
- settings.resolveURL = function(url2) {
- return _FileLoader.resolveURL(this._objectURL, url2);
- };
- context.source = settings;
- context.live2dModel.once("modelLoaded", (internalModel) => {
- internalModel.once("destroy", function() {
- const objectURL = this.settings._objectURL;
- URL.revokeObjectURL(objectURL);
- if (_FileLoader.filesMap[objectURL]) {
- for (const resourceObjectURL of Object.values(_FileLoader.filesMap[objectURL])) {
- URL.revokeObjectURL(resourceObjectURL);
- }
- }
- delete _FileLoader.filesMap[objectURL];
- });
- });
- }
- return next();
- });
- Live2DFactory.live2DModelMiddlewares.unshift(FileLoader.factory);
- const _ZipLoader = class {
- static unzip(reader, settings) {
- return __async(this, null, function* () {
- const filePaths = yield _ZipLoader.getFilePaths(reader);
- const requiredFilePaths = [];
- for (const definedFile of settings.getDefinedFiles()) {
- const actualPath = decodeURI(url.resolve(settings.url, definedFile));
- if (filePaths.includes(actualPath)) {
- requiredFilePaths.push(actualPath);
- }
- }
- const files = yield _ZipLoader.getFiles(reader, requiredFilePaths);
- for (let i = 0; i < files.length; i++) {
- const path = requiredFilePaths[i];
- const file = files[i];
- Object.defineProperty(file, "webkitRelativePath", {
- value: path
- });
- }
- return files;
- });
- }
- static createSettings(reader) {
- return __async(this, null, function* () {
- const filePaths = yield _ZipLoader.getFilePaths(reader);
- const settingsFilePath = filePaths.find((path) => path.endsWith("model.json") || path.endsWith("model3.json"));
- if (!settingsFilePath) {
- throw new Error("Settings file not found");
- }
- const settingsText = yield _ZipLoader.readText(reader, settingsFilePath);
- if (!settingsText) {
- throw new Error("Empty settings file: " + settingsFilePath);
- }
- const settingsJSON = JSON.parse(settingsText);
- settingsJSON.url = settingsFilePath;
- const runtime = Live2DFactory.findRuntime(settingsJSON);
- if (!runtime) {
- throw new Error("Unknown settings JSON");
- }
- return runtime.createModelSettings(settingsJSON);
- });
- }
- static zipReader(data, url2) {
- return __async(this, null, function* () {
- throw new Error("Not implemented");
- });
- }
- static getFilePaths(reader) {
- return __async(this, null, function* () {
- throw new Error("Not implemented");
- });
- }
- static getFiles(reader, paths) {
- return __async(this, null, function* () {
- throw new Error("Not implemented");
- });
- }
- static readText(reader, path) {
- return __async(this, null, function* () {
- throw new Error("Not implemented");
- });
- }
- static releaseReader(reader) {
- }
- };
- let ZipLoader = _ZipLoader;
- ZipLoader.ZIP_PROTOCOL = "zip://";
- ZipLoader.uid = 0;
- ZipLoader.factory = (context, next) => __async(void 0, null, function* () {
- const source = context.source;
- let sourceURL;
- let zipBlob;
- let settings;
- if (typeof source === "string" && (source.endsWith(".zip") || source.startsWith(_ZipLoader.ZIP_PROTOCOL))) {
- if (source.startsWith(_ZipLoader.ZIP_PROTOCOL)) {
- sourceURL = source.slice(_ZipLoader.ZIP_PROTOCOL.length);
- } else {
- sourceURL = source;
- }
- zipBlob = yield Live2DLoader.load({
- url: sourceURL,
- type: "blob",
- target: context.live2dModel
- });
- } else if (Array.isArray(source) && source.length === 1 && source[0] instanceof File && source[0].name.endsWith(".zip")) {
- zipBlob = source[0];
- sourceURL = URL.createObjectURL(zipBlob);
- settings = source.settings;
- }
- if (zipBlob) {
- if (!zipBlob.size) {
- throw new Error("Empty zip file");
- }
- const reader = yield _ZipLoader.zipReader(zipBlob, sourceURL);
- if (!settings) {
- settings = yield _ZipLoader.createSettings(reader);
- }
- settings._objectURL = _ZipLoader.ZIP_PROTOCOL + _ZipLoader.uid + "/" + settings.url;
- const files = yield _ZipLoader.unzip(reader, settings);
- files.settings = settings;
- context.source = files;
- if (sourceURL.startsWith("blob:")) {
- context.live2dModel.once("modelLoaded", (internalModel) => {
- internalModel.once("destroy", function() {
- URL.revokeObjectURL(sourceURL);
- });
- });
- }
- _ZipLoader.releaseReader(reader);
- }
- return next();
- });
- Live2DFactory.live2DModelMiddlewares.unshift(ZipLoader.factory);
- if (!window.Live2D) {
- throw new Error("Could not find Cubism 2 runtime. This plugin requires live2d.min.js to be loaded.");
- }
- const originalUpdateParam = Live2DMotion.prototype.updateParam;
- Live2DMotion.prototype.updateParam = function(model, entry) {
- originalUpdateParam.call(this, model, entry);
- if (entry.isFinished() && this.onFinishHandler) {
- this.onFinishHandler(this);
- delete this.onFinishHandler;
- }
- };
- class Live2DExpression extends AMotion {
- constructor(json) {
- super();
- this.params = [];
- this.setFadeIn(json.fade_in > 0 ? json.fade_in : config.expressionFadingDuration);
- this.setFadeOut(json.fade_out > 0 ? json.fade_out : config.expressionFadingDuration);
- if (Array.isArray(json.params)) {
- json.params.forEach((param) => {
- const calc = param.calc || "add";
- if (calc === "add") {
- const defaultValue = param.def || 0;
- param.val -= defaultValue;
- } else if (calc === "mult") {
- const defaultValue = param.def || 1;
- param.val /= defaultValue;
- }
- this.params.push({
- calc,
- val: param.val,
- id: param.id
- });
- });
- }
- }
- updateParamExe(model, time, weight, motionQueueEnt) {
- this.params.forEach((param) => {
- model.setParamFloat(param.id, param.val * weight);
- });
- }
- }
- class Cubism2ExpressionManager extends ExpressionManager {
- constructor(settings, options) {
- var _a;
- super(settings, options);
- this.queueManager = new MotionQueueManager();
- this.definitions = (_a = this.settings.expressions) != null ? _a : [];
- this.init();
- }
- isFinished() {
- return this.queueManager.isFinished();
- }
- getExpressionIndex(name) {
- return this.definitions.findIndex((def) => def.name === name);
- }
- getExpressionFile(definition) {
- return definition.file;
- }
- createExpression(data, definition) {
- return new Live2DExpression(data);
- }
- _setExpression(motion) {
- return this.queueManager.startMotion(motion);
- }
- stopAllExpressions() {
- this.queueManager.stopAllMotions();
- }
- updateParameters(model, dt) {
- return this.queueManager.updateParam(model);
- }
- }
- class Cubism2MotionManager extends MotionManager {
- constructor(settings, options) {
- super(settings, options);
- this.groups = { idle: "idle" };
- this.motionDataType = "arraybuffer";
- this.queueManager = new MotionQueueManager();
- this.definitions = this.settings.motions;
- this.init(options);
- }
- init(options) {
- super.init(options);
- if (this.settings.expressions) {
- this.expressionManager = new Cubism2ExpressionManager(this.settings, options);
- }
- }
- isFinished() {
- return this.queueManager.isFinished();
- }
- createMotion(data, group, definition) {
- const motion = Live2DMotion.loadMotion(data);
- const defaultFadingDuration = group === this.groups.idle ? config.idleMotionFadingDuration : config.motionFadingDuration;
- motion.setFadeIn(definition.fade_in > 0 ? definition.fade_in : defaultFadingDuration);
- motion.setFadeOut(definition.fade_out > 0 ? definition.fade_out : defaultFadingDuration);
- return motion;
- }
- getMotionFile(definition) {
- return definition.file;
- }
- getMotionName(definition) {
- return definition.file;
- }
- getSoundFile(definition) {
- return definition.sound;
- }
- _startMotion(motion, onFinish) {
- motion.onFinishHandler = onFinish;
- this.queueManager.stopAllMotions();
- return this.queueManager.startMotion(motion);
- }
- _stopAllMotions() {
- this.queueManager.stopAllMotions();
- }
- updateParameters(model, now) {
- return this.queueManager.updateParam(model);
- }
- destroy() {
- super.destroy();
- this.queueManager = void 0;
- }
- }
- class Live2DEyeBlink {
- constructor(coreModel) {
- this.coreModel = coreModel;
- this.blinkInterval = 4e3;
- this.closingDuration = 100;
- this.closedDuration = 50;
- this.openingDuration = 150;
- this.eyeState = 0;
- this.eyeParamValue = 1;
- this.closedTimer = 0;
- this.nextBlinkTimeLeft = this.blinkInterval;
- this.leftParam = coreModel.getParamIndex("PARAM_EYE_L_OPEN");
- this.rightParam = coreModel.getParamIndex("PARAM_EYE_R_OPEN");
- }
- setEyeParams(value) {
- this.eyeParamValue = clamp(value, 0, 1);
- this.coreModel.setParamFloat(this.leftParam, this.eyeParamValue);
- this.coreModel.setParamFloat(this.rightParam, this.eyeParamValue);
- }
- update(dt) {
- switch (this.eyeState) {
- case 0:
- this.nextBlinkTimeLeft -= dt;
- if (this.nextBlinkTimeLeft < 0) {
- this.eyeState = 1;
- this.nextBlinkTimeLeft = this.blinkInterval + this.closingDuration + this.closedDuration + this.openingDuration + rand(0, 2e3);
- }
- break;
- case 1:
- this.setEyeParams(this.eyeParamValue + dt / this.closingDuration);
- if (this.eyeParamValue <= 0) {
- this.eyeState = 2;
- this.closedTimer = 0;
- }
- break;
- case 2:
- this.closedTimer += dt;
- if (this.closedTimer >= this.closedDuration) {
- this.eyeState = 3;
- }
- break;
- case 3:
- this.setEyeParams(this.eyeParamValue + dt / this.openingDuration);
- if (this.eyeParamValue >= 1) {
- this.eyeState = 0;
- }
- }
- }
- }
- const tempMatrixArray = new Float32Array([
- 1,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0,
- 0,
- 0,
- 0,
- 1
- ]);
- class Cubism2InternalModel extends InternalModel {
- constructor(coreModel, settings, options) {
- super();
- this.textureFlipY = true;
- this.drawDataCount = 0;
- this.disableCulling = false;
- this.coreModel = coreModel;
- this.settings = settings;
- this.motionManager = new Cubism2MotionManager(settings, options);
- this.eyeBlink = new Live2DEyeBlink(coreModel);
- this.eyeballXParamIndex = coreModel.getParamIndex("PARAM_EYE_BALL_X");
- this.eyeballYParamIndex = coreModel.getParamIndex("PARAM_EYE_BALL_Y");
- this.angleXParamIndex = coreModel.getParamIndex("PARAM_ANGLE_X");
- this.angleYParamIndex = coreModel.getParamIndex("PARAM_ANGLE_Y");
- this.angleZParamIndex = coreModel.getParamIndex("PARAM_ANGLE_Z");
- this.bodyAngleXParamIndex = coreModel.getParamIndex("PARAM_BODY_ANGLE_X");
- this.breathParamIndex = coreModel.getParamIndex("PARAM_BREATH");
- this.init();
- }
- init() {
- super.init();
- if (this.settings.initParams) {
- this.settings.initParams.forEach(({ id, value }) => this.coreModel.setParamFloat(id, value));
- }
- if (this.settings.initOpacities) {
- this.settings.initOpacities.forEach(({ id, value }) => this.coreModel.setPartsOpacity(id, value));
- }
- this.coreModel.saveParam();
- const arr = this.coreModel.getModelContext()._$aS;
- if (arr == null ? void 0 : arr.length) {
- this.drawDataCount = arr.length;
- }
- let culling = this.coreModel.drawParamWebGL.culling;
- Object.defineProperty(this.coreModel.drawParamWebGL, "culling", {
- set: (v) => culling = v,
- get: () => this.disableCulling ? false : culling
- });
- const clipManager = this.coreModel.getModelContext().clipManager;
- const originalSetupClip = clipManager.setupClip;
- clipManager.setupClip = (modelContext, drawParam) => {
- originalSetupClip.call(clipManager, modelContext, drawParam);
- drawParam.gl.viewport(...this.viewport);
- };
- }
- getSize() {
- return [this.coreModel.getCanvasWidth(), this.coreModel.getCanvasHeight()];
- }
- getLayout() {
- const layout = {};
- if (this.settings.layout) {
- for (const key of Object.keys(this.settings.layout)) {
- let commonKey = key;
- if (key === "center_x") {
- commonKey = "centerX";
- } else if (key === "center_y") {
- commonKey = "centerY";
- }
- layout[commonKey] = this.settings.layout[key];
- }
- }
- return layout;
- }
- updateWebGLContext(gl, glContextID) {
- const drawParamWebGL = this.coreModel.drawParamWebGL;
- drawParamWebGL.firstDraw = true;
- drawParamWebGL.setGL(gl);
- drawParamWebGL.glno = glContextID;
- for (const prop in drawParamWebGL) {
- if (drawParamWebGL.hasOwnProperty(prop) && drawParamWebGL[prop] instanceof WebGLBuffer) {
- drawParamWebGL[prop] = null;
- }
- }
- const clipManager = this.coreModel.getModelContext().clipManager;
- clipManager.curFrameNo = glContextID;
- const framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
- clipManager.getMaskRenderTexture();
- gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
- }
- bindTexture(index, texture) {
- this.coreModel.setTexture(index, texture);
- }
- getHitAreaDefs() {
- var _a;
- return ((_a = this.settings.hitAreas) == null ? void 0 : _a.map((hitArea) => ({
- id: hitArea.id,
- name: hitArea.name,
- index: this.coreModel.getDrawDataIndex(hitArea.id)
- }))) || [];
- }
- getDrawableIDs() {
- const modelContext = this.coreModel.getModelContext();
- const ids = [];
- for (let i = 0; i < this.drawDataCount; i++) {
- const drawData = modelContext.getDrawData(i);
- if (drawData) {
- ids.push(drawData.getDrawDataID().id);
- }
- }
- return ids;
- }
- getDrawableIndex(id) {
- return this.coreModel.getDrawDataIndex(id);
- }
- getDrawableVertices(drawIndex) {
- if (typeof drawIndex === "string") {
- drawIndex = this.coreModel.getDrawDataIndex(drawIndex);
- if (drawIndex === -1)
- throw new TypeError("Unable to find drawable ID: " + drawIndex);
- }
- return this.coreModel.getTransformedPoints(drawIndex).slice();
- }
- update(dt, now) {
- var _a, _b, _c, _d;
- super.update(dt, now);
- const model = this.coreModel;
- this.emit("beforeMotionUpdate");
- const motionUpdated = this.motionManager.update(this.coreModel, now);
- this.emit("afterMotionUpdate");
- model.saveParam();
- (_a = this.motionManager.expressionManager) == null ? void 0 : _a.update(model, now);
- if (!motionUpdated) {
- (_b = this.eyeBlink) == null ? void 0 : _b.update(dt);
- }
- this.updateFocus();
- this.updateNaturalMovements(dt, now);
- (_c = this.physics) == null ? void 0 : _c.update(now);
- (_d = this.pose) == null ? void 0 : _d.update(dt);
- this.emit("beforeModelUpdate");
- model.update();
- model.loadParam();
- }
- updateFocus() {
- this.coreModel.addToParamFloat(this.eyeballXParamIndex, this.focusController.x);
- this.coreModel.addToParamFloat(this.eyeballYParamIndex, this.focusController.y);
- this.coreModel.addToParamFloat(this.angleXParamIndex, this.focusController.x * 30);
- this.coreModel.addToParamFloat(this.angleYParamIndex, this.focusController.y * 30);
- this.coreModel.addToParamFloat(this.angleZParamIndex, this.focusController.x * this.focusController.y * -30);
- this.coreModel.addToParamFloat(this.bodyAngleXParamIndex, this.focusController.x * 10);
- }
- updateNaturalMovements(dt, now) {
- const t = now / 1e3 * 2 * Math.PI;
- this.coreModel.addToParamFloat(this.angleXParamIndex, 15 * Math.sin(t / 6.5345) * 0.5);
- this.coreModel.addToParamFloat(this.angleYParamIndex, 8 * Math.sin(t / 3.5345) * 0.5);
- this.coreModel.addToParamFloat(this.angleZParamIndex, 10 * Math.sin(t / 5.5345) * 0.5);
- this.coreModel.addToParamFloat(this.bodyAngleXParamIndex, 4 * Math.sin(t / 15.5345) * 0.5);
- this.coreModel.setParamFloat(this.breathParamIndex, 0.5 + 0.5 * Math.sin(t / 3.2345));
- }
- draw(gl) {
- const disableCulling = this.disableCulling;
- if (gl.getParameter(gl.FRAMEBUFFER_BINDING)) {
- this.disableCulling = true;
- }
- const matrix = this.drawingMatrix;
- tempMatrixArray[0] = matrix.a;
- tempMatrixArray[1] = matrix.b;
- tempMatrixArray[4] = matrix.c;
- tempMatrixArray[5] = matrix.d;
- tempMatrixArray[12] = matrix.tx;
- tempMatrixArray[13] = matrix.ty;
- this.coreModel.setMatrix(tempMatrixArray);
- this.coreModel.draw();
- this.disableCulling = disableCulling;
- }
- destroy() {
- super.destroy();
- this.coreModel = void 0;
- }
- }
- class Cubism2ModelSettings extends ModelSettings {
- constructor(json) {
- super(json);
- this.motions = {};
- if (!Cubism2ModelSettings.isValidJSON(json)) {
- throw new TypeError("Invalid JSON.");
- }
- this.moc = json.model;
- copyArray("string", json, this, "textures", "textures");
- this.copy(json);
- }
- static isValidJSON(json) {
- var _a;
- return !!json && typeof json.model === "string" && ((_a = json.textures) == null ? void 0 : _a.length) > 0 && json.textures.every((item) => typeof item === "string");
- }
- copy(json) {
- copyProperty("string", json, this, "name", "name");
- copyProperty("string", json, this, "pose", "pose");
- copyProperty("string", json, this, "physics", "physics");
- copyProperty("object", json, this, "layout", "layout");
- copyProperty("object", json, this, "motions", "motions");
- copyArray("object", json, this, "hit_areas", "hitAreas");
- copyArray("object", json, this, "expressions", "expressions");
- copyArray("object", json, this, "init_params", "initParams");
- copyArray("object", json, this, "init_opacities", "initOpacities");
- }
- replaceFiles(replace) {
- super.replaceFiles(replace);
- for (const [group, motions] of Object.entries(this.motions)) {
- for (let i = 0; i < motions.length; i++) {
- motions[i].file = replace(motions[i].file, `motions.${group}[${i}].file`);
- if (motions[i].sound !== void 0) {
- motions[i].sound = replace(motions[i].sound, `motions.${group}[${i}].sound`);
- }
- }
- }
- if (this.expressions) {
- for (let i = 0; i < this.expressions.length; i++) {
- this.expressions[i].file = replace(this.expressions[i].file, `expressions[${i}].file`);
- }
- }
- }
- }
- const SRC_TYPE_MAP = {
- x: PhysicsHair.Src.SRC_TO_X,
- y: PhysicsHair.Src.SRC_TO_Y,
- angle: PhysicsHair.Src.SRC_TO_G_ANGLE
- };
- const TARGET_TYPE_MAP = {
- x: PhysicsHair.Src.SRC_TO_X,
- y: PhysicsHair.Src.SRC_TO_Y,
- angle: PhysicsHair.Src.SRC_TO_G_ANGLE
- };
- class Live2DPhysics {
- constructor(coreModel, json) {
- this.coreModel = coreModel;
- this.physicsHairs = [];
- if (json.physics_hair) {
- this.physicsHairs = json.physics_hair.map((definition) => {
- const physicsHair = new PhysicsHair();
- physicsHair.setup(definition.setup.length, definition.setup.regist, definition.setup.mass);
- definition.src.forEach(({ id, ptype, scale, weight }) => {
- const type = SRC_TYPE_MAP[ptype];
- if (type) {
- physicsHair.addSrcParam(type, id, scale, weight);
- }
- });
- definition.targets.forEach(({ id, ptype, scale, weight }) => {
- const type = TARGET_TYPE_MAP[ptype];
- if (type) {
- physicsHair.addTargetParam(type, id, scale, weight);
- }
- });
- return physicsHair;
- });
- }
- }
- update(elapsed) {
- this.physicsHairs.forEach((physicsHair) => physicsHair.update(this.coreModel, elapsed));
- }
- }
- class Live2DPartsParam {
- constructor(id) {
- this.id = id;
- this.paramIndex = -1;
- this.partsIndex = -1;
- this.link = [];
- }
- initIndex(model) {
- this.paramIndex = model.getParamIndex("VISIBLE:" + this.id);
- this.partsIndex = model.getPartsDataIndex(PartsDataID.getID(this.id));
- model.setParamFloat(this.paramIndex, 1);
- }
- }
- class Live2DPose {
- constructor(coreModel, json) {
- this.coreModel = coreModel;
- this.opacityAnimDuration = 500;
- this.partsGroups = [];
- if (json.parts_visible) {
- this.partsGroups = json.parts_visible.map(({ group }) => group.map(({ id, link }) => {
- const parts = new Live2DPartsParam(id);
- if (link) {
- parts.link = link.map((l) => new Live2DPartsParam(l));
- }
- return parts;
- }));
- this.init();
- }
- }
- init() {
- this.partsGroups.forEach((group) => {
- group.forEach((parts) => {
- parts.initIndex(this.coreModel);
- if (parts.paramIndex >= 0) {
- const visible = this.coreModel.getParamFloat(parts.paramIndex) !== 0;
- this.coreModel.setPartsOpacity(parts.partsIndex, visible ? 1 : 0);
- this.coreModel.setParamFloat(parts.paramIndex, visible ? 1 : 0);
- if (parts.link.length > 0) {
- parts.link.forEach((p) => p.initIndex(this.coreModel));
- }
- }
- });
- });
- }
- normalizePartsOpacityGroup(partsGroup, dt) {
- const model = this.coreModel;
- const phi = 0.5;
- const maxBackOpacity = 0.15;
- let visibleOpacity = 1;
- let visibleIndex = partsGroup.findIndex(({ paramIndex, partsIndex }) => partsIndex >= 0 && model.getParamFloat(paramIndex) !== 0);
- if (visibleIndex >= 0) {
- const originalOpacity = model.getPartsOpacity(partsGroup[visibleIndex].partsIndex);
- visibleOpacity = clamp(originalOpacity + dt / this.opacityAnimDuration, 0, 1);
- } else {
- visibleIndex = 0;
- visibleOpacity = 1;
- }
- partsGroup.forEach(({ partsIndex }, index) => {
- if (partsIndex >= 0) {
- if (visibleIndex == index) {
- model.setPartsOpacity(partsIndex, visibleOpacity);
- } else {
- let opacity = model.getPartsOpacity(partsIndex);
- let a1;
- if (visibleOpacity < phi) {
- a1 = visibleOpacity * (phi - 1) / phi + 1;
- } else {
- a1 = (1 - visibleOpacity) * phi / (1 - phi);
- }
- let backOp = (1 - a1) * (1 - visibleOpacity);
- if (backOp > maxBackOpacity) {
- a1 = 1 - maxBackOpacity / (1 - visibleOpacity);
- }
- if (opacity > a1) {
- opacity = a1;
- }
- model.setPartsOpacity(partsIndex, opacity);
- }
- }
- });
- }
- copyOpacity(partsGroup) {
- const model = this.coreModel;
- partsGroup.forEach(({ partsIndex, link }) => {
- if (partsIndex >= 0 && link) {
- const opacity = model.getPartsOpacity(partsIndex);
- link.forEach(({ partsIndex: partsIndex2 }) => {
- if (partsIndex2 >= 0) {
- model.setPartsOpacity(partsIndex2, opacity);
- }
- });
- }
- });
- }
- update(dt) {
- this.partsGroups.forEach((partGroup) => {
- this.normalizePartsOpacityGroup(partGroup, dt);
- this.copyOpacity(partGroup);
- });
- }
- }
- Live2DFactory.registerRuntime({
- version: 2,
- test(source) {
- return source instanceof Cubism2ModelSettings || Cubism2ModelSettings.isValidJSON(source);
- },
- ready() {
- return Promise.resolve();
- },
- isValidMoc(modelData) {
- if (modelData.byteLength < 3) {
- return false;
- }
- const view = new Int8Array(modelData, 0, 3);
- return String.fromCharCode(...view) === "moc";
- },
- createModelSettings(json) {
- return new Cubism2ModelSettings(json);
- },
- createCoreModel(data) {
- const model = Live2DModelWebGL.loadModel(data);
- const error = Live2D.getError();
- if (error)
- throw error;
- return model;
- },
- createInternalModel(coreModel, settings, options) {
- return new Cubism2InternalModel(coreModel, settings, options);
- },
- createPose(coreModel, data) {
- return new Live2DPose(coreModel, data);
- },
- createPhysics(coreModel, data) {
- return new Live2DPhysics(coreModel, data);
- }
- });
- export { Cubism2ExpressionManager, Cubism2InternalModel, Cubism2ModelSettings, Cubism2MotionManager, ExpressionManager, FileLoader, FocusController, InteractionMixin, InternalModel, LOGICAL_HEIGHT, LOGICAL_WIDTH, Live2DExpression, Live2DEyeBlink, Live2DFactory, Live2DLoader, Live2DModel, Live2DPhysics, Live2DPose, Live2DTransform, ModelSettings, MotionManager, MotionPreloadStrategy, MotionPriority, MotionState, SoundManager, VERSION, XHRLoader, ZipLoader, applyMixins, clamp, config, copyArray, copyProperty, folderName, logger, rand, remove };
|