/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. */ import { Live2DCubismFramework as live2dcubismframework } from '../Framework/src/live2dcubismframework'; import { Live2DCubismFramework as cubismid } from '../Framework/src/id/cubismid'; import { Live2DCubismFramework as cubismusermodel } from '../Framework/src/model/cubismusermodel'; import { Live2DCubismFramework as icubismmodelsetting } from '../Framework/src/icubismmodelsetting'; import { Live2DCubismFramework as cubismmodelsettingjson } from '../Framework/src/cubismmodelsettingjson'; import { Live2DCubismFramework as cubismdefaultparameterid } from '../Framework/src/cubismdefaultparameterid'; import { Live2DCubismFramework as acubismmotion } from '../Framework/src/motion/acubismmotion'; import { Live2DCubismFramework as cubismeyeblink } from '../Framework/src/effect/cubismeyeblink'; import { Live2DCubismFramework as cubismbreath } from '../Framework/src/effect/cubismbreath'; import { Live2DCubismFramework as csmvector } from '../Framework/src/type/csmvector'; import { Live2DCubismFramework as csmmap } from '../Framework/src/type/csmmap'; import { Live2DCubismFramework as cubismmatrix44 } from '../Framework/src/math/cubismmatrix44'; import { Live2DCubismFramework as cubismmotion } from '../Framework/src/motion/cubismmotion'; import { Live2DCubismFramework as cubismmotionqueuemanager } from '../Framework/src/motion/cubismmotionqueuemanager'; import { Live2DCubismFramework as csmstring } from '../Framework/src/type/csmstring'; import { Live2DCubismFramework as csmrect } from '../Framework/src/type/csmrectf'; import { CubismLogInfo } from '../Framework/src/utils/cubismdebug'; import csmRect = csmrect.csmRect; import csmString = csmstring.csmString; import InvalidMotionQueueEntryHandleValue = cubismmotionqueuemanager.InvalidMotionQueueEntryHandleValue; import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle; import CubismMotion = cubismmotion.CubismMotion; import CubismMatrix44 = cubismmatrix44.CubismMatrix44; import csmMap = csmmap.csmMap; import csmVector = csmvector.csmVector; import CubismBreath = cubismbreath.CubismBreath; import BreathParameterData = cubismbreath.BreathParameterData; import CubismEyeBlink = cubismeyeblink.CubismEyeBlink; import ACubismMotion = acubismmotion.ACubismMotion; import FinishedMotionCallback = acubismmotion.FinishedMotionCallback; import CubismFramework = live2dcubismframework.CubismFramework; import CubismIdHandle = cubismid.CubismIdHandle; import CubismUserModel = cubismusermodel.CubismUserModel; import ICubismModelSetting = icubismmodelsetting.ICubismModelSetting; import CubismModelSettingJson = cubismmodelsettingjson.CubismModelSettingJson; import CubismDefaultParameterId = cubismdefaultparameterid; import { LAppPal } from './lapppal'; import { gl, canvas, frameBuffer, LAppDelegate } from './lappdelegate'; import { TextureInfo } from './lapptexturemanager'; import * as LAppDefine from './lappdefine'; import 'whatwg-fetch'; enum LoadStep { LoadAssets, LoadModel, WaitLoadModel, LoadExpression, WaitLoadExpression, LoadPhysics, WaitLoadPhysics, LoadPose, WaitLoadPose, SetupEyeBlink, SetupBreath, LoadUserData, WaitLoadUserData, SetupEyeBlinkIds, SetupLipSyncIds, SetupLayout, LoadMotion, WaitLoadMotion, CompleteInitialize, CompleteSetupModel, LoadTexture, WaitLoadTexture, CompleteSetup } /** * ユーザーが実際に使用するモデルの実装クラス
* モデル生成、機能コンポーネント生成、更新処理とレンダリングの呼び出しを行う。 */ export class LAppModel extends CubismUserModel { /** * model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する * @param dir * @param fileName */ public loadAssets(dir: string, fileName: string): void { console.log('资源路径',dir) this._modelHomeDir = dir; fetch(`${this._modelHomeDir}${fileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { const setting: ICubismModelSetting = new CubismModelSettingJson( arrayBuffer, arrayBuffer.byteLength ); // ステートを更新 this._state = LoadStep.LoadModel; // 結果を保存 this.setupModel(setting); }); } /** * model3.jsonからモデルを生成する。 * model3.jsonの記述に従ってモデル生成、モーション、物理演算などのコンポーネント生成を行う。 * * @param setting ICubismModelSettingのインスタンス */ private setupModel(setting: ICubismModelSetting): void { this._updating = true; this._initialized = false; this._modelSetting = setting; // CubismModel if (this._modelSetting.getModelFileName() != '') { const modelFileName = this._modelSetting.getModelFileName(); fetch(`${this._modelHomeDir}${modelFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { this.loadModel(arrayBuffer); this._state = LoadStep.LoadExpression; // callback loadCubismExpression(); }); this._state = LoadStep.WaitLoadModel; } else { LAppPal.printMessage('Model data does not exist.'); } // Expression const loadCubismExpression = (): void => { if (this._modelSetting.getExpressionCount() > 0) { const count: number = this._modelSetting.getExpressionCount(); for (let i = 0; i < count; i++) { const expressionName = this._modelSetting.getExpressionName(i); const expressionFileName = this._modelSetting.getExpressionFileName( i ); fetch(`${this._modelHomeDir}${expressionFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { const motion: ACubismMotion = this.loadExpression( arrayBuffer, arrayBuffer.byteLength, expressionName ); if (this._expressions.getValue(expressionName) != null) { ACubismMotion.delete( this._expressions.getValue(expressionName) ); this._expressions.setValue(expressionName, null); } this._expressions.setValue(expressionName, motion); this._expressionCount++; if (this._expressionCount >= count) { this._state = LoadStep.LoadPhysics; // callback loadCubismPhysics(); } }); } this._state = LoadStep.WaitLoadExpression; } else { this._state = LoadStep.LoadPhysics; // callback loadCubismPhysics(); } }; // Physics const loadCubismPhysics = (): void => { if (this._modelSetting.getPhysicsFileName() != '') { const physicsFileName = this._modelSetting.getPhysicsFileName(); fetch(`${this._modelHomeDir}${physicsFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { this.loadPhysics(arrayBuffer, arrayBuffer.byteLength); this._state = LoadStep.LoadPose; // callback loadCubismPose(); }); this._state = LoadStep.WaitLoadPhysics; } else { this._state = LoadStep.LoadPose; // callback loadCubismPose(); } }; // Pose const loadCubismPose = (): void => { if (this._modelSetting.getPoseFileName() != '') { const poseFileName = this._modelSetting.getPoseFileName(); fetch(`${this._modelHomeDir}${poseFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { this.loadPose(arrayBuffer, arrayBuffer.byteLength); this._state = LoadStep.SetupEyeBlink; // callback setupEyeBlink(); }); this._state = LoadStep.WaitLoadPose; } else { this._state = LoadStep.SetupEyeBlink; // callback setupEyeBlink(); } }; // EyeBlink const setupEyeBlink = (): void => { if (this._modelSetting.getEyeBlinkParameterCount() > 0) { this._eyeBlink = CubismEyeBlink.create(this._modelSetting); this._state = LoadStep.SetupBreath; } // callback setupBreath(); }; // Breath const setupBreath = (): void => { this._breath = CubismBreath.create(); const breathParameters: csmVector = new csmVector(); breathParameters.pushBack( new BreathParameterData(this._idParamAngleX, 0.0, 15.0, 6.5345, 0.5) ); breathParameters.pushBack( new BreathParameterData(this._idParamAngleY, 0.0, 8.0, 3.5345, 0.5) ); breathParameters.pushBack( new BreathParameterData(this._idParamAngleZ, 0.0, 10.0, 5.5345, 0.5) ); breathParameters.pushBack( new BreathParameterData(this._idParamBodyAngleX, 0.0, 4.0, 15.5345, 0.5) ); breathParameters.pushBack( new BreathParameterData( CubismFramework.getIdManager().getId( CubismDefaultParameterId.ParamBreath ), 0.0, 0.5, 3.2345, 0.5 ) ); this._breath.setParameters(breathParameters); this._state = LoadStep.LoadUserData; // callback loadUserData(); }; // UserData const loadUserData = (): void => { if (this._modelSetting.getUserDataFile() != '') { const userDataFile = this._modelSetting.getUserDataFile(); fetch(`${this._modelHomeDir}${userDataFile}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { this.loadUserData(arrayBuffer, arrayBuffer.byteLength); this._state = LoadStep.SetupEyeBlinkIds; // callback setupEyeBlinkIds(); }); this._state = LoadStep.WaitLoadUserData; } else { this._state = LoadStep.SetupEyeBlinkIds; // callback setupEyeBlinkIds(); } }; // EyeBlinkIds const setupEyeBlinkIds = (): void => { const eyeBlinkIdCount: number = this._modelSetting.getEyeBlinkParameterCount(); for (let i = 0; i < eyeBlinkIdCount; ++i) { this._eyeBlinkIds.pushBack( this._modelSetting.getEyeBlinkParameterId(i) ); } this._state = LoadStep.SetupLipSyncIds; // callback setupLipSyncIds(); }; // LipSyncIds const setupLipSyncIds = (): void => { const lipSyncIdCount = this._modelSetting.getLipSyncParameterCount(); for (let i = 0; i < lipSyncIdCount; ++i) { this._lipSyncIds.pushBack(this._modelSetting.getLipSyncParameterId(i)); } this._state = LoadStep.SetupLayout; // callback setupLayout(); }; // Layout const setupLayout = (): void => { const layout: csmMap = new csmMap(); this._modelSetting.getLayoutMap(layout); this._modelMatrix.setupFromLayout(layout); this._state = LoadStep.LoadMotion; // callback loadCubismMotion(); }; // Motion const loadCubismMotion = (): void => { document.getElementById('live2d-hidden').style.display='block' this._state = LoadStep.WaitLoadMotion; this._model.saveParameters(); this._allMotionCount = 0; this._motionCount = 0; const group: string[] = []; const motionGroupCount: number = this._modelSetting.getMotionGroupCount(); // モーションの総数を求める for (let i = 0; i < motionGroupCount; i++) { group[i] = this._modelSetting.getMotionGroupName(i); this._allMotionCount += this._modelSetting.getMotionCount(group[i]); } // モーションの読み込み // 装入动作 for (let i = 0; i < motionGroupCount; i++) { this.preLoadMotionGroup(group[i]); } // モーションがない場合 if (motionGroupCount == 0) { this._state = LoadStep.LoadTexture; // 全てのモーションを停止する this._motionManager.stopAllMotions(); this._updating = false; this._initialized = true; this.createRenderer(); this.setupTextures(); this.getRenderer().startUp(gl); } }; } /** * テクスチャユニットにテクスチャをロードする */ private setupTextures(): void { // iPhoneでのアルファ品質向上のためTypescriptではpremultipliedAlphaを採用 const usePremultiply = true; if (this._state == LoadStep.LoadTexture) { // テクスチャ読み込み用 const textureCount: number = this._modelSetting.getTextureCount(); for ( let modelTextureNumber = 0; modelTextureNumber < textureCount; modelTextureNumber++ ) { // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ if (this._modelSetting.getTextureFileName(modelTextureNumber) == '') { continue; } // WebGLのテクスチャユニットにテクスチャをロードする // 在WebGL的纹理单元中加载纹理 let texturePath = this._modelSetting.getTextureFileName( modelTextureNumber ); texturePath = this._modelHomeDir + texturePath; // ロード完了時に呼び出すコールバック関数 // 加载完成时调用的回调函数 const onLoad = (textureInfo: TextureInfo): void => { this.getRenderer().bindTexture(modelTextureNumber, textureInfo.id); this._textureCount++; if (this._textureCount >= textureCount) { // ロード完了 this._state = LoadStep.CompleteSetup; } }; // 読み込み LAppDelegate.getInstance() .getTextureManager() .createTextureFromPngFile(texturePath, usePremultiply, onLoad); this.getRenderer().setIsPremultipliedAlpha(usePremultiply); } this._state = LoadStep.WaitLoadTexture; } } /** * レンダラを再構築する */ public reloadRenderer(): void { this.deleteRenderer(); this.createRenderer(); this.setupTextures(); } /** * 更新 */ public update(): void { if (this._state != LoadStep.CompleteSetup) return; const deltaTimeSeconds: number = LAppPal.getDeltaTime(); this._userTimeSeconds += deltaTimeSeconds; this._dragManager.update(deltaTimeSeconds); this._dragX = this._dragManager.getX(); this._dragY = this._dragManager.getY(); // モーションによるパラメータ更新の有無 let motionUpdated = false; //-------------------------------------------------------------------------- this._model.loadParameters(); // 前回セーブされた状態をロード if (this._motionManager.isFinished()) { this.startRandomMotion( LAppDefine.MotionGroupIdle, LAppDefine.PriorityIdle ); // 在没有动作的运行的情况下,从待机动作中随机运行抽取,命运抽牌啦啦啦^ ^ let lucky = Math.floor(Math.random() * 1000 + 100); if (lucky == 999) { this.startRandomMotion( LAppDefine.MotionGroupIdle, LAppDefine.PriorityIdle ); } else if (lucky == 888) { this.startRandomMotion( LAppDefine.MotionGroupDefault, LAppDefine.PriorityIdle ); } } else { motionUpdated = this._motionManager.updateMotion( this._model, deltaTimeSeconds ); // 更新动作 } this._model.saveParameters(); // 状態を保存 //-------------------------------------------------------------------------- // まばたき if (!motionUpdated) { if (this._eyeBlink != null) { // メインモーションの更新がないとき this._eyeBlink.updateParameters(this._model, deltaTimeSeconds); // 目パチ } } if (this._expressionManager != null) { this._expressionManager.updateMotion(this._model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化) } // ドラッグによる変化 // ドラッグによる顔の向きの調整 this._model.addParameterValueById(this._idParamAngleX, this._dragX * 30); // -30から30の値を加える this._model.addParameterValueById(this._idParamAngleY, this._dragY * 30); this._model.addParameterValueById( this._idParamAngleZ, this._dragX * this._dragY * -30 ); // ドラッグによる体の向きの調整 this._model.addParameterValueById( this._idParamBodyAngleX, this._dragX * 10 ); // -10から10の値を加える // ドラッグによる目の向きの調整 this._model.addParameterValueById(this._idParamEyeBallX, this._dragX); // -1から1の値を加える this._model.addParameterValueById(this._idParamEyeBallY, this._dragY); // 呼吸など if (this._breath != null) { this._breath.updateParameters(this._model, deltaTimeSeconds); } // 物理演算の設定 if (this._physics != null) { this._physics.evaluate(this._model, deltaTimeSeconds); } // リップシンクの設定 if (this._lipsync) { const value = 0; // リアルタイムでリップシンクを行う場合、システムから音量を取得して、0~1の範囲で値を入力します。 for (let i = 0; i < this._lipSyncIds.getSize(); ++i) { this._model.addParameterValueById(this._lipSyncIds.at(i), value, 0.8); } } // ポーズの設定 if (this._pose != null) { this._pose.updateParameters(this._model, deltaTimeSeconds); } this._model.update(); } /** * 引数で指定したモーションの再生を開始する * @param group モーショングループ名 * @param no グループ内の番号 * @param priority 優先度 * @param onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するisFinished()の引数で使用する。開始できない時は[-1] */ public startMotion( group: string, no: number, priority: number, onFinishedMotionHandler?: FinishedMotionCallback ): CubismMotionQueueEntryHandle { if (priority == LAppDefine.PriorityForce) { this._motionManager.setReservePriority(priority); } else if (!this._motionManager.reserveMotion(priority)) { if (this._debugMode) { LAppPal.printMessage("[APP]can't start motion."); } return InvalidMotionQueueEntryHandleValue; } const motionFileName = this._modelSetting.getMotionFileName(group, no); // ex) idle_0 const name = `${group}_${no}`; let motion: CubismMotion = this._motions.getValue(name) as CubismMotion; let autoDelete = false; if (motion == null) { fetch(`${this._modelHomeDir}${motionFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { motion = this.loadMotion( arrayBuffer, arrayBuffer.byteLength, null, onFinishedMotionHandler ); let fadeTime: number = this._modelSetting.getMotionFadeInTimeValue( group, no ); if (fadeTime >= 0.0) { motion.setFadeInTime(fadeTime); } fadeTime = this._modelSetting.getMotionFadeOutTimeValue(group, no); if (fadeTime >= 0.0) { motion.setFadeOutTime(fadeTime); } motion.setEffectIds(this._eyeBlinkIds, this._lipSyncIds); autoDelete = true; // 終了時にメモリから削除 }); } else { motion.setFinishedMotionHandler(onFinishedMotionHandler); } if (this._debugMode) { LAppPal.printMessage(`[APP]start motion: [${group}_${no}`); } return this._motionManager.startMotionPriority( motion, autoDelete, priority ); } /** * ランダムに選ばれたモーションの再生を開始する。 * @param group モーショングループ名 * @param priority 優先度 * @param onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数 * @param onFinishedMotionHandler 动作再生结束时调用的回呼函数 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するisFinished()の引数で使用する。開始できない時は[-1] * @return 返回开始动作的识别号码。用于判定个别动作是否结束的isFinished()参数。无法开始时[-1] */ public startRandomMotion( group: string, priority: number, onFinishedMotionHandler?: FinishedMotionCallback ): CubismMotionQueueEntryHandle { if (this._modelSetting.getMotionCount(group) == 0) { return InvalidMotionQueueEntryHandleValue; } const no: number = Math.floor( Math.random() * this._modelSetting.getMotionCount(group) ); return this.startMotion(group, no, priority, onFinishedMotionHandler); } /** * 引数で指定した表情モーションをセットする * * @param expressionId 表情モーションのID */ public setExpression(expressionId: string): void { const motion: ACubismMotion = this._expressions.getValue(expressionId); if (this._debugMode) { LAppPal.printMessage(`[APP]expression: [${expressionId}]`); } if (motion != null) { this._expressionManager.startMotionPriority( motion, false, LAppDefine.PriorityForce ); } else { if (this._debugMode) { LAppPal.printMessage(`[APP]expression[${expressionId}] is null`); } } } /** * ランダムに選ばれた表情モーションをセットする */ public setRandomExpression(): void { if (this._expressions.getSize() == 0) { return; } const no: number = Math.floor(Math.random() * this._expressions.getSize()); for (let i = 0; i < this._expressions.getSize(); i++) { if (i == no) { const name: string = this._expressions._keyValues[i].first; this.setExpression(name); return; } } } /** * イベントの発火を受け取る */ public motionEventFired(eventValue: csmString): void { CubismLogInfo('{0} is fired on LAppModel!!', eventValue.s); } /** * 当たり判定テスト * 指定IDの頂点リストから矩形を計算し、座標をが矩形範囲内か判定する。 * 根据指定ID的顶点列表计算矩形,判定坐标是否在矩形范围内。 * * @param hitArenaName 当たり判定をテストする対象のID * @param x 判定を行うX座標 * @param y 判定を行うY座標 */ public hitTest(hitArenaName: string, x: number, y: number): boolean { // 透明時は当たり判定無し。 if (this._opacity < 1) { return false; } const count: number = this._modelSetting.getHitAreasCount(); for (let i = 0; i < count; i++) { if (this._modelSetting.getHitAreaName(i) == hitArenaName) { const drawId: CubismIdHandle = this._modelSetting.getHitAreaId(i); return this.isHit(drawId, x, y); } } return false; } /** * モーションデータをグループ名から一括でロードする。 * モーションデータの名前は内部でModelSettingから取得する。 * 从组合名称中统一加载动作数据。 * 动作数据的名称在内部从ModelSetting取得。 * * @param group モーションデータのグループ名 * group动作数据的组名称 */ public preLoadMotionGroup(group: string): void { for (let i = 0; i < this._modelSetting.getMotionCount(group); i++) { const motionFileName = this._modelSetting.getMotionFileName(group, i); // ex) idle_0 const name = `${group}_${i}`; if (this._debugMode) { LAppPal.printMessage( `[APP]load motion: ${motionFileName} => [${name}]` ); } fetch(`${this._modelHomeDir}${motionFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { const tmpMotion: CubismMotion = this.loadMotion( arrayBuffer, arrayBuffer.byteLength, name ); let fadeTime = this._modelSetting.getMotionFadeInTimeValue(group, i); if (fadeTime >= 0.0) { tmpMotion.setFadeInTime(fadeTime); } fadeTime = this._modelSetting.getMotionFadeOutTimeValue(group, i); if (fadeTime >= 0.0) { tmpMotion.setFadeOutTime(fadeTime); } tmpMotion.setEffectIds(this._eyeBlinkIds, this._lipSyncIds); if (this._motions.getValue(name) != null) { ACubismMotion.delete(this._motions.getValue(name)); } this._motions.setValue(name, tmpMotion); this._motionCount++; // console.log('this._motionCount',this._motionCount) // console.log('this._allMotionCount',this._allMotionCount) if (this._motionCount >= this._allMotionCount) { this._state = LoadStep.LoadTexture; // 全てのモーションを停止する document.getElementById('live2d-hidden').style.display='none' if(this._motionManager){ this._motionManager.stopAllMotions(); this.createRenderer(); this.setupTextures(); this.getRenderer().startUp(gl); } this._updating = false; this._initialized = true; // this.createRenderer(); // this.setupTextures(); // this.getRenderer().startUp(gl); document.getElementById('live2d').style.visibility='visible' } }); } } /** * すべてのモーションデータを解放する。 */ public releaseMotions(): void { this._motions.clear(); } /** * 全ての表情データを解放する。 */ public releaseExpressions(): void { this._expressions.clear(); } /** * モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。 */ public doDraw(): void { if (this._model == null) return; // キャンバスサイズを渡す const viewport: number[] = [0, 0, canvas.width, canvas.height]; this.getRenderer().setRenderState(frameBuffer, viewport); this.getRenderer().drawModel(); } /** * モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。 */ public draw(matrix: CubismMatrix44): void { if (this._model == null) { return; } // 各読み込み終了後 if (this._state == LoadStep.CompleteSetup) { matrix.multiplyByMatrix(this._modelMatrix); this.getRenderer().setMvpMatrix(matrix); this.doDraw(); } } /** * コンストラクタ */ public constructor() { super(); this._modelSetting = null; this._modelHomeDir = null; this._userTimeSeconds = 0.0; this._eyeBlinkIds = new csmVector(); this._lipSyncIds = new csmVector(); this._motions = new csmMap(); this._expressions = new csmMap(); this._hitArea = new csmVector(); this._userArea = new csmVector(); this._idParamAngleX = CubismFramework.getIdManager().getId( CubismDefaultParameterId.ParamAngleX ); this._idParamAngleY = CubismFramework.getIdManager().getId( CubismDefaultParameterId.ParamAngleY ); this._idParamAngleZ = CubismFramework.getIdManager().getId( CubismDefaultParameterId.ParamAngleZ ); this._idParamEyeBallX = CubismFramework.getIdManager().getId( CubismDefaultParameterId.ParamEyeBallX ); this._idParamEyeBallY = CubismFramework.getIdManager().getId( CubismDefaultParameterId.ParamEyeBallY ); this._idParamBodyAngleX = CubismFramework.getIdManager().getId( CubismDefaultParameterId.ParamBodyAngleX ); this._state = LoadStep.LoadAssets; this._expressionCount = 0; this._textureCount = 0; this._motionCount = 0; this._allMotionCount = 0; } _modelSetting: ICubismModelSetting; // モデルセッティング情報 _modelHomeDir: string; // モデルセッティングが置かれたディレクトリ _userTimeSeconds: number; // デルタ時間の積算値[秒] _eyeBlinkIds: csmVector; // モデルに設定された瞬き機能用パラメータID _lipSyncIds: csmVector; // モデルに設定されたリップシンク機能用パラメータID _motions: csmMap; // 読み込まれているモーションのリスト _expressions: csmMap; // 読み込まれている表情のリスト _hitArea: csmVector; _userArea: csmVector; _idParamAngleX: CubismIdHandle; // パラメータID: ParamAngleX _idParamAngleY: CubismIdHandle; // パラメータID: ParamAngleY _idParamAngleZ: CubismIdHandle; // パラメータID: ParamAngleZ _idParamEyeBallX: CubismIdHandle; // パラメータID: ParamEyeBallX _idParamEyeBallY: CubismIdHandle; // パラメータID: ParamEyeBAllY _idParamBodyAngleX: CubismIdHandle; // パラメータID: ParamBodyAngleX _state: number; // 現在のステータス管理用 _expressionCount: number; // 表情データカウント _textureCount: number; // テクスチャカウント _motionCount: number; // モーションデータカウント _allMotionCount: number; // モーション総数 }