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()); }); }; (function(global, factory) { typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@pixi/utils"), require("@pixi/math"), require("@pixi/core"), require("@pixi/display")) : typeof define === "function" && define.amd ? define(["exports", "@pixi/utils", "@pixi/math", "@pixi/core", "@pixi/display"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory((global.PIXI = global.PIXI || {}, global.PIXI.live2d = global.PIXI.live2d || {}), global.PIXI.utils, global.PIXI, global.PIXI, global.PIXI)); })(this, function(exports2, utils, math, core, display) { "use strict"; const LOGICAL_WIDTH = 2; const LOGICAL_HEIGHT = 2; var CubismConfig; ((CubismConfig2) => { CubismConfig2.supportMoreMaskDivisions = true; CubismConfig2.setOpacityFromMotion = false; })(CubismConfig || (CubismConfig = {})); exports2.config = void 0; ((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; })(exports2.config || (exports2.config = {})); const VERSION = "0.4.0"; const logger = { log(tag, ...messages) { if (exports2.config.logLevel <= exports2.config.LOG_LEVEL_VERBOSE) { console.log(`[${tag}]`, ...messages); } }, warn(tag, ...messages) { if (exports2.config.logLevel <= exports2.config.LOG_LEVEL_WARNING) { console.warn(`[${tag}]`, ...messages); } }, error(tag, ...messages) { if (exports2.config.logLevel <= exports2.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(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; } function remove(array, item) { const index = array.indexOf(item); if (index !== -1) { array.splice(index, 1); } } class ExpressionManager extends utils.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 self2 = this; self2.definitions = void 0; self2.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 utils.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 !exports2.config.preserveExpressionOnMotion && this.currentPriority > 1; } dump(requestedGroup, requestedIndex) { if (this.debug) { const keys = [ "currentPriority", "reservePriority", "currentGroup", "currentIndex", "reservedGroup", "reservedIndex", "reservedIdleGroup", "reservedIdleIndex" ]; return ` 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 utils.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 (exports2.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 (exports2.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 self2 = this; self2.definitions = void 0; self2.motionGroups = void 0; } } const tempBounds = { x: 0, y: 0, width: 0, height: 0 }; class InternalModel extends utils.EventEmitter { constructor() { super(...arguments); this.focusController = new FocusController(); this.originalWidth = 0; this.originalHeight = 0; this.width = 0; this.height = 0; this.localTransform = new math.Matrix(); this.drawingMatrix = new math.Matrix(); this.hitAreas = {}; this.textureFlipY = false; this.viewport = [0, 0, 0, 0]; this.destroyed = false; } init() { this.setupLayout(); this.setupHitAreas(); } setupLayout() { const self2 = this; const size = this.getSize(); self2.originalWidth = size[0]; self2.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); self2.width = this.originalWidth * this.localTransform.a; self2.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, url, status, aborted = false) { super(message); this.url = url; this.status = status; this.aborted = aborted; } } const _XHRLoader = class { 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 = /* @__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", url); 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}): ${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 ? 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(url, options = {}) { var _a; const textureOptions = { resourceOptions: { crossorigin: options.crossOrigin } }; if (core.Texture.fromURL) { return core.Texture.fromURL(url, 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 = core.Texture.from(url, 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(this, 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(this, 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(this, 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(this, null, 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 }); }); 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(this, 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 math.Transform { } const tempPoint = new math.Point(); const tempMatrix$1 = new math.Matrix(); let tickerRef; class Live2DModel extends display.Container { constructor(options) { super(); this.tag = "Live2DModel(uninitialized)"; this.textures = []; this.transform = new Live2DTransform(); this.anchor = new math.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$1.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(utils.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(this, 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(url) { return _FileLoader.resolveURL(this._objectURL, url); }; 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(utils.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, url) { 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(this, 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 : exports2.config.expressionFadingDuration); this.setFadeOut(json.fade_out > 0 ? json.fade_out : exports2.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 ? exports2.config.idleMotionFadingDuration : exports2.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); } }); if (!window.Live2DCubismCore) { throw new Error("Could not find Cubism 4 runtime. This plugin requires live2dcubismcore.js to be loaded."); } class CubismVector2 { constructor(x, y) { this.x = x || 0; this.y = y || 0; } add(vector2) { const ret = new CubismVector2(0, 0); ret.x = this.x + vector2.x; ret.y = this.y + vector2.y; return ret; } substract(vector2) { const ret = new CubismVector2(0, 0); ret.x = this.x - vector2.x; ret.y = this.y - vector2.y; return ret; } multiply(vector2) { const ret = new CubismVector2(0, 0); ret.x = this.x * vector2.x; ret.y = this.y * vector2.y; return ret; } multiplyByScaler(scalar) { return this.multiply(new CubismVector2(scalar, scalar)); } division(vector2) { const ret = new CubismVector2(0, 0); ret.x = this.x / vector2.x; ret.y = this.y / vector2.y; return ret; } divisionByScalar(scalar) { return this.division(new CubismVector2(scalar, scalar)); } getLength() { return Math.sqrt(this.x * this.x + this.y * this.y); } getDistanceWith(a) { return Math.sqrt((this.x - a.x) * (this.x - a.x) + (this.y - a.y) * (this.y - a.y)); } dot(a) { return this.x * a.x + this.y * a.y; } normalize() { const length = Math.pow(this.x * this.x + this.y * this.y, 0.5); this.x = this.x / length; this.y = this.y / length; } isEqual(rhs) { return this.x == rhs.x && this.y == rhs.y; } isNotEqual(rhs) { return !this.isEqual(rhs); } } const _CubismMath = class { static range(value, min, max) { if (value < min) { value = min; } else if (value > max) { value = max; } return value; } static sin(x) { return Math.sin(x); } static cos(x) { return Math.cos(x); } static abs(x) { return Math.abs(x); } static sqrt(x) { return Math.sqrt(x); } static cbrt(x) { if (x === 0) { return x; } let cx = x; const isNegativeNumber = cx < 0; if (isNegativeNumber) { cx = -cx; } let ret; if (cx === Infinity) { ret = Infinity; } else { ret = Math.exp(Math.log(cx) / 3); ret = (cx / (ret * ret) + 2 * ret) / 3; } return isNegativeNumber ? -ret : ret; } static getEasingSine(value) { if (value < 0) { return 0; } else if (value > 1) { return 1; } return 0.5 - 0.5 * this.cos(value * Math.PI); } static max(left, right) { return left > right ? left : right; } static min(left, right) { return left > right ? right : left; } static degreesToRadian(degrees) { return degrees / 180 * Math.PI; } static radianToDegrees(radian) { return radian * 180 / Math.PI; } static directionToRadian(from, to) { const q1 = Math.atan2(to.y, to.x); const q2 = Math.atan2(from.y, from.x); let ret = q1 - q2; while (ret < -Math.PI) { ret += Math.PI * 2; } while (ret > Math.PI) { ret -= Math.PI * 2; } return ret; } static directionToDegrees(from, to) { const radian = this.directionToRadian(from, to); let degree = this.radianToDegrees(radian); if (to.x - from.x > 0) { degree = -degree; } return degree; } static radianToDirection(totalAngle) { const ret = new CubismVector2(); ret.x = this.sin(totalAngle); ret.y = this.cos(totalAngle); return ret; } static quadraticEquation(a, b, c) { if (this.abs(a) < _CubismMath.Epsilon) { if (this.abs(b) < _CubismMath.Epsilon) { return -c; } return -c / b; } return -(b + this.sqrt(b * b - 4 * a * c)) / (2 * a); } static cardanoAlgorithmForBezier(a, b, c, d) { if (this.sqrt(a) < _CubismMath.Epsilon) { return this.range(this.quadraticEquation(b, c, d), 0, 1); } const ba = b / a; const ca = c / a; const da = d / a; const p = (3 * ca - ba * ba) / 3; const p3 = p / 3; const q = (2 * ba * ba * ba - 9 * ba * ca + 27 * da) / 27; const q2 = q / 2; const discriminant = q2 * q2 + p3 * p3 * p3; const center = 0.5; const threshold = center + 0.01; if (discriminant < 0) { const mp3 = -p / 3; const mp33 = mp3 * mp3 * mp3; const r = this.sqrt(mp33); const t = -q / (2 * r); const cosphi = this.range(t, -1, 1); const phi = Math.acos(cosphi); const crtr = this.cbrt(r); const t1 = 2 * crtr; const root12 = t1 * this.cos(phi / 3) - ba / 3; if (this.abs(root12 - center) < threshold) { return this.range(root12, 0, 1); } const root2 = t1 * this.cos((phi + 2 * Math.PI) / 3) - ba / 3; if (this.abs(root2 - center) < threshold) { return this.range(root2, 0, 1); } const root3 = t1 * this.cos((phi + 4 * Math.PI) / 3) - ba / 3; return this.range(root3, 0, 1); } if (discriminant == 0) { let u12; if (q2 < 0) { u12 = this.cbrt(-q2); } else { u12 = -this.cbrt(q2); } const root12 = 2 * u12 - ba / 3; if (this.abs(root12 - center) < threshold) { return this.range(root12, 0, 1); } const root2 = -u12 - ba / 3; return this.range(root2, 0, 1); } const sd = this.sqrt(discriminant); const u1 = this.cbrt(sd - q2); const v1 = this.cbrt(sd + q2); const root1 = u1 - v1 - ba / 3; return this.range(root1, 0, 1); } constructor() { } }; let CubismMath = _CubismMath; CubismMath.Epsilon = 1e-5; class CubismMatrix44 { constructor() { this._tr = new Float32Array(16); this.loadIdentity(); } static multiply(a, b, dst) { const c = new Float32Array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]); const n = 4; for (let i = 0; i < n; ++i) { for (let j = 0; j < n; ++j) { for (let k = 0; k < n; ++k) { c[j + i * 4] += a[k + i * 4] * b[j + k * 4]; } } } for (let i = 0; i < 16; ++i) { dst[i] = c[i]; } } loadIdentity() { const c = new Float32Array([ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]); this.setMatrix(c); } setMatrix(tr) { for (let i = 0; i < 16; ++i) { this._tr[i] = tr[i]; } } getArray() { return this._tr; } getScaleX() { return this._tr[0]; } getScaleY() { return this._tr[5]; } getTranslateX() { return this._tr[12]; } getTranslateY() { return this._tr[13]; } transformX(src) { return this._tr[0] * src + this._tr[12]; } transformY(src) { return this._tr[5] * src + this._tr[13]; } invertTransformX(src) { return (src - this._tr[12]) / this._tr[0]; } invertTransformY(src) { return (src - this._tr[13]) / this._tr[5]; } translateRelative(x, y) { const tr1 = new Float32Array([ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, 0, 1 ]); CubismMatrix44.multiply(tr1, this._tr, this._tr); } translate(x, y) { this._tr[12] = x; this._tr[13] = y; } translateX(x) { this._tr[12] = x; } translateY(y) { this._tr[13] = y; } scaleRelative(x, y) { const tr1 = new Float32Array([ x, 0, 0, 0, 0, y, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]); CubismMatrix44.multiply(tr1, this._tr, this._tr); } scale(x, y) { this._tr[0] = x; this._tr[5] = y; } multiplyByMatrix(m) { CubismMatrix44.multiply(m.getArray(), this._tr, this._tr); } clone() { const cloneMatrix = new CubismMatrix44(); for (let i = 0; i < this._tr.length; i++) { cloneMatrix._tr[i] = this._tr[i]; } return cloneMatrix; } } class CubismRenderer { initialize(model) { this._model = model; } drawModel() { if (this.getModel() == null) return; this.doDrawModel(); } setMvpMatrix(matrix44) { this._mvpMatrix4x4.setMatrix(matrix44.getArray()); } getMvpMatrix() { return this._mvpMatrix4x4; } setModelColor(red, green, blue, alpha) { if (red < 0) { red = 0; } else if (red > 1) { red = 1; } if (green < 0) { green = 0; } else if (green > 1) { green = 1; } if (blue < 0) { blue = 0; } else if (blue > 1) { blue = 1; } if (alpha < 0) { alpha = 0; } else if (alpha > 1) { alpha = 1; } this._modelColor.R = red; this._modelColor.G = green; this._modelColor.B = blue; this._modelColor.A = alpha; } getModelColor() { return Object.assign({}, this._modelColor); } setIsPremultipliedAlpha(enable) { this._isPremultipliedAlpha = enable; } isPremultipliedAlpha() { return this._isPremultipliedAlpha; } setIsCulling(culling) { this._isCulling = culling; } isCulling() { return this._isCulling; } setAnisotropy(n) { this._anisortopy = n; } getAnisotropy() { return this._anisortopy; } getModel() { return this._model; } constructor() { this._isCulling = false; this._isPremultipliedAlpha = false; this._anisortopy = 0; this._modelColor = new CubismTextureColor(); this._mvpMatrix4x4 = new CubismMatrix44(); this._mvpMatrix4x4.loadIdentity(); } } var CubismBlendMode = /* @__PURE__ */ ((CubismBlendMode2) => { CubismBlendMode2[CubismBlendMode2["CubismBlendMode_Normal"] = 0] = "CubismBlendMode_Normal"; CubismBlendMode2[CubismBlendMode2["CubismBlendMode_Additive"] = 1] = "CubismBlendMode_Additive"; CubismBlendMode2[CubismBlendMode2["CubismBlendMode_Multiplicative"] = 2] = "CubismBlendMode_Multiplicative"; return CubismBlendMode2; })(CubismBlendMode || {}); class CubismTextureColor { constructor() { this.R = 1; this.G = 1; this.B = 1; this.A = 1; } } let s_isStarted = false; let s_isInitialized = false; let s_option = void 0; const Constant = { vertexOffset: 0, vertexStep: 2 }; class CubismFramework { static startUp(option) { if (s_isStarted) { CubismLogInfo("CubismFramework.startUp() is already done."); return s_isStarted; } if (Live2DCubismCore._isStarted) { s_isStarted = true; return true; } Live2DCubismCore._isStarted = true; s_option = option; if (s_option) { Live2DCubismCore.Logging.csmSetLogFunction(s_option.logFunction); } s_isStarted = true; if (s_isStarted) { const version = Live2DCubismCore.Version.csmGetVersion(); const major = (version & 4278190080) >> 24; const minor = (version & 16711680) >> 16; const patch = version & 65535; const versionNumber = version; CubismLogInfo(`Live2D Cubism Core version: {0}.{1}.{2} ({3})`, ("00" + major).slice(-2), ("00" + minor).slice(-2), ("0000" + patch).slice(-4), versionNumber); } CubismLogInfo("CubismFramework.startUp() is complete."); return s_isStarted; } static cleanUp() { s_isStarted = false; s_isInitialized = false; s_option = void 0; } static initialize() { if (!s_isStarted) { CubismLogWarning("CubismFramework is not started."); return; } if (s_isInitialized) { CubismLogWarning("CubismFramework.initialize() skipped, already initialized."); return; } s_isInitialized = true; CubismLogInfo("CubismFramework.initialize() is complete."); } static dispose() { if (!s_isStarted) { CubismLogWarning("CubismFramework is not started."); return; } if (!s_isInitialized) { CubismLogWarning("CubismFramework.dispose() skipped, not initialized."); return; } CubismRenderer.staticRelease(); s_isInitialized = false; CubismLogInfo("CubismFramework.dispose() is complete."); } static isStarted() { return s_isStarted; } static isInitialized() { return s_isInitialized; } static coreLogFunction(message) { if (!Live2DCubismCore.Logging.csmGetLogFunction()) { return; } Live2DCubismCore.Logging.csmGetLogFunction()(message); } static getLoggingLevel() { if (s_option != null) { return s_option.loggingLevel; } return LogLevel.LogLevel_Off; } constructor() { } } var LogLevel = /* @__PURE__ */ ((LogLevel2) => { LogLevel2[LogLevel2["LogLevel_Verbose"] = 0] = "LogLevel_Verbose"; LogLevel2[LogLevel2["LogLevel_Debug"] = 1] = "LogLevel_Debug"; LogLevel2[LogLevel2["LogLevel_Info"] = 2] = "LogLevel_Info"; LogLevel2[LogLevel2["LogLevel_Warning"] = 3] = "LogLevel_Warning"; LogLevel2[LogLevel2["LogLevel_Error"] = 4] = "LogLevel_Error"; LogLevel2[LogLevel2["LogLevel_Off"] = 5] = "LogLevel_Off"; return LogLevel2; })(LogLevel || {}); const CSM_ASSERT = () => { }; function CubismLogDebug(fmt, ...args) { CubismDebug.print(LogLevel.LogLevel_Debug, "[CSM][D]" + fmt + "\n", args); } function CubismLogInfo(fmt, ...args) { CubismDebug.print(LogLevel.LogLevel_Info, "[CSM][I]" + fmt + "\n", args); } function CubismLogWarning(fmt, ...args) { CubismDebug.print(LogLevel.LogLevel_Warning, "[CSM][W]" + fmt + "\n", args); } function CubismLogError(fmt, ...args) { CubismDebug.print(LogLevel.LogLevel_Error, "[CSM][E]" + fmt + "\n", args); } class CubismDebug { static print(logLevel, format, args) { if (logLevel < CubismFramework.getLoggingLevel()) { return; } const logPrint = CubismFramework.coreLogFunction; if (!logPrint) return; const buffer = format.replace(/{(\d+)}/g, (m, k) => { return args[k]; }); logPrint(buffer); } static dumpBytes(logLevel, data, length) { for (let i = 0; i < length; i++) { if (i % 16 == 0 && i > 0) this.print(logLevel, "\n"); else if (i % 8 == 0 && i > 0) this.print(logLevel, " "); this.print(logLevel, "{0} ", [data[i] & 255]); } this.print(logLevel, "\n"); } constructor() { } } class ACubismMotion { constructor() { this._fadeInSeconds = -1; this._fadeOutSeconds = -1; this._weight = 1; this._offsetSeconds = 0; this._firedEventValues = []; } release() { this._weight = 0; } updateParameters(model, motionQueueEntry, userTimeSeconds) { if (!motionQueueEntry.isAvailable() || motionQueueEntry.isFinished()) { return; } if (!motionQueueEntry.isStarted()) { motionQueueEntry.setIsStarted(true); motionQueueEntry.setStartTime(userTimeSeconds - this._offsetSeconds); motionQueueEntry.setFadeInStartTime(userTimeSeconds); const duration = this.getDuration(); if (motionQueueEntry.getEndTime() < 0) { motionQueueEntry.setEndTime(duration <= 0 ? -1 : motionQueueEntry.getStartTime() + duration); } } let fadeWeight = this._weight; const fadeIn = this._fadeInSeconds == 0 ? 1 : CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / this._fadeInSeconds); const fadeOut = this._fadeOutSeconds == 0 || motionQueueEntry.getEndTime() < 0 ? 1 : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / this._fadeOutSeconds); fadeWeight = fadeWeight * fadeIn * fadeOut; motionQueueEntry.setState(userTimeSeconds, fadeWeight); this.doUpdateParameters(model, userTimeSeconds, fadeWeight, motionQueueEntry); if (motionQueueEntry.getEndTime() > 0 && motionQueueEntry.getEndTime() < userTimeSeconds) { motionQueueEntry.setIsFinished(true); } } setFadeInTime(fadeInSeconds) { this._fadeInSeconds = fadeInSeconds; } setFadeOutTime(fadeOutSeconds) { this._fadeOutSeconds = fadeOutSeconds; } getFadeOutTime() { return this._fadeOutSeconds; } getFadeInTime() { return this._fadeInSeconds; } setWeight(weight) { this._weight = weight; } getWeight() { return this._weight; } getDuration() { return -1; } getLoopDuration() { return -1; } setOffsetTime(offsetSeconds) { this._offsetSeconds = offsetSeconds; } getFiredEvent(beforeCheckTimeSeconds, motionTimeSeconds) { return this._firedEventValues; } setFinishedMotionHandler(onFinishedMotionHandler) { this._onFinishedMotion = onFinishedMotionHandler; } getFinishedMotionHandler() { return this._onFinishedMotion; } } const DefaultFadeTime = 1; class CubismExpressionMotion extends ACubismMotion { constructor() { super(); this._parameters = []; } static create(json) { const expression = new CubismExpressionMotion(); const fadeInTime = json.FadeInTime; const fadeOutTime = json.FadeOutTime; expression.setFadeInTime(fadeInTime !== void 0 ? fadeInTime : DefaultFadeTime); expression.setFadeOutTime(fadeOutTime !== void 0 ? fadeOutTime : DefaultFadeTime); const parameters = json.Parameters || []; for (let i = 0; i < parameters.length; ++i) { const param = parameters[i]; const parameterId = param.Id; const value = param.Value; let blendType; switch (param.Blend) { case "Multiply": blendType = ExpressionBlendType.ExpressionBlendType_Multiply; break; case "Overwrite": blendType = ExpressionBlendType.ExpressionBlendType_Overwrite; break; case "Add": default: blendType = ExpressionBlendType.ExpressionBlendType_Add; break; } const item = { parameterId, blendType, value }; expression._parameters.push(item); } return expression; } doUpdateParameters(model, userTimeSeconds, weight, motionQueueEntry) { for (let i = 0; i < this._parameters.length; ++i) { const parameter = this._parameters[i]; switch (parameter.blendType) { case ExpressionBlendType.ExpressionBlendType_Add: { model.addParameterValueById(parameter.parameterId, parameter.value, weight); break; } case ExpressionBlendType.ExpressionBlendType_Multiply: { model.multiplyParameterValueById(parameter.parameterId, parameter.value, weight); break; } case ExpressionBlendType.ExpressionBlendType_Overwrite: { model.setParameterValueById(parameter.parameterId, parameter.value, weight); break; } } } } } var ExpressionBlendType = /* @__PURE__ */ ((ExpressionBlendType2) => { ExpressionBlendType2[ExpressionBlendType2["ExpressionBlendType_Add"] = 0] = "ExpressionBlendType_Add"; ExpressionBlendType2[ExpressionBlendType2["ExpressionBlendType_Multiply"] = 1] = "ExpressionBlendType_Multiply"; ExpressionBlendType2[ExpressionBlendType2["ExpressionBlendType_Overwrite"] = 2] = "ExpressionBlendType_Overwrite"; return ExpressionBlendType2; })(ExpressionBlendType || {}); class CubismMotionQueueEntry { constructor() { this._autoDelete = false; this._available = true; this._finished = false; this._started = false; this._startTimeSeconds = -1; this._fadeInStartTimeSeconds = 0; this._endTimeSeconds = -1; this._stateTimeSeconds = 0; this._stateWeight = 0; this._lastEventCheckSeconds = 0; this._motionQueueEntryHandle = this; this._fadeOutSeconds = 0; this._isTriggeredFadeOut = false; } release() { if (this._autoDelete && this._motion) { this._motion.release(); } } setFadeOut(fadeOutSeconds) { this._fadeOutSeconds = fadeOutSeconds; this._isTriggeredFadeOut = true; } startFadeOut(fadeOutSeconds, userTimeSeconds) { const newEndTimeSeconds = userTimeSeconds + fadeOutSeconds; this._isTriggeredFadeOut = true; if (this._endTimeSeconds < 0 || newEndTimeSeconds < this._endTimeSeconds) { this._endTimeSeconds = newEndTimeSeconds; } } isFinished() { return this._finished; } isStarted() { return this._started; } getStartTime() { return this._startTimeSeconds; } getFadeInStartTime() { return this._fadeInStartTimeSeconds; } getEndTime() { return this._endTimeSeconds; } setStartTime(startTime) { this._startTimeSeconds = startTime; } setFadeInStartTime(startTime) { this._fadeInStartTimeSeconds = startTime; } setEndTime(endTime) { this._endTimeSeconds = endTime; } setIsFinished(f) { this._finished = f; } setIsStarted(f) { this._started = f; } isAvailable() { return this._available; } setIsAvailable(v) { this._available = v; } setState(timeSeconds, weight) { this._stateTimeSeconds = timeSeconds; this._stateWeight = weight; } getStateTime() { return this._stateTimeSeconds; } getStateWeight() { return this._stateWeight; } getLastCheckEventSeconds() { return this._lastEventCheckSeconds; } setLastCheckEventSeconds(checkSeconds) { this._lastEventCheckSeconds = checkSeconds; } isTriggeredFadeOut() { return this._isTriggeredFadeOut; } getFadeOutSeconds() { return this._fadeOutSeconds; } } class CubismMotionQueueManager { constructor() { this._userTimeSeconds = 0; this._eventCustomData = null; this._motions = []; } release() { for (let i = 0; i < this._motions.length; ++i) { if (this._motions[i]) { this._motions[i].release(); } } this._motions = void 0; } startMotion(motion, autoDelete, userTimeSeconds) { if (motion == null) { return InvalidMotionQueueEntryHandleValue; } let motionQueueEntry; for (let i = 0; i < this._motions.length; ++i) { motionQueueEntry = this._motions[i]; if (motionQueueEntry == null) { continue; } motionQueueEntry.setFadeOut(motionQueueEntry._motion.getFadeOutTime()); } motionQueueEntry = new CubismMotionQueueEntry(); motionQueueEntry._autoDelete = autoDelete; motionQueueEntry._motion = motion; this._motions.push(motionQueueEntry); return motionQueueEntry._motionQueueEntryHandle; } isFinished() { let i = 0; while (i < this._motions.length) { const motionQueueEntry = this._motions[i]; if (motionQueueEntry == null) { this._motions.splice(i, 1); continue; } const motion = motionQueueEntry._motion; if (motion == null) { motionQueueEntry.release(); this._motions.splice(i, 1); continue; } if (!motionQueueEntry.isFinished()) { return false; } i++; } return true; } isFinishedByHandle(motionQueueEntryNumber) { for (let i = 0; i < this._motions.length; i++) { const motionQueueEntry = this._motions[i]; if (motionQueueEntry == null) { continue; } if (motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber && !motionQueueEntry.isFinished()) { return false; } } return true; } stopAllMotions() { for (let i = 0; i < this._motions.length; i++) { const motionQueueEntry = this._motions[i]; if (motionQueueEntry != null) { motionQueueEntry.release(); } } this._motions = []; } getCubismMotionQueueEntry(motionQueueEntryNumber) { return this._motions.find((entry) => entry != null && entry._motionQueueEntryHandle == motionQueueEntryNumber); } setEventCallback(callback, customData = null) { this._eventCallBack = callback; this._eventCustomData = customData; } doUpdateMotion(model, userTimeSeconds) { let updated = false; let i = 0; while (i < this._motions.length) { const motionQueueEntry = this._motions[i]; if (motionQueueEntry == null) { this._motions.splice(i, 1); continue; } const motion = motionQueueEntry._motion; if (motion == null) { motionQueueEntry.release(); this._motions.splice(i, 1); continue; } motion.updateParameters(model, motionQueueEntry, userTimeSeconds); updated = true; const firedList = motion.getFiredEvent(motionQueueEntry.getLastCheckEventSeconds() - motionQueueEntry.getStartTime(), userTimeSeconds - motionQueueEntry.getStartTime()); for (let i2 = 0; i2 < firedList.length; ++i2) { this._eventCallBack(this, firedList[i2], this._eventCustomData); } motionQueueEntry.setLastCheckEventSeconds(userTimeSeconds); if (motionQueueEntry.isFinished()) { motionQueueEntry.release(); this._motions.splice(i, 1); } else { if (motionQueueEntry.isTriggeredFadeOut()) { motionQueueEntry.startFadeOut(motionQueueEntry.getFadeOutSeconds(), userTimeSeconds); } i++; } } return updated; } } const InvalidMotionQueueEntryHandleValue = -1; class Cubism4ExpressionManager extends ExpressionManager { constructor(settings, options) { var _a; super(settings, options); this.queueManager = new CubismMotionQueueManager(); this.definitions = (_a = 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 CubismExpressionMotion.create(data); } _setExpression(motion) { return this.queueManager.startMotion(motion, false, performance.now()); } stopAllExpressions() { this.queueManager.stopAllMotions(); } updateParameters(model, now) { return this.queueManager.doUpdateMotion(model, now); } } class CubismModelSettingsJson { constructor(json) { this.groups = json.Groups; this.hitAreas = json.HitAreas; this.layout = json.Layout; this.moc = json.FileReferences.Moc; this.expressions = json.FileReferences.Expressions; this.motions = json.FileReferences.Motions; this.textures = json.FileReferences.Textures; this.physics = json.FileReferences.Physics; this.pose = json.FileReferences.Pose; } getEyeBlinkParameters() { var _a, _b; return (_b = (_a = this.groups) == null ? void 0 : _a.find((group) => group.Name === "EyeBlink")) == null ? void 0 : _b.Ids; } getLipSyncParameters() { var _a, _b; return (_b = (_a = this.groups) == null ? void 0 : _a.find((group) => group.Name === "LipSync")) == null ? void 0 : _b.Ids; } } class Cubism4ModelSettings extends ModelSettings { constructor(json) { super(json); if (!Cubism4ModelSettings.isValidJSON(json)) { throw new TypeError("Invalid JSON."); } Object.assign(this, new CubismModelSettingsJson(json)); } static isValidJSON(json) { var _a; return !!(json == null ? void 0 : json.FileReferences) && typeof json.FileReferences.Moc === "string" && ((_a = json.FileReferences.Textures) == null ? void 0 : _a.length) > 0 && json.FileReferences.Textures.every((item) => typeof item === "string"); } replaceFiles(replace) { super.replaceFiles(replace); if (this.motions) { 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`); } } } } applyMixins(Cubism4ModelSettings, [CubismModelSettingsJson]); var CubismMotionCurveTarget = /* @__PURE__ */ ((CubismMotionCurveTarget2) => { CubismMotionCurveTarget2[CubismMotionCurveTarget2["CubismMotionCurveTarget_Model"] = 0] = "CubismMotionCurveTarget_Model"; CubismMotionCurveTarget2[CubismMotionCurveTarget2["CubismMotionCurveTarget_Parameter"] = 1] = "CubismMotionCurveTarget_Parameter"; CubismMotionCurveTarget2[CubismMotionCurveTarget2["CubismMotionCurveTarget_PartOpacity"] = 2] = "CubismMotionCurveTarget_PartOpacity"; return CubismMotionCurveTarget2; })(CubismMotionCurveTarget || {}); var CubismMotionSegmentType = /* @__PURE__ */ ((CubismMotionSegmentType2) => { CubismMotionSegmentType2[CubismMotionSegmentType2["CubismMotionSegmentType_Linear"] = 0] = "CubismMotionSegmentType_Linear"; CubismMotionSegmentType2[CubismMotionSegmentType2["CubismMotionSegmentType_Bezier"] = 1] = "CubismMotionSegmentType_Bezier"; CubismMotionSegmentType2[CubismMotionSegmentType2["CubismMotionSegmentType_Stepped"] = 2] = "CubismMotionSegmentType_Stepped"; CubismMotionSegmentType2[CubismMotionSegmentType2["CubismMotionSegmentType_InverseStepped"] = 3] = "CubismMotionSegmentType_InverseStepped"; return CubismMotionSegmentType2; })(CubismMotionSegmentType || {}); class CubismMotionPoint { constructor(time = 0, value = 0) { this.time = time; this.value = value; } } class CubismMotionSegment { constructor() { this.basePointIndex = 0; this.segmentType = 0; } } class CubismMotionCurve { constructor() { this.id = ""; this.type = 0; this.segmentCount = 0; this.baseSegmentIndex = 0; this.fadeInTime = 0; this.fadeOutTime = 0; } } class CubismMotionEvent { constructor() { this.fireTime = 0; this.value = ""; } } class CubismMotionData { constructor() { this.duration = 0; this.loop = false; this.curveCount = 0; this.eventCount = 0; this.fps = 0; this.curves = []; this.segments = []; this.points = []; this.events = []; } } class CubismMotionJson { constructor(json) { this._json = json; } release() { this._json = void 0; } getMotionDuration() { return this._json.Meta.Duration; } isMotionLoop() { return this._json.Meta.Loop || false; } getEvaluationOptionFlag(flagType) { if (EvaluationOptionFlag.EvaluationOptionFlag_AreBeziersRistricted == flagType) { return !!this._json.Meta.AreBeziersRestricted; } return false; } getMotionCurveCount() { return this._json.Meta.CurveCount; } getMotionFps() { return this._json.Meta.Fps; } getMotionTotalSegmentCount() { return this._json.Meta.TotalSegmentCount; } getMotionTotalPointCount() { return this._json.Meta.TotalPointCount; } getMotionFadeInTime() { return this._json.Meta.FadeInTime; } getMotionFadeOutTime() { return this._json.Meta.FadeOutTime; } getMotionCurveTarget(curveIndex) { return this._json.Curves[curveIndex].Target; } getMotionCurveId(curveIndex) { return this._json.Curves[curveIndex].Id; } getMotionCurveFadeInTime(curveIndex) { return this._json.Curves[curveIndex].FadeInTime; } getMotionCurveFadeOutTime(curveIndex) { return this._json.Curves[curveIndex].FadeOutTime; } getMotionCurveSegmentCount(curveIndex) { return this._json.Curves[curveIndex].Segments.length; } getMotionCurveSegment(curveIndex, segmentIndex) { return this._json.Curves[curveIndex].Segments[segmentIndex]; } getEventCount() { return this._json.Meta.UserDataCount || 0; } getTotalEventValueSize() { return this._json.Meta.TotalUserDataSize; } getEventTime(userDataIndex) { return this._json.UserData[userDataIndex].Time; } getEventValue(userDataIndex) { return this._json.UserData[userDataIndex].Value; } } var EvaluationOptionFlag = /* @__PURE__ */ ((EvaluationOptionFlag2) => { EvaluationOptionFlag2[EvaluationOptionFlag2["EvaluationOptionFlag_AreBeziersRistricted"] = 0] = "EvaluationOptionFlag_AreBeziersRistricted"; return EvaluationOptionFlag2; })(EvaluationOptionFlag || {}); const EffectNameEyeBlink = "EyeBlink"; const EffectNameLipSync = "LipSync"; const TargetNameModel = "Model"; const TargetNameParameter = "Parameter"; const TargetNamePartOpacity = "PartOpacity"; const UseOldBeziersCurveMotion = false; function lerpPoints(a, b, t) { const result = new CubismMotionPoint(); result.time = a.time + (b.time - a.time) * t; result.value = a.value + (b.value - a.value) * t; return result; } function linearEvaluate(points, time) { let t = (time - points[0].time) / (points[1].time - points[0].time); if (t < 0) { t = 0; } return points[0].value + (points[1].value - points[0].value) * t; } function bezierEvaluate(points, time) { let t = (time - points[0].time) / (points[3].time - points[0].time); if (t < 0) { t = 0; } const p01 = lerpPoints(points[0], points[1], t); const p12 = lerpPoints(points[1], points[2], t); const p23 = lerpPoints(points[2], points[3], t); const p012 = lerpPoints(p01, p12, t); const p123 = lerpPoints(p12, p23, t); return lerpPoints(p012, p123, t).value; } function bezierEvaluateCardanoInterpretation(points, time) { const x = time; const x1 = points[0].time; const x2 = points[3].time; const cx1 = points[1].time; const cx2 = points[2].time; const a = x2 - 3 * cx2 + 3 * cx1 - x1; const b = 3 * cx2 - 6 * cx1 + 3 * x1; const c = 3 * cx1 - 3 * x1; const d = x1 - x; const t = CubismMath.cardanoAlgorithmForBezier(a, b, c, d); const p01 = lerpPoints(points[0], points[1], t); const p12 = lerpPoints(points[1], points[2], t); const p23 = lerpPoints(points[2], points[3], t); const p012 = lerpPoints(p01, p12, t); const p123 = lerpPoints(p12, p23, t); return lerpPoints(p012, p123, t).value; } function steppedEvaluate(points, time) { return points[0].value; } function inverseSteppedEvaluate(points, time) { return points[1].value; } function evaluateCurve(motionData, index, time) { const curve = motionData.curves[index]; let target = -1; const totalSegmentCount = curve.baseSegmentIndex + curve.segmentCount; let pointPosition = 0; for (let i = curve.baseSegmentIndex; i < totalSegmentCount; ++i) { pointPosition = motionData.segments[i].basePointIndex + (motionData.segments[i].segmentType == CubismMotionSegmentType.CubismMotionSegmentType_Bezier ? 3 : 1); if (motionData.points[pointPosition].time > time) { target = i; break; } } if (target == -1) { return motionData.points[pointPosition].value; } const segment = motionData.segments[target]; return segment.evaluate(motionData.points.slice(segment.basePointIndex), time); } class CubismMotion extends ACubismMotion { constructor() { super(); this._eyeBlinkParameterIds = []; this._lipSyncParameterIds = []; this._sourceFrameRate = 30; this._loopDurationSeconds = -1; this._isLoop = false; this._isLoopFadeIn = true; this._lastWeight = 0; } static create(json, onFinishedMotionHandler) { const ret = new CubismMotion(); ret.parse(json); ret._sourceFrameRate = ret._motionData.fps; ret._loopDurationSeconds = ret._motionData.duration; ret._onFinishedMotion = onFinishedMotionHandler; return ret; } doUpdateParameters(model, userTimeSeconds, fadeWeight, motionQueueEntry) { if (this._modelCurveIdEyeBlink == null) { this._modelCurveIdEyeBlink = EffectNameEyeBlink; } if (this._modelCurveIdLipSync == null) { this._modelCurveIdLipSync = EffectNameLipSync; } let timeOffsetSeconds = userTimeSeconds - motionQueueEntry.getStartTime(); if (timeOffsetSeconds < 0) { timeOffsetSeconds = 0; } let lipSyncValue = Number.MAX_VALUE; let eyeBlinkValue = Number.MAX_VALUE; const MaxTargetSize = 64; let lipSyncFlags = 0; let eyeBlinkFlags = 0; if (this._eyeBlinkParameterIds.length > MaxTargetSize) { CubismLogDebug("too many eye blink targets : {0}", this._eyeBlinkParameterIds.length); } if (this._lipSyncParameterIds.length > MaxTargetSize) { CubismLogDebug("too many lip sync targets : {0}", this._lipSyncParameterIds.length); } const tmpFadeIn = this._fadeInSeconds <= 0 ? 1 : CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / this._fadeInSeconds); const tmpFadeOut = this._fadeOutSeconds <= 0 || motionQueueEntry.getEndTime() < 0 ? 1 : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / this._fadeOutSeconds); let value; let c, parameterIndex; let time = timeOffsetSeconds; if (this._isLoop) { while (time > this._motionData.duration) { time -= this._motionData.duration; } } const curves = this._motionData.curves; for (c = 0; c < this._motionData.curveCount && curves[c].type == CubismMotionCurveTarget.CubismMotionCurveTarget_Model; ++c) { value = evaluateCurve(this._motionData, c, time); if (curves[c].id == this._modelCurveIdEyeBlink) { eyeBlinkValue = value; } else if (curves[c].id == this._modelCurveIdLipSync) { lipSyncValue = value; } } for (; c < this._motionData.curveCount && curves[c].type == CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter; ++c) { parameterIndex = model.getParameterIndex(curves[c].id); if (parameterIndex == -1) { continue; } const sourceValue = model.getParameterValueByIndex(parameterIndex); value = evaluateCurve(this._motionData, c, time); if (eyeBlinkValue != Number.MAX_VALUE) { for (let i = 0; i < this._eyeBlinkParameterIds.length && i < MaxTargetSize; ++i) { if (this._eyeBlinkParameterIds[i] == curves[c].id) { value *= eyeBlinkValue; eyeBlinkFlags |= 1 << i; break; } } } if (lipSyncValue != Number.MAX_VALUE) { for (let i = 0; i < this._lipSyncParameterIds.length && i < MaxTargetSize; ++i) { if (this._lipSyncParameterIds[i] == curves[c].id) { value += lipSyncValue; lipSyncFlags |= 1 << i; break; } } } let v; if (curves[c].fadeInTime < 0 && curves[c].fadeOutTime < 0) { v = sourceValue + (value - sourceValue) * fadeWeight; } else { let fin; let fout; if (curves[c].fadeInTime < 0) { fin = tmpFadeIn; } else { fin = curves[c].fadeInTime == 0 ? 1 : CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / curves[c].fadeInTime); } if (curves[c].fadeOutTime < 0) { fout = tmpFadeOut; } else { fout = curves[c].fadeOutTime == 0 || motionQueueEntry.getEndTime() < 0 ? 1 : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / curves[c].fadeOutTime); } const paramWeight = this._weight * fin * fout; v = sourceValue + (value - sourceValue) * paramWeight; } // model.setParameterValueByIndex(parameterIndex, v, 1); if (parameterIndex != model.getParameterIndex("ParamMouthOpenY") && parameterIndex != model.getParameterIndex("ParamMouthForm") && parameterIndex != model.getParameterIndex("Part01Mouth001")) { model.setParameterValueByIndex(parameterIndex, v, 1); // console.log(value) } } { if (eyeBlinkValue != Number.MAX_VALUE) { for (let i = 0; i < this._eyeBlinkParameterIds.length && i < MaxTargetSize; ++i) { const sourceValue = model.getParameterValueById(this._eyeBlinkParameterIds[i]); if (eyeBlinkFlags >> i & 1) { continue; } const v = sourceValue + (eyeBlinkValue - sourceValue) * fadeWeight; model.setParameterValueById(this._eyeBlinkParameterIds[i], v); } } if (lipSyncValue != Number.MAX_VALUE) { for (let i = 0; i < this._lipSyncParameterIds.length && i < MaxTargetSize; ++i) { const sourceValue = model.getParameterValueById(this._lipSyncParameterIds[i]); if (lipSyncFlags >> i & 1) { continue; } const v = sourceValue + (lipSyncValue - sourceValue) * fadeWeight; model.setParameterValueById(this._lipSyncParameterIds[i], v); } } } for (; c < this._motionData.curveCount && curves[c].type == CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity; ++c) { value = evaluateCurve(this._motionData, c, time); if (CubismConfig.setOpacityFromMotion) { model.setPartOpacityById(curves[c].id, value); } else { parameterIndex = model.getParameterIndex(curves[c].id); if (parameterIndex == -1) { continue; } model.setParameterValueByIndex(parameterIndex, value); } } if (timeOffsetSeconds >= this._motionData.duration) { if (this._isLoop) { motionQueueEntry.setStartTime(userTimeSeconds); if (this._isLoopFadeIn) { motionQueueEntry.setFadeInStartTime(userTimeSeconds); } } else { if (this._onFinishedMotion) { this._onFinishedMotion(this); } motionQueueEntry.setIsFinished(true); } } this._lastWeight = fadeWeight; } setIsLoop(loop) { this._isLoop = loop; } isLoop() { return this._isLoop; } setIsLoopFadeIn(loopFadeIn) { this._isLoopFadeIn = loopFadeIn; } isLoopFadeIn() { return this._isLoopFadeIn; } getDuration() { return this._isLoop ? -1 : this._loopDurationSeconds; } getLoopDuration() { return this._loopDurationSeconds; } setParameterFadeInTime(parameterId, value) { const curves = this._motionData.curves; for (let i = 0; i < this._motionData.curveCount; ++i) { if (parameterId == curves[i].id) { curves[i].fadeInTime = value; return; } } } setParameterFadeOutTime(parameterId, value) { const curves = this._motionData.curves; for (let i = 0; i < this._motionData.curveCount; ++i) { if (parameterId == curves[i].id) { curves[i].fadeOutTime = value; return; } } } getParameterFadeInTime(parameterId) { const curves = this._motionData.curves; for (let i = 0; i < this._motionData.curveCount; ++i) { if (parameterId == curves[i].id) { return curves[i].fadeInTime; } } return -1; } getParameterFadeOutTime(parameterId) { const curves = this._motionData.curves; for (let i = 0; i < this._motionData.curveCount; ++i) { if (parameterId == curves[i].id) { return curves[i].fadeOutTime; } } return -1; } setEffectIds(eyeBlinkParameterIds, lipSyncParameterIds) { this._eyeBlinkParameterIds = eyeBlinkParameterIds; this._lipSyncParameterIds = lipSyncParameterIds; } release() { this._motionData = void 0; } parse(motionJson) { this._motionData = new CubismMotionData(); let json = new CubismMotionJson(motionJson); this._motionData.duration = json.getMotionDuration(); this._motionData.loop = json.isMotionLoop(); this._motionData.curveCount = json.getMotionCurveCount(); this._motionData.fps = json.getMotionFps(); this._motionData.eventCount = json.getEventCount(); const areBeziersRestructed = json.getEvaluationOptionFlag(EvaluationOptionFlag.EvaluationOptionFlag_AreBeziersRistricted); const fadeInSeconds = json.getMotionFadeInTime(); const fadeOutSeconds = json.getMotionFadeOutTime(); if (fadeInSeconds !== void 0) { this._fadeInSeconds = fadeInSeconds < 0 ? 1 : fadeInSeconds; } else { this._fadeInSeconds = 1; } if (fadeOutSeconds !== void 0) { this._fadeOutSeconds = fadeOutSeconds < 0 ? 1 : fadeOutSeconds; } else { this._fadeOutSeconds = 1; } this._motionData.curves = Array.from({ length: this._motionData.curveCount }).map(() => new CubismMotionCurve()); this._motionData.segments = Array.from({ length: json.getMotionTotalSegmentCount() }).map(() => new CubismMotionSegment()); this._motionData.events = Array.from({ length: this._motionData.eventCount }).map(() => new CubismMotionEvent()); this._motionData.points = []; let totalPointCount = 0; let totalSegmentCount = 0; for (let curveCount = 0; curveCount < this._motionData.curveCount; ++curveCount) { const curve = this._motionData.curves[curveCount]; switch (json.getMotionCurveTarget(curveCount)) { case TargetNameModel: curve.type = CubismMotionCurveTarget.CubismMotionCurveTarget_Model; break; case TargetNameParameter: curve.type = CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter; break; case TargetNamePartOpacity: curve.type = CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity; break; default: CubismLogWarning('Warning : Unable to get segment type from Curve! The number of "CurveCount" may be incorrect!'); } curve.id = json.getMotionCurveId(curveCount); curve.baseSegmentIndex = totalSegmentCount; const fadeInTime = json.getMotionCurveFadeInTime(curveCount); const fadeOutTime = json.getMotionCurveFadeOutTime(curveCount); curve.fadeInTime = fadeInTime !== void 0 ? fadeInTime : -1; curve.fadeOutTime = fadeOutTime !== void 0 ? fadeOutTime : -1; for (let segmentPosition = 0; segmentPosition < json.getMotionCurveSegmentCount(curveCount); ) { if (segmentPosition == 0) { this._motionData.segments[totalSegmentCount].basePointIndex = totalPointCount; this._motionData.points[totalPointCount] = new CubismMotionPoint(json.getMotionCurveSegment(curveCount, segmentPosition), json.getMotionCurveSegment(curveCount, segmentPosition + 1)); totalPointCount += 1; segmentPosition += 2; } else { this._motionData.segments[totalSegmentCount].basePointIndex = totalPointCount - 1; } const segment = json.getMotionCurveSegment(curveCount, segmentPosition); switch (segment) { case CubismMotionSegmentType.CubismMotionSegmentType_Linear: { this._motionData.segments[totalSegmentCount].segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Linear; this._motionData.segments[totalSegmentCount].evaluate = linearEvaluate; this._motionData.points[totalPointCount] = new CubismMotionPoint(json.getMotionCurveSegment(curveCount, segmentPosition + 1), json.getMotionCurveSegment(curveCount, segmentPosition + 2)); totalPointCount += 1; segmentPosition += 3; break; } case CubismMotionSegmentType.CubismMotionSegmentType_Bezier: { this._motionData.segments[totalSegmentCount].segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Bezier; if (areBeziersRestructed || UseOldBeziersCurveMotion) { this._motionData.segments[totalSegmentCount].evaluate = bezierEvaluate; } else { this._motionData.segments[totalSegmentCount].evaluate = bezierEvaluateCardanoInterpretation; } this._motionData.points[totalPointCount] = new CubismMotionPoint(json.getMotionCurveSegment(curveCount, segmentPosition + 1), json.getMotionCurveSegment(curveCount, segmentPosition + 2)); this._motionData.points[totalPointCount + 1] = new CubismMotionPoint(json.getMotionCurveSegment(curveCount, segmentPosition + 3), json.getMotionCurveSegment(curveCount, segmentPosition + 4)); this._motionData.points[totalPointCount + 2] = new CubismMotionPoint(json.getMotionCurveSegment(curveCount, segmentPosition + 5), json.getMotionCurveSegment(curveCount, segmentPosition + 6)); totalPointCount += 3; segmentPosition += 7; break; } case CubismMotionSegmentType.CubismMotionSegmentType_Stepped: { this._motionData.segments[totalSegmentCount].segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Stepped; this._motionData.segments[totalSegmentCount].evaluate = steppedEvaluate; this._motionData.points[totalPointCount] = new CubismMotionPoint(json.getMotionCurveSegment(curveCount, segmentPosition + 1), json.getMotionCurveSegment(curveCount, segmentPosition + 2)); totalPointCount += 1; segmentPosition += 3; break; } case CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped: { this._motionData.segments[totalSegmentCount].segmentType = CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped; this._motionData.segments[totalSegmentCount].evaluate = inverseSteppedEvaluate; this._motionData.points[totalPointCount] = new CubismMotionPoint(json.getMotionCurveSegment(curveCount, segmentPosition + 1), json.getMotionCurveSegment(curveCount, segmentPosition + 2)); totalPointCount += 1; segmentPosition += 3; break; } } ++curve.segmentCount; ++totalSegmentCount; } this._motionData.curves.push(curve); } for (let userdatacount = 0; userdatacount < json.getEventCount(); ++userdatacount) { this._motionData.events[userdatacount].fireTime = json.getEventTime(userdatacount); this._motionData.events[userdatacount].value = json.getEventValue(userdatacount); } json.release(); } getFiredEvent(beforeCheckTimeSeconds, motionTimeSeconds) { this._firedEventValues.length = 0; for (let u = 0; u < this._motionData.eventCount; ++u) { if (this._motionData.events[u].fireTime > beforeCheckTimeSeconds && this._motionData.events[u].fireTime <= motionTimeSeconds) { this._firedEventValues.push(this._motionData.events[u].value); } } return this._firedEventValues; } } class Cubism4MotionManager extends MotionManager { constructor(settings, options) { var _a; super(settings, options); this.groups = { idle: "Idle" }; this.motionDataType = "json"; this.queueManager = new CubismMotionQueueManager(); this.definitions = (_a = settings.motions) != null ? _a : {}; this.eyeBlinkIds = settings.getEyeBlinkParameters() || []; this.lipSyncIds = settings.getLipSyncParameters() || []; this.init(options); } init(options) { super.init(options); if (this.settings.expressions) { this.expressionManager = new Cubism4ExpressionManager(this.settings, options); } this.queueManager.setEventCallback((caller, eventValue, customData) => { this.emit("motion:" + eventValue); }); } isFinished() { return this.queueManager.isFinished(); } _startMotion(motion, onFinish) { motion.setFinishedMotionHandler(onFinish); this.queueManager.stopAllMotions(); return this.queueManager.startMotion(motion, false, performance.now()); } _stopAllMotions() { this.queueManager.stopAllMotions(); } createMotion(data, group, definition) { const motion = CubismMotion.create(data); const json = new CubismMotionJson(data); const defaultFadingDuration = (group === this.groups.idle ? exports2.config.idleMotionFadingDuration : exports2.config.motionFadingDuration) / 1e3; if (json.getMotionFadeInTime() === void 0) { motion.setFadeInTime(definition.FadeInTime > 0 ? definition.FadeInTime : defaultFadingDuration); } if (json.getMotionFadeOutTime() === void 0) { motion.setFadeOutTime(definition.FadeOutTime > 0 ? definition.FadeOutTime : defaultFadingDuration); } motion.setEffectIds(this.eyeBlinkIds, this.lipSyncIds); return motion; } getMotionFile(definition) { return definition.File; } getMotionName(definition) { return definition.File; } getSoundFile(definition) { return definition.Sound; } updateParameters(model, now) { return this.queueManager.doUpdateMotion(model, now); } destroy() { super.destroy(); this.queueManager.release(); this.queueManager = void 0; } } const ParamAngleX = "ParamAngleX"; const ParamAngleY = "ParamAngleY"; const ParamAngleZ = "ParamAngleZ"; const ParamEyeBallX = "ParamEyeBallX"; const ParamEyeBallY = "ParamEyeBallY"; const ParamBodyAngleX = "ParamBodyAngleX"; const ParamBreath = "ParamBreath"; class CubismBreath { constructor() { this._breathParameters = []; this._currentTime = 0; } static create() { return new CubismBreath(); } setParameters(breathParameters) { this._breathParameters = breathParameters; } getParameters() { return this._breathParameters; } updateParameters(model, deltaTimeSeconds) { this._currentTime += deltaTimeSeconds; const t = this._currentTime * 2 * 3.14159; for (let i = 0; i < this._breathParameters.length; ++i) { const data = this._breathParameters[i]; model.addParameterValueById(data.parameterId, data.offset + data.peak * Math.sin(t / data.cycle), data.weight); } } } class BreathParameterData { constructor(parameterId, offset, peak, cycle, weight) { this.parameterId = parameterId == void 0 ? void 0 : parameterId; this.offset = offset == void 0 ? 0 : offset; this.peak = peak == void 0 ? 0 : peak; this.cycle = cycle == void 0 ? 0 : cycle; this.weight = weight == void 0 ? 0 : weight; } } const _CubismEyeBlink = class { static create(modelSetting) { return new _CubismEyeBlink(modelSetting); } setBlinkingInterval(blinkingInterval) { this._blinkingIntervalSeconds = blinkingInterval; } setBlinkingSetting(closing, closed, opening) { this._closingSeconds = closing; this._closedSeconds = closed; this._openingSeconds = opening; } setParameterIds(parameterIds) { this._parameterIds = parameterIds; } getParameterIds() { return this._parameterIds; } updateParameters(model, deltaTimeSeconds) { this._userTimeSeconds += deltaTimeSeconds; let parameterValue; let t = 0; switch (this._blinkingState) { case EyeState.EyeState_Closing: t = (this._userTimeSeconds - this._stateStartTimeSeconds) / this._closingSeconds; if (t >= 1) { t = 1; this._blinkingState = EyeState.EyeState_Closed; this._stateStartTimeSeconds = this._userTimeSeconds; } parameterValue = 1 - t; break; case EyeState.EyeState_Closed: t = (this._userTimeSeconds - this._stateStartTimeSeconds) / this._closedSeconds; if (t >= 1) { this._blinkingState = EyeState.EyeState_Opening; this._stateStartTimeSeconds = this._userTimeSeconds; } parameterValue = 0; break; case EyeState.EyeState_Opening: t = (this._userTimeSeconds - this._stateStartTimeSeconds) / this._openingSeconds; if (t >= 1) { t = 1; this._blinkingState = EyeState.EyeState_Interval; this._nextBlinkingTime = this.determinNextBlinkingTiming(); } parameterValue = t; break; case EyeState.EyeState_Interval: if (this._nextBlinkingTime < this._userTimeSeconds) { this._blinkingState = EyeState.EyeState_Closing; this._stateStartTimeSeconds = this._userTimeSeconds; } parameterValue = 1; break; case EyeState.EyeState_First: default: this._blinkingState = EyeState.EyeState_Interval; this._nextBlinkingTime = this.determinNextBlinkingTiming(); parameterValue = 1; break; } if (!_CubismEyeBlink.CloseIfZero) { parameterValue = -parameterValue; } for (let i = 0; i < this._parameterIds.length; ++i) { model.setParameterValueById(this._parameterIds[i], parameterValue); } } constructor(modelSetting) { var _a, _b; this._blinkingState = EyeState.EyeState_First; this._nextBlinkingTime = 0; this._stateStartTimeSeconds = 0; this._blinkingIntervalSeconds = 4; this._closingSeconds = 0.1; this._closedSeconds = 0.05; this._openingSeconds = 0.15; this._userTimeSeconds = 0; this._parameterIds = []; if (modelSetting == null) { return; } this._parameterIds = (_b = (_a = modelSetting.getEyeBlinkParameters()) == null ? void 0 : _a.slice()) != null ? _b : this._parameterIds; } determinNextBlinkingTiming() { const r = Math.random(); return this._userTimeSeconds + r * (2 * this._blinkingIntervalSeconds - 1); } }; let CubismEyeBlink = _CubismEyeBlink; CubismEyeBlink.CloseIfZero = true; var EyeState = /* @__PURE__ */ ((EyeState2) => { EyeState2[EyeState2["EyeState_First"] = 0] = "EyeState_First"; EyeState2[EyeState2["EyeState_Interval"] = 1] = "EyeState_Interval"; EyeState2[EyeState2["EyeState_Closing"] = 2] = "EyeState_Closing"; EyeState2[EyeState2["EyeState_Closed"] = 3] = "EyeState_Closed"; EyeState2[EyeState2["EyeState_Opening"] = 4] = "EyeState_Opening"; return EyeState2; })(EyeState || {}); class csmRect { constructor(x = 0, y = 0, w = 0, h = 0) { this.x = x; this.y = y; this.width = w; this.height = h; } getCenterX() { return this.x + 0.5 * this.width; } getCenterY() { return this.y + 0.5 * this.height; } getRight() { return this.x + this.width; } getBottom() { return this.y + this.height; } setRect(r) { this.x = r.x; this.y = r.y; this.width = r.width; this.height = r.height; } expand(w, h) { this.x -= w; this.y -= h; this.width += w * 2; this.height += h * 2; } } const ColorChannelCount = 4; const shaderCount = 10; let s_instance; let s_viewport; let s_fbo; class CubismClippingManager_WebGL { getChannelFlagAsColor(channelNo) { return this._channelColors[channelNo]; } getMaskRenderTexture() { let ret = 0; if (this._maskTexture && this._maskTexture.texture != 0) { this._maskTexture.frameNo = this._currentFrameNo; ret = this._maskTexture.texture; } if (ret == 0) { const size = this._clippingMaskBufferSize; this._colorBuffer = this.gl.createTexture(); this.gl.bindTexture(this.gl.TEXTURE_2D, this._colorBuffer); this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, size, size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); this.gl.bindTexture(this.gl.TEXTURE_2D, null); ret = this.gl.createFramebuffer(); this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, ret); this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._colorBuffer, 0); this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, s_fbo); this._maskTexture = new CubismRenderTextureResource(this._currentFrameNo, ret); } return ret; } setGL(gl) { this.gl = gl; } calcClippedDrawTotalBounds(model, clippingContext) { let clippedDrawTotalMinX = Number.MAX_VALUE; let clippedDrawTotalMinY = Number.MAX_VALUE; let clippedDrawTotalMaxX = Number.MIN_VALUE; let clippedDrawTotalMaxY = Number.MIN_VALUE; const clippedDrawCount = clippingContext._clippedDrawableIndexList.length; for (let clippedDrawableIndex = 0; clippedDrawableIndex < clippedDrawCount; clippedDrawableIndex++) { const drawableIndex = clippingContext._clippedDrawableIndexList[clippedDrawableIndex]; const drawableVertexCount = model.getDrawableVertexCount(drawableIndex); const drawableVertexes = model.getDrawableVertices(drawableIndex); let minX = Number.MAX_VALUE; let minY = Number.MAX_VALUE; let maxX = Number.MIN_VALUE; let maxY = Number.MIN_VALUE; const loop = drawableVertexCount * Constant.vertexStep; for (let pi = Constant.vertexOffset; pi < loop; pi += Constant.vertexStep) { const x = drawableVertexes[pi]; const y = drawableVertexes[pi + 1]; if (x < minX) { minX = x; } if (x > maxX) { maxX = x; } if (y < minY) { minY = y; } if (y > maxY) { maxY = y; } } if (minX == Number.MAX_VALUE) { continue; } if (minX < clippedDrawTotalMinX) { clippedDrawTotalMinX = minX; } if (minY < clippedDrawTotalMinY) { clippedDrawTotalMinY = minY; } if (maxX > clippedDrawTotalMaxX) { clippedDrawTotalMaxX = maxX; } if (maxY > clippedDrawTotalMaxY) { clippedDrawTotalMaxY = maxY; } if (clippedDrawTotalMinX == Number.MAX_VALUE) { clippingContext._allClippedDrawRect.x = 0; clippingContext._allClippedDrawRect.y = 0; clippingContext._allClippedDrawRect.width = 0; clippingContext._allClippedDrawRect.height = 0; clippingContext._isUsing = false; } else { clippingContext._isUsing = true; const w = clippedDrawTotalMaxX - clippedDrawTotalMinX; const h = clippedDrawTotalMaxY - clippedDrawTotalMinY; clippingContext._allClippedDrawRect.x = clippedDrawTotalMinX; clippingContext._allClippedDrawRect.y = clippedDrawTotalMinY; clippingContext._allClippedDrawRect.width = w; clippingContext._allClippedDrawRect.height = h; } } } constructor() { this._maskRenderTexture = null; this._colorBuffer = null; this._currentFrameNo = 0; this._clippingMaskBufferSize = 256; this._clippingContextListForMask = []; this._clippingContextListForDraw = []; this._channelColors = []; this._tmpBoundsOnModel = new csmRect(); this._tmpMatrix = new CubismMatrix44(); this._tmpMatrixForMask = new CubismMatrix44(); this._tmpMatrixForDraw = new CubismMatrix44(); let tmp = new CubismTextureColor(); tmp.R = 1; tmp.G = 0; tmp.B = 0; tmp.A = 0; this._channelColors.push(tmp); tmp = new CubismTextureColor(); tmp.R = 0; tmp.G = 1; tmp.B = 0; tmp.A = 0; this._channelColors.push(tmp); tmp = new CubismTextureColor(); tmp.R = 0; tmp.G = 0; tmp.B = 1; tmp.A = 0; this._channelColors.push(tmp); tmp = new CubismTextureColor(); tmp.R = 0; tmp.G = 0; tmp.B = 0; tmp.A = 1; this._channelColors.push(tmp); } release() { var _a, _b, _c; const self2 = this; for (let i = 0; i < this._clippingContextListForMask.length; i++) { if (this._clippingContextListForMask[i]) { (_a = this._clippingContextListForMask[i]) == null ? void 0 : _a.release(); } } self2._clippingContextListForMask = void 0; self2._clippingContextListForDraw = void 0; if (this._maskTexture) { (_b = this.gl) == null ? void 0 : _b.deleteFramebuffer(this._maskTexture.texture); self2._maskTexture = void 0; } self2._channelColors = void 0; (_c = this.gl) == null ? void 0 : _c.deleteTexture(this._colorBuffer); this._colorBuffer = null; } initialize(model, drawableCount, drawableMasks, drawableMaskCounts) { for (let i = 0; i < drawableCount; i++) { if (drawableMaskCounts[i] <= 0) { this._clippingContextListForDraw.push(null); continue; } let clippingContext = this.findSameClip(drawableMasks[i], drawableMaskCounts[i]); if (clippingContext == null) { clippingContext = new CubismClippingContext(this, drawableMasks[i], drawableMaskCounts[i]); this._clippingContextListForMask.push(clippingContext); } clippingContext.addClippedDrawable(i); this._clippingContextListForDraw.push(clippingContext); } } setupClippingContext(model, renderer) { this._currentFrameNo++; let usingClipCount = 0; for (let clipIndex = 0; clipIndex < this._clippingContextListForMask.length; clipIndex++) { const cc = this._clippingContextListForMask[clipIndex]; this.calcClippedDrawTotalBounds(model, cc); if (cc._isUsing) { usingClipCount++; } } if (usingClipCount > 0) { this.gl.viewport(0, 0, this._clippingMaskBufferSize, this._clippingMaskBufferSize); this._maskRenderTexture = this.getMaskRenderTexture(); renderer.getMvpMatrix(); renderer.preDraw(); this.setupLayoutBounds(usingClipCount); this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this._maskRenderTexture); this.gl.clearColor(1, 1, 1, 1); this.gl.clear(this.gl.COLOR_BUFFER_BIT); for (let clipIndex = 0; clipIndex < this._clippingContextListForMask.length; clipIndex++) { const clipContext = this._clippingContextListForMask[clipIndex]; const allClipedDrawRect = clipContext._allClippedDrawRect; const layoutBoundsOnTex01 = clipContext._layoutBounds; const MARGIN = 0.05; this._tmpBoundsOnModel.setRect(allClipedDrawRect); this._tmpBoundsOnModel.expand(allClipedDrawRect.width * MARGIN, allClipedDrawRect.height * MARGIN); const scaleX = layoutBoundsOnTex01.width / this._tmpBoundsOnModel.width; const scaleY = layoutBoundsOnTex01.height / this._tmpBoundsOnModel.height; { this._tmpMatrix.loadIdentity(); { this._tmpMatrix.translateRelative(-1, -1); this._tmpMatrix.scaleRelative(2, 2); } { this._tmpMatrix.translateRelative(layoutBoundsOnTex01.x, layoutBoundsOnTex01.y); this._tmpMatrix.scaleRelative(scaleX, scaleY); this._tmpMatrix.translateRelative(-this._tmpBoundsOnModel.x, -this._tmpBoundsOnModel.y); } this._tmpMatrixForMask.setMatrix(this._tmpMatrix.getArray()); } { this._tmpMatrix.loadIdentity(); { this._tmpMatrix.translateRelative(layoutBoundsOnTex01.x, layoutBoundsOnTex01.y); this._tmpMatrix.scaleRelative(scaleX, scaleY); this._tmpMatrix.translateRelative(-this._tmpBoundsOnModel.x, -this._tmpBoundsOnModel.y); } this._tmpMatrixForDraw.setMatrix(this._tmpMatrix.getArray()); } clipContext._matrixForMask.setMatrix(this._tmpMatrixForMask.getArray()); clipContext._matrixForDraw.setMatrix(this._tmpMatrixForDraw.getArray()); const clipDrawCount = clipContext._clippingIdCount; for (let i = 0; i < clipDrawCount; i++) { const clipDrawIndex = clipContext._clippingIdList[i]; if (!model.getDrawableDynamicFlagVertexPositionsDidChange(clipDrawIndex)) { continue; } renderer.setIsCulling(model.getDrawableCulling(clipDrawIndex) != false); renderer.setClippingContextBufferForMask(clipContext); renderer.drawMesh(model.getDrawableTextureIndices(clipDrawIndex), model.getDrawableVertexIndexCount(clipDrawIndex), model.getDrawableVertexCount(clipDrawIndex), model.getDrawableVertexIndices(clipDrawIndex), model.getDrawableVertices(clipDrawIndex), model.getDrawableVertexUvs(clipDrawIndex), model.getDrawableOpacity(clipDrawIndex), CubismBlendMode.CubismBlendMode_Normal, false); } } this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, s_fbo); renderer.setClippingContextBufferForMask(null); this.gl.viewport(s_viewport[0], s_viewport[1], s_viewport[2], s_viewport[3]); } } findSameClip(drawableMasks, drawableMaskCounts) { for (let i = 0; i < this._clippingContextListForMask.length; i++) { const clippingContext = this._clippingContextListForMask[i]; const count = clippingContext._clippingIdCount; if (count != drawableMaskCounts) { continue; } let sameCount = 0; for (let j = 0; j < count; j++) { const clipId = clippingContext._clippingIdList[j]; for (let k = 0; k < count; k++) { if (drawableMasks[k] == clipId) { sameCount++; break; } } } if (sameCount == count) { return clippingContext; } } return null; } setupLayoutBounds(usingClipCount) { let div = usingClipCount / ColorChannelCount; let mod = usingClipCount % ColorChannelCount; div = ~~div; mod = ~~mod; let curClipIndex = 0; for (let channelNo = 0; channelNo < ColorChannelCount; channelNo++) { const layoutCount = div + (channelNo < mod ? 1 : 0); if (layoutCount == 0) ; else if (layoutCount == 1) { const clipContext = this._clippingContextListForMask[curClipIndex++]; clipContext._layoutChannelNo = channelNo; clipContext._layoutBounds.x = 0; clipContext._layoutBounds.y = 0; clipContext._layoutBounds.width = 1; clipContext._layoutBounds.height = 1; } else if (layoutCount == 2) { for (let i = 0; i < layoutCount; i++) { let xpos = i % 2; xpos = ~~xpos; const cc = this._clippingContextListForMask[curClipIndex++]; cc._layoutChannelNo = channelNo; cc._layoutBounds.x = xpos * 0.5; cc._layoutBounds.y = 0; cc._layoutBounds.width = 0.5; cc._layoutBounds.height = 1; } } else if (layoutCount <= 4) { for (let i = 0; i < layoutCount; i++) { let xpos = i % 2; let ypos = i / 2; xpos = ~~xpos; ypos = ~~ypos; const cc = this._clippingContextListForMask[curClipIndex++]; cc._layoutChannelNo = channelNo; cc._layoutBounds.x = xpos * 0.5; cc._layoutBounds.y = ypos * 0.5; cc._layoutBounds.width = 0.5; cc._layoutBounds.height = 0.5; } } else if (layoutCount <= 9) { for (let i = 0; i < layoutCount; i++) { let xpos = i % 3; let ypos = i / 3; xpos = ~~xpos; ypos = ~~ypos; const cc = this._clippingContextListForMask[curClipIndex++]; cc._layoutChannelNo = channelNo; cc._layoutBounds.x = xpos / 3; cc._layoutBounds.y = ypos / 3; cc._layoutBounds.width = 1 / 3; cc._layoutBounds.height = 1 / 3; } } else if (CubismConfig.supportMoreMaskDivisions && layoutCount <= 16) { for (let i = 0; i < layoutCount; i++) { let xpos = i % 4; let ypos = i / 4; xpos = ~~xpos; ypos = ~~ypos; const cc = this._clippingContextListForMask[curClipIndex++]; cc._layoutChannelNo = channelNo; cc._layoutBounds.x = xpos / 4; cc._layoutBounds.y = ypos / 4; cc._layoutBounds.width = 1 / 4; cc._layoutBounds.height = 1 / 4; } } else { CubismLogError("not supported mask count : {0}", layoutCount); } } } getColorBuffer() { return this._colorBuffer; } getClippingContextListForDraw() { return this._clippingContextListForDraw; } setClippingMaskBufferSize(size) { this._clippingMaskBufferSize = size; } getClippingMaskBufferSize() { return this._clippingMaskBufferSize; } } class CubismRenderTextureResource { constructor(frameNo, texture) { this.frameNo = frameNo; this.texture = texture; } } class CubismClippingContext { constructor(manager, clippingDrawableIndices, clipCount) { this._isUsing = false; this._owner = manager; this._clippingIdList = clippingDrawableIndices; this._clippingIdCount = clipCount; this._allClippedDrawRect = new csmRect(); this._layoutBounds = new csmRect(); this._clippedDrawableIndexList = []; this._matrixForMask = new CubismMatrix44(); this._matrixForDraw = new CubismMatrix44(); } release() { const self2 = this; self2._layoutBounds = void 0; self2._allClippedDrawRect = void 0; self2._clippedDrawableIndexList = void 0; } addClippedDrawable(drawableIndex) { this._clippedDrawableIndexList.push(drawableIndex); } getClippingManager() { return this._owner; } setGl(gl) { this._owner.setGL(gl); } } class CubismShader_WebGL { static getInstance() { if (s_instance == null) { s_instance = new CubismShader_WebGL(); return s_instance; } return s_instance; } static deleteInstance() { if (s_instance) { s_instance.release(); s_instance = void 0; } } constructor() { this._shaderSets = []; } release() { this.releaseShaderProgram(); } setupShaderProgram(renderer, textureId, vertexCount, vertexArray, indexArray, uvArray, bufferData, opacity, colorBlendMode, baseColor, isPremultipliedAlpha, matrix4x4, invertedMask) { if (!isPremultipliedAlpha) { CubismLogError("NoPremultipliedAlpha is not allowed"); } if (this._shaderSets.length == 0) { this.generateShaders(); } let SRC_COLOR; let DST_COLOR; let SRC_ALPHA; let DST_ALPHA; const clippingContextBufferForMask = renderer.getClippingContextBufferForMask(); if (clippingContextBufferForMask != null) { const shaderSet = this._shaderSets[ShaderNames.ShaderNames_SetupMask]; this.gl.useProgram(shaderSet.shaderProgram); this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); this.gl.uniform1i(shaderSet.samplerTexture0Location, 0); if (bufferData.vertex == null) { bufferData.vertex = this.gl.createBuffer(); } this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.vertex); this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); if (bufferData.uv == null) { bufferData.uv = this.gl.createBuffer(); } this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.uv); this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); const channelNo = clippingContextBufferForMask._layoutChannelNo; const colorChannel = clippingContextBufferForMask.getClippingManager().getChannelFlagAsColor(channelNo); this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); this.gl.uniformMatrix4fv(shaderSet.uniformClipMatrixLocation, false, clippingContextBufferForMask._matrixForMask.getArray()); const rect = clippingContextBufferForMask._layoutBounds; this.gl.uniform4f(shaderSet.uniformBaseColorLocation, rect.x * 2 - 1, rect.y * 2 - 1, rect.getRight() * 2 - 1, rect.getBottom() * 2 - 1); SRC_COLOR = this.gl.ZERO; DST_COLOR = this.gl.ONE_MINUS_SRC_COLOR; SRC_ALPHA = this.gl.ZERO; DST_ALPHA = this.gl.ONE_MINUS_SRC_ALPHA; } else { const clippingContextBufferForDraw = renderer.getClippingContextBufferForDraw(); const masked = clippingContextBufferForDraw != null; const offset = masked ? invertedMask ? 2 : 1 : 0; let shaderSet; switch (colorBlendMode) { case CubismBlendMode.CubismBlendMode_Normal: default: shaderSet = this._shaderSets[ShaderNames.ShaderNames_NormalPremultipliedAlpha + offset]; SRC_COLOR = this.gl.ONE; DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; SRC_ALPHA = this.gl.ONE; DST_ALPHA = this.gl.ONE_MINUS_SRC_ALPHA; break; case CubismBlendMode.CubismBlendMode_Additive: shaderSet = this._shaderSets[ShaderNames.ShaderNames_AddPremultipliedAlpha + offset]; SRC_COLOR = this.gl.ONE; DST_COLOR = this.gl.ONE; SRC_ALPHA = this.gl.ZERO; DST_ALPHA = this.gl.ONE; break; case CubismBlendMode.CubismBlendMode_Multiplicative: shaderSet = this._shaderSets[ShaderNames.ShaderNames_MultPremultipliedAlpha + offset]; SRC_COLOR = this.gl.DST_COLOR; DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; SRC_ALPHA = this.gl.ZERO; DST_ALPHA = this.gl.ONE; break; } this.gl.useProgram(shaderSet.shaderProgram); if (bufferData.vertex == null) { bufferData.vertex = this.gl.createBuffer(); } this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.vertex); this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); if (bufferData.uv == null) { bufferData.uv = this.gl.createBuffer(); } this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.uv); this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); if (clippingContextBufferForDraw != null) { this.gl.activeTexture(this.gl.TEXTURE1); const tex = clippingContextBufferForDraw.getClippingManager().getColorBuffer(); this.gl.bindTexture(this.gl.TEXTURE_2D, tex); this.gl.uniform1i(shaderSet.samplerTexture1Location, 1); this.gl.uniformMatrix4fv(shaderSet.uniformClipMatrixLocation, false, clippingContextBufferForDraw._matrixForDraw.getArray()); const channelNo = clippingContextBufferForDraw._layoutChannelNo; const colorChannel = clippingContextBufferForDraw.getClippingManager().getChannelFlagAsColor(channelNo); this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); } this.gl.activeTexture(this.gl.TEXTURE0); this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); this.gl.uniform1i(shaderSet.samplerTexture0Location, 0); this.gl.uniformMatrix4fv(shaderSet.uniformMatrixLocation, false, matrix4x4.getArray()); this.gl.uniform4f(shaderSet.uniformBaseColorLocation, baseColor.R, baseColor.G, baseColor.B, baseColor.A); } if (bufferData.index == null) { bufferData.index = this.gl.createBuffer(); } this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, bufferData.index); this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, indexArray, this.gl.DYNAMIC_DRAW); this.gl.blendFuncSeparate(SRC_COLOR, DST_COLOR, SRC_ALPHA, DST_ALPHA); } releaseShaderProgram() { for (let i = 0; i < this._shaderSets.length; i++) { this.gl.deleteProgram(this._shaderSets[i].shaderProgram); this._shaderSets[i].shaderProgram = 0; } this._shaderSets = []; } generateShaders() { for (let i = 0; i < shaderCount; i++) { this._shaderSets.push({}); } this._shaderSets[0].shaderProgram = this.loadShaderProgram(vertexShaderSrcSetupMask, fragmentShaderSrcsetupMask); this._shaderSets[1].shaderProgram = this.loadShaderProgram(vertexShaderSrc, fragmentShaderSrcPremultipliedAlpha); this._shaderSets[2].shaderProgram = this.loadShaderProgram(vertexShaderSrcMasked, fragmentShaderSrcMaskPremultipliedAlpha); this._shaderSets[3].shaderProgram = this.loadShaderProgram(vertexShaderSrcMasked, fragmentShaderSrcMaskInvertedPremultipliedAlpha); this._shaderSets[4].shaderProgram = this._shaderSets[1].shaderProgram; this._shaderSets[5].shaderProgram = this._shaderSets[2].shaderProgram; this._shaderSets[6].shaderProgram = this._shaderSets[3].shaderProgram; this._shaderSets[7].shaderProgram = this._shaderSets[1].shaderProgram; this._shaderSets[8].shaderProgram = this._shaderSets[2].shaderProgram; this._shaderSets[9].shaderProgram = this._shaderSets[3].shaderProgram; this._shaderSets[0].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[0].shaderProgram, "a_position"); this._shaderSets[0].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[0].shaderProgram, "a_texCoord"); this._shaderSets[0].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[0].shaderProgram, "s_texture0"); this._shaderSets[0].uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets[0].shaderProgram, "u_clipMatrix"); this._shaderSets[0].uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets[0].shaderProgram, "u_channelFlag"); this._shaderSets[0].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[0].shaderProgram, "u_baseColor"); this._shaderSets[1].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[1].shaderProgram, "a_position"); this._shaderSets[1].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[1].shaderProgram, "a_texCoord"); this._shaderSets[1].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[1].shaderProgram, "s_texture0"); this._shaderSets[1].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[1].shaderProgram, "u_matrix"); this._shaderSets[1].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[1].shaderProgram, "u_baseColor"); this._shaderSets[2].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[2].shaderProgram, "a_position"); this._shaderSets[2].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[2].shaderProgram, "a_texCoord"); this._shaderSets[2].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[2].shaderProgram, "s_texture0"); this._shaderSets[2].samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets[2].shaderProgram, "s_texture1"); this._shaderSets[2].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[2].shaderProgram, "u_matrix"); this._shaderSets[2].uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets[2].shaderProgram, "u_clipMatrix"); this._shaderSets[2].uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets[2].shaderProgram, "u_channelFlag"); this._shaderSets[2].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[2].shaderProgram, "u_baseColor"); this._shaderSets[3].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[3].shaderProgram, "a_position"); this._shaderSets[3].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[3].shaderProgram, "a_texCoord"); this._shaderSets[3].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[3].shaderProgram, "s_texture0"); this._shaderSets[3].samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets[3].shaderProgram, "s_texture1"); this._shaderSets[3].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[3].shaderProgram, "u_matrix"); this._shaderSets[3].uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets[3].shaderProgram, "u_clipMatrix"); this._shaderSets[3].uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets[3].shaderProgram, "u_channelFlag"); this._shaderSets[3].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[3].shaderProgram, "u_baseColor"); this._shaderSets[4].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[4].shaderProgram, "a_position"); this._shaderSets[4].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[4].shaderProgram, "a_texCoord"); this._shaderSets[4].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[4].shaderProgram, "s_texture0"); this._shaderSets[4].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[4].shaderProgram, "u_matrix"); this._shaderSets[4].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[4].shaderProgram, "u_baseColor"); this._shaderSets[5].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[5].shaderProgram, "a_position"); this._shaderSets[5].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[5].shaderProgram, "a_texCoord"); this._shaderSets[5].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[5].shaderProgram, "s_texture0"); this._shaderSets[5].samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets[5].shaderProgram, "s_texture1"); this._shaderSets[5].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[5].shaderProgram, "u_matrix"); this._shaderSets[5].uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets[5].shaderProgram, "u_clipMatrix"); this._shaderSets[5].uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets[5].shaderProgram, "u_channelFlag"); this._shaderSets[5].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[5].shaderProgram, "u_baseColor"); this._shaderSets[6].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[6].shaderProgram, "a_position"); this._shaderSets[6].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[6].shaderProgram, "a_texCoord"); this._shaderSets[6].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[6].shaderProgram, "s_texture0"); this._shaderSets[6].samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets[6].shaderProgram, "s_texture1"); this._shaderSets[6].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[6].shaderProgram, "u_matrix"); this._shaderSets[6].uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets[6].shaderProgram, "u_clipMatrix"); this._shaderSets[6].uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets[6].shaderProgram, "u_channelFlag"); this._shaderSets[6].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[6].shaderProgram, "u_baseColor"); this._shaderSets[7].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[7].shaderProgram, "a_position"); this._shaderSets[7].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[7].shaderProgram, "a_texCoord"); this._shaderSets[7].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[7].shaderProgram, "s_texture0"); this._shaderSets[7].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[7].shaderProgram, "u_matrix"); this._shaderSets[7].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[7].shaderProgram, "u_baseColor"); this._shaderSets[8].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[8].shaderProgram, "a_position"); this._shaderSets[8].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[8].shaderProgram, "a_texCoord"); this._shaderSets[8].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[8].shaderProgram, "s_texture0"); this._shaderSets[8].samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets[8].shaderProgram, "s_texture1"); this._shaderSets[8].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[8].shaderProgram, "u_matrix"); this._shaderSets[8].uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets[8].shaderProgram, "u_clipMatrix"); this._shaderSets[8].uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets[8].shaderProgram, "u_channelFlag"); this._shaderSets[8].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[8].shaderProgram, "u_baseColor"); this._shaderSets[9].attributePositionLocation = this.gl.getAttribLocation(this._shaderSets[9].shaderProgram, "a_position"); this._shaderSets[9].attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets[9].shaderProgram, "a_texCoord"); this._shaderSets[9].samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets[9].shaderProgram, "s_texture0"); this._shaderSets[9].samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets[9].shaderProgram, "s_texture1"); this._shaderSets[9].uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets[9].shaderProgram, "u_matrix"); this._shaderSets[9].uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets[9].shaderProgram, "u_clipMatrix"); this._shaderSets[9].uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets[9].shaderProgram, "u_channelFlag"); this._shaderSets[9].uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets[9].shaderProgram, "u_baseColor"); } loadShaderProgram(vertexShaderSource, fragmentShaderSource) { let shaderProgram = this.gl.createProgram(); let vertShader = this.compileShaderSource(this.gl.VERTEX_SHADER, vertexShaderSource); if (!vertShader) { CubismLogError("Vertex shader compile error!"); return 0; } let fragShader = this.compileShaderSource(this.gl.FRAGMENT_SHADER, fragmentShaderSource); if (!fragShader) { CubismLogError("Vertex shader compile error!"); return 0; } this.gl.attachShader(shaderProgram, vertShader); this.gl.attachShader(shaderProgram, fragShader); this.gl.linkProgram(shaderProgram); const linkStatus = this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS); if (!linkStatus) { CubismLogError("Failed to link program: {0}", shaderProgram); this.gl.deleteShader(vertShader); this.gl.deleteShader(fragShader); if (shaderProgram) { this.gl.deleteProgram(shaderProgram); } return 0; } this.gl.deleteShader(vertShader); this.gl.deleteShader(fragShader); return shaderProgram; } compileShaderSource(shaderType, shaderSource) { const source = shaderSource; const shader = this.gl.createShader(shaderType); this.gl.shaderSource(shader, source); this.gl.compileShader(shader); if (!shader) { const log = this.gl.getShaderInfoLog(shader); CubismLogError("Shader compile log: {0} ", log); } const status = this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS); if (!status) { this.gl.deleteShader(shader); return null; } return shader; } setGl(gl) { this.gl = gl; } } var ShaderNames = /* @__PURE__ */ ((ShaderNames2) => { ShaderNames2[ShaderNames2["ShaderNames_SetupMask"] = 0] = "ShaderNames_SetupMask"; ShaderNames2[ShaderNames2["ShaderNames_NormalPremultipliedAlpha"] = 1] = "ShaderNames_NormalPremultipliedAlpha"; ShaderNames2[ShaderNames2["ShaderNames_NormalMaskedPremultipliedAlpha"] = 2] = "ShaderNames_NormalMaskedPremultipliedAlpha"; ShaderNames2[ShaderNames2["ShaderNames_NomralMaskedInvertedPremultipliedAlpha"] = 3] = "ShaderNames_NomralMaskedInvertedPremultipliedAlpha"; ShaderNames2[ShaderNames2["ShaderNames_AddPremultipliedAlpha"] = 4] = "ShaderNames_AddPremultipliedAlpha"; ShaderNames2[ShaderNames2["ShaderNames_AddMaskedPremultipliedAlpha"] = 5] = "ShaderNames_AddMaskedPremultipliedAlpha"; ShaderNames2[ShaderNames2["ShaderNames_AddMaskedPremultipliedAlphaInverted"] = 6] = "ShaderNames_AddMaskedPremultipliedAlphaInverted"; ShaderNames2[ShaderNames2["ShaderNames_MultPremultipliedAlpha"] = 7] = "ShaderNames_MultPremultipliedAlpha"; ShaderNames2[ShaderNames2["ShaderNames_MultMaskedPremultipliedAlpha"] = 8] = "ShaderNames_MultMaskedPremultipliedAlpha"; ShaderNames2[ShaderNames2["ShaderNames_MultMaskedPremultipliedAlphaInverted"] = 9] = "ShaderNames_MultMaskedPremultipliedAlphaInverted"; return ShaderNames2; })(ShaderNames || {}); const vertexShaderSrcSetupMask = "attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;varying vec4 v_myPos;uniform mat4 u_clipMatrix;void main(){ gl_Position = u_clipMatrix * a_position; v_myPos = u_clipMatrix * a_position; v_texCoord = a_texCoord; v_texCoord.y = 1.0 - v_texCoord.y;}"; const fragmentShaderSrcsetupMask = "precision mediump float;varying vec2 v_texCoord;varying vec4 v_myPos;uniform vec4 u_baseColor;uniform vec4 u_channelFlag;uniform sampler2D s_texture0;void main(){ float isInside = step(u_baseColor.x, v_myPos.x/v_myPos.w) * step(u_baseColor.y, v_myPos.y/v_myPos.w) * step(v_myPos.x/v_myPos.w, u_baseColor.z) * step(v_myPos.y/v_myPos.w, u_baseColor.w); gl_FragColor = u_channelFlag * texture2D(s_texture0, v_texCoord).a * isInside;}"; const vertexShaderSrc = "attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;uniform mat4 u_matrix;void main(){ gl_Position = u_matrix * a_position; v_texCoord = a_texCoord; v_texCoord.y = 1.0 - v_texCoord.y;}"; const vertexShaderSrcMasked = "attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;varying vec4 v_clipPos;uniform mat4 u_matrix;uniform mat4 u_clipMatrix;void main(){ gl_Position = u_matrix * a_position; v_clipPos = u_clipMatrix * a_position; v_texCoord = a_texCoord; v_texCoord.y = 1.0 - v_texCoord.y;}"; const fragmentShaderSrcPremultipliedAlpha = "precision mediump float;varying vec2 v_texCoord;uniform vec4 u_baseColor;uniform sampler2D s_texture0;void main(){ gl_FragColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;}"; const fragmentShaderSrcMaskPremultipliedAlpha = "precision mediump float;varying vec2 v_texCoord;varying vec4 v_clipPos;uniform vec4 u_baseColor;uniform vec4 u_channelFlag;uniform sampler2D s_texture0;uniform sampler2D s_texture1;void main(){ vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor; vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag; float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a; col_formask = col_formask * maskVal; gl_FragColor = col_formask;}"; const fragmentShaderSrcMaskInvertedPremultipliedAlpha = "precision mediump float;varying vec2 v_texCoord;varying vec4 v_clipPos;uniform sampler2D s_texture0;uniform sampler2D s_texture1;uniform vec4 u_channelFlag;uniform vec4 u_baseColor;void main(){vec4 col_formask = texture2D(s_texture0, v_texCoord) * u_baseColor;vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;col_formask = col_formask * (1.0 - maskVal);gl_FragColor = col_formask;}"; class CubismRenderer_WebGL extends CubismRenderer { constructor() { super(); this._clippingContextBufferForMask = null; this._clippingContextBufferForDraw = null; this._clippingManager = new CubismClippingManager_WebGL(); this.firstDraw = true; this._textures = {}; this._sortedDrawableIndexList = []; this._bufferData = { vertex: null, uv: null, index: null }; } initialize(model) { if (model.isUsingMasking()) { this._clippingManager = new CubismClippingManager_WebGL(); this._clippingManager.initialize(model, model.getDrawableCount(), model.getDrawableMasks(), model.getDrawableMaskCounts()); } for (let i = model.getDrawableCount() - 1; i >= 0; i--) { this._sortedDrawableIndexList[i] = 0; } super.initialize(model); } bindTexture(modelTextureNo, glTexture) { this._textures[modelTextureNo] = glTexture; } getBindedTextures() { return this._textures; } setClippingMaskBufferSize(size) { this._clippingManager.release(); this._clippingManager = new CubismClippingManager_WebGL(); this._clippingManager.setClippingMaskBufferSize(size); this._clippingManager.initialize(this.getModel(), this.getModel().getDrawableCount(), this.getModel().getDrawableMasks(), this.getModel().getDrawableMaskCounts()); } getClippingMaskBufferSize() { return this._clippingManager.getClippingMaskBufferSize(); } release() { var _a, _b, _c; const self2 = this; this._clippingManager.release(); self2._clippingManager = void 0; (_a = this.gl) == null ? void 0 : _a.deleteBuffer(this._bufferData.vertex); this._bufferData.vertex = null; (_b = this.gl) == null ? void 0 : _b.deleteBuffer(this._bufferData.uv); this._bufferData.uv = null; (_c = this.gl) == null ? void 0 : _c.deleteBuffer(this._bufferData.index); this._bufferData.index = null; self2._bufferData = void 0; self2._textures = void 0; } doDrawModel() { this.preDraw(); if (this._clippingManager != null) { this._clippingManager.setupClippingContext(this.getModel(), this); } const drawableCount = this.getModel().getDrawableCount(); const renderOrder = this.getModel().getDrawableRenderOrders(); for (let i = 0; i < drawableCount; ++i) { const order = renderOrder[i]; this._sortedDrawableIndexList[order] = i; } for (let i = 0; i < drawableCount; ++i) { const drawableIndex = this._sortedDrawableIndexList[i]; if (!this.getModel().getDrawableDynamicFlagIsVisible(drawableIndex)) { continue; } this.setClippingContextBufferForDraw(this._clippingManager != null ? this._clippingManager.getClippingContextListForDraw()[drawableIndex] : null); this.setIsCulling(this.getModel().getDrawableCulling(drawableIndex)); this.drawMesh(this.getModel().getDrawableTextureIndices(drawableIndex), this.getModel().getDrawableVertexIndexCount(drawableIndex), this.getModel().getDrawableVertexCount(drawableIndex), this.getModel().getDrawableVertexIndices(drawableIndex), this.getModel().getDrawableVertices(drawableIndex), this.getModel().getDrawableVertexUvs(drawableIndex), this.getModel().getDrawableOpacity(drawableIndex), this.getModel().getDrawableBlendMode(drawableIndex), this.getModel().getDrawableInvertedMaskBit(drawableIndex)); } } drawMesh(textureNo, indexCount, vertexCount, indexArray, vertexArray, uvArray, opacity, colorBlendMode, invertedMask) { if (this.isCulling()) { this.gl.enable(this.gl.CULL_FACE); } else { this.gl.disable(this.gl.CULL_FACE); } this.gl.frontFace(this.gl.CCW); const modelColorRGBA = this.getModelColor(); if (this.getClippingContextBufferForMask() == null) { modelColorRGBA.A *= opacity; if (this.isPremultipliedAlpha()) { modelColorRGBA.R *= modelColorRGBA.A; modelColorRGBA.G *= modelColorRGBA.A; modelColorRGBA.B *= modelColorRGBA.A; } } let drawtexture = null; if (this._textures[textureNo] != null) { drawtexture = this._textures[textureNo]; } CubismShader_WebGL.getInstance().setupShaderProgram(this, drawtexture, vertexCount, vertexArray, indexArray, uvArray, this._bufferData, opacity, colorBlendMode, modelColorRGBA, this.isPremultipliedAlpha(), this.getMvpMatrix(), invertedMask); this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_SHORT, 0); this.gl.useProgram(null); this.setClippingContextBufferForDraw(null); this.setClippingContextBufferForMask(null); } static doStaticRelease() { CubismShader_WebGL.deleteInstance(); } setRenderState(fbo, viewport) { s_fbo = fbo; s_viewport = viewport; } preDraw() { if (this.firstDraw) { this.firstDraw = false; this._anisortopy = this.gl.getExtension("EXT_texture_filter_anisotropic") || this.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic") || this.gl.getExtension("MOZ_EXT_texture_filter_anisotropic"); } this.gl.disable(this.gl.SCISSOR_TEST); this.gl.disable(this.gl.STENCIL_TEST); this.gl.disable(this.gl.DEPTH_TEST); this.gl.frontFace(this.gl.CW); this.gl.enable(this.gl.BLEND); this.gl.colorMask(true, true, true, true); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null); } setClippingContextBufferForMask(clip) { this._clippingContextBufferForMask = clip; } getClippingContextBufferForMask() { return this._clippingContextBufferForMask; } setClippingContextBufferForDraw(clip) { this._clippingContextBufferForDraw = clip; } getClippingContextBufferForDraw() { return this._clippingContextBufferForDraw; } startUp(gl) { this.gl = gl; this._clippingManager.setGL(gl); CubismShader_WebGL.getInstance().setGl(gl); } } CubismRenderer.staticRelease = () => { CubismRenderer_WebGL.doStaticRelease(); }; const tempMatrix = new CubismMatrix44(); class Cubism4InternalModel extends InternalModel { constructor(coreModel, settings, options) { super(); this.lipSync = true; this.breath = CubismBreath.create(); this.renderer = new CubismRenderer_WebGL(); this.idParamAngleX = ParamAngleX; this.idParamAngleY = ParamAngleY; this.idParamAngleZ = ParamAngleZ; this.idParamEyeBallX = ParamEyeBallX; this.idParamEyeBallY = ParamEyeBallY; this.idParamBodyAngleX = ParamBodyAngleX; this.idParamBreath = ParamBreath; this.pixelsPerUnit = 1; this.centeringTransform = new math.Matrix(); this.coreModel = coreModel; this.settings = settings; this.motionManager = new Cubism4MotionManager(settings, options); this.init(); } init() { var _a; super.init(); if (((_a = this.settings.getEyeBlinkParameters()) == null ? void 0 : _a.length) > 0) { this.eyeBlink = CubismEyeBlink.create(this.settings); } this.breath.setParameters([ new BreathParameterData(this.idParamAngleX, 0, 15, 6.5345, 0.5), new BreathParameterData(this.idParamAngleY, 0, 8, 3.5345, 0.5), new BreathParameterData(this.idParamAngleZ, 0, 10, 5.5345, 0.5), new BreathParameterData(this.idParamBodyAngleX, 0, 4, 15.5345, 0.5), new BreathParameterData(this.idParamBreath, 0, 0.5, 3.2345, 0.5) ]); this.renderer.initialize(this.coreModel); this.renderer.setIsPremultipliedAlpha(true); } getSize() { return [this.coreModel.getModel().canvasinfo.CanvasWidth, this.coreModel.getModel().canvasinfo.CanvasHeight]; } getLayout() { const layout = {}; if (this.settings.layout) { for (const key of Object.keys(this.settings.layout)) { const commonKey = key.charAt(0).toLowerCase() + key.slice(1); layout[commonKey] = this.settings.layout[key]; } } return layout; } setupLayout() { super.setupLayout(); this.pixelsPerUnit = this.coreModel.getModel().canvasinfo.PixelsPerUnit; this.centeringTransform.scale(this.pixelsPerUnit, this.pixelsPerUnit).translate(this.originalWidth / 2, this.originalHeight / 2); } updateWebGLContext(gl, glContextID) { this.renderer.firstDraw = true; this.renderer._bufferData = { vertex: null, uv: null, index: null }; this.renderer.startUp(gl); this.renderer._clippingManager._currentFrameNo = glContextID; this.renderer._clippingManager._maskTexture = void 0; CubismShader_WebGL.getInstance()._shaderSets = []; } bindTexture(index, texture) { this.renderer.bindTexture(index, texture); } getHitAreaDefs() { var _a, _b; return (_b = (_a = this.settings.hitAreas) == null ? void 0 : _a.map((hitArea) => ({ id: hitArea.Id, name: hitArea.Name, index: this.coreModel.getDrawableIndex(hitArea.Id) }))) != null ? _b : []; } getDrawableIDs() { return this.coreModel.getDrawableIds(); } getDrawableIndex(id) { return this.coreModel.getDrawableIndex(id); } getDrawableVertices(drawIndex) { if (typeof drawIndex === "string") { drawIndex = this.coreModel.getDrawableIndex(drawIndex); if (drawIndex === -1) throw new TypeError("Unable to find drawable ID: " + drawIndex); } const arr = this.coreModel.getDrawableVertices(drawIndex).slice(); for (let i = 0; i < arr.length; i += 2) { arr[i] = arr[i] * this.pixelsPerUnit + this.originalWidth / 2; arr[i + 1] = -arr[i + 1] * this.pixelsPerUnit + this.originalHeight / 2; } return arr; } updateTransform(transform) { this.drawingMatrix.copyFrom(this.centeringTransform).prepend(this.localTransform).prepend(transform); } update(dt, now) { var _a, _b, _c, _d; super.update(dt, now); dt /= 1e3; now /= 1e3; const model = this.coreModel; this.emit("beforeMotionUpdate"); const motionUpdated = this.motionManager.update(this.coreModel, now); this.emit("afterMotionUpdate"); model.saveParameters(); (_a = this.motionManager.expressionManager) == null ? void 0 : _a.update(model, now); if (!motionUpdated) { (_b = this.eyeBlink) == null ? void 0 : _b.updateParameters(model, dt); } this.updateFocus(); this.updateNaturalMovements(dt * 1e3, now * 1e3); (_c = this.physics) == null ? void 0 : _c.evaluate(model, dt); (_d = this.pose) == null ? void 0 : _d.updateParameters(model, dt); this.emit("beforeModelUpdate"); model.update(); model.loadParameters(); } updateFocus() { this.coreModel.addParameterValueById(this.idParamEyeBallX, this.focusController.x); this.coreModel.addParameterValueById(this.idParamEyeBallY, this.focusController.y); this.coreModel.addParameterValueById(this.idParamAngleX, this.focusController.x * 30); this.coreModel.addParameterValueById(this.idParamAngleY, this.focusController.y * 30); this.coreModel.addParameterValueById(this.idParamAngleZ, this.focusController.x * this.focusController.y * -30); this.coreModel.addParameterValueById(this.idParamBodyAngleX, this.focusController.x * 10); } updateNaturalMovements(dt, now) { var _a; (_a = this.breath) == null ? void 0 : _a.updateParameters(this.coreModel, dt / 1e3); } draw(gl) { const matrix = this.drawingMatrix; const array = tempMatrix.getArray(); array[0] = matrix.a; array[1] = matrix.b; array[4] = -matrix.c; array[5] = -matrix.d; array[12] = matrix.tx; array[13] = matrix.ty; this.renderer.setMvpMatrix(tempMatrix); this.renderer.setRenderState(gl.getParameter(gl.FRAMEBUFFER_BINDING), this.viewport); this.renderer.drawModel(); } destroy() { super.destroy(); this.renderer.release(); this.coreModel.release(); this.renderer = void 0; this.coreModel = void 0; } } let startupPromise; let startupRetries = 20; function cubism4Ready() { if (CubismFramework.isStarted()) { return Promise.resolve(); } startupPromise != null ? startupPromise : startupPromise = new Promise((resolve, reject) => { function startUpWithRetry() { try { startUpCubism4(); resolve(); } catch (e) { startupRetries--; if (startupRetries < 0) { const err = new Error("Failed to start up Cubism 4 framework."); err.cause = e; reject(err); return; } logger.log("Cubism4", "Startup failed, retrying 10ms later..."); setTimeout(startUpWithRetry, 10); } } startUpWithRetry(); }); return startupPromise; } function startUpCubism4(options) { options = Object.assign({ logFunction: console.log, loggingLevel: LogLevel.LogLevel_Verbose }, options); CubismFramework.startUp(options); CubismFramework.initialize(); } const Epsilon = 1e-3; const DefaultFadeInSeconds = 0.5; class CubismPose { static create(pose3json) { const ret = new CubismPose(); if (typeof pose3json.FadeInTime === "number") { ret._fadeTimeSeconds = pose3json.FadeInTime; if (ret._fadeTimeSeconds <= 0) { ret._fadeTimeSeconds = DefaultFadeInSeconds; } } const poseListInfo = pose3json.Groups; const poseCount = poseListInfo.length; for (let poseIndex = 0; poseIndex < poseCount; ++poseIndex) { const idListInfo = poseListInfo[poseIndex]; const idCount = idListInfo.length; let groupCount = 0; for (let groupIndex = 0; groupIndex < idCount; ++groupIndex) { const partInfo = idListInfo[groupIndex]; const partData = new PartData(); partData.partId = partInfo.Id; const linkListInfo = partInfo.Link; if (linkListInfo) { const linkCount = linkListInfo.length; for (let linkIndex = 0; linkIndex < linkCount; ++linkIndex) { const linkPart = new PartData(); linkPart.partId = linkListInfo[linkIndex]; partData.link.push(linkPart); } } ret._partGroups.push(partData); ++groupCount; } ret._partGroupCounts.push(groupCount); } return ret; } updateParameters(model, deltaTimeSeconds) { if (model != this._lastModel) { this.reset(model); } this._lastModel = model; if (deltaTimeSeconds < 0) { deltaTimeSeconds = 0; } let beginIndex = 0; for (let i = 0; i < this._partGroupCounts.length; i++) { const partGroupCount = this._partGroupCounts[i]; this.doFade(model, deltaTimeSeconds, beginIndex, partGroupCount); beginIndex += partGroupCount; } this.copyPartOpacities(model); } reset(model) { let beginIndex = 0; for (let i = 0; i < this._partGroupCounts.length; ++i) { const groupCount = this._partGroupCounts[i]; for (let j = beginIndex; j < beginIndex + groupCount; ++j) { this._partGroups[j].initialize(model); const partsIndex = this._partGroups[j].partIndex; const paramIndex = this._partGroups[j].parameterIndex; if (partsIndex < 0) { continue; } model.setPartOpacityByIndex(partsIndex, j == beginIndex ? 1 : 0); model.setParameterValueByIndex(paramIndex, j == beginIndex ? 1 : 0); for (let k = 0; k < this._partGroups[j].link.length; ++k) { this._partGroups[j].link[k].initialize(model); } } beginIndex += groupCount; } } copyPartOpacities(model) { for (let groupIndex = 0; groupIndex < this._partGroups.length; ++groupIndex) { const partData = this._partGroups[groupIndex]; if (partData.link.length == 0) { continue; } const partIndex = this._partGroups[groupIndex].partIndex; const opacity = model.getPartOpacityByIndex(partIndex); for (let linkIndex = 0; linkIndex < partData.link.length; ++linkIndex) { const linkPart = partData.link[linkIndex]; const linkPartIndex = linkPart.partIndex; if (linkPartIndex < 0) { continue; } model.setPartOpacityByIndex(linkPartIndex, opacity); } } } doFade(model, deltaTimeSeconds, beginIndex, partGroupCount) { let visiblePartIndex = -1; let newOpacity = 1; const phi = 0.5; const backOpacityThreshold = 0.15; for (let i = beginIndex; i < beginIndex + partGroupCount; ++i) { const partIndex = this._partGroups[i].partIndex; const paramIndex = this._partGroups[i].parameterIndex; if (model.getParameterValueByIndex(paramIndex) > Epsilon) { if (visiblePartIndex >= 0) { break; } visiblePartIndex = i; newOpacity = model.getPartOpacityByIndex(partIndex); newOpacity += deltaTimeSeconds / this._fadeTimeSeconds; if (newOpacity > 1) { newOpacity = 1; } } } if (visiblePartIndex < 0) { visiblePartIndex = 0; newOpacity = 1; } for (let i = beginIndex; i < beginIndex + partGroupCount; ++i) { const partsIndex = this._partGroups[i].partIndex; if (visiblePartIndex == i) { model.setPartOpacityByIndex(partsIndex, newOpacity); } else { let opacity = model.getPartOpacityByIndex(partsIndex); let a1; if (newOpacity < phi) { a1 = newOpacity * (phi - 1) / phi + 1; } else { a1 = (1 - newOpacity) * phi / (1 - phi); } const backOpacity = (1 - a1) * (1 - newOpacity); if (backOpacity > backOpacityThreshold) { a1 = 1 - backOpacityThreshold / (1 - newOpacity); } if (opacity > a1) { opacity = a1; } model.setPartOpacityByIndex(partsIndex, opacity); } } } constructor() { this._fadeTimeSeconds = DefaultFadeInSeconds; this._lastModel = void 0; this._partGroups = []; this._partGroupCounts = []; } } class PartData { constructor(v) { this.parameterIndex = 0; this.partIndex = 0; this.partId = ""; this.link = []; if (v != void 0) { this.assignment(v); } } assignment(v) { this.partId = v.partId; this.link = v.link.map((link) => link.clone()); return this; } initialize(model) { this.parameterIndex = model.getParameterIndex(this.partId); this.partIndex = model.getPartIndex(this.partId); model.setParameterValueByIndex(this.parameterIndex, 1); } clone() { const clonePartData = new PartData(); clonePartData.partId = this.partId; clonePartData.parameterIndex = this.parameterIndex; clonePartData.partIndex = this.partIndex; clonePartData.link = this.link.map((link) => link.clone()); return clonePartData; } } class CubismModel { update() { this._model.update(); this._model.drawables.resetDynamicFlags(); } getCanvasWidth() { if (this._model == null) { return 0; } return this._model.canvasinfo.CanvasWidth / this._model.canvasinfo.PixelsPerUnit; } getCanvasHeight() { if (this._model == null) { return 0; } return this._model.canvasinfo.CanvasHeight / this._model.canvasinfo.PixelsPerUnit; } saveParameters() { const parameterCount = this._model.parameters.count; const savedParameterCount = this._savedParameters.length; for (let i = 0; i < parameterCount; ++i) { if (i < savedParameterCount) { this._savedParameters[i] = this._parameterValues[i]; } else { this._savedParameters.push(this._parameterValues[i]); } } } getModel() { return this._model; } getPartIndex(partId) { let partIndex; const partCount = this._model.parts.count; for (partIndex = 0; partIndex < partCount; ++partIndex) { if (partId == this._partIds[partIndex]) { return partIndex; } } if (partId in this._notExistPartId) { return this._notExistPartId[partId]; } partIndex = partCount + this._notExistPartId.length; this._notExistPartId[partId] = partIndex; this._notExistPartOpacities[partIndex] = 0; return partIndex; } getPartCount() { return this._model.parts.count; } setPartOpacityByIndex(partIndex, opacity) { if (partIndex in this._notExistPartOpacities) { this._notExistPartOpacities[partIndex] = opacity; return; } CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount()); this._partOpacities[partIndex] = opacity; } setPartOpacityById(partId, opacity) { const index = this.getPartIndex(partId); if (index < 0) { return; } this.setPartOpacityByIndex(index, opacity); } getPartOpacityByIndex(partIndex) { if (partIndex in this._notExistPartOpacities) { return this._notExistPartOpacities[partIndex]; } CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount()); return this._partOpacities[partIndex]; } getPartOpacityById(partId) { const index = this.getPartIndex(partId); if (index < 0) { return 0; } return this.getPartOpacityByIndex(index); } getParameterIndex(parameterId) { let parameterIndex; const idCount = this._model.parameters.count; for (parameterIndex = 0; parameterIndex < idCount; ++parameterIndex) { if (parameterId != this._parameterIds[parameterIndex]) { continue; } return parameterIndex; } if (parameterId in this._notExistParameterId) { return this._notExistParameterId[parameterId]; } parameterIndex = this._model.parameters.count + Object.keys(this._notExistParameterId).length; this._notExistParameterId[parameterId] = parameterIndex; this._notExistParameterValues[parameterIndex] = 0; return parameterIndex; } getParameterCount() { return this._model.parameters.count; } getParameterMaximumValue(parameterIndex) { return this._model.parameters.maximumValues[parameterIndex]; } getParameterMinimumValue(parameterIndex) { return this._model.parameters.minimumValues[parameterIndex]; } getParameterDefaultValue(parameterIndex) { return this._model.parameters.defaultValues[parameterIndex]; } getParameterValueByIndex(parameterIndex) { if (parameterIndex in this._notExistParameterValues) { return this._notExistParameterValues[parameterIndex]; } CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount()); return this._parameterValues[parameterIndex]; } getParameterValueById(parameterId) { const parameterIndex = this.getParameterIndex(parameterId); return this.getParameterValueByIndex(parameterIndex); } setParameterValueByIndex(parameterIndex, value, weight = 1) { // if (parameterIndex == this.getParameterIndex("ParamMouthOpenY")) { // console.log(value) // } if (parameterIndex in this._notExistParameterValues) { this._notExistParameterValues[parameterIndex] = weight == 1 ? value : this._notExistParameterValues[parameterIndex] * (1 - weight) + value * weight; return; } CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount()); if (this._model.parameters.maximumValues[parameterIndex] < value) { value = this._model.parameters.maximumValues[parameterIndex]; } if (this._model.parameters.minimumValues[parameterIndex] > value) { value = this._model.parameters.minimumValues[parameterIndex]; } this._parameterValues[parameterIndex] = weight == 1 ? value : this._parameterValues[parameterIndex] = this._parameterValues[parameterIndex] * (1 - weight) + value * weight; } setParameterValueById(parameterId, value, weight = 1) { const index = this.getParameterIndex(parameterId); this.setParameterValueByIndex(index, value, weight); } addParameterValueByIndex(parameterIndex, value, weight = 1) { this.setParameterValueByIndex(parameterIndex, this.getParameterValueByIndex(parameterIndex) + value * weight); } addParameterValueById(parameterId, value, weight = 1) { const index = this.getParameterIndex(parameterId); this.addParameterValueByIndex(index, value, weight); } multiplyParameterValueById(parameterId, value, weight = 1) { const index = this.getParameterIndex(parameterId); this.multiplyParameterValueByIndex(index, value, weight); } multiplyParameterValueByIndex(parameterIndex, value, weight = 1) { this.setParameterValueByIndex(parameterIndex, this.getParameterValueByIndex(parameterIndex) * (1 + (value - 1) * weight)); } getDrawableIds() { return this._drawableIds.slice(); } getDrawableIndex(drawableId) { const drawableCount = this._model.drawables.count; for (let drawableIndex = 0; drawableIndex < drawableCount; ++drawableIndex) { if (this._drawableIds[drawableIndex] == drawableId) { return drawableIndex; } } return -1; } getDrawableCount() { return this._model.drawables.count; } getDrawableId(drawableIndex) { return this._model.drawables.ids[drawableIndex]; } getDrawableRenderOrders() { return this._model.drawables.renderOrders; } getDrawableTextureIndices(drawableIndex) { return this._model.drawables.textureIndices[drawableIndex]; } getDrawableDynamicFlagVertexPositionsDidChange(drawableIndex) { const dynamicFlags = this._model.drawables.dynamicFlags; return Live2DCubismCore.Utils.hasVertexPositionsDidChangeBit(dynamicFlags[drawableIndex]); } getDrawableVertexIndexCount(drawableIndex) { return this._model.drawables.indexCounts[drawableIndex]; } getDrawableVertexCount(drawableIndex) { return this._model.drawables.vertexCounts[drawableIndex]; } getDrawableVertices(drawableIndex) { return this.getDrawableVertexPositions(drawableIndex); } getDrawableVertexIndices(drawableIndex) { return this._model.drawables.indices[drawableIndex]; } getDrawableVertexPositions(drawableIndex) { return this._model.drawables.vertexPositions[drawableIndex]; } getDrawableVertexUvs(drawableIndex) { return this._model.drawables.vertexUvs[drawableIndex]; } getDrawableOpacity(drawableIndex) { return this._model.drawables.opacities[drawableIndex]; } getDrawableCulling(drawableIndex) { const constantFlags = this._model.drawables.constantFlags; return !Live2DCubismCore.Utils.hasIsDoubleSidedBit(constantFlags[drawableIndex]); } getDrawableBlendMode(drawableIndex) { const constantFlags = this._model.drawables.constantFlags; return Live2DCubismCore.Utils.hasBlendAdditiveBit(constantFlags[drawableIndex]) ? CubismBlendMode.CubismBlendMode_Additive : Live2DCubismCore.Utils.hasBlendMultiplicativeBit(constantFlags[drawableIndex]) ? CubismBlendMode.CubismBlendMode_Multiplicative : CubismBlendMode.CubismBlendMode_Normal; } getDrawableInvertedMaskBit(drawableIndex) { const constantFlags = this._model.drawables.constantFlags; return Live2DCubismCore.Utils.hasIsInvertedMaskBit(constantFlags[drawableIndex]); } getDrawableMasks() { return this._model.drawables.masks; } getDrawableMaskCounts() { return this._model.drawables.maskCounts; } isUsingMasking() { for (let d = 0; d < this._model.drawables.count; ++d) { if (this._model.drawables.maskCounts[d] <= 0) { continue; } return true; } return false; } getDrawableDynamicFlagIsVisible(drawableIndex) { const dynamicFlags = this._model.drawables.dynamicFlags; return Live2DCubismCore.Utils.hasIsVisibleBit(dynamicFlags[drawableIndex]); } getDrawableDynamicFlagVisibilityDidChange(drawableIndex) { const dynamicFlags = this._model.drawables.dynamicFlags; return Live2DCubismCore.Utils.hasVisibilityDidChangeBit(dynamicFlags[drawableIndex]); } getDrawableDynamicFlagOpacityDidChange(drawableIndex) { const dynamicFlags = this._model.drawables.dynamicFlags; return Live2DCubismCore.Utils.hasOpacityDidChangeBit(dynamicFlags[drawableIndex]); } getDrawableDynamicFlagRenderOrderDidChange(drawableIndex) { const dynamicFlags = this._model.drawables.dynamicFlags; return Live2DCubismCore.Utils.hasRenderOrderDidChangeBit(dynamicFlags[drawableIndex]); } loadParameters() { let parameterCount = this._model.parameters.count; const savedParameterCount = this._savedParameters.length; if (parameterCount > savedParameterCount) { parameterCount = savedParameterCount; } for (let i = 0; i < parameterCount; ++i) { this._parameterValues[i] = this._savedParameters[i]; } } initialize() { this._parameterValues = this._model.parameters.values; this._partOpacities = this._model.parts.opacities; this._parameterMaximumValues = this._model.parameters.maximumValues; this._parameterMinimumValues = this._model.parameters.minimumValues; { const parameterIds = this._model.parameters.ids; const parameterCount = this._model.parameters.count; for (let i = 0; i < parameterCount; ++i) { this._parameterIds.push(parameterIds[i]); } } { const partIds = this._model.parts.ids; const partCount = this._model.parts.count; for (let i = 0; i < partCount; ++i) { this._partIds.push(partIds[i]); } } { const drawableIds = this._model.drawables.ids; const drawableCount = this._model.drawables.count; for (let i = 0; i < drawableCount; ++i) { this._drawableIds.push(drawableIds[i]); } } } constructor(model) { this._model = model; this._savedParameters = []; this._parameterIds = []; this._drawableIds = []; this._partIds = []; this._notExistPartId = {}; this._notExistParameterId = {}; this._notExistParameterValues = {}; this._notExistPartOpacities = {}; this.initialize(); } release() { this._model.release(); this._model = void 0; } } class CubismMoc { static create(mocBytes) { const moc = Live2DCubismCore.Moc.fromArrayBuffer(mocBytes); if (moc) { return new CubismMoc(moc); } throw new Error("Unknown error"); } createModel() { let cubismModel; const model = Live2DCubismCore.Model.fromMoc(this._moc); if (model) { cubismModel = new CubismModel(model); ++this._modelCount; return cubismModel; } throw new Error("Unknown error"); } deleteModel(model) { if (model != null) { --this._modelCount; } } constructor(moc) { this._moc = moc; this._modelCount = 0; } release() { this._moc._release(); this._moc = void 0; } } var CubismPhysicsTargetType = /* @__PURE__ */ ((CubismPhysicsTargetType2) => { CubismPhysicsTargetType2[CubismPhysicsTargetType2["CubismPhysicsTargetType_Parameter"] = 0] = "CubismPhysicsTargetType_Parameter"; return CubismPhysicsTargetType2; })(CubismPhysicsTargetType || {}); var CubismPhysicsSource = /* @__PURE__ */ ((CubismPhysicsSource2) => { CubismPhysicsSource2[CubismPhysicsSource2["CubismPhysicsSource_X"] = 0] = "CubismPhysicsSource_X"; CubismPhysicsSource2[CubismPhysicsSource2["CubismPhysicsSource_Y"] = 1] = "CubismPhysicsSource_Y"; CubismPhysicsSource2[CubismPhysicsSource2["CubismPhysicsSource_Angle"] = 2] = "CubismPhysicsSource_Angle"; return CubismPhysicsSource2; })(CubismPhysicsSource || {}); class CubismPhysicsParticle { constructor() { this.initialPosition = new CubismVector2(0, 0); this.position = new CubismVector2(0, 0); this.lastPosition = new CubismVector2(0, 0); this.lastGravity = new CubismVector2(0, 0); this.force = new CubismVector2(0, 0); this.velocity = new CubismVector2(0, 0); } } class CubismPhysicsSubRig { constructor() { this.normalizationPosition = {}; this.normalizationAngle = {}; } } class CubismPhysicsInput { constructor() { this.source = {}; } } class CubismPhysicsOutput { constructor() { this.destination = {}; this.translationScale = new CubismVector2(0, 0); } } class CubismPhysicsRig { constructor() { this.settings = []; this.inputs = []; this.outputs = []; this.particles = []; this.gravity = new CubismVector2(0, 0); this.wind = new CubismVector2(0, 0); } } class CubismPhysicsJson { constructor(json) { this._json = json; } release() { this._json = void 0; } getGravity() { const ret = new CubismVector2(0, 0); ret.x = this._json.Meta.EffectiveForces.Gravity.X; ret.y = this._json.Meta.EffectiveForces.Gravity.Y; return ret; } getWind() { const ret = new CubismVector2(0, 0); ret.x = this._json.Meta.EffectiveForces.Wind.X; ret.y = this._json.Meta.EffectiveForces.Wind.Y; return ret; } getSubRigCount() { return this._json.Meta.PhysicsSettingCount; } getTotalInputCount() { return this._json.Meta.TotalInputCount; } getTotalOutputCount() { return this._json.Meta.TotalOutputCount; } getVertexCount() { return this._json.Meta.VertexCount; } getNormalizationPositionMinimumValue(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Normalization.Position.Minimum; } getNormalizationPositionMaximumValue(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Normalization.Position.Maximum; } getNormalizationPositionDefaultValue(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Normalization.Position.Default; } getNormalizationAngleMinimumValue(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Normalization.Angle.Minimum; } getNormalizationAngleMaximumValue(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Normalization.Angle.Maximum; } getNormalizationAngleDefaultValue(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Normalization.Angle.Default; } getInputCount(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Input.length; } getInputWeight(physicsSettingIndex, inputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Input[inputIndex].Weight; } getInputReflect(physicsSettingIndex, inputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Input[inputIndex].Reflect; } getInputType(physicsSettingIndex, inputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Input[inputIndex].Type; } getInputSourceId(physicsSettingIndex, inputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Input[inputIndex].Source.Id; } getOutputCount(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Output.length; } getOutputVertexIndex(physicsSettingIndex, outputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Output[outputIndex].VertexIndex; } getOutputAngleScale(physicsSettingIndex, outputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Output[outputIndex].Scale; } getOutputWeight(physicsSettingIndex, outputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Output[outputIndex].Weight; } getOutputDestinationId(physicsSettingIndex, outputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Output[outputIndex].Destination.Id; } getOutputType(physicsSettingIndex, outputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Output[outputIndex].Type; } getOutputReflect(physicsSettingIndex, outputIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Output[outputIndex].Reflect; } getParticleCount(physicsSettingIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Vertices.length; } getParticleMobility(physicsSettingIndex, vertexIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Vertices[vertexIndex].Mobility; } getParticleDelay(physicsSettingIndex, vertexIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Vertices[vertexIndex].Delay; } getParticleAcceleration(physicsSettingIndex, vertexIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Vertices[vertexIndex].Acceleration; } getParticleRadius(physicsSettingIndex, vertexIndex) { return this._json.PhysicsSettings[physicsSettingIndex].Vertices[vertexIndex].Radius; } getParticlePosition(physicsSettingIndex, vertexIndex) { const ret = new CubismVector2(0, 0); ret.x = this._json.PhysicsSettings[physicsSettingIndex].Vertices[vertexIndex].Position.X; ret.y = this._json.PhysicsSettings[physicsSettingIndex].Vertices[vertexIndex].Position.Y; return ret; } } const PhysicsTypeTagX = "X"; const PhysicsTypeTagY = "Y"; const PhysicsTypeTagAngle = "Angle"; const AirResistance = 5; const MaximumWeight = 100; const MovementThreshold = 1e-3; class CubismPhysics { static create(json) { const ret = new CubismPhysics(); ret.parse(json); ret._physicsRig.gravity.y = 0; return ret; } evaluate(model, deltaTimeSeconds) { let totalAngle; let weight; let radAngle; let outputValue; const totalTranslation = new CubismVector2(); let currentSetting; let currentInput; let currentOutput; let currentParticles; let parameterValue; let parameterMaximumValue; let parameterMinimumValue; let parameterDefaultValue; parameterValue = model.getModel().parameters.values; parameterMaximumValue = model.getModel().parameters.maximumValues; parameterMinimumValue = model.getModel().parameters.minimumValues; parameterDefaultValue = model.getModel().parameters.defaultValues; for (let settingIndex = 0; settingIndex < this._physicsRig.subRigCount; ++settingIndex) { totalAngle = { angle: 0 }; totalTranslation.x = 0; totalTranslation.y = 0; currentSetting = this._physicsRig.settings[settingIndex]; currentInput = this._physicsRig.inputs.slice(currentSetting.baseInputIndex); currentOutput = this._physicsRig.outputs.slice(currentSetting.baseOutputIndex); currentParticles = this._physicsRig.particles.slice(currentSetting.baseParticleIndex); for (let i = 0; i < currentSetting.inputCount; ++i) { weight = currentInput[i].weight / MaximumWeight; if (currentInput[i].sourceParameterIndex == -1) { currentInput[i].sourceParameterIndex = model.getParameterIndex(currentInput[i].source.id); } currentInput[i].getNormalizedParameterValue(totalTranslation, totalAngle, parameterValue[currentInput[i].sourceParameterIndex], parameterMinimumValue[currentInput[i].sourceParameterIndex], parameterMaximumValue[currentInput[i].sourceParameterIndex], parameterDefaultValue[currentInput[i].sourceParameterIndex], currentSetting.normalizationPosition, currentSetting.normalizationAngle, currentInput[i].reflect, weight); } radAngle = CubismMath.degreesToRadian(-totalAngle.angle); totalTranslation.x = totalTranslation.x * CubismMath.cos(radAngle) - totalTranslation.y * CubismMath.sin(radAngle); totalTranslation.y = totalTranslation.x * CubismMath.sin(radAngle) + totalTranslation.y * CubismMath.cos(radAngle); updateParticles(currentParticles, currentSetting.particleCount, totalTranslation, totalAngle.angle, this._options.wind, MovementThreshold * currentSetting.normalizationPosition.maximum, deltaTimeSeconds, AirResistance); for (let i = 0; i < currentSetting.outputCount; ++i) { const particleIndex = currentOutput[i].vertexIndex; if (particleIndex < 1 || particleIndex >= currentSetting.particleCount) { break; } if (currentOutput[i].destinationParameterIndex == -1) { currentOutput[i].destinationParameterIndex = model.getParameterIndex(currentOutput[i].destination.id); } const translation = new CubismVector2(); translation.x = currentParticles[particleIndex].position.x - currentParticles[particleIndex - 1].position.x; translation.y = currentParticles[particleIndex].position.y - currentParticles[particleIndex - 1].position.y; outputValue = currentOutput[i].getValue(translation, currentParticles, particleIndex, currentOutput[i].reflect, this._options.gravity); const destinationParameterIndex = currentOutput[i].destinationParameterIndex; const outParameterValue = !Float32Array.prototype.slice && "subarray" in Float32Array.prototype ? JSON.parse(JSON.stringify(parameterValue.subarray(destinationParameterIndex))) : parameterValue.slice(destinationParameterIndex); updateOutputParameterValue(outParameterValue, parameterMinimumValue[destinationParameterIndex], parameterMaximumValue[destinationParameterIndex], outputValue, currentOutput[i]); for (let offset = destinationParameterIndex, outParamIndex = 0; offset < parameterValue.length; offset++, outParamIndex++) { parameterValue[offset] = outParameterValue[outParamIndex]; } } } } setOptions(options) { this._options = options; } getOption() { return this._options; } constructor() { this._options = new Options(); this._options.gravity.y = -1; this._options.gravity.x = 0; this._options.wind.x = 0; this._options.wind.y = 0; } release() { this._physicsRig = void 0; } parse(physicsJson) { this._physicsRig = new CubismPhysicsRig(); let json = new CubismPhysicsJson(physicsJson); this._physicsRig.gravity = json.getGravity(); this._physicsRig.wind = json.getWind(); this._physicsRig.subRigCount = json.getSubRigCount(); let inputIndex = 0, outputIndex = 0, particleIndex = 0; for (let i = 0; i < this._physicsRig.subRigCount; ++i) { const setting = new CubismPhysicsSubRig(); setting.normalizationPosition.minimum = json.getNormalizationPositionMinimumValue(i); setting.normalizationPosition.maximum = json.getNormalizationPositionMaximumValue(i); setting.normalizationPosition.defalut = json.getNormalizationPositionDefaultValue(i); setting.normalizationAngle.minimum = json.getNormalizationAngleMinimumValue(i); setting.normalizationAngle.maximum = json.getNormalizationAngleMaximumValue(i); setting.normalizationAngle.defalut = json.getNormalizationAngleDefaultValue(i); setting.inputCount = json.getInputCount(i); setting.baseInputIndex = inputIndex; inputIndex += setting.inputCount; for (let j = 0; j < setting.inputCount; ++j) { const input = new CubismPhysicsInput(); input.sourceParameterIndex = -1; input.weight = json.getInputWeight(i, j); input.reflect = json.getInputReflect(i, j); switch (json.getInputType(i, j)) { case PhysicsTypeTagX: input.type = CubismPhysicsSource.CubismPhysicsSource_X; input.getNormalizedParameterValue = getInputTranslationXFromNormalizedParameterValue; break; case PhysicsTypeTagY: input.type = CubismPhysicsSource.CubismPhysicsSource_Y; input.getNormalizedParameterValue = getInputTranslationYFromNormalizedParamterValue; break; case PhysicsTypeTagAngle: input.type = CubismPhysicsSource.CubismPhysicsSource_Angle; input.getNormalizedParameterValue = getInputAngleFromNormalizedParameterValue; break; } input.source.targetType = CubismPhysicsTargetType.CubismPhysicsTargetType_Parameter; input.source.id = json.getInputSourceId(i, j); this._physicsRig.inputs.push(input); } setting.outputCount = json.getOutputCount(i); setting.baseOutputIndex = outputIndex; outputIndex += setting.outputCount; for (let j = 0; j < setting.outputCount; ++j) { const output = new CubismPhysicsOutput(); output.destinationParameterIndex = -1; output.vertexIndex = json.getOutputVertexIndex(i, j); output.angleScale = json.getOutputAngleScale(i, j); output.weight = json.getOutputWeight(i, j); output.destination.targetType = CubismPhysicsTargetType.CubismPhysicsTargetType_Parameter; output.destination.id = json.getOutputDestinationId(i, j); switch (json.getOutputType(i, j)) { case PhysicsTypeTagX: output.type = CubismPhysicsSource.CubismPhysicsSource_X; output.getValue = getOutputTranslationX; output.getScale = getOutputScaleTranslationX; break; case PhysicsTypeTagY: output.type = CubismPhysicsSource.CubismPhysicsSource_Y; output.getValue = getOutputTranslationY; output.getScale = getOutputScaleTranslationY; break; case PhysicsTypeTagAngle: output.type = CubismPhysicsSource.CubismPhysicsSource_Angle; output.getValue = getOutputAngle; output.getScale = getOutputScaleAngle; break; } output.reflect = json.getOutputReflect(i, j); this._physicsRig.outputs.push(output); } setting.particleCount = json.getParticleCount(i); setting.baseParticleIndex = particleIndex; particleIndex += setting.particleCount; for (let j = 0; j < setting.particleCount; ++j) { const particle = new CubismPhysicsParticle(); particle.mobility = json.getParticleMobility(i, j); particle.delay = json.getParticleDelay(i, j); particle.acceleration = json.getParticleAcceleration(i, j); particle.radius = json.getParticleRadius(i, j); particle.position = json.getParticlePosition(i, j); this._physicsRig.particles.push(particle); } this._physicsRig.settings.push(setting); } this.initialize(); json.release(); } initialize() { let strand; let currentSetting; let radius; for (let settingIndex = 0; settingIndex < this._physicsRig.subRigCount; ++settingIndex) { currentSetting = this._physicsRig.settings[settingIndex]; strand = this._physicsRig.particles.slice(currentSetting.baseParticleIndex); strand[0].initialPosition = new CubismVector2(0, 0); strand[0].lastPosition = new CubismVector2(strand[0].initialPosition.x, strand[0].initialPosition.y); strand[0].lastGravity = new CubismVector2(0, -1); strand[0].lastGravity.y *= -1; strand[0].velocity = new CubismVector2(0, 0); strand[0].force = new CubismVector2(0, 0); for (let i = 1; i < currentSetting.particleCount; ++i) { radius = new CubismVector2(0, 0); radius.y = strand[i].radius; strand[i].initialPosition = new CubismVector2(strand[i - 1].initialPosition.x + radius.x, strand[i - 1].initialPosition.y + radius.y); strand[i].position = new CubismVector2(strand[i].initialPosition.x, strand[i].initialPosition.y); strand[i].lastPosition = new CubismVector2(strand[i].initialPosition.x, strand[i].initialPosition.y); strand[i].lastGravity = new CubismVector2(0, -1); strand[i].lastGravity.y *= -1; strand[i].velocity = new CubismVector2(0, 0); strand[i].force = new CubismVector2(0, 0); } } } } class Options { constructor() { this.gravity = new CubismVector2(0, 0); this.wind = new CubismVector2(0, 0); } } function getInputTranslationXFromNormalizedParameterValue(targetTranslation, targetAngle, value, parameterMinimumValue, parameterMaximumValue, parameterDefaultValue, normalizationPosition, normalizationAngle, isInverted, weight) { targetTranslation.x += normalizeParameterValue(value, parameterMinimumValue, parameterMaximumValue, parameterDefaultValue, normalizationPosition.minimum, normalizationPosition.maximum, normalizationPosition.defalut, isInverted) * weight; } function getInputTranslationYFromNormalizedParamterValue(targetTranslation, targetAngle, value, parameterMinimumValue, parameterMaximumValue, parameterDefaultValue, normalizationPosition, normalizationAngle, isInverted, weight) { targetTranslation.y += normalizeParameterValue(value, parameterMinimumValue, parameterMaximumValue, parameterDefaultValue, normalizationPosition.minimum, normalizationPosition.maximum, normalizationPosition.defalut, isInverted) * weight; } function getInputAngleFromNormalizedParameterValue(targetTranslation, targetAngle, value, parameterMinimumValue, parameterMaximumValue, parameterDefaultValue, normalizaitionPosition, normalizationAngle, isInverted, weight) { targetAngle.angle += normalizeParameterValue(value, parameterMinimumValue, parameterMaximumValue, parameterDefaultValue, normalizationAngle.minimum, normalizationAngle.maximum, normalizationAngle.defalut, isInverted) * weight; } function getOutputTranslationX(translation, particles, particleIndex, isInverted, parentGravity) { let outputValue = translation.x; if (isInverted) { outputValue *= -1; } return outputValue; } function getOutputTranslationY(translation, particles, particleIndex, isInverted, parentGravity) { let outputValue = translation.y; if (isInverted) { outputValue *= -1; } return outputValue; } function getOutputAngle(translation, particles, particleIndex, isInverted, parentGravity) { let outputValue; if (particleIndex >= 2) { parentGravity = particles[particleIndex - 1].position.substract(particles[particleIndex - 2].position); } else { parentGravity = parentGravity.multiplyByScaler(-1); } outputValue = CubismMath.directionToRadian(parentGravity, translation); if (isInverted) { outputValue *= -1; } return outputValue; } function getRangeValue(min, max) { return Math.abs(Math.max(min, max) - Math.min(min, max)); } function getDefaultValue(min, max) { const minValue = Math.min(min, max); return minValue + getRangeValue(min, max) / 2; } function getOutputScaleTranslationX(translationScale, angleScale) { return translationScale.x; } function getOutputScaleTranslationY(translationScale, angleScale) { return translationScale.y; } function getOutputScaleAngle(translationScale, angleScale) { return angleScale; } function updateParticles(strand, strandCount, totalTranslation, totalAngle, windDirection, thresholdValue, deltaTimeSeconds, airResistance) { let totalRadian; let delay; let radian; let currentGravity; let direction = new CubismVector2(0, 0); let velocity = new CubismVector2(0, 0); let force = new CubismVector2(0, 0); let newDirection = new CubismVector2(0, 0); strand[0].position = new CubismVector2(totalTranslation.x, totalTranslation.y); totalRadian = CubismMath.degreesToRadian(totalAngle); currentGravity = CubismMath.radianToDirection(totalRadian); currentGravity.normalize(); for (let i = 1; i < strandCount; ++i) { strand[i].force = currentGravity.multiplyByScaler(strand[i].acceleration).add(windDirection); strand[i].lastPosition = new CubismVector2(strand[i].position.x, strand[i].position.y); delay = strand[i].delay * deltaTimeSeconds * 30; direction = strand[i].position.substract(strand[i - 1].position); radian = CubismMath.directionToRadian(strand[i].lastGravity, currentGravity) / airResistance; direction.x = CubismMath.cos(radian) * direction.x - direction.y * CubismMath.sin(radian); direction.y = CubismMath.sin(radian) * direction.x + direction.y * CubismMath.cos(radian); strand[i].position = strand[i - 1].position.add(direction); velocity = strand[i].velocity.multiplyByScaler(delay); force = strand[i].force.multiplyByScaler(delay).multiplyByScaler(delay); strand[i].position = strand[i].position.add(velocity).add(force); newDirection = strand[i].position.substract(strand[i - 1].position); newDirection.normalize(); strand[i].position = strand[i - 1].position.add(newDirection.multiplyByScaler(strand[i].radius)); if (CubismMath.abs(strand[i].position.x) < thresholdValue) { strand[i].position.x = 0; } if (delay != 0) { strand[i].velocity = strand[i].position.substract(strand[i].lastPosition); strand[i].velocity = strand[i].velocity.divisionByScalar(delay); strand[i].velocity = strand[i].velocity.multiplyByScaler(strand[i].mobility); } strand[i].force = new CubismVector2(0, 0); strand[i].lastGravity = new CubismVector2(currentGravity.x, currentGravity.y); } } function updateOutputParameterValue(parameterValue, parameterValueMinimum, parameterValueMaximum, translation, output) { let outputScale; let value; let weight; outputScale = output.getScale(output.translationScale, output.angleScale); value = translation * outputScale; if (value < parameterValueMinimum) { if (value < output.valueBelowMinimum) { output.valueBelowMinimum = value; } value = parameterValueMinimum; } else if (value > parameterValueMaximum) { if (value > output.valueExceededMaximum) { output.valueExceededMaximum = value; } value = parameterValueMaximum; } weight = output.weight / MaximumWeight; if (weight >= 1) { parameterValue[0] = value; } else { value = parameterValue[0] * (1 - weight) + value * weight; parameterValue[0] = value; } } function normalizeParameterValue(value, parameterMinimum, parameterMaximum, parameterDefault, normalizedMinimum, normalizedMaximum, normalizedDefault, isInverted) { let result = 0; const maxValue = CubismMath.max(parameterMaximum, parameterMinimum); if (maxValue < value) { value = maxValue; } const minValue = CubismMath.min(parameterMaximum, parameterMinimum); if (minValue > value) { value = minValue; } const minNormValue = CubismMath.min(normalizedMinimum, normalizedMaximum); const maxNormValue = CubismMath.max(normalizedMinimum, normalizedMaximum); const middleNormValue = normalizedDefault; const middleValue = getDefaultValue(minValue, maxValue); const paramValue = value - middleValue; switch (Math.sign(paramValue)) { case 1: { const nLength = maxNormValue - middleNormValue; const pLength = maxValue - middleValue; if (pLength != 0) { result = paramValue * (nLength / pLength); result += middleNormValue; } break; } case -1: { const nLength = minNormValue - middleNormValue; const pLength = minValue - middleValue; if (pLength != 0) { result = paramValue * (nLength / pLength); result += middleNormValue; } break; } case 0: { result = middleNormValue; break; } } return isInverted ? result : result * -1; } Live2DFactory.registerRuntime({ version: 4, ready: cubism4Ready, test(source) { return source instanceof Cubism4ModelSettings || Cubism4ModelSettings.isValidJSON(source); }, isValidMoc(modelData) { if (modelData.byteLength < 4) { return false; } const view = new Int8Array(modelData, 0, 4); return String.fromCharCode(...view) === "MOC3"; }, createModelSettings(json) { return new Cubism4ModelSettings(json); }, createCoreModel(data) { const moc = CubismMoc.create(data); try { const model = moc.createModel(); model.__moc = moc; return model; } catch (e) { try { moc.release(); } catch (ignored) { } throw e; } }, createInternalModel(coreModel, settings, options) { const model = new Cubism4InternalModel(coreModel, settings, options); const coreModelWithMoc = coreModel; if (coreModelWithMoc.__moc) { model.__moc = coreModelWithMoc.__moc; delete coreModelWithMoc.__moc; model.once("destroy", releaseMoc); } return model; }, createPhysics(coreModel, data) { return CubismPhysics.create(data); }, createPose(coreModel, data) { return CubismPose.create(data); } }); function releaseMoc() { var _a; (_a = this.__moc) == null ? void 0 : _a.release(); } exports2.Cubism2ExpressionManager = Cubism2ExpressionManager; exports2.Cubism2InternalModel = Cubism2InternalModel; exports2.Cubism2ModelSettings = Cubism2ModelSettings; exports2.Cubism2MotionManager = Cubism2MotionManager; exports2.Cubism4ExpressionManager = Cubism4ExpressionManager; exports2.Cubism4InternalModel = Cubism4InternalModel; exports2.Cubism4ModelSettings = Cubism4ModelSettings; exports2.Cubism4MotionManager = Cubism4MotionManager; exports2.ExpressionManager = ExpressionManager; exports2.FileLoader = FileLoader; exports2.FocusController = FocusController; exports2.InteractionMixin = InteractionMixin; exports2.InternalModel = InternalModel; exports2.LOGICAL_HEIGHT = LOGICAL_HEIGHT; exports2.LOGICAL_WIDTH = LOGICAL_WIDTH; exports2.Live2DExpression = Live2DExpression; exports2.Live2DEyeBlink = Live2DEyeBlink; exports2.Live2DFactory = Live2DFactory; exports2.Live2DLoader = Live2DLoader; exports2.Live2DModel = Live2DModel; exports2.Live2DPhysics = Live2DPhysics; exports2.Live2DPose = Live2DPose; exports2.Live2DTransform = Live2DTransform; exports2.ModelSettings = ModelSettings; exports2.MotionManager = MotionManager; exports2.MotionPreloadStrategy = MotionPreloadStrategy; exports2.MotionPriority = MotionPriority; exports2.MotionState = MotionState; exports2.SoundManager = SoundManager; exports2.VERSION = VERSION; exports2.XHRLoader = XHRLoader; exports2.ZipLoader = ZipLoader; exports2.applyMixins = applyMixins; exports2.clamp = clamp; exports2.copyArray = copyArray; exports2.copyProperty = copyProperty; exports2.cubism4Ready = cubism4Ready; exports2.folderName = folderName; exports2.logger = logger; exports2.rand = rand; exports2.remove = remove; exports2.startUpCubism4 = startUpCubism4; Object.defineProperties(exports2, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); });