dead-end-colosseum/www/js/plugins/JsScript63Set.js
2026-01-17 11:28:46 -06:00

2171 lines
94 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*:
* @plugindesc
* @author 奏ねこま(おとぶきねこま)
* @url http:
* @target MZ
*
* @param json file
* @type string[]
* @default []
* @desc Live2Dファイル(*.model3.json)
*
* @help
*/
'use strict';
let Load_TextureArr = [];
class _Load_Texture {
constructor(_MdlName) {
this._MdlName = _MdlName;
this._TextureCnt = 0;
}
}
class _SeParam {
constructor(_SeName){
this._SeName = _SeName;
this._OnFlg = false;
}
}
class _VoiceParams {
constructor (_VoiceChara , _VoiceName)
{
this._VoiceChara = _VoiceChara;
this._VoiceName = _VoiceName;
this._OnFlg = false;
}
}
class _CmnEvParam {
constructor(_CmnEvNo){
this._CmnEvNo = _CmnEvNo;
this._OnFlg = false;
}
}
let Live2D_JsonKeep = (p => ({
'json file' : eval(p['json file']),
'live2d data' : {}
}))(PluginManager.parameters('JsScript63Set'));
!function() {
let $p = (p => ({
'json file' : eval(p['json file']),
'live2d data' : {}
}))(PluginManager.parameters('JsScript63Set'));
function load() {
let loader = new (PIXI.Loader || PIXI.loaders.Loader)();
//for (let file of $p['json file']) {
for (let file of modelSetting) {
let fileName = file._MdlName + "/" + file._MdlName;
let name = fileName.replace(/\.(?:json|model3.json)$/i, '');
$p['live2d data'][name] = false;
Live2D_JsonKeep['live2d data'][name] = null;
loader = loader.add(name, `img/live2d/${name}.model3.json`);
}
loader.load((loader, resource) => {
for (let name in $p['live2d data']) {
$p['live2d data'][name] = resource[name].live2dData;
Live2D_JsonKeep['live2d data'][name] = resource[name].live2dData;
}
});
}
if (!window.Live2DCubismCore) {
let js = null;
for (let element of document.getElementsByTagName('script')) {
if (element.src.match('live2dcubismcore.min.js')) {
js = element;
}
}
if (!js) {
js = document.createElement('script');
js.type = 'text/javascript';
js.src = 'js/libs/live2dcubismcore.min.js';
document.body.appendChild(js);
}
js.addEventListener('load', load);
} else {
load();
}
class MosaicFilter extends PIXI.Filter {
constructor(size = 10 , _XZure = 0 , _YZure = 0) {
let vertex = '' +
'attribute vec2 aVertexPosition;' +
'attribute vec2 aTextureCoord;' +
'uniform mat3 projectionMatrix;' +
'varying vec2 vTextureCoord;' +
'void main(void){' +
'gl_Position=vec4((projectionMatrix*vec3(aVertexPosition,1.0)).xy,0.0,1.0);' +
'vTextureCoord=aTextureCoord;' +
'}';
let fragment = '' +
'precision mediump float;' +
'varying vec2 vTextureCoord;' +
'uniform vec2 size;' +
'uniform vec2 zure;' +
'uniform sampler2D uSampler;' +
'uniform vec4 filterArea;' +
'vec2 mapCoord(vec2 coord){' +
'coord*=filterArea.xy;' +
'coord+=filterArea.zw;' +
'return coord;' +
'}' +
'vec2 unmapCoord(vec2 coord){' +
'coord-=filterArea.zw;' +
'coord/=filterArea.xy;' +
'return coord;' +
'}' +
'vec2 pixelate(vec2 coord, vec2 size){' +
'coord+=zure;' +
'return floor(coord / size) * size;' +
'}' +
'void main(void){' +
'vec2 coord=mapCoord(vTextureCoord);' +
'coord=pixelate(coord, size);' +
'coord=unmapCoord(coord);' +
'gl_FragColor=texture2D(uSampler, coord);' +
'}';
super(vertex, fragment);
this.uniforms.size = [size, size];
this.uniforms.zure = [_XZure , _YZure];
}
}
function convars(obj) {
if (typeof obj == 'string') {
let _obj = obj.replace(/\\v\[(\d+)\]/gi, (match, p1) => {
return $gameVariables.value(Number(p1));
});
obj = _obj != obj ? convars(_obj) : _obj;
} else if (obj instanceof Array) {
obj = obj.map(value => convars(value));
} else if (typeof obj == 'object') {
obj = {...obj};
for (let key in obj) {
obj[key] = convars(obj[key]);
}
}
return obj;
}
class Game_Live2D {
constructor() {
this.init();
}
static live2dData() {
return $p['live2d data'];
}
static fullName(name = '') {
for (let key in this.live2dData()) {
if (key.match(`(?:^|/)${name}$`)) {
return key;
}
}
return '';
}
get model() { return this._model; }
get track() { return this._track; }
get timeScale() { return this._timeScale; }
get weight() { return this._weight; }
get mix() { return this._mix; }
get color() { return this._color; }
get mosaic() { return this._mosaic; }
get offset() { return this._offset; }
get scale() { return this._scale; }
get visible() { return this._visible; }
init() {
this._model = '';
this._track = {};
this._timeScale = 1;
this._weight = [];
this._mix = {};
this._color = {};
this._mosaic = {};
this._offset = { x: 0, y: 0 };
this._scale = { x: 1, y: 1 };
this._visible = true;
this._IdleMtn = "";
this._TgtAlpha = 0;
this._TgtAlphaCng = 0;
this._TgtAlphaFlame = 0;
this._expression = [];
for (let i = 0; i <= 10 - 1; i++) {
this._expression.push("");
}
}
get expression() { return this._expression; }
setModel(name = '') {
name = convars(name);
this.init();
this._name = name;
this._model = `${name}_${Date.now()}`;
return this;
}
setAnimation(id, animations, ...args) {
[id, animations, args] = convars([id, animations, args]);
this._track = {...this._track};
let list, order, continuance, interrupt;
if (typeof animations == 'string') {
list = [animations];
order = 'sequential';
continuance = args[0] || 'continue';
interrupt = typeof args[1] == 'boolean' ? args[1] : args[1] == 'true';
} else {
list = animations;
order = args[0] || 'sequential';
continuance = args[1] || 'continue';
interrupt = typeof args[2] == 'boolean' ? args[2] : args[2] == 'true';
}
this._track[id] = { list: [], order: order, continuance: continuance, interrupt: interrupt };
list.forEach(animation => {
let [name, options] = `${animation}/`.replace(/ +/, '').split(/\//);
let times = 1;
let timeScale = 1;
let weight = 1;
for (let option of options.replace(/ +/, '').split(/,/)) {
if (option.match(/^times=(\d+)$/i)) {
times = Number(RegExp.$1);
}
if (option.match(/^timeScale=(\d+\.?\d*)$/i)) {
timeScale = Number(RegExp.$1);
}
if (option.match(/^weight=(\d+\.?\d*)$/i)) {
weight = Number(RegExp.$1);
}
}
this._track[id].list.push({ name: name, times: times, timeScale: timeScale, weight: weight });
});
return this;
}
setExpression(id , expStr) {
this._expression[id] = expStr;
}
setTimeScale(value) {
value = convars(value);
this._timeScale = Number(value);
return this;
}
setWeight(id, value) {
[id, value] = convars([id, value]);
this._weight = this._weight.slice();
this._weight[id] = Number(value);
return this;
}
setMix(...args) {
args = convars(args);
this._mix = {...this._mix};
let from, to, duration;
if (args.length == 1) {
from = '/default';
to = '';
duration = Number(args[0]);
} else {
from = args[0];
to = args[1];
duration = args.length > 2 ? Number(args[2]) : null;
}
if (duration !== null) {
this._mix[`${from}/${to}`] = duration;
} else {
delete this._mix[`${from}/${to}`];
}
return this;
}
setColor(...args) {
args = convars(args);
this._color = {...this._color};
let id, r, g, b, a;
if (args.length == 3) {
id = '/default/';
r = Number(args[0]);
g = Number(args[1]);
b = Number(args[2]);
if(this._color[id] == undefined) {
a = 1;
} else {
a = this._color[id][3];
}
} else if (args.length == 4) {
id = '/default/';
r = Number(args[0]);
g = Number(args[1]);
b = Number(args[2]);
a = Number(args[3]);
} else {
id = args[0];
r = Number(args[1]);
g = Number(args[2]);
b = Number(args[3]);
a = Number(args[4]);
}
if (r != 1 || g != 1 || b != 1 || a != 1) {
this._color[id] = [r, g, b, a];
} else {
this._color[id] = [r, g, b, a];
}
return this;
}
setMosaic(...args) {
args = convars(args);
this._mosaic = {...this._mosaic};
let id, size;
if (args.length == 1) {
id = '/default/';
size = Number(args[0]);
} else {
id = args[0];
size = Number(args[1]);
}
if (size > 1) {
this._mosaic[id] = size;
} else {
delete this._mosaic[id];
}
return this;
}
setOffset(x, y) {
[x, y] = convars([x, y]);
this._offset = { x: Number(x), y: Number(y) };
return this;
}
setScale(x, y) {
[x, y] = convars([x, y]);
this._scale = { x: Number(x), y: Number(y) };
return this;
}
setVisible(visible) {
this._visible = !!convars(visible);
return this;
}
setParams(_prmId , _value){
let _ckid = this._model;
let _AddFlg = true;
for (let i = 0; i <= L2D_SetParams_Arr.length - 1; i++) {
if(L2D_SetParams_Arr[i]._modelId == _ckid){
_AddFlg = false;
let _ckNo = L2D_SetParams_Arr[i]._ids.indexOf(_prmId);
if(_ckNo != -1){
L2D_SetParams_Arr[i]._values[_ckNo] = _value;
} else {
L2D_SetParams_Arr[i]._ids.push(_prmId);
L2D_SetParams_Arr[i]._values.push(_value);
}
}
}
if(_AddFlg){
let _SetVar = new L2D_SetParams();
_SetVar._modelId = _ckid;
_SetVar._ids = [_prmId];
_SetVar._values = [_value];
L2D_SetParams_Arr.push(_SetVar);
}
return this;
}
delParams(_prmId){
let _ckid = this._model;
let _AddFlg = true;
for (let i = 0; i <= L2D_DelParams_Arr.length - 1; i++) {
if(L2D_DelParams_Arr[i]._modelId == _ckid){
_AddFlg = false;
let _ckNo = L2D_DelParams_Arr[i]._ids.indexOf(_prmId);
if(_ckNo == -1){
L2D_DelParams_Arr[i]._ids.push(_prmId);
}
}
}
if(_AddFlg){
let _SetVar = new L2D_SetParams();
_SetVar._modelId = _ckid;
_SetVar._ids = [_prmId];
L2D_DelParams_Arr.push(_SetVar);
}
return this;
}
}
window.Game_Live2D = Game_Live2D;
class Sprite_Live2D extends Sprite {
constructor(...args) {
super();
this._pictureId = typeof args[0] == 'number' ? args[0] : 0;
this._live2d = args[0] instanceof Game_Live2D ? args[0] : null;
this._isRestore = false;
this.init();
}
init() {
this.removeChild(this._data);
this._data = null;
this._model = '';
this._track = {};
this._timeScale = 1;
this._weight = [];
this._mix = {};
this._color = {};
this._mosaic = {};
this._offset = null;
this._scale = null;
this._mdlAlpha = 1;
this.blnk_flg = false;
this.blnk_flame = 100 + Math.floor(Math.random() * 300);
this.blnk_LClosePrm = 0;
this.blnk_LOpenPrm = 0; this.blnk_LBaseOpenPrm = 0;
this.blnk_LIdNo = -1;
this.blnk_RClosePrm = 0;
this.blnk_ROpenPrm = 0; this.blnk_RBaseOpenPrm = 0;
this.blnk_RIdNo = -1;
}
live2d() {
if (this._live2d) {
return this._live2d;
}
return null;
}
update() {
let live2d = this.live2d();
this.updateModel(live2d);
if (this._data) {
this.updateColor(live2d);
if(this.parent._mdlAlpha == undefined) this.parent._mdlAlpha = 1;
if(!this.parent._mdlAlpha < 0.00001) {
this.updateMosaic(live2d);
this.updateOffset(live2d);
this.updateScale(live2d);
this.updateVisible(live2d);
if (!this._isRestore) {
this.updateTimeScale(live2d);
this.updateWeight(live2d);
this.updateMix(live2d);
this.updateAnimation(live2d);
this.snapshot(live2d);
} else {
this.restore(live2d);
}
}
}
super.update();
}
updateModel(live2d) {
if (live2d) {
if (live2d.model != this._model) {
let _ckdata = Game_Live2D.live2dData()[Game_Live2D.fullName(live2d._name)];
if(_ckdata == null){
throw new Error("Live2D_Errモデル「" + live2d._name + "」が存在しない");
}
if(_ckdata == false){
console.log("Json 読込中:" + live2d._name);
return;
}
if(_ckdata.Textures.indexOf(null) != -1) {
console.log("Err_updateModel:TextLoad_Wait:" + live2d._name);
return;
}
this.init();
this._name = live2d._name; //nupu:Sprite_Live2Dに_name(モデル名)追加
this._model = live2d.model;
let model = this._model.replace(/_\d+$/, '');
if (model) {
let data = Game_Live2D.live2dData()[Game_Live2D.fullName(model)];
data.name = live2d._name;
this._data = new PIXI.Live2D(data);
this._data.animation.addListener('start', this.onStart.bind(this));
if(data.Expressions != null){
for (let i = 0; i <= data.Expressions.length - 1; i++) {
this._data.animation._expression.push(data.Expressions[i])
}
}
this.addChild(this._data);
if (live2d.snapshot) {
this._isRestore = true;
}
let _ckModel = this._data._model;
let _ckids = _ckModel.parameters.ids;
if (_ckids.indexOf("eyeOpenL") != -1) {
this.blnk_flg = true;
let _LeyeId = _ckids.indexOf("eyeOpenL");
this.blnk_LIdNo = _LeyeId;
if(_ckModel.parameters.keyValues[_LeyeId].length > 0){
let _ckLength = _ckModel.parameters.keyValues[_LeyeId].length;
this.blnk_LOpenPrm = _ckModel.parameters.keyValues[_LeyeId][0];
this.blnk_LClosePrm = _ckModel.parameters.keyValues[_LeyeId][_ckLength - 1];
this.blnk_LBaseOpenPrm = this.blnk_LOpenPrm;
}
}
if (_ckids.indexOf("eyeOpenR") != -1) {
this.blnk_flg = true;
let _ReyeId = _ckids.indexOf("eyeOpenR");
this.blnk_RIdNo = _ReyeId;
if(_ckModel.parameters.keyValues[_ReyeId].length > 0){
let _ckLength = _ckModel.parameters.keyValues[_ReyeId].length;
this.blnk_ROpenPrm = _ckModel.parameters.keyValues[_ReyeId][0];
this.blnk_RClosePrm = _ckModel.parameters.keyValues[_ReyeId][_ckLength - 1];
this.blnk_RBaseOpenPrm = this.blnk_ROpenPrm;
}
}
}
}
} else if (this._model) {
this.init();
}
}
updateTimeScale(live2d) {
if (live2d.timeScale == this._timeScale) return;
this._timeScale = live2d.timeScale;
this._data.animation.setTimeScale(this._timeScale);
}
updateWeight(live2d) {
if (live2d.weight == this._weight) return;
this._weight = live2d.weight;
try {
this._weight.forEach((value, index) => {
this._data.animation.setWeight(index, value);
});
} catch (e) { }
}
updateMix(live2d) {
if (live2d.mix == this._mix) return;
for (let key in live2d.mix) {
if (live2d.mix[key] != this._mix[key]) {
let time = live2d.mix[key];
if (key == '/default/') {
this._data.animation.setDefaultMix(time);
} else {
let [from, to] = key.split('/');
this._data.animation.setMix(from, to, time);
}
}
}
for (let key in this._mix) {
if (key in live2d.mix == false) {
if (key == '/default/') {
this._data.animation.setDefaultMix(0);
} else {
let [from, to] = key.split('/');
this._data.animation.setMix(from, to, 0);
}
}
}
this._mix = live2d.mix;
}
updateColor(live2d) {
let _ckArr = live2d.color["/default/"];
if(_ckArr == undefined){
if(this._color["/default/"] != undefined) {
live2d.color["/default/"] = this._color["/default/"];
_ckArr = live2d.color["/default/"];
}
else{
live2d.color["/default/"] = [1, 1, 1, 1];
_ckArr = live2d.color["/default/"];
}
}
if(live2d._TgtAlphaFlame > 0){
try {
let _baseAlpha = live2d.color["/default/"][3];
_baseAlpha += live2d._TgtAlphaCng;
live2d._TgtAlphaFlame--;
if(_baseAlpha < 0){
_baseAlpha = 0;
live2d._TgtAlphaFlame = 0;
}
if(live2d._TgtAlphaFlame == 0) _baseAlpha = live2d._TgtAlpha;
live2d.setColor(_ckArr[0] , _ckArr[1] , _ckArr[2] , _baseAlpha);
} catch (e) { }
}
if (live2d.color == this._color) return;
for (let id in live2d.color) {
if (live2d.color[id] != this._color[id]) {
let color = live2d.color[id];
let filter = new PIXI.filters.ColorMatrixFilter();
filter.matrix = [
color[0], 0, 0, 0, 0,
0, color[1], 0, 0, 0,
0, 0, color[2], 0, 0,
0, 0, 0, color[3], 0
];
let target = (id == '/default/') ? this._data : this.getArtMesh(id);
let filters = (target.filters || []).filter(filter => {
return filter instanceof PIXI.filters.ColorMatrixFilter == false;
});
filters.push(filter);
target.filters = filters;
}
if(id == '/default/') {
this._mdlAlpha = live2d.color[id][3];
}
}
for (let id in this._color) {
if (id in live2d.color == false) {
let target = (id == '/default/') ? this._data : this.getArtMesh(id);
let filters = (target.filters || []).filter(filter => {
return filter instanceof PIXI.filters.ColorMatrixFilter == false;
});
target.filters = filters.length > 0 ? filters : null;
}
}
this._color = live2d.color;
}
updateMosaic(live2d) {
if (live2d.mosaic == this._mosaic) return;
for (let id in live2d.mosaic) {
if (live2d.mosaic[id] != this._mosaic[id]) {
let size = live2d.mosaic[id];
let _MosData = L2D_MosaicGet(live2d._name , id);
let _XZure = -_MosData._ZureX;
let _YZure = -_MosData._ZureY;
let filter = new MosaicFilter(size , _XZure , _YZure);
let target = (id == '/default/') ? this._data : this.getArtMesh(id);
let filters = (target.filters || []).filter(filter => {
return filter instanceof MosaicFilter == false;
});
filters.push(filter);
target.filters = filters;
}
}
for (let id in this._mosaic) {
if (id in live2d.mosaic == false) {
let target = (id == '/default/') ? this._data : this.getArtMesh(id);
let filters = (target.filters || []).filter(filter => {
return filter instanceof MosaicFilter == false;
});
target.filters = filters.length > 0 ? filters : null;
}
}
this._mosaic = live2d.mosaic;
}
updateOffset(live2d) {
if (live2d.offset == this._offset) return;
this._offset = live2d.offset;
this.x = this._offset.x;
this.y = this._offset.y;
}
updateScale(live2d) {
this.children.some( _CkLive2D => {
if(_CkLive2D.constructor.name === "Live2D") {
if(_CkLive2D.mask != live2d._SetMask){
_CkLive2D.mask = live2d._SetMask;
}
}
});
if (live2d.scale == this._scale) return;
this._scale = live2d.scale;
this.scale.x = this._scale.x;
this.scale.y = this._scale.y;
}
updateVisible(live2d) {
this.visible = live2d.visible;
}
updateAnimation(live2d) {
for (let i = 0; i <= live2d._expression.length - 1; i++) {
if(live2d._expression[i] != "") {
this._data.setExpression(i , live2d._expression[i] , live2d);
live2d._expression[i] = "";
}
}
if (live2d.TrackCkSkipFlg == undefined) live2d.TrackCkSkipFlg = false;
if (!live2d.TrackCkSkipFlg) {
if (live2d.track == this._track) return;
}
for (let id in live2d.track) {
if (live2d.track[id] != this._track[id] || live2d.TrackCkSkipFlg) {
let track = live2d.track[id];
let list = [];
let loop = track.continuance != 'none';
for (let animation of track.list) {
for (let j = 0; j < animation.times; j++) {
list.push(animation);
}
}
if (track.order == 'shuffle') {
let _list = [...list];
list = [];
while (_list.length > 0) {
let index = Math.floor(Math.random() * _list.length);
list.push(_list.splice(index, 1)[0]);
}
} else if (track.order == 'random') {
let index = Math.floor(Math.random() * list.length);
list = [list[index]];
}
list.forEach((animation, index) => {
let entry;
if ((index == 0 && track.interrupt) || live2d.TrackCkSkipFlg) {
entry = this._data.animation.setAnimation(Number(id), animation.name, loop);
} else {
entry = this._data.animation.addAnimation(Number(id), animation.name, loop);
}
entry.timeScale = animation.timeScale;
entry.weight = animation.weight;
});
}
}
this._track = live2d.track;
live2d.TrackCkSkipFlg = false;
}
getArtMesh(id) {
let index = this._data.model.drawables.ids.indexOf(id);
return this._data._meshes[index];
}
onStart(trackInfo) {
if (trackInfo.track.entries.length == 1) {
let live2d = this.live2d();
let index = trackInfo.index;
if (live2d && live2d.track[index]) {
if (live2d.track[index] == this._track[index]) {
if (this._track[index].continuance == 'reset') {
live2d.track[index].interrupt = false;
this._track = {...this._track};
this._track[index] = null;
}
}
}
}
}
onEnd(trackInfo) {
}
snapshot(live2d) {
live2d.snapshot = this._data.snapshot();
}
restore(live2d) {
this._data.restore(live2d.snapshot);
this._timeScale = live2d.timeScale;
this._weight = live2d.weight;
this._mix = live2d.mix;
this._track = live2d.track;
this._isRestore = false;
}
}
window.Sprite_Live2D = Sprite_Live2D;
// Game_Screen.prototype.live2d = function(id) {
// let picture = this.picture(id);
// if(picture == null) return null;
// if (!picture._live2d) {
// picture._live2d = new Game_Live2D();
// Game_Picture.prototype.initialize = function() {
// __initialize.apply(this, arguments);
// })(Game_Picture.prototype.initialize);
// Game_Picture.prototype.erase = function() {
// __erase.apply(this, arguments);
// })(Game_Picture.prototype.erase);
// Sprite_Picture.prototype.initialize = function(pictureId) {
// __initialize.apply(this, arguments);
// this.addChild(new Sprite_Live2D(pictureId))
// })(Sprite_Picture.prototype.initialize);
}();
let SetSpriteLive2D = function(_No , _MdlName , _x , _y , _mx , _my) {
_x = typeof _x !== 'undefined' ? _x : 0;
_y = typeof _y !== 'undefined' ? _y : 0;
_mx = typeof _mx !== 'undefined' ? _mx : 100;
_my = typeof _my !== 'undefined' ? _my : 100;
let _N_Sprite = SelSprite(_No);
DelSprite(_No);
let _INNo = _GetSpriteInNo(_No);
let _SetSprite = _NSprite(_No ,"" , "" , _x , _y , 255 , _mx , _my);
_SetSprite._live2d = new Game_Live2D();
_SetSprite._live2d.setModel(_MdlName);
let _Set_SpriteLive2D = new Sprite_Live2D(_No);
_Set_SpriteLive2D._live2d = _SetSprite._live2d;
_SetSprite.addChild(_Set_SpriteLive2D);
for (let i = 0; i <= L2D_MosaicDataArr.length - 1; i++) {
if(L2D_MosaicDataArr[i]._Model == _MdlName){
_SetSprite._live2d.setMosaic(L2D_MosaicDataArr[i]._ArtMesh, L2D_MosaicDataArr[i]._MosPx);
}
}
_N_Sprite.addChildAt(_SetSprite , _INNo);
ViewSpriteArr_Add(_No);
DebugSpriteNo(_No, "SetSpriteLive2D");
}
!function() {
if (!PIXI.SimpleMesh) {
PIXI.SimpleMesh = class extends PIXI.mesh.Mesh {
constructor(texture, vertices, uvs, indices, drawMode) {
super(texture, vertices, uvs, indices, drawMode);
this.state = {};
this.texture.baseTexture.resource = {
source: this.texture.baseTexture.source
};
Object.defineProperty(this.state, 'blendMode', {
set: value => this.blendMode = value
});
}
}
}
class Mesh extends PIXI.SimpleMesh {
constructor(texture, vertices, uvs, indices, drawMode) {
super(texture, vertices, uvs, indices, drawMode);
this.uvs = this.uvs || this.uvBuffer.data;
this.indices = this.indices || this.geometry.indexBuffer.data;
this.orderIndex = 0;
}
}
class CopyMesh extends Mesh {
constructor(mesh) {
super(mesh.texture, mesh.vertices, mesh.uvs, mesh.indices, mesh.drawMode);
this._mesh = mesh;
}
refresh() {
this.vertices = this._mesh.vertices;
}
}
class MaskMesh extends CopyMesh {
constructor(mesh) {
super(mesh);
this.maskTexture = null;
this.orderIndex = -Infinity;
this.setup();
}
setup() {
this.maskTexture = new PIXI.Texture(new PIXI.BaseTexture());
this.maskTexture.baseTexture.valid = true;
let filter = new PIXI.Filter(null, PIXI.Filter.defaultFragmentSrc.replace(/\S+uS.+/, 'vec4(0.);'));
filter.apply = this.apply.bind(this);
this.filters = [filter];
}
copy(gl, uid, width, height) {
let _texture = gl.getParameter(gl.TEXTURE_BINDING_2D);
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0);
gl.bindTexture(gl.TEXTURE_2D, _texture);
this.maskTexture.baseTexture._glTextures[uid] = { dirtyId: 0, texture: texture };
}
apply(filterManager, input, output, clear, currentState) {
let gl = filterManager.renderer.gl;
let uid = filterManager.renderer.CONTEXT_UID;
let frame = {}, size = {};
if (input.filterFrame) {
frame.x = input.filterFrame.x;
frame.y = input.filterFrame.y;
frame.width = input.filterFrame.width;
frame.height = input.filterFrame.height;
size.width = input.width;
size.height = input.height;
} else {
frame.x = input.sourceFrame.x;
frame.y = input.sourceFrame.y;
frame.width = input.sourceFrame.width;
frame.height = input.sourceFrame.height;
size.width = input.size.width;
size.height = input.size.height;
}
this.copy(gl, uid, size.width, size.height);
this.maskTexture.maskInfo = { frame: frame, size: size };
filterManager.applyFilter(this.filters[0], input, output, clear, currentState);
}
update() {
super.update();
this.children.forEach(child => child.update());
}
}
class MeshMaskFilter extends PIXI.Filter {
constructor(mask, invert) {
let vertexSrc = 'attribute vec2 aVertexPosition;attribute vec2 aTextureCoord;uniform mat3 projectionMatrix;uniform mat3 otherMatrix;uniform vec2 offset;varying vec2 vMaskCoord;varying vec2 vTextureCoord;void main(void){gl_Position=vec4((projectionMatrix*vec3(aVertexPosition,1.)).xy,0.,1.);vTextureCoord=aTextureCoord;vMaskCoord=(otherMatrix*vec3(aTextureCoord,1.)).xy+offset;}';
let fragmentSrc = 'precision mediump float;varying vec2 vMaskCoord;varying vec2 vTextureCoord;uniform sampler2D uSampler;uniform sampler2D mask;uniform vec2 size;uniform float invert;void main(void){float clip=step(3.5,step(0.,vMaskCoord.x)+step(0.,vMaskCoord.y)+step(vMaskCoord.x,size.x)+step(vMaskCoord.y,size.y));vec4 original=texture2D(uSampler,vTextureCoord);vec4 masky=texture2D(mask,vMaskCoord);gl_FragColor=original*abs(1.*invert-masky.a*clip);}';
super(vertexSrc, fragmentSrc);
this._mask = mask;
this.uniforms.invert = invert ? 1 : 0;
}
apply(filterManager, input, output, clear, currentState) {
let texture = this._mask.maskTexture;
let inputRect = {};
if (input.filterFrame) {
inputRect.x = input.filterFrame.x;
inputRect.y = input.filterFrame.y;
inputRect.width = input.width;
inputRect.height = input.height;
} else {
inputRect.x = input.sourceFrame.x;
inputRect.y = input.sourceFrame.y;
inputRect.width = input.size.width;
inputRect.height = input.size.height;
}
let maskInfo = texture.maskInfo;
this.uniforms.otherMatrix = new PIXI.Matrix(inputRect.width / maskInfo.size.width, 0, 0, inputRect.height / maskInfo.size.height, 0, 0);
this.uniforms.offset = [(inputRect.x - maskInfo.frame.x) / maskInfo.size.width, (inputRect.y - maskInfo.frame.y) / maskInfo.size.height];
this.uniforms.mask = texture;
this.uniforms.size = [maskInfo.frame.width / maskInfo.size.width, maskInfo.frame.height / maskInfo.size.height];
filterManager.applyFilter(this, input, output, clear);
}
}
class Vector2 {
constructor(x, y) {
this.x = x || 0;
this.y = y || 0;
}
add(vector2) {
return new Vector2(this.x + vector2.x, this.y + vector2.y);
}
substract(vector2) {
return new Vector2(this.x - vector2.x, this.y - vector2.y);
}
multiplyScalar(scalar) {
return new Vector2(this.x * scalar, this.y * scalar);
}
normalize() {
let length = Math.pow(this.x * this.x + this.y * this.y, 0.5);
this.x /= length;
this.y /= length;
return this;
}
}
class Physics {
constructor(physics, parameters) {
this._settings = {};
this._parameters = parameters;
this.init(physics);
}
get settings() { return this._settings; }
init(physics) {
let parameters = this._parameters;
let dictionary = physics.Meta.PhysicsDictionary;
let settings = JSON.parse(JSON.stringify(physics.PhysicsSettings).replace(/(?<=")[^"]+(?=":)/g, m => m[0].toLowerCase() + m.slice(1)));
for (let setting of settings) {
let id = setting.id;
delete setting.id;
setting.name = (dictionary.find(item => item.Id == id) || { Name: '' }).Name;
for (let input of setting.input) {
input.source.index = parameters.ids.indexOf(input.source.id);
}
for (let output of setting.output) {
output.destination.index = parameters.ids.indexOf(output.destination.id);
}
for (let vertex of setting.vertices) {
vertex.position = new Vector2(vertex.position.x, vertex.position.y);
vertex.lastGravity = new Vector2(0, 1);
vertex.velocity = new Vector2();
}
this._settings[id] = setting;
}
}
apply(delta) {
let values = this._parameters.values;
let minimumValues = this._parameters.minimumValues;
let maximumValues = this._parameters.maximumValues;
let defaultValues = this._parameters.defaultValues;
for (let id in this._settings) {
let setting = this._settings[id];
let vertices = setting.vertices;
let normalization = setting.normalization;
let translation = { x: 0, y: 0 };
let angle = 0;
for (let input of setting.input) {
let index = input.source.index;
let type = input.type;
let value = this.normalize(
values[index], minimumValues[index], maximumValues[index], defaultValues[index],
type == 'Angle' ? normalization.angle : normalization.position, input.reflect
);
value *= input.weight / 100;
switch (type) {
case 'X':
translation.x += value;
break;
case 'Y':
translation.y += value;
break;
case 'Angle':
angle += value;
break;
}
}
angle = -angle / 180 * Math.PI;
translation = {
x: translation.x * Math.cos(angle) - translation.y * Math.sin(angle),
y: translation.x * Math.sin(angle) + translation.y * Math.cos(angle)
};
this.updateVertices(vertices, translation, -angle, normalization.position.maximum * 0.001, delta);
for (let output of setting.output) {
let index = output.destination.index;
let vertexIndex = output.vertexIndex;
let gravity = vertexIndex > 1 ? vertices[vertexIndex - 1].position.substract(vertices[vertexIndex - 2].position) : new Vector2(0, 1);
if(vertices.length > vertexIndex) {
translation = {
x: vertices[vertexIndex].position.x - vertices[vertexIndex - 1].position.x,
y: vertices[vertexIndex].position.y - vertices[vertexIndex - 1].position.y
};
}
let value = this.directionToRadian(gravity, translation);
let outValues = values.slice(index);
this.updateValues(outValues, minimumValues[index], maximumValues[index], value * output.scale, output.weight);
for (let i = index, j = 0; i < values.length; i++, j++) {
values[i] = outValues[j];
}
}
}
}
normalize(value, minimumValue, maximumValue, defaultValue, normalization, reflect) {
let result = 0;
value = Math.min(Math.max(value, minimumValue), maximumValue) - defaultValue;
if (value != 0) {
let p = (value > 0 ? maximumValue : minimumValue) - defaultValue;
if (p != 0) {
let n = (value > 0 ? normalization.maximum : normalization.minimum) - normalization.default;
result = value * n / p + normalization.default;
}
} else {
result = normalization.default;
}
return reflect ? result :-result;
}
updateVertices(vertices, translation, angle, shreshold, delta) {
let gravity = new Vector2(Math.sin(angle), Math.cos(angle)).normalize();
vertices[0].position = new Vector2(translation.x, translation.y);
for (let i = 1; i < vertices.length; ++i) {
let delay = vertices[i].delay * delta * 30;
let velocity = vertices[i].velocity.multiplyScalar(delay);
let force = gravity.multiplyScalar(vertices[i].acceleration * delay * delay);
let direction = vertices[i].position.substract(vertices[i - 1].position);
let radian = this.directionToRadian(vertices[i].lastGravity, gravity) / 5;
direction = new Vector2(
Math.cos(radian) * direction.x - direction.y * Math.sin(radian),
Math.sin(radian) * direction.x + direction.y * Math.cos(radian)
);
let lastPosition = new Vector2(vertices[i].position.x, vertices[i].position.y);
vertices[i].position = vertices[i - 1].position.add(direction).add(velocity).add(force);
direction = vertices[i].position.substract(vertices[i - 1].position).normalize();
vertices[i].position = vertices[i - 1].position.add(direction.multiplyScalar(vertices[i].radius));
if (Math.abs(vertices[i].position.x) < shreshold) {
vertices[i].position.x = 0;
}
if (delay != 0) {
vertices[i].velocity = vertices[i].position.substract(lastPosition).multiplyScalar(vertices[i].mobility / delay);
}
vertices[i].lastGravity = new Vector2(gravity.x, gravity.y);
}
}
updateValues(values, minimum, maximum, value, weight) {
value = Math.min(Math.max(value, minimum), maximum);
weight /= 100;
if (weight >= 1) {
values[0] = value;
} else {
values[0] = values[0] * (1 - weight) + value * weight;
}
}
directionToRadian(from, to) {
let q1 = Math.atan2(to.y, to.x);
let 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;
}
}
class Curve {
constructor(curve, beziersRestricted = false) {
this._beziersRestricted = beziersRestricted;
this._target = '';
this._id = '';
this._segments = [];
this._points = [];
this.create(curve);
}
get target() { return this._target; }
get id() { return this._id; }
create(curve) {
this._target = curve.Target;
this._id = curve.Id;
this._fadeInTime = curve.FadeInTime;
this._fadeOutTime = curve.FadeOutTime;
this._segments = [];
this._points = [];
let basePoint = 0;
let endPoint = 0;
for (let i = 0; i < curve.Segments.length; i++) {
let evaluate = null;
if (i > 0) {
let type = curve.Segments[i];
basePoint = endPoint;
this._points.push({ time: curve.Segments[i + 1], value: curve.Segments[i + 2] });
if (type == 1) {
this._points.push({ time: curve.Segments[i + 3], value: curve.Segments[i + 4] });
this._points.push({ time: curve.Segments[i + 5], value: curve.Segments[i + 6] });
endPoint = basePoint + 3;
evaluate = this.bezier;
i += 6;
} else {
endPoint = basePoint + 1;
evaluate = type == 0 ? this.linear
: type == 2 ? this.stepped
: type == 3 ? this.inverseStepped
: null;
i += 2;
}
} else {
this._points.push({ time: curve.Segments[0], value: curve.Segments[1] });
i++;
}
this._segments.push({ basePoint: basePoint, endPoint: endPoint, evaluate: evaluate });
}
}
value(time) {
let segments = this._segments;
let points = this._points;
for (let i = 0; i < segments.length; i++) {
if (points[segments[i].endPoint].time > time) {
let basePoint = segments[i].basePoint;
let endPoint = segments[i].endPoint;
let evaluate = segments[i].evaluate;
if (evaluate) {
return evaluate.call(this, points.slice(basePoint, endPoint + 1), time);
}
break;
}
}
return points.slice(-1)[0].value;
}
lerp(a, b, t) {
let time = a.time + (b.time - a.time) * t;
let value = a.value + (b.value - a.value) * t;
return { time: time, value: value };
}
linear(points, time) {
let t = (time - points[0].time) / (points[1].time - points[0].time);
return points[0].value + (points[1].value - points[0].value) * Math.max(t, 0);
}
bezier(points, time) {
if (!this._beziersRestricted) {
return this.cardano(points, time);
}
let t = Math.max((time - points[0].time) / (points[3].time - points[0].time), 0);
let p0 = this.lerp(points[0], points[1], t);
let p1 = this.lerp(points[1], points[2], t);
let p2 = this.lerp(points[2], points[3], t);
let p3 = this.lerp(p0, p1, t);
let p4 = this.lerp(p1, p2, t);
return this.lerp(p3, p4, t).value;
}
cardano(points, time) {
let t0 = points[0].time;
let t1 = points[1].time;
let t2 = points[2].time;
let t3 = points[3].time;
let t4 = t3 + 3.0 * (t1 - t2) - t0;
let t5 = 3.0 * (t0 + t2) - 6.0 * t1;
let t6 = 3.0 * (t1 - t0);
let t7 = t0 - time;
let t = this.cardanoAlgorithm(t4, t5, t6, t7);
let p0 = this.lerp(points[0], points[1], t);
let p1 = this.lerp(points[1], points[2], t);
let p2 = this.lerp(points[2], points[3], t);
let p3 = this.lerp(p0, p1, t);
let p4 = this.lerp(p1, p2, t);
return this.lerp(p3, p4, t).value;
}
stepped(points) {
return points[0].value;
}
inverseStepped(points) {
return points[1].value;
}
range(value, min, max) {
return Math.min(Math.max(value, min), max);
}
cbrt(x) {
if (x == 0) {
return x;
}
var cx = x;
var isNegativeNumber = cx < 0;
if (isNegativeNumber) {
cx = -cx;
}
var 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;
}
quadratic(a, b, c) {
if (Math.abs(a) < 0.00001) {
if (Math.abs(b) < 0.00001) {
return -c;
}
return -c / b;
}
return -(b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
}
cardanoAlgorithm(a, b, c, d) {
if (Math.sqrt(a) < 0.00001) {
return this.range(this.quadratic(b, c, d), 0, 1);
}
let ba = b / a;
let ca = c / a;
let da = d / a;
let p = (3 * ca - ba * ba) / 3;
let p3 = p / 3;
let q = (2 * ba * ba * ba - 9 * ba * ca + 27 * da) / 27;
let q2 = q / 2;
let discriminant = q2 * q2 + p3 * p3 * p3;
if (discriminant < 0) {
let mp3 = -p / 3;
let mp33 = mp3 * mp3 * mp3;
let r = Math.sqrt(mp33);
let t = -q / (2 * r);
let cosphi = this.range(t, -1, 1);
let phi = Math.acos(cosphi);
let crtr = this.cbrt(r);
let t1 = 2 * crtr;
let root1_1 = t1 * Math.cos(phi / 3) - ba / 3;
if (Math.abs(root1_1 - 0.5) < 0.51) {
return this.range(root1_1, 0, 1);
}
let root2 = t1 * Math.cos((phi + 2 * Math.PI) / 3) - ba / 3;
if (Math.abs(root2 - 0.5) < 0.51) {
return this.range(root2, 0, 1);
}
let root3 = t1 * Math.cos((phi + 4 * Math.PI) / 3) - ba / 3;
return this.range(root3, 0, 1);
} else if (discriminant == 0) {
let u1_1;
if (q2 < 0) {
u1_1 = this.cbrt(-q2);
} else {
u1_1 = -this.cbrt(q2);
}
let root1_2 = 2 * u1_1 - ba / 3;
if (Math.abs(root1_2 - 0.5) < 0.51) {
return this.range(root1_2, 0, 1);
}
let root2 = -u1_1 - ba / 3;
return this.range(root2, 0, 1);
}
let sd = Math.sqrt(discriminant);
let u1 = this.cbrt(sd - q2);
let v1 = this.cbrt(sd + q2);
let root1 = u1 - v1 - ba / 3;
return this.range(root1, 0, 1);
}
}
class Motion {
constructor(motion) {
let meta = motion.Data.Meta;
this._duration = meta.Duration;
this._loop = meta.Loop;
this._beziersRestricted = meta.AreBeziersRestricted;
this._group = motion.Group;
this._name = motion.Name;
this._fadeInTime = motion.FadeInTime;
this._fadeOutTime = motion.FadeOutTime;
this._curves = [];
this.createCurve(motion.Data.Curves, this._beziersRestricted);
}
get duration() {
return this._duration;
}
get group() {
return this._group;
};
get name() {
return this._name;
};
createCurve(curves) {
this._curves = curves.map(curve => new Curve(curve));
}
values(time) {
let remain = Math.max(this._duration - time, 0);
let values = {};
for (let curve of this._curves) {
let fadeInTime = curve._fadeInTime != null ? curve._fadeInTime : this._fadeInTime;
let fadeOutTime = curve._fadeOutTime != null ? curve._fadeOutTime : this._fadeOutTime;
let fadeInWeight = time < fadeInTime ? time / fadeInTime : 1;
let fadeOutWeight = remain < fadeOutTime ? remain / fadeOutTime : 1;
let target = curve.target;
let id = curve.id;
let value = curve.value(time);
let weight = fadeInWeight * fadeOutWeight;
values[target] = values[target] || {};
values[target][id] = { value: value, weight: weight };
}
return values;
}
}
class Entry {
constructor(motion, elapsed = 0) {
this._motion = motion;
this._elapsed = elapsed;
this.loop = false;
this.timeScale = 1;
this.weight = 1;
this.mixTime = 0;
}
get name() {
return this._motion.name;
}
get duration() {
return this._motion.duration;
}
get elapsed() {
return this._elapsed;
}
get remain() {
return this.duration - this._elapsed;
}
values(delta) {
this._elapsed += (delta * this.timeScale);
if (this.loop) {
this._elapsed %= this.duration;
}
let values = this._motion.values(this._elapsed);
for (let target in values) {
for (let id in values[target]) {
values[target][id].weight *= this.weight;
}
}
return values;
}
}
class Track {
constructor(active = false) {
this._entries = [];
this._active = active;
this.weight = 1;
}
get entries() { return this._entries; }
get active() { return this._active; }
add(entry) {
let last = this.entry(-1);
if (last) {
last.loop = false;
}
this._entries.push(entry);
}
entry(index) {
return this._entries.slice(index)[0];
}
mix(values, next_values, rate) {
let r0 = 1 - rate;
let r1 = rate;
for (let target in next_values) {
for (let id in next_values[target]) {
let value, weight;
if (values[target] && values[target][id]) {
let p0 = values[target][id];
let p1 = next_values[target][id];
value = p0.value * r0 + p1.value * r1;
weight = p0.weight * r0 + p1.weight * r1;
} else {
let p = next_values[target][id];
value = p.value;
weight = p.weight * r1;
}
values[target] = values[target] || {};
values[target][id] = { value: value, weight: weight };
}
}
}
values(delta) {
try {
let entry = this._entries[0];
let next_entry = this._entries[1];
if (!entry) {
return null;
}
if (!this._active) {
delta = 0;
}
let _remain = entry.remain;
let mixTime = next_entry ? next_entry.mixTime : 0;
let values = entry.values(delta);
let remain = entry.remain;
if (remain > 0) {
if (mixTime >= remain) {
delta = Math.min(mixTime - remain, _remain - remain);
let next_values = next_entry.values(delta);
let rate = (mixTime - remain) / mixTime;
this.mix(values, next_values, rate);
}
} else {
if (next_entry) {
delta = -remain / entry.timeScale;
values = next_entry.values(delta);
}
this._entries.shift();
}
this._active = remain > 0 || !!next_entry;
return values;
} catch (e) {
return false;
}
}
}
class Animation {
constructor(motions, parameters, parts) {
this._motions = [];
this._parameters = parameters;
this._parts = parts;
this._tracks = [];
this._timeScale = 1;
this._mixTime = {};
this._listeners = {};
this._expression = [];
this.createMotion(motions);
}
get motions() { return this._motions; }
get tracks() { return this._tracks; }
get timeScale() { return this._timeScale; }
get mixTime() { return this._mixTime; }
createMotion(motions) {
this._motions = motions.map(motion => new Motion(motion));
}
track(index) {
if (!this._tracks[index]) {
this._tracks[index] = new Track();
}
return this._tracks[index];
}
setAnimation(index, name, loop) {
let track = this._tracks[index];
if (track && track.active) {
this.callListener('end', { index: index, track: track, entry: track.entry(0) });
}
this._tracks[index] = null;
return this.addAnimation(index, name, loop);
}
addAnimation(index, name, loop) {
let motion = this._motions.find(motion => motion.name == name);
let entry = new Entry(motion);
let track = this.track(index);
let last = track.entry(-1);
if (last) {
let key = `${last.name},${name}`;
entry.mixTime = this._mixTime[key] || this._mixTime.default || 0;
}
entry.loop = loop;
track.add(entry);
return entry;
}
setTimeScale(scale) {
this._timeScale = scale;
}
setWeight(index, value) {
this.track(index).weight = value;
}
setMix(from, to, time) {
if (time > 0) {
this._mixTime[`${from},${to}`] = time;
} else {
delete this._mixTime[`${from},${to}`];
}
}
setDefaultMix(time) {
if (time > 0) {
this._mixTime.default = time;
} else {
delete this._mixTime.default;
}
}
addListener(event, callback) {
this._listeners[event] = this._listeners[event] || [];
this._listeners[event].push(callback);
}
removeListener(event, callback) {
if (this._listeners[event]) {
let index = this._listeners[event].indexOf(callback);
if (index >= 0) {
this._listeners[event].splice(index, 1);
}
}
}
callListener(event, trackInfo) {
if (this._listeners[event]) {
this._listeners[event].forEach(callback => callback(trackInfo));
}
}
apply(delta) {
delta *= this._timeScale;
let parameters = this._parameters;
let parts = this._parts;
for (let track of this._tracks) {
if(track == null) continue;
let entry = track.entry(0);
let active = track.active;
let values = track.values(delta);
if (!values) {
continue;
}
for (let target in values) {
for (let id in values[target]) {
let p = values[target][id];
let value = p.value;
let weight = p.weight * track.weight;
if (target == 'Parameter') {
let index = parameters.ids.indexOf(id);
let _value = parameters.values[index];
parameters.values[index] = _value * (1 - weight) + value * weight;
} else if (target == 'PartOpacity') {
let index = parts.ids.indexOf(id);
let _value = parts.opacities[index];
parts.opacities[index] = _value * (1 - weight) + value * weight;
}
}
}
let index = this._tracks.indexOf(track);
let _entry = track.entry(0);
let _active = track.active;
if (!active && _active) {
this.callListener('start', { index: index, track: track, entry: entry });
}
if (entry != _entry) {
if (entry) {
this.callListener('end', { index: index, track: track, entry: entry });
}
if (_entry) {
this.callListener('start', { index: index, track: track, entry: _entry });
}
}
}
}
}
class Live2D extends PIXI.Container {
constructor(live2dData) {
super();
this._data = live2dData;
this._model = new Live2DCubismCore.Model(this._data.Moc);
this._meshes = [];
this._masks = {};
this._physics = null;
this._animation = null;
this._updateTime = 0;
this.createMesh();
this.createMask();
this.createAnimation();
this.createPhysics();
this._exp_tracks = [];
this._exp_SetTracks = [];
this._SEParams = [];
this._VoiceParams = [];
for (let i = 0; i <= seSetting.length - 1; i++) {
if(seSetting[i]._MdlName == this._data.name){
if(seSetting[i]._VoiceChara == "") {
this._SEParams.push(new _SeParam(seSetting[i]._SeName));
} else {
this._VoiceParams.push(
new _VoiceParams(seSetting[i]._VoiceChara , seSetting[i]._SeName)
)
}
}
}
this._CmnParams = [];
for (let i = 0; i <= this._model.parameters.ids.length - 1; i++) {
if(this._model.parameters.ids[i].indexOf("CmnEv_") != -1){
let _SetCmnNo = this._model.parameters.ids[i].replace("CmnEv_" , "");
this._CmnParams.push(new _CmnEvParam(Number(_SetCmnNo)));
}
}
if($gameSystem.L2D_SetParams_Arr == undefined) $gameSystem.L2D_SetParams_Arr = [];
for (let i = 0; i <= $gameSystem.L2D_SetParams_Arr.length - 1; i++) {
if($gameSystem.L2D_SetParams_Arr[i]._modelId == this._data.name) {
for (let j = 0; j <= $gameSystem.L2D_SetParams_Arr[i]._ids.length - 1; j++) {
let _CkId = $gameSystem.L2D_SetParams_Arr[i]._ids[j];
let _nSetNo = this._model.parameters.ids.indexOf(_CkId);
if(_nSetNo != -1) {
this._model.parameters.values[_nSetNo] = $gameSystem.L2D_SetParams_Arr[i]._values[j];
} else {
$gameSystem.L2D_SetParams_Arr[i]._ids.splice(j , 1);
$gameSystem.L2D_SetParams_Arr[i]._values.splice(j , 1);
j--;
}
}
}
}
}
get model() { return this._model; }
get animation() { return this._animation; }
createMesh() {
let drawables = this._model.drawables;
for (let i = 0; i < drawables.count; i++) {
let textureIndex = drawables.textureIndices[i];
let texture = this._data.Textures[textureIndex];
let vertices = this.localVertices(drawables.vertexPositions[i]);
let uvs = new Float32Array(drawables.vertexUvs[i]);
let indices = new Uint16Array(drawables.indices[i]);
for (let j = 0; j < drawables.vertexCounts[i]; j++) {
uvs[j * 2 + 1] = 1 - uvs[j * 2 + 1];
}
for (let j = 1; j < drawables.indexCounts[i]; j += 3) {
[indices[j], indices[j + 1]] = [indices[j + 1], indices[j]];
}
let mesh = new Mesh(texture, vertices, uvs, indices, PIXI.DRAW_MODES.TRIANGLES);
mesh.alpha = drawables.opacities[i];
mesh.visible = drawables.dynamicFlags[i] & 0x1;
mesh.blendMode = drawables.constantFlags[i] & 0x3;
mesh.state.culling = !(drawables.constantFlags[i] & 0x4);
mesh.orderIndex = drawables.renderOrders[i];
this._meshes.push(mesh);
this.addChild(mesh);
}
this.sortMesh();
}
createMask() {
let drawables = this._model.drawables;
for (let i = 0; i < drawables.count; i++) {
let mesh = this._meshes[i];
let invert = !!(drawables.constantFlags[i] & 0x8);
let masks = [...drawables.masks[i]].sort();
if (masks.length > 0) {
let mask = this._masks[masks];
if (!mask) {
mask = new MaskMesh(this._meshes[masks[0]]);
this.addChildAt(mask, 0);
this._masks[masks] = mask;
for (let j = 1; j < masks.length; j++) {
mask.addChild(new CopyMesh(this._meshes[masks[j]]));
}
}
let filters = mesh.filters || [];
filters.push(new MeshMaskFilter(mask, invert));
if (mesh.blendMode > 0) {
let filter = new PIXI.Filter();
filter.blendMode = mesh.blendMode;
mesh.blendMode = 0;
filters.push(filter);
}
mesh.filters = filters;
}
}
}
createPhysics() {
if (this._data.Physics) {
this._physics = new Physics(this._data.Physics, this._model.parameters);
}
}
createAnimation() {
if (this._data.Motions) {
let motions = [];
let parameters = this._model.parameters;
let parts = this._model.parts;
for (let name in this._data.Motions) {
motions.push(...this._data.Motions[name]);
}
this._animation = new Animation(motions, parameters, parts);
this._animation.parent = this;
}
}
sortMesh() {
this.children.sort((a, b) => a.orderIndex - b.orderIndex);
}
localVertices(vertices) {
let canvasinfo = this._model.canvasinfo;
let cox = canvasinfo.CanvasOriginX;
let coy = canvasinfo.CanvasOriginY;
let ppu = canvasinfo.PixelsPerUnit;
return vertices.map((vertex, index) => index % 2 ? coy - vertex * ppu : vertex * ppu + cox);
}
setExpression(index , name) {
for (let i = this._exp_tracks.length; i <= index; i++) {
this._exp_tracks.push(null);
}
for (let i = 0; i <= this._data.Expressions.length - 1; i++) {
if(this._data.Expressions[i].Name == name){
this._exp_tracks[index] = this._data.Expressions[i];
let _LSetFlg = false; var _RSetFlg = false;
this._data.Expressions[i].Parameters.forEach( _Prm => {
if(_Prm.Id == "eyeOpenL") {
this.parent.blnk_LOpenPrm = _Prm.Value;
_LSetFlg = true;
}
if(_Prm.Id == "eyeOpenR") {
this.parent.blnk_ROpenPrm = _Prm.Value;
_RSetFlg = true;
}
});
if(!_LSetFlg) this.parent.blnk_LOpenPrm = this.parent.blnk_LBaseOpenPrm;
if(!_RSetFlg) this.parent.blnk_ROpenPrm = this.parent.blnk_RBaseOpenPrm;
}
}
}
delExpression(index) {
for (var i = this._exp_tracks.length; i <= index; i++) {
this._exp_tracks.push(null);
}
this._exp_tracks[index] = null;
}
update() {
if(this.parent._mdlAlpha == undefined) this.parent._mdlAlpha = 1;
if(this.parent._mdlAlpha < 0.00001){
return;
}
//★Live2Dのビューワーと見え方を合わせる為、時刻制御(performance.now())では無く、フレーム制御に変更
let time = 0;
switch (L2D_Mode) {
case L2D_PFSMode.Nomal:
time = performance.now() / 1000;
break;
case L2D_PFSMode.FPS30:
time = this._updateTime + (1 / 60);
break;
case L2D_PFSMode.FPS60:
time = this._updateTime + (1 / 30);
break;
}
if (this._updateTime > 0) {
let delta = time - this._updateTime;
if(L2D_Mode == L2D_PFSMode.FPS30) {
let ck_Var = Math.fround(time / delta) % 2;
if(ck_Var != 0) delta = 0;
}
this.applyAnimation(delta);
this.applyPhysics(delta);
}
this._model.update();
for (let etrack of this._exp_SetTracks) {
if(etrack == null) continue;
for (let i = 0; i <= etrack.Parameters.length - 1; i++) {
let _EditMode = etrack.Parameters[i].Blend;
let _id = etrack.Parameters[i].Id;
let _Setvalue = etrack.Parameters[i].Value;
switch(_EditMode){
case "Add":
let index = this._model.parameters.ids.indexOf(_id);
let _value = this._model.parameters.values[index];
this._model.parameters.values[index] = _value - _Setvalue;
break;
}
}
}
this._exp_SetTracks = [];
for (let etrack of this._exp_tracks) {
if(etrack == null) continue;
for (let i = 0; i <= etrack.Parameters.length - 1; i++) {
let _EditMode = etrack.Parameters[i].Blend;
let _id = etrack.Parameters[i].Id;
let _Setvalue = etrack.Parameters[i].Value;
switch(_EditMode){
case "Add":
let index = this._model.parameters.ids.indexOf(_id);
let _value = this._model.parameters.values[index];
this._model.parameters.values[index] = _value + _Setvalue;
break;
}
}
this._exp_SetTracks.push(etrack);
}
this.updateMesh();
this.refreshMask();
this._model.drawables.resetDynamicFlags();
this._updateTime = time;
if(this.NSet_ids == undefined) this.NSet_ids = [];
if(this.NSet_values == undefined) this.NSet_values = [];
for (let i = 0; i <= L2D_DelParams_Arr.length - 1; i++) {
if(L2D_DelParams_Arr[i]._modelId == this.parent._model) {
for (let j = 0; j <= L2D_DelParams_Arr[i]._ids.length - 1; j++) {
let _nSetNo = this.NSet_ids.indexOf(L2D_DelParams_Arr[i]._ids[j]);
if(_nSetNo != -1) {
this.NSet_ids.splice(_nSetNo , 1);
this.NSet_values.splice(_nSetNo , 1);
}
}
L2D_DelParams_Arr.splice(i , 1);
break;
}
}
for (let i = 0; i <= L2D_SetParams_Arr.length - 1; i++) {
if(L2D_SetParams_Arr[i]._modelId == this.parent._model) {
for (let j = 0; j <= L2D_SetParams_Arr[i]._ids.length - 1; j++) {
let _nSetNo = this.NSet_ids.indexOf(L2D_SetParams_Arr[i]._ids[j]);
if(_nSetNo != -1){
this.NSet_values[_nSetNo] = L2D_SetParams_Arr[i]._values[j];
} else {
this.NSet_ids.push(L2D_SetParams_Arr[i]._ids[j]);
this.NSet_values.push(L2D_SetParams_Arr[i]._values[j]);
}
}
L2D_SetParams_Arr.splice(i , 1);
break;
}
}
for (let i = 0; i <= this.NSet_ids.length - 1; i++) {
let _nSetNo = this._model.parameters.ids.indexOf(this.NSet_ids[i]);
if(_nSetNo != -1){
this._model.parameters.values[_nSetNo] = this.NSet_values[i];
} else {
this.NSet_ids.splice(i , 1);
this.NSet_values.splice(i , 1);
i--;
}
}
if($gameSystem.L2D_SetParams_Arr == undefined) $gameSystem.L2D_SetParams_Arr = [];
for (let i = 0; i <= $gameSystem.L2D_SetParams_Arr.length - 1; i++) {
if($gameSystem.L2D_SetParams_Arr[i]._modelId == this.parent._name){
for (let j = 0; j <= $gameSystem.L2D_SetParams_Arr[i]._ids.length - 1; j++) {
let _CkId = $gameSystem.L2D_SetParams_Arr[i]._ids[j];
let _nSetNo = this._model.parameters.ids.indexOf(_CkId);
if(_nSetNo != -1) {
this._model.parameters.values[_nSetNo] = $gameSystem.L2D_SetParams_Arr[i]._values[j];
} else {
$gameSystem.L2D_SetParams_Arr[i]._ids.splice(j , 1);
$gameSystem.L2D_SetParams_Arr[i]._values.splice(j , 1);
j--;
}
}
}
}
if(L2D_SetParamsOne_Arr == undefined) L2D_SetParamsOne_Arr = [];
for (let i = 0; i <= L2D_SetParamsOne_Arr.length - 1; i++) {
if(L2D_SetParamsOne_Arr[i]._modelId == this.parent._name){
for (let j = 0; j <= L2D_SetParamsOne_Arr[i]._ids.length - 1; j++) {
let _CkId = L2D_SetParamsOne_Arr[i]._ids[j];
let _nSetNo = this._model.parameters.ids.indexOf(_CkId);
if(_nSetNo != -1) {
this._model.parameters.values[_nSetNo] = L2D_SetParamsOne_Arr[i]._values[j];
L2D_SetParamsOne_Arr.splice(i , 1);
i--;
if(i == -1) break;
} else {
L2D_SetParamsOne_Arr[i]._ids.splice(j , 1);
L2D_SetParamsOne_Arr[i]._values.splice(j , 1);
j--;
}
}
}
}
const _bCloseFlame = 5;
const _bOpenFlame = 10;
if(this.parent.blnk_flg){
this.parent.blnk_flame--;
var _CngParaL = this.parent.blnk_LOpenPrm;
var _CngParaR = this.parent.blnk_LOpenPrm;
if(this.parent.blnk_flame < 0){
let WariMabL = this.parent.blnk_LClosePrm - this.parent.blnk_LOpenPrm;
let WariMabR = this.parent.blnk_RClosePrm - this.parent.blnk_ROpenPrm;
if (this.parent.blnk_flame >= -_bCloseFlame) {
let _Var = (-this.parent.blnk_flame);
_CngParaL = this.parent.blnk_LOpenPrm + (WariMabL * (_Var / 5));
_CngParaR = this.parent.blnk_ROpenPrm + (WariMabR * (_Var / 5));
} else if (this.parent.blnk_flame >= -(_bCloseFlame + _bOpenFlame)) {
let _Var = (-this.parent.blnk_flame) - _bCloseFlame;
_CngParaL = this.parent.blnk_LClosePrm - (WariMabL * (_Var / _bOpenFlame));
_CngParaR = this.parent.blnk_LClosePrm - (WariMabR * (_Var / _bOpenFlame));
} else if (this.parent.blnk_flame >= -16) {
if (Math.random() > 0.5 && !this.blink_dflg) {
this.parent.blnk_flame = 0;
this.blink_dflg = true;
} else {
this.parent.blnk_flame = Math.floor(Math.random() * 300 + 50);
this.blink_dflg = false;
}
}
}
if (this.parent.blnk_LIdNo != -1) {
this._model.parameters.values[this.parent.blnk_LIdNo] = _CngParaL;
}
if(this.parent.blnk_RIdNo != -1){
this._model.parameters.values[this.parent.blnk_RIdNo] = _CngParaR;
}
}
for (let i = 0; i <= this._SEParams.length - 1; i++) {
let _idNo = this._model.parameters.ids.indexOf(this._SEParams[i]._SeName);
if(_idNo == -1) {
this._SEParams.splice(i , 1);
i--; continue;
}
let _ckVar = this._model.parameters.values[_idNo];
if(!this._SEParams[i]._OnFlg) {
if(_ckVar >= 28){
this._SEParams[i]._OnFlg = true;
L2D_SePlayEvArr.push(this._SEParams[i]._SeName)
}
} else {
if(_ckVar < 28){
this._SEParams[i]._OnFlg = false;
}
}
}
for (let i = 0; i <= this._VoiceParams.length - 1; i++) {
let _idNo = this._model.parameters.ids.indexOf(this._VoiceParams[i]._VoiceName);
if(_idNo == -1) {
this._VoiceParams.splice(i , 1);
i--; continue;
}
let _ckVar = this._model.parameters.values[_idNo];
if(!this._VoiceParams[i]._OnFlg) {
if(_ckVar >= 28){
this._VoiceParams[i]._OnFlg = true;
L2D_VoicePlayEvArr.push(
[this._VoiceParams[i]._VoiceChara , this._VoiceParams[i]._VoiceName]
);
}
} else {
if(_ckVar < 28) {
this._VoiceParams[i]._OnFlg = false;
}
}
}
}
updateMesh() {
let drawables = this._model.drawables;
let vertices = drawables.vertexPositions;
let opacities = drawables.opacities;
let renderOrders = drawables.renderOrders;
let dynamicFlags = drawables.dynamicFlags;
let needsSort = false;
this._meshes.forEach((mesh, index) => {
mesh.visible = !!(dynamicFlags[index] & 0x1);
mesh.alpha = opacities[index];
mesh.orderIndex = renderOrders[index];
if (dynamicFlags[index] & 0x10) {
needsSort = true;
}
if (dynamicFlags[index] & 0x20) {
mesh.vertices = this.localVertices(vertices[index]);
}
});
if (needsSort) {
this.sortMesh();
}
}
refreshMask() {
for (let key in this._masks) {
this._masks[key].refresh();
}
}
applyPhysics(delta) {
if (this._physics) {
this._physics.apply(delta);
}
}
applyAnimation(delta) {
if (this._animation) {
this._animation.apply(delta);
}
}
snapshot() {
if (!this._animation) {
return null;
}
let parameters = {
ids: [...this._model.parameters.ids],
values: [...this._model.parameters.values]
};
let parts = {
ids: [...this._model.parts.ids],
opacities: [...this._model.parts.opacities]
};
let animation = {
tracks: [],
timeScale: this._animation.timeScale,
mixTime: {}
};
for (let key in this._animation.mixTime) {
animation.mixTime[key] = this._animation.mixTime[key];
}
this._animation.tracks.forEach((track, index) => {
let entries = [];
animation.tracks[index] = {
entries: entries,
active: track.active,
weight: track.weight
};
try {
track.entries.forEach(entry => {
entries.push({
name: entry.name,
elapsed: entry.elapsed,
loop: entry.loop,
timeScale: entry.timeScale,
weight: entry.weight,
mixTime: entry.mixTime
});
});
} catch (e) {
console.log("Live2D::TrackEntryErr");
}
});
let physics = {};
if(this._physics != null){
for (let key in this._physics.settings) {
physics[key] = [];
for (let vertex of this._physics.settings[key].vertices) {
physics[key].push({
position: {...vertex.position},
lastGravity: {...vertex.lastGravity},
velocity: {...vertex.velocity}
});
}
}
}
return {
parameters: parameters,
parts: parts,
animation: animation,
physics: physics
};
}
restore(snapshot) {
if (!snapshot) {
return;
}
let parameters = snapshot.parameters;
let parts = snapshot.parts;
let animation = snapshot.animation;
let physics = snapshot.physics;
parameters.ids.forEach((id, index) => {
let _index = this._model.parameters.ids.indexOf(id);
if (_index >= 0) {
this._model.parameters.values[_index] = parameters.values[index];
}
});
parts.ids.forEach((id, index) => {
let _index = this._model.parts.ids.indexOf(id);
if (_index >= 0) {
this._model.parts.opacities[_index] = parts.opacities[index];
}
});
this._animation.setTimeScale(animation.timeScale);
for (let key in animation.mixTime) {
if (key == 'default') {
this._animation.setDefaultMix(animation.mixTime[key]);
} else {
let [from, to] = key.split(/(?<=^[^,]+),/);
this._animation.setMix(from, to, animation.mixTime[key]);
}
}
let motions = this._animation.motions;
this._animation.tracks.splice(0);
animation.tracks.forEach((trackData, index) => {
let track = new Track(trackData.active);
track.weight = trackData.weight;
for (let entryData of trackData.entries) {
let motion = motions.find(motion => motion.name == entryData.name);
let entry = new Entry(motion, entryData.elapsed);
entry.loop = entryData.loop;
entry.timeScale = entryData.timeScale;
entry.weight = entryData.weight;
entry.mixTime = entryData.mixTime;
track.add(entry);
}
this._animation.tracks[index] = track;
});
for (let key in physics) {
if (key in this._physics.settings) {
let vertices = this._physics.settings[key].vertices;
physics[key].forEach((vertex, index) => {
if (vertices[index]) {
Object.assign(vertices[index].position, vertex.position);
Object.assign(vertices[index].lastGravity, vertex.lastGravity);
Object.assign(vertices[index].velocity, vertex.velocity);
}
});
}
}
}
}
Live2D.Mesh = Mesh;
Live2D.MaskMesh = MaskMesh;
Live2D.MeshMaskFilter = MeshMaskFilter;
Live2D.Vector2 = Vector2;
Live2D.Physics = Physics;
Live2D.Curve = Curve;
Live2D.Motion = Motion;
Live2D.Entry = Entry;
Live2D.Track = Track;
Live2D.Animation = Animation;
PIXI.Live2D = Live2D;
let Model3Parser = (function() {
let LoaderResource = PIXI.LoaderResource || PIXI.loaders.Resource;
LoaderResource.setExtensionXhrType('moc3', LoaderResource.XHR_RESPONSE_TYPE.BUFFER);
function isJson(resource) {
return resource.type == LoaderResource.TYPE.JSON;
}
function Model3Parser() {
return Model3Parser.use;
}
Model3Parser.use = function(resource, next) {
if (!isJson(resource) || !resource.data.FileReferences) {
return next();
}
let _loadFileName = resource.data.FileReferences.Moc.replace(".moc3","");
Load_TextureArr.push(new _Load_Texture(_loadFileName));
let data = resource.data;
let fileReferences = resource.data.FileReferences;
let baseUrl = resource.url.replace(/[^/]+$/, '');
let loadOption = { parentResource: resource };
let live2dData = {
Version: data.Version,
Moc: null,
Textures: [],
Physics: null,
Pose: null,
UserData: null,
Motions: null,
Expressions: null,
Groups: data.Groups,
HitAreas: data.HitAreas
};
for (let index in fileReferences) {
if (index == 'Moc') {
let url = baseUrl + fileReferences.Moc;
this.add(`${resource.name}/Moc`, url, loadOption, function (resource) {
live2dData.Moc = new Live2DCubismCore.Moc(resource.data);
next();
});
} else if (index == 'Textures') {
for (let i = 0; i < fileReferences.Textures.length; i++) {
let url = baseUrl + fileReferences.Textures[i];
if(live2dData.Texture_url == undefined) live2dData.Texture_url = [];
live2dData.Texture_url.push(url)
live2dData.Textures.push(null);
this.add(`${resource.name}/Texture_${i}`, url, loadOption, function (resource) {
var _setIndex = live2dData.Texture_url.indexOf(resource.url);
live2dData.Textures[_setIndex] = resource.texture;
next();
});
Load_TextureArr[Load_TextureArr.length - 1]._TextureCnt++;
}
} else if (['Physics', 'Pose', 'UserData'].includes(index)) {
if(fileReferences[index] != null ) {
let url = baseUrl + fileReferences[index];
this.add(`${resource.name}/${index}`, url, loadOption, function (resource) {
live2dData[index] = resource.data;
next();
});
}
} else if (index == 'Motions') {
live2dData.Motions = {};
for (let group in fileReferences.Motions) {
live2dData.Motions[group] = [];
let motion = fileReferences.Motions[group];
for (let i = 0; i < motion.length; i++) {
live2dData.Motions[group][i] = {
FadeInTime: motion[i].FadeInTime,
FadeOutTime: motion[i].FadeOutTime
};
let url = baseUrl + motion[i].File;
this.add(`${resource.name}/Motion/${group}_${i}`, url, loadOption, function (resource) {
live2dData.Motions[group][i].Group = group;
live2dData.Motions[group][i].Name = motion[i].File.replace("motions/" , "").replace(".motion3.json" , "");
//live2dData.Motions[group][i].Name = motion[i].Name || group + String(i + 1).padStart(2, '0');
live2dData.Motions[group][i].Data = resource.data;
next();
});
}
}
} else if (index == "Expressions") {
live2dData.Expressions = fileReferences.Expressions;
for (let i = 0; i < live2dData.Expressions.length; i++) {
live2dData.Expressions[i].Parameters = [];
let url = baseUrl + live2dData.Expressions[i].File;
let ename = live2dData.Expressions[i].Name;
this.add(`${resource.name}/Expression/${ename}`, url, loadOption, function (resource) {
live2dData.Expressions.forEach( _EXP => {
var _ckStrArr = resource.name.split('/');
if(_EXP.Name == _ckStrArr[_ckStrArr.length - 1]) _EXP.Parameters = resource.data.Parameters;
});
next();
});
}
}
}
resource.live2dData = live2dData;
next();
};
return Model3Parser;
})();
if (PIXI.Loader) {
PIXI.Loader.registerPlugin(Model3Parser);
} else {
PIXI.loaders.Loader.addPixiMiddleware(Model3Parser);
}
}();