/*:
 * @plugindesc 
 * @author 奏ねこま（おとぶきねこま）
 * @url http://makonet.sakura.ne.jp/rpg_tkool
 * @target MZ
 *
 * @param json file
 * @type string[]
 * @default []
 * @desc Live2Dファイル(*.model3.json)
 *
 * @param disable auto loading
 * @type boolean
 * @default false
 * @desc Live2Dの自動読み込みを無効にする
 *
 * @param Speed Load Live2D Model
 * @type string[]
 * @default []
 * @desc ロードを優先するモデルの指定
 *
 * @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('JsScript190Set'));
let $p = (p => ({
    'json file': eval(p['json file']),
    'Speed Load Live2D Model': eval(p['Speed Load Live2D Model']),
    'live2d data': {}
}))(PluginManager.parameters('JsScript190Set'));
let mainLoadMdlSetting = []; 
let subLoadMdlSetting = [];  
function addModelsToLoader(loader, modelSettings) {
    for (let file of modelSettings) {
        let fileName = file._MdlName + "/" + file._MdlName;
        let name = fileName.replace(/\.(?:json|model3.json)$/i, '');
        loader.add(name, `img/live2d/${name}.model3.json`);
    }
}
function addModels(modelSettings) {
    for (let file of modelSettings) {
        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;
    }
}
function handleLoaderCompletion(loader, modelSettings, callback) {
    loader.load((loader, resources) => {
        for (let name in $p['live2d data']) {
            if (resources[name] == undefined) continue;
            $p['live2d data'][name] = resources[name].live2dData;
            Live2D_JsonKeep['live2d data'][name] = resources[name].live2dData;
        }
        callback();
    });
}
let Live2DSubCounter = 0;
let Live2DSubLoading = false;
let Live2D_NUpdateSc = Game_Interpreter.prototype.NUpdateSc;
Game_Interpreter.prototype.NUpdateSc = function () {
    Live2D_NUpdateSc.call(this);
    if (Live2DFirstLoadCompFlg) {
        if (Live2DSubCounter < subLoadMdlSetting.length && !Live2DSubLoading) {
            let loader2 = new (PIXI.Loader || PIXI.loaders.Loader)();
            let subArr = [];
            let exitCnt = 0;
            for (let i = Live2DSubCounter; i < subLoadMdlSetting.length; i++) {
                subArr.push(subLoadMdlSetting[i]);
                exitCnt++;
                Live2DSubCounter++;
                if (exitCnt >= 5) break;
            }
            Live2DSubLoading = true;
            addModelsToLoader(loader2, subArr);
            handleLoaderCompletion(loader2, subArr, () => {
                Live2DSubLoading = false;
            });
        }
    }
}
let Live2DFirstLoadCompFlg = false;
!function () {
    function load() {
        modelSetting = [];
        for (let i = 0; i < $Live2dSettingData.modelSetting.length; i++) {
            let setData = $Live2dSettingData.modelSetting[i];
            modelSetting.push(
                new _L2dDtlSet(setData.MdlFile , setData.ViewName , setData.FirstLoadFlg ,
                    setData.ZureX , setData.ZureY , setData.VoiceDirName)
            );
        }
        console.log("PictureLive2DLoad開始！！！");
        let speedLoadModels = $p['Speed Load Live2D Model'];
        for (let i = 0; i < modelSetting.length; i++) {
            let mainFlg = false;
            for (let j = 0; j < speedLoadModels.length; j++) {
                if (modelSetting[i]._MdlName == speedLoadModels[j]) {
                    mainFlg = true;
                    break;
                }
            }
            if (mainFlg) mainLoadMdlSetting.push(modelSetting[i]);
            else subLoadMdlSetting.push(modelSetting[i]);
        }
        addModels(mainLoadMdlSetting);
        addModels(subLoadMdlSetting);
        console.log("Live2D：１次ロード開始");
        let loader = new (PIXI.Loader || PIXI.loaders.Loader)();
        addModelsToLoader(loader, mainLoadMdlSetting);
        handleLoaderCompletion(loader, mainLoadMdlSetting, () => {
            Live2DFirstLoadCompFlg = true;
            console.log("Live2D：２次ロード開始");
        });
    }
    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() {
            if (!isFinite(this._updateTime) || this._updateTime < 0) {
                this._updateTime = 0;
            }
            let live2d = this.live2d();
            this.updateModel(live2d);
            let ckData = this._data;
            if (!ckData || !ckData._model || !ckData._model.parameters || !ckData._model.parameters.ids) return;
            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;
                        if (!_ckModel || !_ckModel.parameters || !_ckModel.parameters.ids) return; 
                        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) {
    console.log("SetSpriteLive2D::" + _MdlName);
    _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 () {
    class MultiplyScreenFilter extends PIXI.Filter {
        constructor(multiplyColor, screenColor) {
            let fragment = 'varying vec2 vTextureCoord;uniform sampler2D uSampler;uniform vec3 multiplyColor;uniform vec3 screenColor;void main(void){vec4 color=texture2D(uSampler, vTextureCoord);color.rgb*=multiplyColor;color.rgb=color.rgb+screenColor*color.a-color.rgb*screenColor;gl_FragColor=color;}';
            super(null, fragment);
            this.uniforms.multiplyColor = multiplyColor;
            this.uniforms.screenColor = screenColor;
        }
        get enabled() {
            return this.uniforms.multiplyColor.some(value => value != 1)
                || this.uniforms.screenColor.some(value => value != 0);
        }
        set enabled(value) { }
    }
    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.shader = {};
                this.texture.baseTexture.resource = {
                    source: this.texture.baseTexture.source
                };
                Object.defineProperty(this.state, 'blendMode', {
                    set: value => this.blendMode = value
                });
            }
        }
    }
    if (!PIXI.filters.VoidFilter) {
        PIXI.filters.VoidFilter = PIXI.filters.AlphaFilter;
    }
    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;
        }
        _render(renderer) {
            if (!this.state.culling) {
                super._render(renderer);
                return;
            }
            let gl = renderer.gl;
            gl.frontFace(gl.getParameter(gl.FRAMEBUFFER_BINDING) ? gl.CW : gl.CCW);
            super._render(renderer);
            gl.frontFace(gl.CCW);
        }
        _renderWebGL(renderer) {
            if (!this.state.culling) {
                super._renderWebGL(renderer);
                return;
            }
            let gl = renderer.gl;
            gl.enable(gl.CULL_FACE);
            gl.frontFace(gl.getParameter(gl.FRAMEBUFFER_BINDING) ? gl.CW : gl.CCW);
            super._renderWebGL(renderer);
            gl.frontFace(gl.CCW);
            gl.disable(gl.CULL_FACE);
        }
    }
    class CopyMesh extends Mesh {
        constructor(mesh) {
            super(mesh.texture, mesh.vertices, mesh.uvs, mesh.indices, mesh.drawMode);
            this.state  = mesh.state;
            this.shader = mesh.shader;
            this._mesh = mesh;
        }
        update() {
            this.vertices = this._mesh.vertices;
        }
    }
    class MaskMesh extends CopyMesh {
        constructor(mesh) {
            super(mesh);
            this.maskTexture = null;
            this.texturePool = {};
            this.orderIndex = -Infinity;
            this.setup();
        }
        setup() {
            this.maskTexture = new PIXI.Texture(new PIXI.BaseTexture());
            this.maskTexture.baseTexture.valid = true;
            let filter = new PIXI.filters.VoidFilter();
            filter.apply = this.apply.bind(this);
            this.filters = [filter, new PIXI.filters.VoidFilter()];
        }
        render(renderer) {
            let pool = renderer.filter.texturePool.texturePool;
            renderer.filter.texturePool.texturePool = this.texturePool;
            super.render(renderer);
            renderer.filter.texturePool.texturePool = pool;
        }
        renderWebGL(renderer) {
            let pool = renderer.filterManager.pool;
            renderer.filterManager.pool = this.texturePool;
            super.renderWebGL(renderer);
            renderer.filterManager.pool = pool;
        }
        apply(filterManager, input, output, clear, currentState) {
            let gl = filterManager.renderer.gl;
            let uid = filterManager.renderer.CONTEXT_UID;
            let frame = {}, size = {};
            let texture;
            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;
                texture = input.baseTexture._glTextures[uid].texture;
            } 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;
                texture = input.texture.texture;
            }
            this.maskTexture.baseTexture._glTextures[uid] = {dirtyId: 0, texture: texture};
            this.maskTexture.maskInfo = { frame: frame, size: size };
        }
        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) {
            if (!physics || !physics.Meta || !physics.PhysicsSettings) {
                this._settings = this._settings || {};
                return;
            }
            const parameters = this._parameters || {};
            const ids = Array.isArray(parameters.ids) ? parameters.ids : [];
            const dictionary = (physics.Meta && Array.isArray(physics.Meta.PhysicsDictionary))
                ? physics.Meta.PhysicsDictionary
                : [];
            let settings = [];
            try {
                settings = JSON.parse(
                    JSON.stringify(physics.PhysicsSettings).replace(
                        /"[^"]+(?=":)/g,
                        m => '"' + m[1].toLowerCase() + m.slice(2)
                    )
                );
                if (!Array.isArray(settings)) settings = [];
            } catch (e) {
                settings = [];
            }
            this._settings = this._settings || {};
            for (let setting of settings) {
                if (!setting) continue;
                const id = setting.id;
                delete setting.id;
                const dictItem = dictionary.find(item => item && item.Id == id);
                setting.name = (dictItem || { Name: '' }).Name;
                const inputs = Array.isArray(setting.input) ? setting.input : [];
                for (let input of inputs) {
                    if (!input || !input.source) continue;
                    const srcId = input.source.id;
                    input.source.index = ids.indexOf(srcId);
                }
                const outputs = Array.isArray(setting.output) ? setting.output : [];
                for (let output of outputs) {
                    if (!output || !output.destination) continue;
                    const dstId = output.destination.id;
                    output.destination.index = ids.indexOf(dstId);
                }
                const vertices = Array.isArray(setting.vertices) ? setting.vertices : [];
                for (let vertex of vertices) {
                    if (!vertex || !vertex.position) continue;
                    vertex.position = new Vector2(vertex.position.x, vertex.position.y);
                    vertex.lastGravity = new Vector2(0, 1);
                    vertex.velocity = new Vector2();
                }
                if (id == null) continue;
                this._settings[id] = setting;
            }
            // let settings = JSON.parse(JSON.stringify(physics.PhysicsSettings).replace(/"[^"]+(?=":)/g, m => '"' + m[1].toLowerCase() + m.slice(2)));
            // for (let setting of settings) {
            //     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();
        }
        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;
                    if (vertexIndex < 1 || vertexIndex >= vertices.length) {
                        continue;
                    }
                    translation = {
                        x: vertices[vertexIndex].position.x - vertices[vertexIndex - 1].position.x,
                        y: vertices[vertexIndex].position.y - vertices[vertexIndex - 1].position.y
                    };
                    let gravity   = vertexIndex > 1 ? vertices[vertexIndex - 1].position.substract(vertices[vertexIndex - 2].position) : new Vector2(0, 1);
                    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) {
            if (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._baseName = motion.BaseName;
                this._fadeInTime = motion.FadeInTime;
                this._fadeOutTime = motion.FadeOutTime;
                this._sound = motion.Sound;
                this._curves = [];
                this.createCurve(motion.Data.Curves, this._beziersRestricted);
            } else {
                this._duration = 0;
                this._loop = false;
                this._beziersRestricted = false;
                this._group = '';
                this._name = '';
                this._baseName = '';
                this._fadeInTime = 0;
                this._fadeOutTime = 0;
                this._sound = '';
                this._curves = [];
            }
        }
        get duration() {
            return this._duration;
        }
        get group() {
            return this._group;
        };
        get name() {
            return this._name;
        };
        get baseName() {
            return this._baseName;
        }
        get sound() {
            return this._sound;
        }
        createCurve(curves, beziersRestricted) {
            this._curves = curves.map(curve => new Curve(curve, beziersRestricted));
        }
        fadeWeight(value) {
            return 0.5 - 0.5 * Math.cos(value * Math.PI);
        }
        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 ? this.fadeWeight(time / fadeInTime) : 1;
                let fadeOutWeight = remain < fadeOutTime ? this.fadeWeight(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;
            this.endTime   = 0;
        }
        get name() { return this._motion.name; }
        get duration() { return this.endTime || this._motion.duration; }
        get elapsed() { return this._elapsed; }
        get remain() { return this.duration - this._elapsed; }
        get sound() { return this._motion.sound; }
        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, mixing = false) {
            this._entries = [];
            this._active = active;
            this._mixing = mixing;
            this._history = [];
            this.weight = 1;
        }
        get entries() { return this._entries; }
        get active() { return this._active; }
        get mixing() { return this._mixing; }
        get history() { return this._history.shift(); }
        add(entry) {
            let last = this.entry(-1);
            if (last) {
                last.loop = false;
                if (last.endTime > 0) {
                    last.endTime += entry.mixTime;
                }
            }
            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 v0 = values[target][id];
                        let v1 = next_values[target][id];
                        value  = v0.value * r0 + v1.value * r1;
                        weight = v0.weight * r0 + v1.weight * r1;
                    } else {
                        let v = next_values[target][id];
                        value  = v.value;
                        weight = v.weight * r1;
                    }
                    values[target] = values[target] || {};
                    values[target][id] = { value: value, weight: weight };
                }
            }
            for (let target in values) {
                for (let id in values[target]) {
                    if (!next_values[target] || !next_values[target][id]) {
                        values[target][id].weight *= r0;
                    }
                }
            }
        }
        suspend() {
            if (!this.active) {
                return;
            }
            let entry = this._entries[0];
            entry.endTime = entry.elapsed;
            entry.loop = false;
            this._entries.splice(1);
        }
        values(delta) {
            try {
                let entry = this._entries[0];
                let next_entry = this._entries[1];
                if (!entry) {
                    return null;
                }
                if (!this._active) {
                    delta = 0;
                    this._history.push({ start: entry });
                }
                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);
                        if (!this._mixing) {
                            this._history.push({ start: next_entry });
                            this._mixing = true;
                        }
                    }
                } else {
                    this._entries.shift();
                    this._history.push({ end: entry });
                    if (next_entry) {
                        delta = -remain / entry.timeScale;
                        values = next_entry.values(delta);
                        if (!this._mixing) {
                            this._history.push({ start: next_entry });
                        }
                    }
                    this._mixing = false;
                }
                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.suspend();
            }
            return this.addAnimation(index, name, loop);
        }
        addAnimation(index, name, loop) {
            let motion = this._motions.find(motion => [motion.name, motion.baseName].includes(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;
        }
        clearAnimation(index, mixTime = 0) {
            let track = this._tracks[index];
            if (!track) {
                return;
            }
            track.suspend();
            let entry = new Entry(new Motion());
            entry.mixTime = mixTime;
            track.add(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, index, track, entry) {
            if (this._listeners[event]) {
                let trackInfo = { index: index, track: track, entry: entry };
                this._listeners[event].forEach(callback => callback(trackInfo));
            }
        }
        apply(delta) {
            delta *= this._timeScale;
            let parameters = this._parameters;
            if (!parameters || !parameters.ids) return;
            let parts = this._parts;
            for (let track of this._tracks) {
                if (track == null) continue; 
                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);
                for (let history; history = track.history;) {
                    let event = history.start ? 'start' : 'end';
                    let entry = history.start || history.end;
                    this.callListener(event, index, track, entry);
                    if (event == 'end' && track.entries.length > 0) {
                        let _entry = track.entries[0];
                        try {
                            if(_entry._motion._name.indexOf("wait") == -1 && _entry._motion._name.indexOf("Wait")) {
                                Motion_EyeSetting(this.parent.parent._name, _entry._motion._name);
                            } else {
                                console.log("waitモーションは瞬き設定をさせない");
                            }
                        } catch (e) {
                            console.log("モーション設定失敗");
                        }
                    }
                }
            }
        }
    }
    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]._VoiceFol == "") {
                        this._SEParams.push(new _SeParam(seSetting[i]._SeName));
                    } else {
                        this._VoiceParams.push(
                            new _VoiceParams(seSetting[i]._VoiceFol, seSetting[i]._SeName)
                        );
                    }
                }
            }
            this._CmnParams = [];
            (function () {
                var self = this;
                var maxAttempts = 10;
                var intervalMs = 100; 
                var attempt = 0;
                function hasModelParamsIds() {
                    return !!(self._model &&　self._model.parameters &&　Array.isArray(self._model.parameters.ids));
                }
                function waitForModelLoaded() {
                    if (hasModelParamsIds() || attempt >= maxAttempts) {
                        onReadyOrGiveUp(); 
                        return;
                    }
                    attempt++;
                    console.log("モデルロード待機処理...：" + attempt);
                    setTimeout(waitForModelLoaded, intervalMs);
                }
                function onReadyOrGiveUp() {
                    if (!hasModelParamsIds()) {
                        console.log("モデルロードの失敗");
                        return; 
                    }
                    var ids = self._model.parameters.ids;
                    for (var i = 0; i < ids.length; i++) {
                        var id = ids[i];
                        if (id.indexOf("CmnEv_") !== -1) {
                            var cmnNo = id.replace("CmnEv_", "");
                            self._CmnParams.push(new _CmnEvParam(Number(cmnNo)));
                        }
                    }
                    if ($gameSystem.L2D_SetParams_Arr === undefined) $gameSystem.L2D_SetParams_Arr = [];
                    for (var a = 0; a < $gameSystem.L2D_SetParams_Arr.length; a++) {
                        var item = $gameSystem.L2D_SetParams_Arr[a];
                        if (item._modelId == self._data.name) {
                            for (var j = 0; j < item._ids.length; j++) {
                                var ckId = item._ids[j];
                                var setIndex = ids.indexOf(ckId);
                                if (setIndex !== -1) {
                                    self._model.parameters.values[setIndex] = item._values[j];
                                } else {
                                    item._ids.splice(j, 1);
                                    item._values.splice(j, 1);
                                    j--;
                                }
                            }
                        }
                    }
                }
                waitForModelLoaded();
            }).call(this);
            // if (!this._model?.parameters?.ids) return;
            // 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 _nSetNo = this._model.parameters.ids.indexOf(_CkId);
            //             if (_nSetNo != -1) {
            //                 $gameSystem.L2D_SetParams_Arr[i]._ids.splice(j, 1);
            //                 $gameSystem.L2D_SetParams_Arr[i]._values.splice(j, 1);
        }
        get model() {
            return this._model;
        }
        get animation() {
            return this._animation;
        }
        createMesh() {
            if (this._meshes && this._meshes.length) return;
            if (!this._model || !this._model.drawables) {
                this._createMeshRetries = (this._createMeshRetries || 0) + 1;
                if (this._createMeshRetries <= 6) {
                    const delay = Math.min(200 * Math.pow(2, this._createMeshRetries - 1), 2000);
                    console.warn(`Live2D.createMesh: drawables undefined for model ${this._data && this._data.name}, retry #${this._createMeshRetries} in ${delay}ms`);
                    setTimeout(() => {
                        if (this._data) this.createMesh();
                    }, delay);
                } else {
                    console.error(`Live2D.createMesh: drawables still undefined after retries for ${this._data && this._data.name}`);
                }
                return;
            }
            if (!this._model || !this._model.drawables) {
                console.warn(`Live2D.createMesh: drawables is undefined for model ${this._data && this._data.name}`);
                return;
            }
            let drawables = this._model.drawables;
            if (drawables.count != undefined) {
                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];
                    }
                    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];
                    if (mesh.state.culling) {
                        mesh.shader.batchable = false;
                    }
                    mesh.filters = [new MultiplyScreenFilter(
                        drawables.multiplyColors.slice(i * 4, i * 4 + 3),
                        drawables.screenColors.slice(i * 4, i * 4 + 3)
                    )];
                    this._meshes.push(mesh);
                    this.addChild(mesh);
                }
            }
            this.sortMesh();
        }
        createMask() {
            if (!this._model || !this._model.drawables) {
                this._createMaskRetries = (this._createMaskRetries || 0) + 1;
                if (this._createMaskRetries <= 6) {
                    const delay = Math.min(200 * Math.pow(2, this._createMaskRetries - 1), 2000);
                    console.warn(
                        `Live2D.createMask: drawables undefined for model ${this._data && this._data.name}, retry #${this._createMaskRetries} in ${delay}ms`
                    );
                    setTimeout(() => {
                        if (this._data) this.createMask();
                    }, delay);
                } else {
                    console.error(
                        `Live2D.createMask: drawables still undefined after retries for ${this._data && this._data.name}`
                    );
                }
                return;
            }
            if (!this._model || !this._model.drawables) {
                console.warn(`Live2D.createMask: drawables is undefined for model ${this._data && this._data.name}`);
                return;
            }
            let drawables = this._model.drawables;
            if (drawables.count != undefined) {
                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, container) {
            let canvasinfo = this._model.canvasinfo;
            let cox = canvasinfo.CanvasOriginX;
            let coy = canvasinfo.CanvasOriginY;
            let ppu = canvasinfo.PixelsPerUnit;
            let result = container || new Float32Array(vertices.length);
            for (let i = 0; i < vertices.length; i++) {
                result[i] = i % 2 ?  coy - vertices[i] * ppu : vertices[i] * ppu + cox;
            }
            return result;
        }
        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) {
                this._updateTime = time;
                return;
            }
            let delta = time - this._updateTime;
            if (!isFinite(delta) || delta <= 0 || delta > 1) {
                delta = 1 / 60;
            }
            if (L2D_Mode == L2D_PFSMode.FPS30) {
                this._fps30Counter = (this._fps30Counter || 0) + 1;
                if (this._fps30Counter % 2 !== 0) {
                    delta = 0;
                }
            }
            this.applyAnimation(delta);
            this.applyPhysics(delta);
            this._model.drawables.resetDynamicFlags();
            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); 
            }
            if ($gameSwitches.value(DownFpsSwt)) {
                if (this.donwUpdateFlame == 0) {
                    this.updateMesh();
                    this.updateMask();
                    this.donwUpdateFlame = 1;
                } else {
                    if (this.donwUpdateFlame == undefined) this.donwUpdateFlame = 5;
                    this.donwUpdateFlame--;
                }
            } else {
                this.updateMesh();
                this.updateMask();
            }
            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_ROpenPrm; 
                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_LOpenPrm > this.parent.blnk_LClosePrm) this.parent.blnk_LClosePrm = this.parent.blnk_LOpenPrm;
                    if (this.parent.blnk_ROpenPrm > this.parent.blnk_RClosePrm) 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_RClosePrm - (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) {
                    this.localVertices(vertices[index], mesh.vertices);
                }
                if (mesh.visible) {
                    let uniforms = mesh.filters.find(filter => filter instanceof MultiplyScreenFilter).uniforms;
                    uniforms.multiplyColor = drawables.multiplyColors.slice(index * 4, index * 4 + 3);
                    uniforms.screenColor   = drawables.screenColors.slice(index * 4, index * 4 + 3);
                }
            });
            if (needsSort) {
                this.sortMesh();
            }
        }
        updateMask() {
            for (let key in this._masks) {
                this._masks[key].update();
            }
        }
        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,
                    mixing: track.mixing,
                    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,
                            endTime: entry.endTime
                        });
                    });
                } 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, trackData.mixing);
                track.weight = trackData.weight;
                for (let entryData of trackData.entries) {
                    let motion = entryData.name ? motions.find(motion => motion.name == entryData.name) : new Motion();
                    let entry = new Entry(motion, entryData.elapsed);
                    entry.loop = entryData.loop;
                    entry.timeScale = entryData.timeScale;
                    entry.weight = entryData.weight;
                    entry.mixTime = entryData.mixTime;
                    entry.endTime = entryData.endTime;
                    track.entries.push(entry);
                }
                this._animation.tracks[index] = track;
            });
            if (this._physics && physics) {
                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.CopyMesh = CopyMesh;
    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);
    }
}();
