From 9d8bf296d893fe2eafe739883df38941d0fdc9ee Mon Sep 17 00:00:00 2001 From: cubism-dev Date: Thu, 25 Oct 2018 16:57:55 +0900 Subject: [PATCH 1/4] Add gitattributes. --- .gitattributes | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..59599dd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.ts text +*.js text +*.json text +*.html text +*.md text \ No newline at end of file From 197f7b377955188874e536a125ff61af355fad7c Mon Sep 17 00:00:00 2001 From: cubism-dev Date: Thu, 25 Oct 2018 17:05:42 +0900 Subject: [PATCH 2/4] Deleted for line feed code correction --- Framework/cubismdefaultparameterid.ts | 66 - Framework/cubismframeworkconfig.ts | 32 - Framework/cubismmodelsettingjson.ts | 681 ------ Framework/effect/cubismbreath.ts | 140 -- Framework/effect/cubismeyeblink.ts | 238 -- Framework/effect/cubismpose.ts | 416 ---- Framework/icubismallcator.ts | 47 - Framework/icubismmodelsetting.ts | 193 -- Framework/id/cubismid.ts | 90 - Framework/id/cubismidmanager.ts | 131 -- Framework/live2dcubismframework.ts | 283 --- Framework/math/cubismmath.ts | 226 -- Framework/math/cubismmatrix44.ts | 279 --- Framework/math/cubismmodelmatrix.ts | 263 --- Framework/math/cubismtargetpoint.ts | 172 -- Framework/math/cubismvector2.ts | 180 -- Framework/math/cubismviewmatrix.ts | 312 --- Framework/model/cubismmoc.ts | 106 - Framework/model/cubismmodel.ts | 803 ------- Framework/model/cubismmodeluserdata.ts | 139 -- Framework/model/cubismmodeluserdatajson.ts | 99 - Framework/model/cubismusermodel.ts | 466 ---- Framework/motion/acubismmotion.ts | 239 -- Framework/motion/cubismexpressionmotion.ts | 189 -- Framework/motion/cubismmotion.ts | 805 ------- Framework/motion/cubismmotioninternal.ts | 157 -- Framework/motion/cubismmotionjson.ts | 282 --- Framework/motion/cubismmotionmanager.ts | 127 -- Framework/motion/cubismmotionqueueentry.ts | 240 -- Framework/motion/cubismmotionqueuemanager.ts | 342 --- Framework/physics/cubismphysics.ts | 826 ------- Framework/physics/cubismphysicsinternal.ts | 248 -- Framework/physics/cubismphysicsjson.ts | 407 ---- Framework/rendering/cubismrenderer.ts | 312 --- Framework/rendering/cubismrenderer_WebGL.ts | 1986 ----------------- Framework/tsconfig.json | 13 - Framework/type/csmmap.ts | 360 --- Framework/type/csmrectf.ts | 92 - Framework/type/csmstring.ts | 117 - Framework/type/csmvector.ts | 396 ---- Framework/utils/cubismdebug.ts | 194 -- Framework/utils/cubismjson.ts | 1249 ----------- Framework/utils/cubismstring.ts | 136 -- Sample/TypeScript/Demo/src/lappdefine.ts | 70 - Sample/TypeScript/Demo/src/lappdelegate.ts | 340 --- .../TypeScript/Demo/src/lapplive2dmanager.ts | 218 -- Sample/TypeScript/Demo/src/lappmodel.ts | 993 --------- Sample/TypeScript/Demo/src/lapppal.ts | 102 - Sample/TypeScript/Demo/src/lappsprite.ts | 137 -- .../TypeScript/Demo/src/lapptexturemanager.ts | 168 -- Sample/TypeScript/Demo/src/lappview.ts | 290 --- Sample/TypeScript/Demo/src/main.ts | 32 - Sample/TypeScript/Demo/src/touchmanager.ts | 199 -- 53 files changed, 16628 deletions(-) delete mode 100644 Framework/cubismdefaultparameterid.ts delete mode 100644 Framework/cubismframeworkconfig.ts delete mode 100644 Framework/cubismmodelsettingjson.ts delete mode 100644 Framework/effect/cubismbreath.ts delete mode 100644 Framework/effect/cubismeyeblink.ts delete mode 100644 Framework/effect/cubismpose.ts delete mode 100644 Framework/icubismallcator.ts delete mode 100644 Framework/icubismmodelsetting.ts delete mode 100644 Framework/id/cubismid.ts delete mode 100644 Framework/id/cubismidmanager.ts delete mode 100644 Framework/live2dcubismframework.ts delete mode 100644 Framework/math/cubismmath.ts delete mode 100644 Framework/math/cubismmatrix44.ts delete mode 100644 Framework/math/cubismmodelmatrix.ts delete mode 100644 Framework/math/cubismtargetpoint.ts delete mode 100644 Framework/math/cubismvector2.ts delete mode 100644 Framework/math/cubismviewmatrix.ts delete mode 100644 Framework/model/cubismmoc.ts delete mode 100644 Framework/model/cubismmodel.ts delete mode 100644 Framework/model/cubismmodeluserdata.ts delete mode 100644 Framework/model/cubismmodeluserdatajson.ts delete mode 100644 Framework/model/cubismusermodel.ts delete mode 100644 Framework/motion/acubismmotion.ts delete mode 100644 Framework/motion/cubismexpressionmotion.ts delete mode 100644 Framework/motion/cubismmotion.ts delete mode 100644 Framework/motion/cubismmotioninternal.ts delete mode 100644 Framework/motion/cubismmotionjson.ts delete mode 100644 Framework/motion/cubismmotionmanager.ts delete mode 100644 Framework/motion/cubismmotionqueueentry.ts delete mode 100644 Framework/motion/cubismmotionqueuemanager.ts delete mode 100644 Framework/physics/cubismphysics.ts delete mode 100644 Framework/physics/cubismphysicsinternal.ts delete mode 100644 Framework/physics/cubismphysicsjson.ts delete mode 100644 Framework/rendering/cubismrenderer.ts delete mode 100644 Framework/rendering/cubismrenderer_WebGL.ts delete mode 100644 Framework/tsconfig.json delete mode 100644 Framework/type/csmmap.ts delete mode 100644 Framework/type/csmrectf.ts delete mode 100644 Framework/type/csmstring.ts delete mode 100644 Framework/type/csmvector.ts delete mode 100644 Framework/utils/cubismdebug.ts delete mode 100644 Framework/utils/cubismjson.ts delete mode 100644 Framework/utils/cubismstring.ts delete mode 100644 Sample/TypeScript/Demo/src/lappdefine.ts delete mode 100644 Sample/TypeScript/Demo/src/lappdelegate.ts delete mode 100644 Sample/TypeScript/Demo/src/lapplive2dmanager.ts delete mode 100644 Sample/TypeScript/Demo/src/lappmodel.ts delete mode 100644 Sample/TypeScript/Demo/src/lapppal.ts delete mode 100644 Sample/TypeScript/Demo/src/lappsprite.ts delete mode 100644 Sample/TypeScript/Demo/src/lapptexturemanager.ts delete mode 100644 Sample/TypeScript/Demo/src/lappview.ts delete mode 100644 Sample/TypeScript/Demo/src/main.ts delete mode 100644 Sample/TypeScript/Demo/src/touchmanager.ts diff --git a/Framework/cubismdefaultparameterid.ts b/Framework/cubismdefaultparameterid.ts deleted file mode 100644 index ad7514b..0000000 --- a/Framework/cubismdefaultparameterid.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -/** - * @brief パラメータIDのデフォルト値を保持する定数
- * デフォルト値の仕様は以下のマニュアルに基づく
- * http://docs.live2d.com/cubism-editor-manual/standard-parametor-list/ - */ -export namespace Live2DCubismFramework -{ - // パーツID - export const HitAreaPrefix: string = "HitArea"; - export const HitAreaHead: string = "Head"; - export const HitAreaBody: string = "Body"; - export const PartsIdCore: string = "Parts01Core"; - export const PartsArmPrefix: string = "Parts01Arm_"; - export const PartsArmLPrefix: string = "Parts01ArmL_"; - export const PartsArmRPrefix: string = "Parts01ArmR_"; - - // パラメータID - export const ParamAngleX: string = "ParamAngleX"; - export const ParamAngleY: string = "ParamAngleY"; - export const ParamAngleZ: string = "ParamAngleZ"; - export const ParamEyeLOpen: string = "ParamEyeLOpen"; - export const ParamEyeLSmile: string = "ParamEyeLSmile"; - export const ParamEyeROpen: string = "ParamEyeROpen"; - export const ParamEyeRSmile: string = "ParamEyeRSmile"; - export const ParamEyeBallX: string = "ParamEyeBallX"; - export const ParamEyeBallY: string = "ParamEyeBallY"; - export const ParamEyeBallForm: string = "ParamEyeBallForm"; - export const ParamBrowLY: string = "ParamBrowLY"; - export const ParamBrowRY: string = "ParamBrowRY"; - export const ParamBrowLX: string = "ParamBrowLX"; - export const ParamBrowRX: string = "ParamBrowRX"; - export const ParamBrowLAngle: string = "ParamBrowLAngle"; - export const ParamBrowRAngle: string = "ParamBrowRAngle"; - export const ParamBrowLForm: string = "ParamBrowLForm"; - export const ParamBrowRForm: string = "ParamBrowRForm"; - export const ParamMouthForm: string = "ParamMouthForm"; - export const ParamMouthOpenY: string = "ParamMouthOpenY"; - export const ParamCheek: string = "ParamCheek"; - export const ParamBodyAngleX: string = "ParamBodyAngleX"; - export const ParamBodyAngleY: string = "ParamBodyAngleY"; - export const ParamBodyAngleZ: string = "ParamBodyAngleZ"; - export const ParamBreath: string = "ParamBreath"; - export const ParamArmLA: string = "ParamArmLA"; - export const ParamArmRA: string = "ParamArmRA"; - export const ParamArmLB: string = "ParamArmLB"; - export const ParamArmRB: string = "ParamArmRB"; - export const ParamHandL: string = "ParamHandL"; - export const ParamHandR: string = "ParamHandR"; - export const ParamHairFront: string = "ParamHairFront"; - export const ParamHairSide: string = "ParamHairSide"; - export const ParamHairBack: string = "ParamHairBack"; - export const ParamHairFluffy: string = "ParamHairFluffy"; - export const ParamShoulderY: string = "ParamShoulderY"; - export const ParamBustX: string = "ParamBustX"; - export const ParamBustY: string = "ParamBustY"; - export const ParamBaseX: string = "ParamBaseX"; - export const ParamBaseY: string = "ParamBaseY"; - export const ParamNONE: string = "NONE:"; -} \ No newline at end of file diff --git a/Framework/cubismframeworkconfig.ts b/Framework/cubismframeworkconfig.ts deleted file mode 100644 index b6edc37..0000000 --- a/Framework/cubismframeworkconfig.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -//======================================================== -// ログ出力関数の設定 -//======================================================== - -//---------- ログ出力レベル 選択項目 定義 ---------- -/// 詳細ログ出力設定 -export const CSM_LOG_LEVEL_VERBOSE: number = 0; -/// デバッグログ出力設定 -export const CSM_LOG_LEVEL_DEBUG: number = 1; -/// Infoログ出力設定 -export const CSM_LOG_LEVEL_INFO: number = 2; -/// 警告ログ出力設定 -export const CSM_LOG_LEVEL_WARNING: number = 3; -/// エラーログ出力設定 -export const CSM_LOG_LEVEL_ERROR: number = 4; -/// ログ出力オフ設定 -export const CSM_LOG_LEVEL_OFF: number = 5; - -/** -* ログ出力レベル設定。 -* -* 強制的にログ出力レベルを変える時に定義を有効にする。 -* CSM_LOG_LEVEL_VERBOSE ~ CSM_LOG_LEVEL_OFF を選択する。 -*/ -export const CSM_LOG_LEVEL: number = CSM_LOG_LEVEL_VERBOSE; \ No newline at end of file diff --git a/Framework/cubismmodelsettingjson.ts b/Framework/cubismmodelsettingjson.ts deleted file mode 100644 index b0bed8e..0000000 --- a/Framework/cubismmodelsettingjson.ts +++ /dev/null @@ -1,681 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismframework} from "./live2dcubismframework"; -import {Live2DCubismFramework as icubismmodelsetting} from "./icubismmodelsetting"; -import {Live2DCubismFramework as cubismid} from "./id/cubismid"; -import {Live2DCubismFramework as cubismjson} from "./utils/cubismjson"; -import {Live2DCubismFramework as csmmap} from"./type/csmmap"; -import csmMap = csmmap.csmMap; -import CubismFramework = cubismframework.CubismFramework; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismJson = cubismjson.CubismJson; -import Value = cubismjson.Value; -import ICubismModelSetting = icubismmodelsetting.ICubismModelSetting; - - -export namespace Live2DCubismFramework -{ - /** - * Model3Jsonのキー文字列 - */ - - // JSON Keys - const Version: string = "Version"; - const FileReferences: string = "FileReferences"; - const Groups: string = "Groups"; - const Layout: string = "Layout"; - const HitAreas: string = "HitAreas"; - - const Moc: string = "Moc"; - const Textures: string = "Textures"; - const Physics: string = "Physics"; - const Pose: string = "Pose"; - const Expressions: string = "Expressions"; - const Motions: string = "Motions"; - - const UserData: string = "UserData"; - const Name: string = "Name"; - const FilePath: string = "File"; - const Id: string = "Id"; - const Ids: string = "Ids"; - const Target: string = "Target"; - - // Motions - const Idle: string = "Idle"; - const TapBody: string = "TapBody"; - const PinchIn: string = "PinchIn"; - const PinchOut: string = "PinchOut"; - const Shake: string = "Shake"; - const FlickHead: string = "FlickHead"; - const Parameter: string = "Parameter"; - - const SoundPath: string = "Sound"; - const FadeInTime: string = "FadeInTime"; - const FadeOutTime: string = "FadeOutTime"; - - // Layout - const CenterX: string = "CenterX"; - const CenterY: string = "CenterY"; - const X: string = "X"; - const Y: string = "Y"; - const Width: string = "Width"; - const Height: string = "Height"; - - const LipSync: string = "LipSync"; - const EyeBlink: string = "EyeBlink"; - - const InitParameter: string = "init_param"; - const InitPartsVisible: string = "init_parts_visible"; - const Val: string = "val"; - - - /** - * Model3Jsonパーサー - * - * model3.jsonファイルをパースして値を取得する - */ - export class CubismModelSettingJson extends ICubismModelSetting - { - /** - * 引数付きコンストラクタ - * - * @param buffer Model3Jsonをバイト配列として読み込んだデータバッファ - * @param size Model3Jsonのデータサイズ - */ - public constructor(buffer: ArrayBuffer, size: number) - { - super(); - this._json = CubismJson.create(buffer, size); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - CubismJson.delete(this._json); - } - - /** - * CubismJsonオブジェクトを取得する - * - * @return CubismJson - */ - public GetJson(): CubismJson - { - return this._json; - } - - /** - * Mocファイルの名前を取得する - * @return Mocファイルの名前 - */ - public getModelFileName(): string - { - if(!this.isExistModelFile()) - { - return ""; - } - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Moc).getRawString(); - } - - /** - * モデルが使用するテクスチャの数を取得する - * テクスチャの数 - */ - public getTextureCount(): number - { - if(!this.isExistTextureFiles()) - { - return 0; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Textures).getSize(); - } - - /** - * テクスチャが配置されたディレクトリの名前を取得する - * @return テクスチャが配置されたディレクトリの名前 - */ - public getTextureDirectory(): string - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Textures).getRawString(); - } - - /** - * モデルが使用するテクスチャの名前を取得する - * @param index 配列のインデックス値 - * @return テクスチャの名前 - */ - public getTextureFileName(index: number): string - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Textures).getVector().at(index).getRawString(); - } - - /** - * モデルに設定された当たり判定の数を取得する - * @return モデルに設定された当たり判定の数 - */ - public getHitAreasCount(): number - { - if(!this.isExistHitAreas()) - { - return 0; - } - - return this._json.getRoot().getMap().getValue(HitAreas).getSize(); - } - - /** - * 当たり判定に設定されたIDを取得する - * - * @param index 配列のindex - * @return 当たり判定に設定されたID - */ - public getHitAreaId(index: number): CubismIdHandle - { - return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(HitAreas).getVector().at(index).getMap().getValue(Id).getRawString()); - } - - /** - * 当たり判定に設定された名前を取得する - * @param index 配列のインデックス値 - * @return 当たり判定に設定された名前 - */ - public getHitAreaName(index: number): string - { - return this._json.getRoot().getMap().getValue(HitAreas).getVector().at(index).getMap().getValue(Name).getRawString(); - } - - /** - * 物理演算設定ファイルの名前を取得する - * @return 物理演算設定ファイルの名前 - */ - public getPhysicsFileName(): string - { - if(!this.isExistPhysicsFile()) - { - return ""; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Physics).getRawString(); - } - - /** - * パーツ切り替え設定ファイルの名前を取得する - * @return パーツ切り替え設定ファイルの名前 - */ - public getPoseFileName(): string - { - if(!this.isExistPoseFile()) - { - return ""; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Pose).getRawString(); - } - - /** - * 表情設定ファイルの数を取得する - * @return 表情設定ファイルの数 - */ - public getExpressionCount(): number - { - if(!this.isExistExpressionFile()) - { - return 0; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Expressions).getSize(); - } - - /** - * 表情設定ファイルを識別する名前(別名)を取得する - * @param index 配列のインデックス値 - * @return 表情の名前 - */ - public getExpressionName(index: number): string - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Expressions).getVector().at(index).getMap().getValue(Name).getRawString(); - } - - /** - * 表情設定ファイルの名前を取得する - * @param index 配列のインデックス値 - * @return 表情設定ファイルの名前 - */ - public getExpressionFileName(index: number): string - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Expressions).getVector().at(index).getMap().getValue(FilePath).getRawString(); - } - - /** - * モーショングループの数を取得する - * @return モーショングループの数 - */ - public getMotionGroupCount(): number - { - if(!this.isExistMotionGroups()) - { - return 0; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getSize(); - } - - /** - * モーショングループの名前を取得する - * @param index 配列のインデックス値 - * @return モーショングループの名前 - */ - public getMotionGroupName(index: number): string - { - if(!this.isExistMotionGroups()) - { - return null; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getKeys().at(index); - } - - /** - * モーショングループに含まれるモーションの数を取得する - * @param groupName モーショングループの名前 - * @return モーショングループの数 - */ - public getMotionCount(groupName: string): number - { - if(!this.isExistMotionGroupName(groupName)) - { - return 0; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getSize(); - } - - /** - * グループ名とインデックス値からモーションファイル名を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return モーションファイルの名前 - */ - public getMotionFileName(groupName: string, index: number): string - { - if(!this.isExistMotionGroupName(groupName)) - { - return ""; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(FilePath).getRawString(); - } - - /** - * モーションに対応するサウンドファイルの名前を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return サウンドファイルの名前 - */ - public getMotionSoundFileName(groupName: string, index: number): string - { - if(!this.isExistMotionSoundFile(groupName, index)) - { - return ""; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(SoundPath).getRawString(); - } - - /** - * モーション開始時のフェードイン処理時間を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return フェードイン処理時間[秒] - */ - public getMotionFadeInTimeValue(groupName: string, index: number): number - { - if(!this.isExistMotionFadeIn(groupName, index)) - { - return -1.0; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(FadeInTime).toFloat(); - } - - /** - * モーション終了時のフェードアウト処理時間を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return フェードアウト処理時間[秒] - */ - public getMotionFadeOutTimeValue(groupName: string, index: number): number - { - if(!this.isExistMotionFadeOut(groupName, index)) - { - return -1.0; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(FadeOutTime).toFloat(); - } - - /** - * ユーザーデータのファイル名を取得する - * @return ユーザーデータのファイル名 - */ - public getUserDataFile(): string - { - if(!this.isExistUserDataFile()) - { - return ""; - } - - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(UserData).getRawString(); - } - - /** - * レイアウト情報を取得する - * @param outLayoutMap csmMapクラスのインスタンス - * @return true レイアウト情報が存在する - * @return false レイアウト情報が存在しない - */ - public getLayoutMap(outLayoutMap: csmMap): boolean - { - // 存在しない要素にアクセスするとエラーになるためValueがnullの場合はnullを代入する - let map: csmMap = (this._json.getRoot().getMap().isExist(Layout)) - ? this._json.getRoot().getMap().getValue(Layout).getMap() - : null; - - if(map == null) - { - return false; - } - - let ret: boolean = false; - - for(const ite: csmMap.iterator = map.begin(); ite.notEqual(map.end()); ite.preIncrement()) - { - outLayoutMap.setValue(ite.ptr().first, ite.ptr().second.toFloat()); - ret = true; - } - - return ret; - } - - /** - * 目パチに関連付けられたパラメータの数を取得する - * @return 目パチに関連付けられたパラメータの数 - */ - public getEyeBlinkParameterCount(): number - { - if (!this.isExistEyeBlinkParameters()) - { - return 0; - } - - let num: number = 0; - for (let i = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) - { - if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == EyeBlink) - { - num = this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().getSize(); - break; - } - } - - return num; - } - - /** - * 目パチに関連付けられたパラメータのIDを取得する - * @param index 配列のインデックス値 - * @return パラメータID - */ - public getEyeBlinkParameterId(index: number): CubismIdHandle - { - if (!this.isExistEyeBlinkParameters()) - { - return null; - } - - for (let i = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) - { - if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == EyeBlink) - { - return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().at(index).getRawString()); - } - } - return null; - } - - /** - * リップシンクに関連付けられたパラメータの数を取得する - * @return リップシンクに関連付けられたパラメータの数 - */ - public getLipSyncParameterCount(): number - { - if (!this.isExistLipSyncParameters()) - { - return 0; - } - - let num: number = 0; - for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) - { - if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == LipSync) - { - num = this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().getSize(); - break; - } - } - - return num; - } - - /** - * リップシンクに関連付けられたパラメータの数を取得する - * @param index 配列のインデックス値 - * @return パラメータID - */ - public getLipSyncParameterId(index: number): CubismIdHandle - { - if (!this.isExistLipSyncParameters()) - { - return null; - } - - for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) - { - if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == LipSync) - { - return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().at(index).getRawString()); - } - } - return null; - } - - /** - * モデルファイルのキーが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistModelFile(): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Moc); - } - - /** - * テクスチャファイルのキーが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistTextureFiles(): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Textures); - } - - /** - * 当たり判定のキーが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistHitAreas(): boolean - { - return this._json.getRoot().getMap().isExist(HitAreas); - } - - /** - * 物理演算ファイルのキーが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistPhysicsFile(): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Physics); - } - - /** - * ポーズ設定ファイルのキーが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistPoseFile(): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Pose); - } - - /** - * 表情設定ファイルのキーが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistExpressionFile(): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Expressions); - } - - /** - * モーショングループのキーが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistMotionGroups(): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Motions); - } - - /** - * 引数で指定したモーショングループのキーが存在するかどうかを確認する - * @param groupName グループ名 - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistMotionGroupName(groupName: string): boolean - { - if(!this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Motions)) - { - return false; - } - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().isExist(groupName); - } - - /** - * 引数で指定したモーションに対応するサウンドファイルのキーが存在するかどうかを確認する - * @param groupName グループ名 - * @param index 配列のインデックス値 - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistMotionSoundFile(groupName: string, index: number): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().isExist(SoundPath); - } - - /** - * 引数で指定したモーションに対応するフェードイン時間のキーが存在するかどうかを確認する - * @param groupName グループ名 - * @param index 配列のインデックス値 - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistMotionFadeIn(groupName: string, index: number): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().isExist(FadeInTime); - } - - /** - * 引数で指定したモーションに対応するフェードアウト時間のキーが存在するかどうかを確認する - * @param groupName グループ名 - * @param index 配列のインデックス値 - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistMotionFadeOut(groupName: string, index: number): boolean - { - return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().isExist(FadeOutTime); - } - - /** - * UserDataのファイル名が存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistUserDataFile(): boolean - { - if(!this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(UserData)) - { - return false; - } - return !this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(UserData).isNull(); - } - - /** - * 目ぱちに対応付けられたパラメータが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistEyeBlinkParameters(): boolean - { - if(!this._json.getRoot().getMap().isExist(Groups)) - { - return false; - } - for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); ++i) - { - if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == EyeBlink) - { - return true; - } - } - - return false; - } - - /** - * リップシンクに対応付けられたパラメータが存在するかどうかを確認する - * @return true キーが存在する - * @return false キーが存在しない - */ - private isExistLipSyncParameters(): boolean - { - if(!this._json.getRoot().getMap().isExist(Groups)) - { - return false; - } - for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); ++i) - { - if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == LipSync) - { - return true; - } - } - return false; - } - - - private _json: CubismJson; - } -} \ No newline at end of file diff --git a/Framework/effect/cubismbreath.ts b/Framework/effect/cubismbreath.ts deleted file mode 100644 index 2a2a407..0000000 --- a/Framework/effect/cubismbreath.ts +++ /dev/null @@ -1,140 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; -import {Live2DCubismFramework as cubismid} from "../id/cubismid"; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismModel = cubismmodel.CubismModel; -import csmVector = csmvector.csmVector; - - -export namespace Live2DCubismFramework -{ - /** - * 呼吸機能 - * - * 呼吸機能を提供する。 - */ - export class CubismBreath - { - - /** - * インスタンスの作成 - */ - public static create(): CubismBreath - { - return new CubismBreath(); - } - - /** - * インスタンスの破棄 - * @param instance 対象のCubismBreath - */ - public static delete(instance: CubismBreath): void - { - instance = void 0; - instance = null; - } - - /** - * 呼吸のパラメータの紐づけ - * @param breathParameters 呼吸を紐づけたいパラメータのリスト - */ - public setParameters(breathParameters: csmVector): void - { - this._breathParameters = breathParameters; - } - - /** - * 呼吸に紐づいているパラメータの取得 - * @return 呼吸に紐づいているパラメータのリスト - */ - public getParameters(): csmVector - { - return this._breathParameters; - } - - /** - * モデルのパラメータの更新 - * @param model 対象のモデル - * @param deltaTimeSeconds デルタ時間[秒] - */ - public updateParameters(model: CubismModel, deltaTimeSeconds: number): void - { - this._currentTime += deltaTimeSeconds; - - const t: number = this._currentTime * 2.0 * 3.14159; - - for(let i: number = 0; i < this._breathParameters.getSize(); ++i) - { - let data: CubismBreath.BreathParameterData = this._breathParameters.at(i); - - model.addParameterValueById( - data.parameterId, - data.offset + (data.peak * Math.sin(t / data.cycle)), - data.weight - ); - } - } - - - /** - * コンストラクタ - */ - public constructor() - { - this._currentTime = 0.0; - } - - _breathParameters: csmVector; // 呼吸にひもづいているパラメータのリスト - _currentTime: number; // 積算時間[秒] - } - - export namespace CubismBreath - { - /** - * 呼吸のパラメータ情報 - */ - export class BreathParameterData - { - /** - * コンストラクタ - * @param parameterId 呼吸をひもづけるパラメータID - * @param offset 呼吸を正弦波としたときの、波のオフセット - * @param peak 呼吸を正弦波としたときの、波の高さ - * @param cycle 呼吸を正弦波としたときの、波の周期 - * @param weight パラメータへの重み - */ - constructor(parameterId?: CubismIdHandle, offset?: number, peak?: number, cycle?: number, weight?: number) - { - this.parameterId = (parameterId == undefined) - ? null - : parameterId; - this.offset = (offset == undefined) - ? 0.0 - : offset; - this.peak = (peak == undefined) - ? 0.0 - : peak; - this.cycle = (cycle == undefined) - ? 0.0 - : cycle; - this.weight = (weight == undefined) - ? 0.0 - : weight; - } - - parameterId: CubismIdHandle; // 呼吸をひもづけるパラメータID\ - offset: number; // 呼吸を正弦波としたときの、波のオフセット - peak: number; // 呼吸を正弦波としたときの、波の高さ - cycle: number; // 呼吸を正弦波としたときの、波の周期 - weight: number; // パラメータへの重み - } - - } -} \ No newline at end of file diff --git a/Framework/effect/cubismeyeblink.ts b/Framework/effect/cubismeyeblink.ts deleted file mode 100644 index 15fb7ac..0000000 --- a/Framework/effect/cubismeyeblink.ts +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {Live2DCubismFramework as icubismmodelsetting} from "../icubismmodelsetting"; -import {Live2DCubismFramework as cubismid} from "../id/cubismid"; -import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; -import CubismModel = cubismmodel.CubismModel; -import CubismIdHandle = cubismid.CubismIdHandle; -import ICubismModelSetting = icubismmodelsetting.ICubismModelSetting; -import csmVector = csmvector.csmVector; - -export namespace Live2DCubismFramework -{ - /** - * 自動まばたき機能 - * - * 自動まばたき機能を提供する。 - */ - export class CubismEyeBlink - { - /** - * インスタンスを作成する - * @param modelSetting モデルの設定情報 - * @return 作成されたインスタンス - * @note 引数がNULLの場合、パラメータIDが設定されていない空のインスタンスを作成する。 - */ - public static create(modelSetting: ICubismModelSetting = null): CubismEyeBlink - { - return new CubismEyeBlink(modelSetting); - } - - /** - * インスタンスの破棄 - * @param eyeBlink 対象のCubismEyeBlink - */ - public static delete(eyeBlink: CubismEyeBlink): void - { - eyeBlink = void 0; - eyeBlink = null; - } - - /** - * まばたきの間隔の設定 - * @param blinkingInterval まばたきの間隔の時間[秒] - */ - public setBlinkingInterval(blinkingInterval: number): void - { - this._blinkingIntervalSeconds = blinkingInterval; - } - - /** - * まばたきのモーションの詳細設定 - * @param closing まぶたを閉じる動作の所要時間[秒] - * @param closed まぶたを閉じている動作の所要時間[秒] - * @param opening まぶたを開く動作の所要時間[秒] - */ - public setBlinkingSetting(closing: number, closed: number, opening: number): void - { - this._closingSeconds = closing; - this._closedSeconds = closed; - this._openingSeconds = opening; - } - - /** - * まばたきさせるパラメータIDのリストの設定 - * @param parameterIds パラメータのIDのリスト - */ - public setParameterIds(parameterIds: csmVector): void - { - this._parameterIds = parameterIds; - } - - /** - * まばたきさせるパラメータIDのリストの取得 - * @return パラメータIDのリスト - */ - public getParameterIds(): csmVector - { - return this._parameterIds; - } - - /** - * モデルのパラメータの更新 - * @param model 対象のモデル - * @param deltaTimeSeconds デルタ時間[秒] - */ - public updateParameters(model: CubismModel, deltaTimeSeconds: number): void - { - this._userTimeSeconds += deltaTimeSeconds; - let parameterValue: number; - let t: number = 0.0; - - switch(this._blinkingState) - { - case CubismEyeBlink.EyeState.EyeState_Closing: - t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._closingSeconds); - - if(t >= 1.0) - { - t = 1.0; - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Closed; - this._stateStartTimeSeconds = this._userTimeSeconds; - } - - parameterValue = 1.0 - t; - - break; - case CubismEyeBlink.EyeState.EyeState_Closed: - t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._closedSeconds); - - if(t >= 1.0) - { - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Opening; - this._stateStartTimeSeconds = this._userTimeSeconds; - } - - parameterValue = 0.0; - - break; - case CubismEyeBlink.EyeState.EyeState_Opening: - t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._openingSeconds); - - if(t >= 1.0) - { - t = 1.0; - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Interval; - this._nextBlinkingTime = this.determinNextBlinkingTiming(); - } - - parameterValue = t; - - break; - case CubismEyeBlink.EyeState.EyeState_Interval: - if(this._nextBlinkingTime < this._userTimeSeconds) - { - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Closing; - this._stateStartTimeSeconds = this._userTimeSeconds; - } - - parameterValue = 1.0; - - break; - case CubismEyeBlink.EyeState.EyeState_First: - default: - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Interval; - this._nextBlinkingTime = this.determinNextBlinkingTiming(); - - parameterValue = 1.0; - break; - } - - if(!CubismEyeBlink.CloseIfZero) - { - parameterValue = -parameterValue; - } - - for(let i: number = 0; i < this._parameterIds.getSize(); ++i) - { - model.setParameterValueById(this._parameterIds.at(i), parameterValue); - } - } - - /** - * コンストラクタ - * @param modelSetting モデルの設定情報 - */ - public constructor(modelSetting: ICubismModelSetting) - { - this._blinkingState = CubismEyeBlink.EyeState.EyeState_First; - this._nextBlinkingTime = 0.0; - this._stateStartTimeSeconds = 0.0; - this._blinkingIntervalSeconds = 4.0; - this._closingSeconds = 0.1; - this._closedSeconds = 0.05; - this._openingSeconds = 0.15; - this._userTimeSeconds = 0.0; - this._parameterIds = new csmVector(); - - if(modelSetting == null) - { - return; - } - - for(let i: number = 0; i < modelSetting.getEyeBlinkParameterCount(); ++i) - { - this._parameterIds.pushBack(modelSetting.getEyeBlinkParameterId(i)); - } - } - - /** - * 次の瞬きのタイミングの決定 - * - * @return 次のまばたきを行う時刻[秒] - */ - public determinNextBlinkingTiming(): number - { - const r: number = Math.random(); - return this._userTimeSeconds + (r * (2.0 * this._blinkingIntervalSeconds - 1.0)); - } - - _blinkingState: number; // 現在の状態 - _parameterIds: csmVector; // 操作対象のパラメータのIDのリスト - _nextBlinkingTime: number; // 次のまばたきの時刻[秒] - _stateStartTimeSeconds: number; // 現在の状態が開始した時刻[秒] - _blinkingIntervalSeconds: number; // まばたきの間隔[秒] - _closingSeconds: number; // まぶたを閉じる動作の所要時間[秒] - _closedSeconds: number; // まぶたを閉じている動作の所要時間[秒] - _openingSeconds: number; // まぶたを開く動作の所要時間[秒] - _userTimeSeconds: number; // デルタ時間の積算値[秒] - } - - export namespace CubismEyeBlink - { - /** - * まばたきの状態 - * - * まばたきの状態を表す列挙型 - */ - export enum EyeState - { - EyeState_First = 0, // 初期状態 - EyeState_Interval, // まばたきしていない状態 - EyeState_Closing, // まぶたが閉じていく途中の状態 - EyeState_Closed, // まぶたが閉じている状態 - EyeState_Opening // まぶたが開いていく途中の状態 - } - - /** - * IDで指定された目のパラメータが、0のときに閉じるなら true 、1の時に閉じるなら false 。 - */ - export const CloseIfZero = true; - } -} \ No newline at end of file diff --git a/Framework/effect/cubismpose.ts b/Framework/effect/cubismpose.ts deleted file mode 100644 index cd4aff6..0000000 --- a/Framework/effect/cubismpose.ts +++ /dev/null @@ -1,416 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismid} from "../id/cubismid"; -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; -import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; -import {Live2DCubismFramework as cubismjson} from "../utils/cubismjson"; -import CubismIdHandle = cubismid.CubismIdHandle; -import csmVector = csmvector.csmVector; -import CubismModel = cubismmodel.CubismModel; -import CubismFramework = cubismframework.CubismFramework; -import CubismJson = cubismjson.CubismJson; -import Value = cubismjson.Value; - - -export namespace Live2DCubismFramework -{ - const Epsilon: number = 0.001; - const DefaultFadeInSeconds: number = 0.5; - - // Pose.jsonのタグ - const FadeIn: string = "FadeInTime"; - const Link: string = "Link"; - const Groups: string = "Groups"; - const Id: string = "Id"; - - - /** - * パーツの不透明度の設定 - * - * パーツの不透明度の管理と設定を行う。 - */ - export class CubismPose - { - /** - * インスタンスの作成 - * @param pose3json pose3.jsonのデータ - * @param size pose3.jsonのデータのサイズ[byte] - * @return 作成されたインスタンス - */ - public static create(pose3json: ArrayBuffer, size: number): CubismPose - { - let ret: CubismPose = new CubismPose(); - let json: CubismJson = CubismJson.create(pose3json, size); - let root: Value = json.getRoot(); - - // フェード時間の指定 - if(root.getMap().isExist(FadeIn)) - { - ret._fadeTimeSeconds = root.getMap().getValue(FadeIn).toFloat(DefaultFadeInSeconds); - - if(ret._fadeTimeSeconds <= 0.0) - { - ret._fadeTimeSeconds = DefaultFadeInSeconds; - } - } - - // パーツグループ - let poseListInfo: Value = root.getMap().getValue(Groups); - const poseCount: number = poseListInfo.getSize(); - - for(let poseIndex: number = 0; poseIndex < poseCount; ++poseIndex) - { - let idListInfo: Value = poseListInfo.getVector().at(poseIndex); - const idCount: number = idListInfo.getSize(); - let groupCount: number = 0; - - for(let groupIndex: number = 0; groupIndex < idCount; ++groupIndex) - { - let partInfo: Value = idListInfo.getVector().at(groupIndex); - let partData: CubismPose.PartData = new CubismPose.PartData(); - const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(partInfo.getMap().getValue(Id).getRawString()); - - partData.partId = parameterId; - - // リンクするパーツの設定 - if(partInfo.getMap().isExist(Link)) - { - let linkListInfo: Value = partInfo.getMap().getValue(Link); - const linkCount: number = linkListInfo.getSize(); - - for(let linkIndex: number = 0; linkIndex < linkCount; ++linkIndex) - { - let linkPart: CubismPose.PartData = new CubismPose.PartData(); - const linkId: CubismIdHandle = CubismFramework.getIdManager().getId(linkListInfo.getVector().at(linkIndex).getString()); - - linkPart.partId = linkId; - - partData.link.pushBack(linkPart); - } - } - - ret._partGroups.pushBack(partData.clone()); - - ++groupCount; - } - - ret._partGroupCounts.pushBack(groupCount); - } - - CubismJson.delete(json); - - return ret; - } - - /** - * インスタンスを破棄する - * @param pose 対象のCubismPose - */ - public static delete(pose: CubismPose): void - { - pose = void 0; - pose = null; - } - - /** - * モデルのパラメータの更新 - * @param model 対象のモデル - * @param deltaTimeSeconds デルタ時間[秒] - */ - public updateParameters(model: CubismModel, deltaTimeSeconds: number): void - { - // 前回のモデルと同じでない場合は初期化が必要 - if(model != this._lastModel) - { - // パラメータインデックスの初期化 - this.reset(model); - } - - this._lastModel = model; - - // 設定から時間を変更すると、経過時間がマイナスになる事があるので、経過時間0として対応 - if(deltaTimeSeconds < 0.0) - { - deltaTimeSeconds = 0.0; - } - - let beginIndex: number = 0; - - for(let i = 0; i < this._partGroupCounts.getSize(); i++) - { - const partGroupCount: number = this._partGroupCounts.at(i); - - this.doFade(model, deltaTimeSeconds, beginIndex, partGroupCount); - - beginIndex += partGroupCount; - } - - this.copyPartOpacities(model); - } - - /** - * 表示を初期化 - * @param model 対象のモデル - * @note 不透明度の初期値が0でないパラメータは、不透明度を1に設定する - */ - public reset(model: CubismModel): void - { - let beginIndex: number = 0; - - for(let i: number = 0; i < this._partGroupCounts.getSize(); ++i) - { - const groupCount: number = this._partGroupCounts.at(i); - - for(let j: number = beginIndex; j < beginIndex + groupCount; ++j) - { - this._partGroups.at(j).initialize(model); - - const partsIndex: number = this._partGroups.at(j).partIndex; - const paramIndex: number = this._partGroups.at(j).parameterIndex; - - if(partsIndex < 0) - { - continue; - } - - model.setPartOpacityByIndex(partsIndex, (j == beginIndex ? 1.0 : 0.0)); - model.setParameterValueByIndex(paramIndex, (j == beginIndex ? 1.0: 0.0)); - - for(let k: number = 0; k < this._partGroups.at(j).link.getSize(); ++k) - { - this._partGroups.at(j).link.at(k).initialize(model); - } - } - - beginIndex += groupCount; - } - } - - /** - * パーツの不透明度をコピー - * - * @param model 対象のモデル - */ - public copyPartOpacities(model: CubismModel): void - { - for(let groupIndex: number = 0; groupIndex < this._partGroups.getSize(); ++groupIndex) - { - let partData: CubismPose.PartData = this._partGroups.at(groupIndex); - - if(partData.link.getSize() == 0) - { - continue; // 連動するパラメータはない - } - - const partIndex: number = this._partGroups.at(groupIndex).partIndex; - const opacity: number = model.getPartOpacityByIndex(partIndex); - - for(let linkIndex: number = 0; linkIndex < partData.link.getSize(); ++linkIndex) - { - let linkPart: CubismPose.PartData = partData.link.at(linkIndex); - const linkPartIndex: number = linkPart.partIndex; - - if(linkPartIndex < 0) - { - continue; - } - - model.setPartOpacityByIndex(linkPartIndex, opacity); - } - } - } - - /** - * パーツのフェード操作を行う。 - * @param model 対象のモデル - * @param deltaTimeSeconds デルタ時間[秒] - * @param beginIndex フェード操作を行うパーツグループの先頭インデックス - * @param partGroupCount フェード操作を行うパーツグループの個数 - */ - public doFade(model: CubismModel, deltaTimeSeconds: number, beginIndex: number, partGroupCount: number): void - { - let visiblePartIndex: number = -1; - let newOpacity: number = 1.0; - - const phi: number = 0.5; - const backOpacityThreshold: number = 0.15; - - // 現在、表示状態になっているパーツを取得 - for(let i: number = beginIndex; i < beginIndex + partGroupCount; ++i) - { - const partIndex: number = this._partGroups.at(i).partIndex; - const paramIndex: number = this._partGroups.at(i).parameterIndex; - - if(model.getParameterValueByIndex(paramIndex) > Epsilon) - { - if(visiblePartIndex >= 0) - { - break; - } - - visiblePartIndex = i; - newOpacity = model.getPartOpacityByIndex(partIndex); - - // 新しい不透明度を計算 - newOpacity += (deltaTimeSeconds / this._fadeTimeSeconds); - - if(newOpacity > 1.0) - { - newOpacity = 1.0; - } - } - } - - if(visiblePartIndex < 0) - { - visiblePartIndex = 0; - newOpacity = 1.0; - } - - // 表示パーツ、非表示パーツの不透明度を設定する - for(let i: number = beginIndex; i < beginIndex + partGroupCount; ++i) - { - const partsIndex: number = this._partGroups.at(i).partIndex; - - // 表示パーツの設定 - if(visiblePartIndex == i) - { - model.setPartOpacityByIndex(partsIndex, newOpacity); // 先に設定 - } - // 非表示パーツの設定 - else - { - let opacity: number = model.getPartOpacityByIndex(partsIndex); - let a1: number; // 計算によって求められる不透明度 - - if(newOpacity < phi) - { - a1 = newOpacity * (phi - 1) / phi + 1.0; // (0,1),(phi,phi)を通る直線式 - } - else - { - a1 = (1 - newOpacity) * phi / (1.0 - phi); // (1,0),(phi,phi)を通る直線式 - } - - // 背景の見える割合を制限する場合 - const backOpacity: number = (1.0 - a1) * (1.0 - newOpacity); - - if(backOpacity > backOpacityThreshold) - { - a1 = 1.0 - backOpacityThreshold / (1.0 - newOpacity); - } - - if(opacity > a1) - { - opacity = a1; // 計算の不透明度よりも大きければ(濃ければ)不透明度を上げる - } - - model.setPartOpacityByIndex(partsIndex, opacity); - } - } - } - - /** - * コンストラクタ - */ - public constructor() - { - this._fadeTimeSeconds = DefaultFadeInSeconds; - this._lastModel = null; - this._partGroups = new csmVector(); - this._partGroupCounts = new csmVector(); - } - - _partGroups: csmVector; // パーツグループ - _partGroupCounts: csmVector; // それぞれのパーツグループの個数 - _fadeTimeSeconds: number; // フェード時間[秒] - _lastModel: CubismModel; // 前回操作したモデル - } - - export namespace CubismPose - { - /** - * パーツにまつわるデータを管理 - */ - export class PartData - { - /** - * コンストラクタ - */ - constructor(v?: PartData) - { - this.parameterIndex = 0; - this.partIndex = 0; - this.link = new csmVector(); - - if(v != undefined) - { - this.partId = v.partId; - - for(const ite: csmVector.iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) - { - this.link.pushBack(ite.ptr().clone()); - } - } - } - - /** - * =演算子のオーバーロード - */ - public assignment(v: PartData): PartData - { - this.partId = v.partId; - - for(const ite: csmVector.iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) - { - this.link.pushBack(ite.ptr().clone()); - } - - return this; - } - - /** - * 初期化 - * @param model 初期化に使用するモデル - */ - public initialize(model: CubismModel): void - { - this.parameterIndex = model.getParameterIndex(this.partId); - this.partIndex = model.getPartIndex(this.partId); - - model.setParameterValueByIndex(this.parameterIndex, 1); - } - - /** - * オブジェクトのコピーを生成する - */ - public clone(): PartData - { - let clonePartData: PartData = new PartData(); - - clonePartData.partId = this.partId; - clonePartData.parameterIndex = this.parameterIndex; - clonePartData.partIndex = this.partIndex; - clonePartData.link = new csmVector(); - - for(let ite: csmVector.iterator = this.link.begin(); ite.notEqual(this.link.end()); ite.increment()) - { - clonePartData.link.pushBack(ite.ptr().clone()); - } - - return clonePartData; - } - - partId: CubismIdHandle; // パーツID - parameterIndex: number; // パラメータのインデックス - partIndex: number; // パーツのインデックス - link: csmVector; // 連動するパラメータ - } - } -} \ No newline at end of file diff --git a/Framework/icubismallcator.ts b/Framework/icubismallcator.ts deleted file mode 100644 index 93fd333..0000000 --- a/Framework/icubismallcator.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -export namespace Live2DCubismFramework -{ - /** - * メモリアロケーションを抽象化したクラス - * - * メモリ確保・解放処理をプラットフォーム側で実装して - * フレームワークから呼び出すためのインターフェース - */ - export abstract class ICubismAllocator - { - /** - * アラインメント制約なしのヒープ・メモリーを確保します - * - * @param size 確保するバイト数 - * @return 成功すると割り当てられたメモリのアドレス。そうでなければ'0'を返す - */ - public abstract allocate(size: number): any; - - /** - * アラインメント制約なしのヒープ・メモリーを解放します。 - * - * @param memory 解放するメモリのアドレス - */ - public abstract deallocate(memory: any): void; - - /** - * アラインメント制約有のヒープ・メモリーを確保します。 - * @param size 確保するバイト数 - * @param alignment メモリーブロックのアラインメント幅 - * @return 成功すると割り当てられたメモリのアドレス。そうでなければ'0'を返す - */ - public abstract allocateAligned(size: number, alignment: number): any; - - /** - * アラインメント制約ありのヒープ・メモリーを解放します。 - * @param alignedMemory 解放するメモリのアドレス - */ - public abstract deallocateAligned(alignedMemory: any): void; - } -} diff --git a/Framework/icubismmodelsetting.ts b/Framework/icubismmodelsetting.ts deleted file mode 100644 index 943838b..0000000 --- a/Framework/icubismmodelsetting.ts +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismid} from './id/cubismid'; -import {Live2DCubismFramework as csmmap} from './type/csmmap'; -import csmMap = csmmap.csmMap; -import CubismIdHandle = cubismid.CubismIdHandle; - -export namespace Live2DCubismFramework -{ - /** - * モデル設定情報を取り扱う関数を宣言した純粋仮想クラス。 - * - * このクラスを継承することで、モデル設定情報を取り扱うクラスになる。 - */ - export abstract class ICubismModelSetting - { - /** - * Mocファイルの名前を取得する - * @return Mocファイルの名前 - */ - public abstract getModelFileName(): string; - - /** - * モデルが使用するテクスチャの数を取得する - * テクスチャの数 - */ - public abstract getTextureCount(): number; - - /** - * テクスチャが配置されたディレクトリの名前を取得する - * @return テクスチャが配置されたディレクトリの名前 - */ - public abstract getTextureDirectory(): string; - - /** - * モデルが使用するテクスチャの名前を取得する - * @param index 配列のインデックス値 - * @return テクスチャの名前 - */ - public abstract getTextureFileName(index: number): string; - - /** - * モデルに設定された当たり判定の数を取得する - * @return モデルに設定された当たり判定の数 - */ - public abstract getHitAreasCount(): number; - - /** - * 当たり判定に設定されたIDを取得する - * - * @param index 配列のindex - * @return 当たり判定に設定されたID - */ - public abstract getHitAreaId(index: number): CubismIdHandle; - - /** - * 当たり判定に設定された名前を取得する - * @param index 配列のインデックス値 - * @return 当たり判定に設定された名前 - */ - public abstract getHitAreaName(index: number): string; - - /** - * 物理演算設定ファイルの名前を取得する - * @return 物理演算設定ファイルの名前 - */ - public abstract getPhysicsFileName(): string; - - /** - * パーツ切り替え設定ファイルの名前を取得する - * @return パーツ切り替え設定ファイルの名前 - */ - public abstract getPoseFileName(): string; - - /** - * 表情設定ファイルの数を取得する - * @return 表情設定ファイルの数 - */ - public abstract getExpressionCount(): number; - - /** - * 表情設定ファイルを識別する名前(別名)を取得する - * @param index 配列のインデックス値 - * @return 表情の名前 - */ - public abstract getExpressionName(index: number): string; - - /** - * 表情設定ファイルの名前を取得する - * @param index 配列のインデックス値 - * @return 表情設定ファイルの名前 - */ - public abstract getExpressionFileName(index: number): string; - - /** - * モーショングループの数を取得する - * @return モーショングループの数 - */ - public abstract getMotionGroupCount(): number; - - /** - * モーショングループの名前を取得する - * @param index 配列のインデックス値 - * @return モーショングループの名前 - */ - public abstract getMotionGroupName(index: number): string; - - /** - * モーショングループに含まれるモーションの数を取得する - * @param groupName モーショングループの名前 - * @return モーショングループの数 - */ - public abstract getMotionCount(groupName: string): number; - - /** - * グループ名とインデックス値からモーションファイル名を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return モーションファイルの名前 - */ - public abstract getMotionFileName(groupName: string, index: number): string; - - /** - * モーションに対応するサウンドファイルの名前を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return サウンドファイルの名前 - */ - public abstract getMotionSoundFileName(groupName: string, index: number): string; - - /** - * モーション開始時のフェードイン処理時間を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return フェードイン処理時間[秒] - */ - public abstract getMotionFadeInTimeValue(groupName: string, index: number): number; - - /** - * モーション終了時のフェードアウト処理時間を取得する - * @param groupName モーショングループの名前 - * @param index 配列のインデックス値 - * @return フェードアウト処理時間[秒] - */ - public abstract getMotionFadeOutTimeValue(groupName: string, index: number): number; - - /** - * ユーザーデータのファイル名を取得する - * @return ユーザーデータのファイル名 - */ - public abstract getUserDataFile(): string; - - /** - * レイアウト情報を取得する - * @param outLayoutMap csmMapクラスのインスタンス - * @return true レイアウト情報が存在する - * @return false レイアウト情報が存在しない - */ - public abstract getLayoutMap(outLayoutMap: csmMap): boolean; - - - /** - * 目パチに関連付けられたパラメータの数を取得する - * @return 目パチに関連付けられたパラメータの数 - */ - public abstract getEyeBlinkParameterCount(): number; - - /** - * 目パチに関連付けられたパラメータのIDを取得する - * @param index 配列のインデックス値 - * @return パラメータID - */ - public abstract getEyeBlinkParameterId(index: number): CubismIdHandle; - - /** - * リップシンクに関連付けられたパラメータの数を取得する - * @return リップシンクに関連付けられたパラメータの数 - */ - public abstract getLipSyncParameterCount(): number; - - /** - * リップシンクに関連付けられたパラメータの数を取得する - * @param index 配列のインデックス値 - * @return パラメータID - */ - public abstract getLipSyncParameterId(index: number): CubismIdHandle; - } -} \ No newline at end of file diff --git a/Framework/id/cubismid.ts b/Framework/id/cubismid.ts deleted file mode 100644 index 3ab56fb..0000000 --- a/Framework/id/cubismid.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as csmstring} from "../type/csmstring"; -import csmString = csmstring.csmString; - -export namespace Live2DCubismFramework -{ - /** - * パラメータ名・パーツ名・Drawable名を保持 - * - * パラメータ名・パーツ名・Drawable名を保持するクラス。 - */ - export class CubismId - { - /** - * ID名を取得する - */ - public getString(): csmString - { - return this._id; - } - - /** - * コンストラクタ - */ - public constructor(id: string | csmString) - { - if(typeof(id) === 'string') - { - this._id = new csmString(id); - return; - } - - this._id = id; - } - - /** - * idを比較 - * @param c 比較するid - * @return 同じならばtrue,異なっていればfalseを返す - */ - public isEqual(c: string | csmString | CubismId): boolean - { - if (typeof(c) === 'string') - { - return this._id.isEqual(c); - } - else if (c instanceof csmString) - { - return this._id.isEqual(c.s); - } - else if (c instanceof CubismId) - { - return this._id.isEqual(c._id.s); - } - return false; - } - - /** - * idを比較 - * @param c 比較するid - * @return 同じならばtrue,異なっていればfalseを返す - */ - public isNotEqual(c: string | csmString | CubismId): boolean - { - if (typeof(c) == 'string') - { - return !this._id.isEqual(c); - } - else if (c instanceof csmString) - { - return !this._id.isEqual(c.s); - } - else if (c instanceof CubismId) - { - return !this._id.isEqual(c._id.s); - } - return false; - } - - private _id: csmString; // ID名 - } - - export declare type CubismIdHandle = CubismId; -} \ No newline at end of file diff --git a/Framework/id/cubismidmanager.ts b/Framework/id/cubismidmanager.ts deleted file mode 100644 index 012c70f..0000000 --- a/Framework/id/cubismidmanager.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {Live2DCubismFramework as cubismid} from "./cubismid"; -import {Live2DCubismFramework as csmstring} from "../type/csmstring"; -import csmString = csmstring.csmString; -import CubismId = cubismid.CubismId; -import csmVector = csmvector.csmVector; - -export namespace Live2DCubismFramework -{ - /** - * ID名の管理 - * - * ID名を管理する。 - */ - export class CubismIdManager - { - /** - * コンストラクタ - */ - public constructor() - { - this._ids = new csmVector(); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - for(let i: number = 0; i < this._ids.getSize(); ++i) - { - this._ids.set(i, void 0); - } - this._ids = null; - } - - /** - * ID名をリストから登録 - * - * @param ids ID名リスト - * @param count IDの個数 - */ - public registerIds(ids: string[] | csmString[]): void - { - for(let i: number = 0; i < ids.length; i++) - { - this.registerId(ids[i]); - } - } - - /** - * ID名を登録 - * - * @param id ID名 - */ - public registerId(id: string | csmString): CubismId - { - let result: CubismId = null; - - if ('string' == typeof(id)) - { - if ((result = this.findId(id)) != null) - { - return result; - } - - result = new CubismId(id); - this._ids.pushBack(result); - } - else - { - return this.registerId(id.s); - } - - return result; - } - - /** - * ID名からIDを取得する - * - * @param id ID名 - */ - public getId(id: csmString | string): CubismId - { - return this.registerId(id); - } - - /** - * ID名からIDの確認 - * - * @return true 存在する - * @return false 存在しない - */ - public isExist(id: csmString | string): boolean - { - if ('string' == typeof(id)) - { - return (this.findId(id) != null); - } - return this.isExist(id.s); - } - - /** - * ID名からIDを検索する。 - * - * @param id ID名 - * @return 登録されているID。なければNULL。 - */ - private findId(id: string): CubismId - { - for(let i: number = 0; i < this._ids.getSize(); ++i) - { - if(this._ids.at(i).getString().isEqual(id)) - { - return this._ids.at(i); - } - } - - return null; - } - - private _ids: csmVector; // 登録されているIDのリスト - } -} \ No newline at end of file diff --git a/Framework/live2dcubismframework.ts b/Framework/live2dcubismframework.ts deleted file mode 100644 index 956bb5a..0000000 --- a/Framework/live2dcubismframework.ts +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismjson} from "./utils/cubismjson"; -import {Live2DCubismFramework as cubismidmanager} from "./id/cubismidmanager"; -import {Live2DCubismFramework as cubismrenderer} from "./rendering/cubismrenderer"; -import {CubismLogInfo, CubismLogWarning, CSM_ASSERT} from "./utils/cubismdebug"; -import Value = cubismjson.Value; -import CubismIdManager = cubismidmanager.CubismIdManager; -import CubismRenderer = cubismrenderer.CubismRenderer; - -export function strtod(s: string, endPtr: string[]): number -{ - let index: number = 0; - for(let i: number = 1; ; i++) - { - let testC: string = s.slice(i - 1, i); - - // 指数・マイナスの可能性があるのでスキップする - if(testC=='e' || testC=='-' || testC == 'E') - { - continue; - } - -    // 文字列の範囲を広げていく - let test: string = s.substring(0, i); - let number: number = Number(test); - if(isNaN(number)) - { -     // 数値として認識できなくなったので終了 - break; - } - -    // 最後に数値としてできたindexを格納しておく - index = i; - } - let d = parseFloat(s); // パースした数値 - - if(isNaN(d)) - { -     // 数値として認識できなくなったので終了 - d = NaN; - } - - endPtr[0] = s.slice(index); // 後続の文字列 - - return d; -} - -export namespace Live2DCubismFramework -{ - // ファイルスコープの変数を初期化 - - let s_isStarted: boolean = false; - let s_isInitialized: boolean = false; - let s_option: Option = null; - let s_cubismIdManager: CubismIdManager = null; - - /** - * Framework内で使う定数の宣言 - */ - export namespace Constant - { - export const vertexOffset: number = 0; // メッシュ頂点のオフセット値 - export const vertexStep: number = 2; // メッシュ頂点のステップ値 - } - - export function csmDelete(address: T): void - { - if(!address) - { - return; - } - - address = void 0; - } - - /** - * Live2D Cubism3 Original Workflow SDKのエントリポイント - * 利用開始時はCubismFramework.initialize()を呼び、CubismFramework.dispose()で終了する。 - */ - export class CubismFramework - { - /** - * @brief Cubism FrameworkのAPIを使用可能にする。
- * APIを実行する前に必ずこの関数を実行すること。
- * 引数に必ずメモリアロケータを渡してください。
- * 一度準備が完了して以降は、再び実行しても内部処理がスキップされます。 - * - * @param allocator ICubismAllocatorクラスのインスタンス - * @param option Optionクラスのインスタンス - * - * @return 準備処理が完了したらtrueが返ります。 - */ - public static startUp(option: Option = null): boolean - { - if(s_isStarted) - { - CubismLogInfo("CubismFramework::StartUp() is already done."); - return s_isStarted; - } - - s_option = option; - - if(s_option != null) - { - // TODO Core::csmSetLogFunction(s_option->LogFunction); - } - - s_isStarted = true; - - // Live2D Cubism Coreバージョン情報を表示 - if(s_isStarted) - { - const version: number = 1; // TODO Core::csmGetVersion() - const major: number = ((version & 0xFF000000) >> 24); - const minor: number = ((version & 0x00FF0000) >> 16); - const patch: number = ((version & 0x0000FFFF)); - const versionNumber: number = version; - - CubismLogInfo("Live2D Cubism Core version: %02d.%02d.%04d (%d)", major, minor, patch, versionNumber); - } - - CubismLogInfo("CubismFramework::StartUp() is complete."); - - return s_isStarted; - } - - /** - * StartUp()で初期化したCubismFrameworkの各パラメータをクリアします。 - * Dispose()したCubismFrameworkを再利用する際に利用してください。 - */ - public static cleanUp(): void - { - s_isStarted = false; - s_isInitialized = false; - s_option = null; - s_cubismIdManager = null; - } - - /** - * Cubism Framework内のリソースを初期化してモデルを表示可能な状態にします。
- * 再度Initialize()するには先にDispose()を実行する必要があります。 - */ - public static initialize(): void - { - CSM_ASSERT(s_isStarted); - if(!s_isStarted) - { - CubismLogWarning("CubismFramework is not started."); - return; - } - - // --- s_isInitializedによる連続初期化ガード --- - // 連続してリソース確保が行われないようにする。 - // 再度Initialize()するには先にDispose()を実行する必要がある。 - if (s_isInitialized) - { - CubismLogWarning("CubismFramework::Initialize() skipped, already initialized."); - return; - } - - //---- static 初期化 ---- - Value.staticInitializeNotForClientCall(); - - s_cubismIdManager = new CubismIdManager(); - - s_isInitialized = true; - - CubismLogInfo("CubismFramework::Initialize() is complete."); - } - - /** - * Cubism Framework内の全てのリソースを解放します。 - * ただし、外部で確保されたリソースについては解放しません。 - * 外部で適切に破棄する必要があります。 - */ - public static dispose(): void - { - CSM_ASSERT(s_isStarted); - if(!s_isStarted) - { - CubismLogWarning("CubismFramework is not started."); - return; - } - - // --- s_isInitializedによる未初期化解放ガード --- - // dispose()するには先にinitialize()を実行する必要がある。 - if(!s_isInitialized) // false...リソース未確保の場合 - { - CubismLogWarning("CubismFramework::Dispose() skipped, not initialized."); - return; - } - - Value.staticReleaseNotForClientCall(); - - s_cubismIdManager.release(); - s_cubismIdManager = void 0; - - // レンダラの静的リソース(シェーダプログラム他)を解放する - CubismRenderer.StaticRelease(); - - s_isInitialized = false; - - CubismLogInfo("CubismFramework::Dispose() is complete."); - } - - /** - * 現在のログ出力レベル設定の値を返す。 - * - * @return 現在のログ出力レベル設定の値 - */ - public static getLoggingLevel(): Option.LogLevel - { - if (s_option != null) - { - return s_option.loggingLevel; - } - return Option.LogLevel.LogLevel_Off; - } - - /** - * Cubism FrameworkのAPIを使用する準備が完了したかどうか - * @return APIを使用する準備が完了していればtrueが返ります。 - */ - public static isStarted(): boolean - { - return s_isStarted; - } - - /** - * Cubism Frameworkのリソース初期化がすでに行われているかどうか - * @return リソース確保が完了していればtrueが返ります - */ - public static isInitialized(): boolean - { - return s_isInitialized; - } - - /** - * IDマネージャのインスタンスを取得する - * @return CubismManagerクラスのインスタンス - */ - public static getIdManager(): CubismIdManager - { - return s_cubismIdManager; - } - - /** - * 静的クラスとして使用する - * インスタンス化させない - */ - private constructor() - { - - } - } -} - -export class Option -{ - loggingLevel: Option.LogLevel; // ログ出力レベルの設定 -} - -/** - * ログ出力のレベル - */ -export namespace Option -{ - export enum LogLevel - { - LogLevel_Verbose = 0, // 詳細ログ - LogLevel_Debug, // デバッグログ - LogLevel_Info, // Infoログ - LogLevel_Warning, // 警告ログ - LogLevel_Error, // エラーログ - LogLevel_Off // ログ出力無効 - } -} diff --git a/Framework/math/cubismmath.ts b/Framework/math/cubismmath.ts deleted file mode 100644 index 6e62b58..0000000 --- a/Framework/math/cubismmath.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismvector2} from "./cubismvector2"; -import CubismVector2 = cubismvector2.CubismVector2; - -export namespace Live2DCubismFramework -{ - /** - * 数値計算などに使用するユーティリティクラス - */ - export class CubismMath - { - /** - * 第一引数の値を最小値と最大値の範囲に収めた値を返す - * - * @param value 収められる値 - * @param min 範囲の最小値 - * @param max 範囲の最大値 - * @return 最小値と最大値の範囲に収めた値 - */ - static range(value: number, min: number, max: number): number - { - if (value < min) - { - value = min; - } - else if (value > max) - { - value = max; - } - - return value; - } - - /** - * サイン関数の値を求める - * - * @param x 角度値(ラジアン) - * @return サイン関数sin(x)の値 - */ - static sin(x: number): number - { - return Math.sin(x); - } - - /** - * コサイン関数の値を求める - * - * @param x 角度値(ラジアン) - * @return コサイン関数cos(x)の値 - */ - static cos(x: number): number - { - return Math.cos(x); - } - - /** - * 値の絶対値を求める - * - * @param x 絶対値を求める値 - * @return 値の絶対値 - */ - static abs(x: number): number - { - return Math.abs(x); - } - - /** - * 平方根(ルート)を求める - * @param x -> 平方根を求める値 - * @return 値の平方根 - */ - static sqrt(x: number): number - { - return Math.sqrt(x); - } - - /** - * イージング処理されたサインを求める - * フェードイン・アウト時のイージングに利用できる - * - * @param value イージングを行う値 - * @return イージング処理されたサイン値 - */ - static getEasingSine(value: number): number - { - if (value < 0.0) - { - return 0.0; - } - else if (value > 1.0) - { - return 1.0; - } - - return 0.5 - 0.5 * this.cos(value * Math.PI); - } - - /** - * 大きい方の値を返す - * - * @param left 左辺の値 - * @param right 右辺の値 - * @return 大きい方の値 - */ - static max(left: number, right: number): number - { - return (left > right) - ? left - : right; - } - - /** - * 小さい方の値を返す - * - * @param left 左辺の値 - * @param right 右辺の値  - * @return 小さい方の値 - */ - static min(left: number, right: number): number - { - return (left > right) - ? right - : left; - } - - /** - * 角度値をラジアン値に変換する - * - * @param degrees 角度値 - * @return 角度値から変換したラジアン値 - */ - static degreesToRadian(degrees: number): number - { - return (degrees / 180.0) * Math.PI; - } - - /** - * ラジアン値を角度値に変換する - * - * @param radian ラジアン値 - * @return ラジアン値から変換した角度値 - */ - static radianToDegrees(radian: number): number - { - return (radian * 180.0) / Math.PI; - } - - /** - * 2つのベクトルからラジアン値を求める - * - * @param from 始点ベクトル - * @param to 終点ベクトル - * @return ラジアン値から求めた方向ベクトル - */ - static directionToRadian(from: CubismVector2, to: CubismVector2): number - { - const q1: number = Math.atan2(to.y, to.x); - const q2: number = Math.atan2(from.y, from.x); - - let ret: number = q1 - q2; - - while(ret < -Math.PI) - { - ret += Math.PI * 2.0; - } - - while(ret > Math.PI) - { - ret -= Math.PI * 2.0; - } - - return ret; - } - - /** - * 2つのベクトルから角度値を求める - * - * @param from 始点ベクトル - * @param to 終点ベクトル - * @return 角度値から求めた方向ベクトル - */ - static directionToDegrees(from: CubismVector2, to: CubismVector2): number - { - const radian: number = this.directionToRadian(from, to); - let degree: number = this.radianToDegrees(radian); - - if ((to.x - from.x) > 0.0) - { - degree = -degree; - } - - return degree; - } - - /** - * ラジアン値を方向ベクトルに変換する。 - * - * @param totalAngle ラジアン値 - * @return ラジアン値から変換した方向ベクトル - */ - - static radianToDirection(totalAngle: number): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(); - - ret.x = this.sin(totalAngle); - ret.y = this.cos(totalAngle); - - return ret; - } - - /** - * コンストラクタ - */ - private constructor() - { - - } - } -} \ No newline at end of file diff --git a/Framework/math/cubismmatrix44.ts b/Framework/math/cubismmatrix44.ts deleted file mode 100644 index bef0756..0000000 --- a/Framework/math/cubismmatrix44.ts +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -export namespace Live2DCubismFramework -{ - /** - * 4x4の行列 - * - * 4x4行列の便利クラス。 - */ - export class CubismMatrix44 - { - /** - * コンストラクタ - */ - public constructor() - { - this._tr = new Float32Array(16); // 4 * 4のサイズ - this.loadIdentity(); - } - - /** - * 受け取った2つの行列の乗算を行う。 - * - * @param a 行列a - * @param b 行列b - * @return 乗算結果の行列 - */ - public static multiply(a: Float32Array, b: Float32Array, dst: Float32Array): void - { - let c: Float32Array = new Float32Array( - [ - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0 - ] - ); - - let n: number = 4; - - for (let i: number = 0; i < n; ++i) - { - for(let j: number = 0; j < n; ++j) - { - for(let k: number = 0; k < n; ++k) - { - c[j + i * 4] += a[k + i * 4] * b[j + k * 4]; - } - } - } - - for(let i: number = 0; i < 16; ++i) - { - dst[i] = c[i]; - } - } - - /** - * 単位行列に初期化する - */ - public loadIdentity(): void - { - let c: Float32Array = new Float32Array( - [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ] - ); - - this.setMatrix(c); - } - - /** - * 行列を設定 - * - * @param tr 16個の浮動小数点数で表される4x4の行列 - */ - public setMatrix(tr: Float32Array): void - { - for(let i = 0; i < 16; ++i) - { - this._tr[i] = tr[i]; - } - } - - /** - * 行列を浮動小数点数の配列で取得 - * - * @return 16個の浮動小数点数で表される4x4の行列 - */ - public getArray(): Float32Array - { - return this._tr; - } - - /** - * X軸の拡大率を取得 - * @return X軸の拡大率 - */ - public getScaleX(): number - { - return this._tr[0]; - } - - /** - * Y軸の拡大率を取得する - * - * @return Y軸の拡大率 - */ - public getScaleY(): number - { - return this._tr[5]; - } - - /** - * X軸の移動量を取得 - * @return X軸の移動量 - */ - public getTranslateX(): number - { - return this._tr[12]; - } - - /** - * Y軸の移動量を取得 - * @return Y軸の移動量 - */ - public getTranslateY(): number - { - return this._tr[13]; - } - - /** - * X軸の値を現在の行列で計算 - * - * @param src X軸の値 - * @return 現在の行列で計算されたX軸の値 - */ - public transformX(src: number): number - { - return this._tr[0] * src + this._tr[12]; - } - - /** - * Y軸の値を現在の行列で計算 - * - * @param src Y軸の値 - * @return 現在の行列で計算されたY軸の値 - */ - public transformY(src: number): number - { - return this._tr[5] * src + this._tr[13]; - } - - /** - * X軸の値を現在の行列で逆計算 - */ - public invertTransformX(src: number): number - { - return (src - this._tr[12]) / this._tr[0]; - } - - /** - * Y軸の値を現在の行列で逆計算 - */ - public invertTransformY(src: number): number - { - return (src - this._tr[13]) / this._tr[5]; - } - - /** - * 現在の行列の位置を起点にして移動 - * - * 現在の行列の位置を起点にして相対的に移動する。 - * - * @param x X軸の移動量 - * @param y Y軸の移動量 - */ - public translateRelative(x: number, y: number): void - { - let tr1: Float32Array = new Float32Array( - [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - x, y, 0.0, 1.0 - ] - ); - - CubismMatrix44.multiply(tr1, this._tr, this._tr); - } - - /** - * 現在の行列の位置を移動 - * - * 現在の行列の位置を指定した位置へ移動する - * - * @param x X軸の移動量 - * @param y y軸の移動量 - */ - public translate(x: number, y: number): void - { - this._tr[12] = x; - this._tr[13] = y; - } - - /** - * 現在の行列のX軸の位置を指定した位置へ移動する - * - * @param x X軸の移動量 - */ - public translateX(x: number): void - { - this._tr[12] = x; - } - - /** - * 現在の行列のY軸の位置を指定した位置へ移動する - * - * @param y Y軸の移動量 - */ - public translateY(y: number): void - { - this._tr[13] = y; - } - - - /** - * 現在の行列の拡大率を相対的に設定する - * - * @param x X軸の拡大率 - * @param y Y軸の拡大率 - */ - public scaleRelative(x: number, y:number): void - { - let tr1: Float32Array = new Float32Array( - [ - x, 0.0, 0.0, 0.0, - 0.0, y, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ] - ); - - CubismMatrix44.multiply(tr1, this._tr, this._tr); - } - - /** - * 現在の行列の拡大率を指定した倍率に設定する - * - * @param x X軸の拡大率 - * @param y Y軸の拡大率 - */ - public scale(x: number, y: number): void - { - this._tr[0] = x; - this._tr[5] = y; - } - - /** - * 現在の行列に行列を乗算 - * - * @param m 行列 - */ - public multiplyByMatrix(m: CubismMatrix44): void - { - CubismMatrix44.multiply(m.getArray(), this._tr, this._tr); - } - - protected _tr: Float32Array; // 4x4行列データ - } -} \ No newline at end of file diff --git a/Framework/math/cubismmodelmatrix.ts b/Framework/math/cubismmodelmatrix.ts deleted file mode 100644 index aa694be..0000000 --- a/Framework/math/cubismmodelmatrix.ts +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as csmmap} from "../type/csmmap"; -import {Live2DCubismFramework as cubismmatrix44} from "./cubismmatrix44"; -import csmMap = csmmap.csmMap; -import CubismMatrix44 = cubismmatrix44.CubismMatrix44; - - -export namespace Live2DCubismFramework -{ - /** - * モデル座標設定用の4x4行列 - * - * モデル座標設定用の4x4行列クラス - */ - export class CubismModelMatrix extends CubismMatrix44 - { - /** - * コンストラクタ - * - * @param w 横幅 - * @param h 縦幅 - */ - constructor(w?: number, h?: number) - { - super(); - - this._width = (w !== undefined) - ? w - : 0.0; - this._height = (h !== undefined) - ? h - : 0.0; - - // 原点(0, 0)を中心にして、画面に納まるような大きさで初期化 - if (this._width > this._height) - { - this.setWidth(this._height / this._width); - } - else - { - this.setHeight(1.0); - } - } - - /** - * 横幅を設定 - * - * @param w 横幅 - */ - public setWidth(w: number): void - { - const scaleX: number = w / this._width; - const scaleY: number = scaleX; - this.scale(scaleX, scaleY); - } - - /** - * 縦幅を設定 - * @param h 縦幅 - */ - public setHeight(h: number): void - { - const scaleX: number = h / this._height; - const scaleY: number = scaleX; - this.scale(scaleX, scaleY); - } - - /** - * 位置を設定 - * - * @param x X軸の位置 - * @param y Y軸の位置 - */ - public setPosition(x: number, y: number): void - { - this.translate(x, y); - } - - /** - * 中心位置を設定 - * - * @param x X軸の中心位置 - * @param y Y軸の中心位置 - * - * @note widthかheightを設定したあとでないと、拡大率が正しく取得できないためずれる。 - */ - public setCenterPosition(x: number, y: number) - { - this.centerX(x); - this.centerY(y); - } - - /** - * 上辺の位置を設定する - * - * @param y 上辺のY軸位置 - */ - public top(y: number): void - { - this.setY(y); - } - - /** - * 下辺の位置を設定する - * - * @param y 下辺のY軸位置 - */ - public bottom(y: number) - { - const h: number = this._height * this.getScaleY(); - - this.translateY(y - h); - } - - /** - * 左辺の位置を設定 - * - * @param x 左辺のX軸位置 - */ - public left(x: number): void - { - this.setX(x); - } - - /** - * 右辺の位置を設定 - * - * @param x 右辺のX軸位置 - */ - public right(x: number): void - { - const w = this._width * this.getScaleX(); - - this.translateX(x - w); - } - - /** - * X軸の中心位置を設定 - * - * @param x X軸の中心位置 - */ - public centerX(x: number): void - { - const w = this._width * this.getScaleX(); - - this.translateX(x - (w / 2.0)); - } - - /** - * X軸の位置を設定 - * - * @param x X軸の位置 - */ - public setX(x: number): void - { - this.translateX(x); - } - - /** - * Y軸の中心位置を設定 - * - * @param y Y軸の中心位置 - */ - public centerY(y: number): void - { - const h: number = this._height * this.getScaleY(); - - this.translateY(y - (h / 2.0)); - } - - /** - * Y軸の位置を設定する - * - * @param y Y軸の位置 - */ - public setY(y: number): void - { - this.translateY(y); - } - - /** - * レイアウト情報から位置を設定 - * - * @param layout レイアウト情報 - */ - public setupFromLayout(layout: csmMap): void - { - const keyWidth = "width"; - const keyHeight = "height"; - const keyX = "x"; - const keyY = "y"; - const keyCenterX = "center_x"; - const keyCenterY = "center_y"; - const keyTop = "top"; - const keyBottom = "bottom"; - const keyLeft = "left"; - const keyRight = "right"; - - for(const ite: csmMap.iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) - { - const key: string = ite.ptr().first; - const value: number = ite.ptr().second; - - if(key == keyWidth) - { - this.setWidth(value); - } - else if(key == keyHeight) - { - this.setHeight(value); - } - } - - for(const ite: csmMap.iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) - { - const key: string = ite.ptr().first; - const value: number = ite.ptr().second; - - if(key == keyX) - { - this.setX(value); - } - else if(key == keyY) - { - this.setY(value); - } - else if(key == keyCenterX) - { - this.centerX(value); - } - else if(key == keyCenterY) - { - this.centerY(value); - } - else if(key == keyTop) - { - this.top(value); - } - else if(key == keyBottom) - { - this.bottom(value); - } - else if(key == keyLeft) - { - this.left(value); - } - else if(key == keyRight) - { - this.right(value); - } - } - } - - private _width: number; // 横幅 - private _height: number; // 縦幅 - } -} \ No newline at end of file diff --git a/Framework/math/cubismtargetpoint.ts b/Framework/math/cubismtargetpoint.ts deleted file mode 100644 index f27f3f6..0000000 --- a/Framework/math/cubismtargetpoint.ts +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismmath} from "./cubismmath"; -import CubismMath = cubismmath.CubismMath; - - -export namespace Live2DCubismFramework -{ - const FrameRate: number = 30; - const Epsilon: number = 0.01; - - /** - * 顔の向きの制御機能 - * - * 顔の向きの制御機能を提供するクラス。 - */ - export class CubismTargetPoint - { - /** - * コンストラクタ - */ - public constructor() - { - this._faceTargetX = 0.0; - this._faceTargetY = 0.0; - this._faceX = 0.0; - this._faceY = 0.0; - this._faceVX = 0.0; - this._faceVY = 0.0; - this._lastTimeSeconds = 0.0; - this._userTimeSeconds = 0.0; - } - - /** - * 更新処理 - */ - public update(deltaTimeSeconds: number): void - { - // デルタ時間を加算する - this._userTimeSeconds += deltaTimeSeconds; - - // 首を中央から左右に振るときの平均的な速さは 秒速度。加速・減速を考慮して、その2倍を最高速度とする - // 顔の振り具合を、中央(0.0)から、左右は(+-1.0)とする - const faceParamMaxV: number = 40.0 / 10.0; // 7.5秒間に40分移動(5.3/sc) - const maxV: number = faceParamMaxV * 1.0 / FrameRate; // 1frameあたりに変化できる速度の上限 - - if(this._lastTimeSeconds == 0.0) - { - this._lastTimeSeconds = this._userTimeSeconds; - return; - } - - const deltaTimeWeight: number = (this._userTimeSeconds - this._lastTimeSeconds) * FrameRate; - this._lastTimeSeconds = this._userTimeSeconds; - - // 最高速度になるまでの時間を - const timeToMaxSpeed: number = 0.15; - const frameToMaxSpeed: number = timeToMaxSpeed * FrameRate; // sec * frame/sec - const maxA: number = deltaTimeWeight * maxV / frameToMaxSpeed; // 1frameあたりの加速度 - - // 目指す向きは、(dx, dy)方向のベクトルとなる - const dx: number = this._faceTargetX - this._faceX; - const dy: number = this._faceTargetY - this._faceY; - - if(CubismMath.abs(dx) <= Epsilon && CubismMath.abs(dy) <= Epsilon) - { - return; // 変化なし - } - - // 速度の最大よりも大きい場合は、速度を落とす - const d: number = CubismMath.sqrt((dx * dx) + (dy * dy)); - - // 進行方向の最大速度ベクトル - const vx: number = maxV * dx / d; - const vy: number = maxV * dy / d; - - // 現在の速度から、新規速度への変化(加速度)を求める - let ax: number = vx - this._faceVX; - let ay: number = vy - this._faceVY; - - const a: number = CubismMath.sqrt((ax * ax) + (ay * ay)); - - // 加速のとき - if(a < -maxA || a > maxA) - { - ax *= maxA / a; - ay *= maxA / a; - } - - // 加速度を元の速度に足して、新速度とする - this._faceVX += ax; - this._faceVY += ay; - - // 目的の方向に近づいたとき、滑らかに減速するための処理 - // 設定された加速度で止まる事の出来る距離と速度の関係から - // 現在とりうる最高速度を計算し、それ以上の時は速度を落とす - // ※本来、人間は筋力で力(加速度)を調整できるため、より自由度が高いが、簡単な処理で済ませている - { - // 加速度、速度、距離の関係式。 - // 2 6 2 3 - // sqrt(a t + 16 a h t - 8 a h) - a t - // v = -------------------------------------- - // 2 - // 4 t - 2 - // (t=1) - // 時刻tは、あらかじめ加速度、速度を1/60(フレームレート、単位なし)で - // 考えているので、t=1として消してよい(※未検証) - - const maxV: number = 0.5 * (CubismMath.sqrt((maxA * maxA) + 16.0 * maxA * d - 8.0 * maxA * d) - maxA); - const curV: number = CubismMath.sqrt((this._faceVX * this._faceVX) + (this._faceVY * this._faceVY)); - - if(curV > maxV) - { - // 現在の速度 > 最高速度のとき、最高速度まで減速 - this._faceVX *= maxV / curV; - this._faceVY *= maxV / curV; - } - } - - this._faceX += this._faceVX; - this._faceY += this._faceVY; - } - - /** - * X軸の顔の向きの値を取得 - * - * @return X軸の顔の向きの値(-1.0 ~ 1.0) - */ - public getX(): number - { - return this._faceX; - } - - /** - * Y軸の顔の向きの値を取得 - * - * @return Y軸の顔の向きの値(-1.0 ~ 1.0) - */ - public getY(): number - { - return this._faceY; - } - - /** - * 顔の向きの目標値を設定 - * - * @param x X軸の顔の向きの値(-1.0 ~ 1.0) - * @param y Y軸の顔の向きの値(-1.0 ~ 1.0) - */ - public set(x: number, y: number): void - { - this._faceTargetX = x; - this._faceTargetY = y; - } - - - private _faceTargetX: number; // 顔の向きのX目標値(この値に近づいていく) - private _faceTargetY: number; // 顔の向きのY目標値(この値に近づいていく) - private _faceX: number; // 顔の向きX(-1.0 ~ 1.0) - private _faceY: number; // 顔の向きY(-1.0 ~ 1.0) - private _faceVX: number; // 顔の向きの変化速度X - private _faceVY: number; // 顔の向きの変化速度Y - private _lastTimeSeconds: number; // 最後の実行時間[秒] - private _userTimeSeconds: number; // デルタ時間の積算値[秒] - - } -} \ No newline at end of file diff --git a/Framework/math/cubismvector2.ts b/Framework/math/cubismvector2.ts deleted file mode 100644 index 2f61e90..0000000 --- a/Framework/math/cubismvector2.ts +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -export namespace Live2DCubismFramework -{ - /** - * 2次元ベクトル型 - * - * 2次元ベクトル型の機能を提供する。 - */ - export class CubismVector2 - { - /** - * コンストラクタ - */ - public constructor(public x?: number, public y?: number) - { - this.x = (x == undefined) - ? 0.0 - : x; - - this.y = (y == undefined) - ? 0.0 - : y; - } - - /** - * ベクトルの加算 - * - * @param vector2 加算するベクトル値 - * @return 加算結果 ベクトル値 - */ - public add(vector2: CubismVector2): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(0.0, 0.0); - ret.x = this.x + vector2.x; - ret.y = this.y + vector2.y; - return ret; - } - - /** - * ベクトルの減算 - * - * @param vector2 減算するベクトル値 - * @return 減算結果 ベクトル値 - */ - public substract(vector2: CubismVector2): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(0.0, 0.0); - ret.x = this.x - vector2.x; - ret.y = this.y - vector2.y; - return ret; - } - - /** - * ベクトルの乗算 - * - * @param vector2 乗算するベクトル値 - * @return 乗算結果 ベクトル値 - */ - public multiply(vector2: CubismVector2): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(0.0, 0.0); - ret.x = this.x * vector2.x; - ret.y = this.y * vector2.y; - return ret; - } - - /** - * ベクトルの乗算(スカラー) - * - * @param scalar 乗算するスカラー値 - * @return 乗算結果 ベクトル値 - */ - public multiplyByScaler(scalar: number): CubismVector2 - { - return this.multiply(new CubismVector2(scalar, scalar)); - } - - /** - * ベクトルの除算 - * - * @param vector2 除算するベクトル値 - * @return 除算結果 ベクトル値 - */ - public division(vector2: CubismVector2): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(0.0, 0.0); - ret.x = this.x / vector2.x; - ret.y = this.y / vector2.y; - return ret; - } - - /** - * ベクトルの除算(スカラー) - * - * @param scalar 除算するスカラー値 - * @return 除算結果 ベクトル値 - */ - public divisionByScalar(scalar: number): CubismVector2 - { - return this.division(new CubismVector2(scalar, scalar)); - } - - /** - * ベクトルの長さを取得する - * - * @return ベクトルの長さ - */ - public getLength(): number - { - return Math.sqrt(this.x * this.x + this.y * this.y); - } - - /** - * ベクトルの距離の取得 - * - * @param a 点 - * @return ベクトルの距離 - */ - public getDistanceWith(a: CubismVector2): number - { - return Math.sqrt(((this.x - a.x) * (this.x - a.x)) + ((this.y - a.y) * (this.y - a.y))); - } - - /** - * ドット積の計算 - * - * @param a 値 - * @return 結果 - */ - public dot(a: CubismVector2): number - { - return (this.x * a.x) + (this.y * a.y); - } - - /** - * 正規化の適用 - */ - public normalize(): void - { - const length: number = Math.pow((this.x * this.x) + (this.y * this.y), 0.5); - - this.x = this.x / length; - this.y = this.y / length; - } - - /** - * 等しさの確認(等しいか?) - * - * 値が等しいか? - * - * @param rhs 確認する値 - * @return true 値は等しい - * @return false 値は等しくない - */ - public isEqual(rhs: CubismVector2): boolean - { - return (this.x == rhs.x) && (this.y == rhs.y); - } - - /** - * 等しさの確認(等しくないか?) - * - * 値が等しくないか? - * - * @param rhs 確認する値 - * @return true 値は等しくない - * @return false 値は等しい - */ - public isNotEqual(rhs: CubismVector2): boolean - { - return !(this.isEqual(rhs)); - } - } -} \ No newline at end of file diff --git a/Framework/math/cubismviewmatrix.ts b/Framework/math/cubismviewmatrix.ts deleted file mode 100644 index 17b0acd..0000000 --- a/Framework/math/cubismviewmatrix.ts +++ /dev/null @@ -1,312 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismmatrix44} from "./cubismmatrix44"; -import CubismMatrix44 = cubismmatrix44.CubismMatrix44; - -export namespace Live2DCubismFramework -{ - /** - * カメラの位置変更に使うと便利な4x4行列 - * - * カメラの位置変更に使うと便利な4x4行列のクラス。 - */ - export class CubismViewMatrix extends CubismMatrix44 - { - - /** - * コンストラクタ - */ - public constructor() - { - super(); - this._screenLeft = 0.0; - this._screenRight = 0.0; - this._screenTop = 0.0; - this._screenBottom = 0.0; - this._maxLeft = 0.0; - this._maxRight = 0.0; - this._maxTop = 0.0; - this._maxBottom = 0.0; - this._maxScale = 0.0; - this._minScale = 0.0; - } - - /** - * 移動を調整 - * - * @param x X軸の移動量 - * @param y Y軸の移動量 - */ - public adjustTranslate(x: number, y: number): void - { - if(this._tr[0] * this._maxLeft + (this._tr[12] + x) > this._screenLeft) - { - x = this._screenLeft - this._tr[0] * this._maxLeft - this._tr[12]; - } - - if(this._tr[0] * this._maxRight + (this._tr[12] + x) < this._screenRight) - { - x = this._screenRight - this._tr[0] * this._maxRight - this._tr[12]; - } - - if(this._tr[5] * this._maxTop + (this._tr[13] + y) < this._screenTop) - { - y = this._screenTop - this._tr[5] * this._maxTop - this._tr[13]; - } - - if(this._tr[5] * this._maxBottom + (this._tr[13] + y) > this._screenBottom) - { - y = this._screenBottom - this._tr[5] * this._maxBottom - this._tr[13]; - } - - let tr1: Float32Array = new Float32Array( - [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - x, y, 0.0, 1.0 - ] - ); - - CubismMatrix44.multiply(tr1, this._tr, this._tr); - } - - /** - * 拡大率を調整 - * - * @param cx 拡大を行うX軸の中心位置 - * @param cy 拡大を行うY軸の中心位置 - * @param scale 拡大率 - */ - public adjustScale(cx: number, cy: number, scale: number): void - { - let maxScale: number = this.getMaxScale(); - let minScale: number = this.getMinScale(); - - let targetScale = scale * this._tr[0]; - - if(targetScale < minScale) - { - if(this._tr[0] > 0.0) - { - scale = minScale / this._tr[0]; - } - } - else if(targetScale > maxScale) - { - if(this._tr[0] > 0.0) - { - scale = maxScale / this._tr[0]; - } - } - - let tr1: Float32Array = new Float32Array( - [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - cx, cy, 0.0, 1.0 - ] - ); - - let tr2: Float32Array = new Float32Array( - [ - scale, 0.0, 0.0, 0.0, - 0.0, scale, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ] - ); - - let tr3: Float32Array = new Float32Array( - [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - -cx, -cy, 0.0, 1.0, - ] - ); - - CubismMatrix44.multiply(tr3, this._tr, this._tr); - CubismMatrix44.multiply(tr2, this._tr, this._tr); - CubismMatrix44.multiply(tr1, this._tr, this._tr); - } - - /** - * デバイスに対応する論理座養生の範囲の設定 - * - * @param left 左辺のX軸の位置 - * @param right 右辺のX軸の位置 - * @param bottom 下辺のY軸の位置 - * @param top 上辺のY軸の位置 - */ - public setScreenRect(left: number, right: number, bottom: number, top: number): void - { - this._screenLeft = left; - this._screenRight = right; - this._screenBottom = bottom; - this._screenTop = top; - } - - /** - * デバイスに対応する論理座標上の移動可能範囲の設定 - * @param left 左辺のX軸の位置 - * @param right 右辺のX軸の位置 - * @param bottom 下辺のY軸の位置 - * @param top 上辺のY軸の位置 - */ - public setMaxScreenRect(left: number, right: number, bottom: number, top: number): void - { - this._maxLeft = left; - this._maxRight = right; - this._maxTop = top; - this._maxBottom = bottom; - } - - /** - * 最大拡大率の設定 - * @param maxScale 最大拡大率 - */ - public setMaxScale(maxScale: number): void - { - this._maxScale = maxScale; - } - - /** - * 最小拡大率の設定 - * @param minScale 最小拡大率 - */ - public setMinScale(minScale: number): void - { - this._minScale = minScale; - } - - /** - * 最大拡大率の取得 - * @return 最大拡大率 - */ - public getMaxScale(): number - { - return this._maxScale; - } - - /** - * 最小拡大率の取得 - * @return 最小拡大率 - */ - public getMinScale(): number - { - return this._minScale; - } - - /** - * 拡大率が最大になっているかを確認する - * - * @return true 拡大率は最大 - * @return false 拡大率は最大ではない - */ - public isMaxScale(): boolean - { - return this.getScaleX() >= this._maxScale; - } - - /** - * 拡大率が最小になっているかを確認する - * - * @return true 拡大率は最小 - * @return false 拡大率は最小ではない - */ - public isMinScale(): boolean - { - return this.getScaleX() <= this._minScale; - } - - /** - * デバイスに対応する論理座標の左辺のX軸位置を取得する - * @return デバイスに対応する論理座標の左辺のX軸位置 - */ - public getScreenLeft(): number - { - return this._screenLeft; - } - - /** - * デバイスに対応する論理座標の右辺のX軸位置を取得する - * @return デバイスに対応する論理座標の右辺のX軸位置 - */ - public getScreenRight(): number - { - return this._screenRight; - } - - /** - * デバイスに対応する論理座標の下辺のY軸位置を取得する - * @return デバイスに対応する論理座標の下辺のY軸位置 - */ - public getScreenBottom(): number - { - return this._screenBottom; - } - - /** - * デバイスに対応する論理座標の上辺のY軸位置を取得する - * @return デバイスに対応する論理座標の上辺のY軸位置 - */ - public getScreenTop(): number - { - return this._screenTop; - } - - /** - * 左辺のX軸位置の最大値の取得 - * @return 左辺のX軸位置の最大値 - */ - public getMaxLeft(): number - { - return this._maxLeft; - } - - /** - * 右辺のX軸位置の最大値の取得 - * @return 右辺のX軸位置の最大値 - */ - public getMaxRight(): number - { - return this._maxRight; - } - - /** - * 下辺のY軸位置の最大値の取得 - * @return 下辺のY軸位置の最大値 - */ - public getMaxBottom(): number - { - return this._maxBottom; - } - - /** - * 上辺のY軸位置の最大値の取得 - * @return 上辺のY軸位置の最大値 - */ - public getMaxTop(): number - { - return this._maxTop; - } - - private _screenLeft: number; // デバイスに対応する論理座標上の範囲(左辺X軸位置) - private _screenRight: number; // デバイスに対応する論理座標上の範囲(右辺X軸位置) - private _screenTop: number; // デバイスに対応する論理座標上の範囲(上辺Y軸位置) - private _screenBottom: number; // デバイスに対応する論理座標上の範囲(下辺Y軸位置) - private _maxLeft: number; // 論理座標上の移動可能範囲(左辺X軸位置) - private _maxRight: number; // 論理座標上の移動可能範囲(右辺X軸位置) - private _maxTop: number; // 論理座標上の移動可能範囲(上辺Y軸位置) - private _maxBottom: number; // 論理座標上の移動可能範囲(下辺Y軸位置) - private _maxScale: number; // 拡大率の最大値 - private _minScale: number; // 拡大率の最小値 - } -} \ No newline at end of file diff --git a/Framework/model/cubismmoc.ts b/Framework/model/cubismmoc.ts deleted file mode 100644 index 2f09698..0000000 --- a/Framework/model/cubismmoc.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismmodel} from "./cubismmodel"; -import CubismModel = cubismmodel.CubismModel; -import { CSM_ASSERT } from "../utils/cubismdebug"; - -export namespace Live2DCubismFramework -{ - /** - * Mocデータの管理 - * - * Mocデータの管理を行うクラス。 - */ - export class CubismMoc - { - /** - * Mocデータの作成 - */ - public static create(mocBytes: ArrayBuffer): CubismMoc - { - let cubismMoc: CubismMoc = null; - let moc: Live2DCubismCore.Moc = Live2DCubismCore.Moc.fromArrayBuffer(mocBytes); - - if (moc) - { - cubismMoc = new CubismMoc(moc); - } - - return cubismMoc; - } - - /** - * Mocデータを削除 - * - * Mocデータを削除する - */ - public static delete(moc: CubismMoc): void - { - moc._moc._release(); - moc._moc = null; - moc = null; - } - - /** - * モデルを作成する - * - * @return Mocデータから作成されたモデル - */ - createModel(): CubismModel - { - let cubismModel: CubismModel = null; - - let model: Live2DCubismCore.Model = Live2DCubismCore.Model.fromMoc(this._moc); - - if (model) - { - cubismModel = new CubismModel(model); - cubismModel.initialize(); - - ++this._modelCount; - } - - return cubismModel; - } - - /** - * モデルを削除する - */ - deleteModel(model: CubismModel): void - { - model.release(); - model = void 0; - - --this._modelCount; - } - - - /** - * コンストラクタ - */ - private constructor(moc: Live2DCubismCore.Moc) - { - this._moc = moc; - this._modelCount = 0; - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - CSM_ASSERT(this._modelCount == 0); - - this._moc._release(); - this._moc = null; - } - - _moc: Live2DCubismCore.Moc; ///< Mocデータ - _modelCount: number; ///< Mocデータから作られたモデルの個数 - } -} \ No newline at end of file diff --git a/Framework/model/cubismmodel.ts b/Framework/model/cubismmodel.ts deleted file mode 100644 index 833520e..0000000 --- a/Framework/model/cubismmodel.ts +++ /dev/null @@ -1,803 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -/// -import {Live2DCubismFramework as cubismrenderer} from "../rendering/cubismrenderer"; -import {Live2DCubismFramework as cubismid} from "../id/cubismid"; -import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; -import {Live2DCubismFramework as csmmap} from "../type/csmmap"; -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {CSM_ASSERT} from "../utils/cubismdebug"; -import CubismFramework = cubismframework.CubismFramework; -import CubismRenderer = cubismrenderer.CubismRenderer; -import csmVector = csmvector.csmVector; -import csmMap = csmmap.csmMap; -import CubismIdHandle = cubismid.CubismIdHandle; - -export namespace Live2DCubismFramework -{ - /** - * モデル - * - * Mocデータから生成されるモデルのクラス。 - */ - export class CubismModel - { - /** - * モデルのパラメータの更新 - */ - public update(): void - { - // Update model - this._model.update(); - - this._model.drawables.resetDynamicFlags(); - } - - /** - * キャンバスの幅を取得する - */ - public getCanvasWidth(): number - { - if (this._model == null) - { - return 0.0; - } - - return this._model.canvasinfo.CanvasWidth / this._model.canvasinfo.PixelsPerUnit; - } - - /** - * キャンバスの高さを取得する - */ - public getCanvasHeight(): number - { - if (this._model == null) - { - return 0.0; - } - - return this._model.canvasinfo.CanvasHeight / this._model.canvasinfo.PixelsPerUnit; - } - - /** - * パラメータを保存する - */ - public saveParameters(): void - { - const parameterCount: number = this._model.parameters.count; - const savedParameterCount: number = this._savedParameters.getSize(); - - for (let i: number = 0; i < parameterCount; ++i) - { - if (i < savedParameterCount) - { - this._savedParameters.set(i, this._parameterValues[i]); - } - else - { - this._savedParameters.pushBack(this._parameterValues[i]); - } - } - } - - /** - * モデルを取得 - */ - public getModel(): Live2DCubismCore.Model - { - return this._model; - } - - /** - * パーツのインデックスを取得 - * @param partId パーツのID - * @return パーツのインデックス - */ - public getPartIndex(partId: CubismIdHandle): number - { - let partIndex: number; - const partCount: number = this._model.parts.count; - - for(partIndex = 0; partIndex < partCount; ++partIndex) - { - if(partId == this._partIds.at(partIndex)) - { - return partIndex; - } - } - - // モデルに存在していない場合、非存在パーツIDリスト内にあるかを検索し、そのインデックスを返す - if(this._notExistPartId.isExist(partId)) - { - return this._notExistPartId.getValue(partId); - } - - // 非存在パーツIDリストにない場合、新しく要素を追加する - partIndex = partCount + this._notExistPartId.getSize(); - this._notExistPartId.setValue(partId, partIndex); - this._notExistPartOpacities.appendKey(partIndex); - - return partIndex; - } - - /** - * パーツの個数の取得 - * @return パーツの個数 - */ - public getPartCount(): number - { - const partCount: number = this._model.parts.count; - return partCount; - } - - /** - * パーツの不透明度の設定(Index) - * @param partIndex パーツのインデックス - * @param opacity 不透明度 - */ - public setPartOpacityByIndex(partIndex: number, opacity: number): void - { - if(this._notExistPartOpacities.isExist(partIndex)) - { - this._notExistPartOpacities.setValue(partIndex,opacity); - return; - } - - // インデックスの範囲内検知 - CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount()); - - this._partOpacities[partIndex] = opacity; - } - - /** - * パーツの不透明度の設定(Id) - * @param partId パーツのID - * @param opacity パーツの不透明度 - */ - public setPartOpacityById(partId: CubismIdHandle, opacity: number): void - { - // 高速化のためにPartIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要 - const index: number = this.getPartIndex(partId); - - if(index < 0) - { - return; // パーツがないのでスキップ - } - - this.setPartOpacityByIndex(index, opacity); - } - - /** - * パーツの不透明度の取得(index) - * @param partIndex パーツのインデックス - * @return パーツの不透明度 - */ - public getPartOpacityByIndex(partIndex: number): number - { - if(this._notExistPartOpacities.isExist(partIndex)) - { - // モデルに存在しないパーツIDの場合、非存在パーツリストから不透明度を返す。 - return this._notExistPartOpacities.getValue(partIndex); - } - - // インデックスの範囲内検知 - CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount()); - - return this._partOpacities[partIndex]; - } - - /** - * パーツの不透明度の取得(id) - * @param partId パーツのId - * @return パーツの不透明度 - */ - public getPartOpacityById(partId: CubismIdHandle): number - { - // 高速化のためにPartIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要 - const index: number = this.getPartIndex(partId); - - if(index < 0) - { - return 0; // パーツが無いのでスキップ - } - - return this.getPartOpacityByIndex(index); - } - - /** - * パラメータのインデックスの取得 - * @param パラメータID - * @return パラメータのインデックス - */ - public getParameterIndex(parameterId: CubismIdHandle): number - { - let parameterIndex: number; - const idCount: number = this._model.parameters.count; - - for(parameterIndex = 0; parameterIndex < idCount; ++parameterIndex) - { - if(parameterId != this._parameterIds.at(parameterIndex)) - { - continue; - } - - return parameterIndex; - } - - // モデルに存在していない場合、非存在パラメータIDリスト内を検索し、そのインデックスを返す - if(this._notExistParameterId.isExist(parameterId)) - { - return this._notExistParameterId.getValue(parameterId); - } - - // 非存在パラメータIDリストにない場合新しく要素を追加する - parameterIndex = this._model.parameters.count + this._notExistParameterId.getSize(); - - this._notExistParameterId.setValue(parameterId, parameterIndex); - this._notExistParameterValues.appendKey(parameterIndex); - - return parameterIndex; - } - - /** - * パラメータの個数の取得 - * @return パラメータの個数 - */ - public getParameterCount(): number - { - return this._model.parameters.count; - } - - /** - * パラメータの最大値の取得 - * @param parameterIndex パラメータのインデックス - * @return パラメータの最大値 - */ - public getParameterMaximumValue(parameterIndex: number): number - { - return this._model.parameters.maximumValues[parameterIndex]; - } - - /** - * パラメータの最小値の取得 - * @param parameterIndex パラメータのインデックス - * @return パラメータの最小値 - */ - public getParameterMinimumValue(parameterIndex: number): number - { - return this._model.parameters.minimumValues[parameterIndex]; - } - - /** - * パラメータのデフォルト値の取得 - * @param parameterIndex パラメータのインデックス - * @return パラメータのデフォルト値 - */ - public getParameterDefaultValue(parameterIndex: number): number - { - return this._model.parameters.defaultValues[parameterIndex]; - } - - /** - * パラメータの値の取得 - * @param parameterIndex パラメータのインデックス - * @return パラメータの値 - */ - public getParameterValueByIndex(parameterIndex: number): number - { - if(this._notExistParameterValues.isExist(parameterIndex)) - { - return this._notExistParameterValues.getValue(parameterIndex); - } - - // インデックスの範囲内検知 - CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount()); - - return this._parameterValues[parameterIndex]; - } - - /** - * パラメータの値の取得 - * @param parameterId パラメータのID - * @return パラメータの値 - */ - public getParameterValueById(parameterId: CubismIdHandle): number - { - // 高速化のためにparameterIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要 - const parameterIndex: number = this.getParameterIndex(parameterId); - return this.getParameterValueByIndex(parameterIndex); - } - - /** - * パラメータの値の設定 - * @param parameterIndex パラメータのインデックス - * @param value パラメータの値 - * @param weight 重み - */ - public setParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void - { - if(this._notExistParameterValues.isExist(parameterIndex)) - { - this._notExistParameterValues.setValue( - parameterIndex, - (weight == 1) - ? value - : (this._notExistParameterValues.getValue(parameterIndex) * (1 - weight)) + (value * weight) - ); - - return; - } - - // インデックスの範囲内検知 - CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount()); - - if(this._model.parameters.maximumValues[parameterIndex] < value) - { - value = this._model.parameters.maximumValues[parameterIndex]; - } - if(this._model.parameters.minimumValues[parameterIndex] > value) - { - value = this._model.parameters.minimumValues[parameterIndex]; - } - - this._parameterValues[parameterIndex] = (weight == 1) - ? value - : this._parameterValues[parameterIndex] = (this._parameterValues[parameterIndex] * (1 - weight)) + (value * weight); - } - - /** - * パラメータの値の設定 - * @param parameterId パラメータのID - * @param value パラメータの値 - * @param weight 重み - */ - public setParameterValueById(parameterId: CubismIdHandle, value: number, weight: number = 1.0): void - { - const index: number = this.getParameterIndex(parameterId); - this.setParameterValueByIndex(index, value, weight); - } - - /** - * パラメータの値の加算(index) - * @param parameterIndex パラメータインデックス - * @param value 加算する値 - * @param weight 重み - */ - public addParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void - { - this.setParameterValueByIndex(parameterIndex, (this.getParameterValueByIndex(parameterIndex) + (value * weight))); - } - - /** - * パラメータの値の加算(id) - * @param parameterId パラメータID - * @param value 加算する値 - * @param weight 重み - */ - public addParameterValueById(parameterId: any, value: number, weight: number = 1.0): void - { - const index: number = this.getParameterIndex(parameterId); - this.addParameterValueByIndex(index, value, weight); - } - - /** - * パラメータの値の乗算 - * @param parameterId パラメータのID - * @param value 乗算する値 - * @param weight 重み - */ - public multiplyParameterValueById(parameterId: CubismIdHandle, value: number, weight: number = 1.0): void - { - const index: number = this.getParameterIndex(parameterId); - this.multiplyParameterValueByIndex(index, value, weight); - } - - /** - * パラメータの値の乗算 - * @param parameterIndex パラメータのインデックス - * @param value 乗算する値 - * @param weight 重み - */ - public multiplyParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void - { - this.setParameterValueByIndex(parameterIndex, (this.getParameterValueByIndex(parameterIndex) * (1.0 + (value - 1.0) * weight))); - } - - - /** - * Drawableのインデックスの取得 - * @param drawableId DrawableのID - * @return Drawableのインデックス - */ - public getDrawableIndex(drawableId: CubismIdHandle): number - { - const drawableCount = this._model.drawables.count; - - for(let drawableIndex: number = 0; drawableIndex < drawableCount; ++drawableIndex) - { - if(this._drawableIds.at(drawableIndex) == drawableId) - { - return drawableIndex; - } - } - - return -1; - } - - /** - * Drawableの個数の取得 - * @return drawableの個数 - */ - public getDrawableCount(): number - { - const drawableCount = this._model.drawables.count; - return drawableCount; - } - - /** - * DrawableのIDを取得する - * @param drawableIndex Drawableのインデックス - * @return drawableのID - */ - public getDrawableId(drawableIndex: number): CubismIdHandle - { - const parameterIds: string[] = this._model.drawables.ids; - return CubismFramework.getIdManager().getId(parameterIds[drawableIndex]); - } - - /** - * Drawableの描画順リストの取得 - * @return Drawableの描画順リスト - */ - public getDrawableRenderOrders(): Int32Array - { - const renderOrders: Int32Array = this._model.drawables.renderOrders; - return renderOrders; - } - - /** - * Drawableのテクスチャインデックスリストの取得 - * @param drawableIndex Drawableのインデックス - * @return drawableのテクスチャインデックスリスト - */ - public getDrawableTextureIndices(drawableIndex: number): number - { - const textureIndices: Int32Array = this._model.drawables.textureIndices; - return textureIndices[drawableIndex]; - } - - /** - * DrawableのVertexPositionsの変化情報の取得 - * - * 直近のCubismModel.update関数でDrawableの頂点情報が変化したかを取得する。 - * - * @param drawableIndex Drawableのインデックス - * @retval true Drawableの頂点情報が直近のCubismModel.update関数で変化した - * @retval false Drawableの頂点情報が直近のCubismModel.update関数で変化していない - */ - public getDrawableDynamicFlagVertexPositionsDidChange(drawableIndex: number): boolean - { - const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; - return Live2DCubismCore.Utils.hasVertexPositionsDidChangeBit(dynamicFlags[drawableIndex]); - } - - /** - * Drawableの頂点インデックスの個数の取得 - * @param drawableIndex Drawableのインデックス - * @return drawableの頂点インデックスの個数 - */ - public getDrawableVertexIndexCount(drawableIndex: number): number - { - const indexCounts: Int32Array = this._model.drawables.indexCounts; - return indexCounts[drawableIndex]; - } - - /** - * Drawableの頂点の個数の取得 - * @param drawableIndex Drawableのインデックス - * @return drawableの頂点の個数 - */ - public getDrawableVertexCount(drawableIndex: number): number - { - const vertexCounts = this._model.drawables.vertexCounts; - return vertexCounts[drawableIndex]; - } - - /** - * Drawableの頂点リストの取得 - * @param drawableIndex drawableのインデックス - * @return drawableの頂点リスト - */ - public getDrawableVertices(drawableIndex: number): Float32Array - { - return this.getDrawableVertexPositions(drawableIndex); - } - - /** - * Drawableの頂点インデックスリストの取得 - * @param drarableIndex Drawableのインデックス - * @return drawableの頂点インデックスリスト - */ - public getDrawableVertexIndices(drawableIndex: number): Uint16Array - { - const indicesArray: Uint16Array[] = this._model.drawables.indices; - return indicesArray[drawableIndex]; - } - - /** - * Drawableの頂点リストの取得 - * @param drawableIndex Drawableのインデックス - * @return drawableの頂点リスト - */ - public getDrawableVertexPositions(drawableIndex: number): Float32Array - { - const verticesArray: Float32Array[] = this._model.drawables.vertexPositions; - return verticesArray[drawableIndex]; - } - - /** - * Drawableの頂点のUVリストの取得 - * @param drawableIndex Drawableのインデックス - * @return drawableの頂点UVリスト - */ - public getDrawableVertexUvs(drawableIndex: number): Float32Array - { - const uvsArray: Float32Array[] = this._model.drawables.vertexUvs; - return uvsArray[drawableIndex]; - } - - /** - * Drawableの不透明度の取得 - * @param drawableIndex Drawableのインデックス - * @return drawableの不透明度 - */ - public getDrawableOpacity(drawableIndex: number): number - { - const opacities: Float32Array = this._model.drawables.opacities; - return opacities[drawableIndex]; - } - - /** - * Drawableのカリング情報の取得 - * @param drawableIndex Drawableのインデックス - * @return drawableのカリング情報 - */ - public getDrawableCulling(drawableIndex: number): boolean - { - const constantFlags = this._model.drawables.constantFlags; - - return !Live2DCubismCore.Utils.hasIsDoubleSidedBit(constantFlags[drawableIndex]); - } - - /** - * Drawableのブレンドモードを取得 - * @param drawableIndex Drawableのインデックス - * @return drawableのブレンドモード - */ - public getDrawableBlendMode(drawableIndex: number): CubismRenderer.CubismBlendMode - { - const constantFlags = this._model.drawables.constantFlags; - - return (Live2DCubismCore.Utils.hasBlendAdditiveBit(constantFlags[drawableIndex])) - ? CubismRenderer.CubismBlendMode.CubismBlendMode_Additive - : (Live2DCubismCore.Utils.hasBlendMultiplicativeBit(constantFlags[drawableIndex])) - ? CubismRenderer.CubismBlendMode.CubismBlendMode_Multiplicative - : CubismRenderer.CubismBlendMode.CubismBlendMode_Normal; - } - - /** - * Drawableのクリッピングマスクリストの取得 - * @return Drawableのクリッピングマスクリスト - */ - public getDrawableMasks(): Int32Array[] - { - const masks: Int32Array[] = this._model.drawables.masks; - return masks; - } - - /** - * Drawableのクリッピングマスクの個数リストの取得 - * @return Drawableのクリッピングマスクの個数リスト - */ - public getDrawableMaskCounts(): Int32Array - { - const maskCounts: Int32Array = this._model.drawables.maskCounts; - return maskCounts; - } - - /** - * クリッピングマスクの使用状態 - * - * @return true クリッピングマスクを使用している - * @return false クリッピングマスクを使用していない - */ - public isUsingMasking(): boolean - { - for(let d: number = 0; d < this._model.drawables.count; ++d) - { - if(this._model.drawables.maskCounts[d] <= 0) - { - continue; - } - return true; - } - return false; - } - - /** - * Drawableの表示情報を取得する - * - * @param drawableIndex Drawableのインデックス - * @return true Drawableが表示 - * @return false Drawableが非表示 - */ - public getDrawableDynamicFlagIsVisible(drawableIndex: number): boolean - { - const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; - return Live2DCubismCore.Utils.hasIsVisibleBit(dynamicFlags[drawableIndex]); - } - - /** - * DrawableのDrawOrderの変化情報の取得 - * - * 直近のCubismModel.update関数でdrawableのdrawOrderが変化したかを取得する。 - * drawOrderはartMesh上で指定する0から1000の情報 - * @param drawableIndex drawableのインデックス - * @return true drawableの不透明度が直近のCubismModel.update関数で変化した - * @return false drawableの不透明度が直近のCubismModel.update関数で変化している - */ - public getDrawableDynamicFlagVisibilityDidChange(drawableIndex: number): boolean - { - const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; - return Live2DCubismCore.Utils.hasVisibilityDidChangeBit(dynamicFlags[drawableIndex]); - } - - /** - * Drawableの不透明度の変化情報の取得 - * - * 直近のCubismModel.update関数でdrawableの不透明度が変化したかを取得する。 - * - * @param drawableIndex drawableのインデックス - * @return true Drawableの不透明度が直近のCubismModel.update関数で変化した - * @return false Drawableの不透明度が直近のCubismModel.update関数で変化してない - */ - public getDrawableDynamicFlagOpacityDidChange(drawableIndex: number): boolean - { - const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; - return Live2DCubismCore.Utils.hasOpacityDidChangeBit(dynamicFlags[drawableIndex]); - } - - /** - * Drawableの描画順序の変化情報の取得 - * - * 直近のCubismModel.update関数でDrawableの描画の順序が変化したかを取得する。 - * - * @param drawableIndex Drawableのインデックス - * @return true Drawableの描画の順序が直近のCubismModel.update関数で変化した - * @return false Drawableの描画の順序が直近のCubismModel.update関数で変化してない - */ - public getDrawableDynamicFlagRenderOrderDidChange(drawableIndex: number): boolean - { - const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; - return Live2DCubismCore.Utils.hasRenderOrderDidChangeBit(dynamicFlags[drawableIndex]); - } - - /** - * 保存されたパラメータの読み込み - */ - public loadParameters(): void - { - let parameterCount: number = this._model.parameters.count; - const savedParameterCount: number = this._savedParameters.getSize(); - - if(parameterCount > savedParameterCount) - { - parameterCount = savedParameterCount; - } - - for(let i: number = 0; i < parameterCount; ++i) - { - this._parameterValues[i] = this._savedParameters.at(i); - } - } - - /** - * 初期化する - */ - public initialize(): void - { - CSM_ASSERT(this._model); - - this._parameterValues = this._model.parameters.values; - this._partOpacities = this._model.parts.opacities; - this._parameterMaximumValues = this._model.parameters.maximumValues; - this._parameterMinimumValues = this._model.parameters.minimumValues; - - { - const parameterIds: string[] = this._model.parameters.ids; - const parameterCount: number = this._model.parameters.count; - - for(let i: number = 0; i < parameterCount; ++i) - { - this._parameterIds.pushBack(CubismFramework.getIdManager().getId(parameterIds[i])); - } - } - - { - const partIds: string[] = this._model.parts.ids; - const partCount: number = this._model.parts.count; - - for(let i: number = 0; i < partCount; ++i) - { - this._partIds.pushBack(CubismFramework.getIdManager().getId(partIds[i])); - } - } - - { - const drawableIds: string[] = this._model.drawables.ids; - const drawableCount: number = this._model.drawables.count; - - for(let i: number = 0; i < drawableCount; ++i) - { - this._drawableIds.pushBack(CubismFramework.getIdManager().getId(drawableIds[i])); - } - } - } - - /** - * コンストラクタ - * @param model モデル - */ - public constructor(model: Live2DCubismCore.Model) - { - this._model = model; - this._parameterValues = null; - this._parameterMaximumValues = null; - this._parameterMinimumValues = null; - this._partOpacities = null; - this._savedParameters = new csmVector(); - this._parameterIds = new csmVector(); - this._drawableIds = new csmVector(); - this._partIds = new csmVector(); - - this._notExistPartId = new csmMap(); - this._notExistParameterId = new csmMap(); - this._notExistParameterValues = new csmMap(); - this._notExistPartOpacities = new csmMap(); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - this._model.release(); - this._model = null; - } - - private _notExistPartOpacities: csmMap; // 存在していないパーツの不透明度のリスト - private _notExistPartId: csmMap; // 存在していないパーツIDのリスト - - private _notExistParameterValues: csmMap; // 存在していないパラメータの値のリスト - private _notExistParameterId: csmMap; // 存在していないパラメータIDのリスト - - private _savedParameters: csmVector; // 保存されたパラメータ - - private _model: Live2DCubismCore.Model; // モデル - - private _parameterValues: Float32Array; // パラメータの値のリスト - private _parameterMaximumValues: Float32Array; // パラメータの最大値のリスト - private _parameterMinimumValues: Float32Array; // パラメータの最小値のリスト - - private _partOpacities: Float32Array; // パーツの不透明度のリスト - - private _parameterIds: csmVector; - private _partIds: csmVector; - private _drawableIds: csmVector; - } -} \ No newline at end of file diff --git a/Framework/model/cubismmodeluserdata.ts b/Framework/model/cubismmodeluserdata.ts deleted file mode 100644 index e84724e..0000000 --- a/Framework/model/cubismmodeluserdata.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as cubismmodeluserdatajson} from "./cubismmodeluserdatajson"; -import {Live2DCubismFramework as cubismid} from "../id/cubismid"; -import {Live2DCubismFramework as csmstring} from "../type/csmstring"; -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; -import CubismFramework = cubismframework.CubismFramework; -import csmVector = csmvector.csmVector; -import csmString = csmstring.csmString; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismModelUserDataJson = cubismmodeluserdatajson.CubismModelUserDataJson; - -export namespace Live2DCubismFramework -{ - const ArtMesh: string = "ArtMesh"; - - /** - * ユーザーデータインターフェース - * - * Jsonから読み込んだユーザーデータを記録しておくための構造体 - */ - export class CubismModelUserDataNode - { - targetType: CubismIdHandle; // ユーザーデータターゲットタイプ - targetId: CubismIdHandle; // ユーザーデータターゲットのID - value: csmString; // ユーザーデータ - } - - /** - * ユーザデータの管理クラス - * - * ユーザデータをロード、管理、検索インターフェイス、解放までを行う。 - */ - export class CubismModelUserData - { - /** - * インスタンスの作成 - * - * @param buffer userdata3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - * @return 作成されたインスタンス - */ - public static create(buffer: ArrayBuffer, size: number): CubismModelUserData - { - let ret: CubismModelUserData = new CubismModelUserData(); - - ret.parseUserData(buffer, size); - - return ret; - } - - /** - * インスタンスを破棄する - * - * @param modelUserData 破棄するインスタンス - */ - public static delete(modelUserData: CubismModelUserData): void - { - modelUserData.release(); - modelUserData = void 0; - modelUserData = null; - } - - /** - * ArtMeshのユーザーデータのリストの取得 - * - * @return ユーザーデータリスト - */ - public getArtMeshUserDatas(): csmVector - { - return this._artMeshUserDataNode; - } - - /** - * userdata3.jsonのパース - * - * @param buffer userdata3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public parseUserData(buffer: ArrayBuffer, size: number): void - { - let json: CubismModelUserDataJson = new CubismModelUserDataJson(buffer, size); - - const typeOfArtMesh = CubismFramework.getIdManager().getId(ArtMesh); - const nodeCount: number = json.getUserDataCount(); - - for(let i: number = 0; i < nodeCount; i++) - { - let addNode: CubismModelUserDataNode = new CubismModelUserDataNode(); - - addNode.targetId = json.getUserDataId(i); - addNode.targetType = CubismFramework.getIdManager().getId(json.getUserDataTargetType(i)); - addNode.value = new csmString(json.getUserDataValue(i)); - this._userDataNodes.pushBack(addNode); - - if(addNode.targetType == typeOfArtMesh) - { - this._artMeshUserDataNode.pushBack(addNode); - } - } - - json.release(); - json = void 0; - } - - /** - * コンストラクタ - */ - public constructor() - { - this._userDataNodes = new csmVector(); - this._artMeshUserDataNode = new csmVector(); - } - - /** - * デストラクタ相当の処理 - * - * ユーザーデータ構造体配列を解放する - */ - public release(): void - { - for(let i: number = 0; i < this._userDataNodes.getSize(); ++i) - { - this._userDataNodes.set(i, void 0); - } - - this._userDataNodes = null; - } - - private _userDataNodes: csmVector; // ユーザーデータ構造体配列 - private _artMeshUserDataNode: csmVector; // 閲覧リストの保持 - } -} \ No newline at end of file diff --git a/Framework/model/cubismmodeluserdatajson.ts b/Framework/model/cubismmodeluserdatajson.ts deleted file mode 100644 index c81ab6c..0000000 --- a/Framework/model/cubismmodeluserdatajson.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismjson} from "../utils/cubismjson"; -import {Live2DCubismFramework as cubismid} from "../id/cubismid"; -import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; -import CubismFramework = cubismframework.CubismFramework; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismJson = cubismjson.CubismJson; - - -export namespace Live2DCubismFramework -{ - const Meta: string = "Meta"; - const UserDataCount: string = "UserDataCount"; - const TotalUserDataSize: string = "TotalUserDataSize"; - const UserData: string = "UserData"; - const Target: string = "Target"; - const Id: string = "Id"; - const Value: string = "Value"; - - export class CubismModelUserDataJson - { - /** - * コンストラクタ - * @param buffer userdata3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public constructor(buffer: ArrayBuffer, size: number) - { - this._json = CubismJson.create(buffer, size); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - CubismJson.delete(this._json); - } - - /** - * ユーザーデータ個数の取得 - * @return ユーザーデータの個数 - */ - public getUserDataCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(UserDataCount).toInt(); - } - - /** - * ユーザーデータ総文字列数の取得 - * - * @return ユーザーデータ総文字列数 - */ - public getTotalUserDataSize(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalUserDataSize).toInt(); - } - - /** - * ユーザーデータのタイプの取得 - * - * @return ユーザーデータのタイプ - */ - public getUserDataTargetType(i: number): string - { - return this._json.getRoot().getMap().getValue(UserData).getVector().at(i).getMap().getValue(Target).getRawString(); - } - - /** - * ユーザーデータのターゲットIDの取得 - * - * @param i インデックス - * @return ユーザーデータターゲットID - */ - public getUserDataId(i: number): CubismIdHandle - { - return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(UserData).getVector().at(i).getMap().getValue(Id).getRawString()); - } - - /** - * ユーザーデータの文字列の取得 - * - * @param i インデックス - * @return ユーザーデータ - */ - public getUserDataValue(i: number): string - { - return this._json.getRoot().getMap().getValue(UserData).getVector().at(i).getMap().getValue(Value).getRawString(); - } - - private _json: CubismJson; - } -} \ No newline at end of file diff --git a/Framework/model/cubismusermodel.ts b/Framework/model/cubismusermodel.ts deleted file mode 100644 index 667cb2f..0000000 --- a/Framework/model/cubismusermodel.ts +++ /dev/null @@ -1,466 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; -import {Live2DCubismFramework as cubismmotionmanager} from "../motion/cubismmotionmanager"; -import {Live2DCubismFramework as cubismtargetpoint} from "../math/cubismtargetpoint"; -import {Live2DCubismFramework as cubismmodelmatrix} from "../math/cubismmodelmatrix"; -import {Live2DCubismFramework as cubismmoc} from "./cubismmoc"; -import {Live2DCubismFramework as cubismmodel} from "./cubismmodel"; -import {Live2DCubismFramework as acubismmotion} from "../motion/acubismmotion"; -import {Live2DCubismFramework as cubismmotion} from "../motion/cubismmotion"; -import {Live2DCubismFramework as cubismexpressionmotion} from "../motion/cubismexpressionmotion"; -import {Live2DCubismFramework as cubismpose} from "../effect/cubismpose"; -import {Live2DCubismFramework as cubismmodeluserdata} from "./cubismmodeluserdata"; -import {Live2DCubismFramework as cubismphysics} from "../physics/cubismphysics"; -import {Live2DCubismFramework as cubismid} from "../id/cubismid"; -import {Live2DCubismFramework as csmstring} from "../type/csmstring"; -import {Live2DCubismFramework as cubismmotionqueuemanager} from "../motion/cubismmotionqueuemanager"; -import {Live2DCubismFramework as cubismbreath} from "../effect/cubismbreath"; -import {Live2DCubismFramework as cubismeyeblink} from "../effect/cubismeyeblink"; -import {Live2DCubismFramework as cubismrenderer_webgl} from "../rendering/cubismrenderer_WebGL"; -import {CubismLogError, CubismLogInfo} from "../utils/cubismdebug"; -import CubismRenderer_WebGL = cubismrenderer_webgl.CubismRenderer_WebGL; -import CubismEyeBlink = cubismeyeblink.CubismEyeBlink; -import CubismBreath = cubismbreath.CubismBreath; -import CubismMotionQueueManager = cubismmotionqueuemanager.CubismMotionQueueManager; -import csmString = csmstring.csmString; -import Constant = cubismframework.Constant; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismPhysics = cubismphysics.CubismPhysics; -import CubismModelUserData = cubismmodeluserdata.CubismModelUserData; -import CubismPose = cubismpose.CubismPose; -import CubismExpressionMotion = cubismexpressionmotion.CubismExpressionMotion; -import CubismMotion = cubismmotion.CubismMotion; -import ACubismMotion = acubismmotion.ACubismMotion; -import CubismModel = cubismmodel.CubismModel; -import CubismMoc = cubismmoc.CubismMoc; -import CubismModelMatrix = cubismmodelmatrix.CubismModelMatrix; -import CubismTargetPoint = cubismtargetpoint.CubismTargetPoint; -import CubismMotionManager = cubismmotionmanager.CubismMotionManager; - -export namespace Live2DCubismFramework -{ - /** - * ユーザーが実際に使用するモデル - * - * ユーザーが実際に使用するモデルの基底クラス。これを継承してユーザーが実装する。 - */ - export class CubismUserModel - { - /** - * 初期化状態の取得 - * - * 初期化されている状態か? - * - * @return true 初期化されている - * @return false 初期化されていない - */ - public isInitialized(): boolean - { - return this._initialized; - } - - /** - * 初期化状態の設定 - * - * 初期化状態を設定する。 - * - * @param v 初期化状態 - */ - public setInitialized(v: boolean): void - { - this._initialized = v; - } - - /** - * 更新状態の取得 - * - * 更新されている状態か? - * - * @return true 更新されている - * @return false 更新されていない - */ - public isUpdating(): boolean - { - return this._updating; - } - - /** - * 更新状態の設定 - * - * 更新状態を設定する - * - * @param v 更新状態 - */ - public setUpdating(v: boolean): void - { - this._updating = v; - } - - /** - * マウスドラッグ情報の設定 - * @param ドラッグしているカーソルのX位置 - * @param ドラッグしているカーソルのY位置 - */ - public setDragging(x: number, y: number): void - { - this._dragManager.set(x, y); - } - - /** - * 加速度の情報を設定する - * @param x X軸方向の加速度 - * @param y Y軸方向の加速度 - * @param z Z軸方向の加速度 - */ - public setAcceleration(x: number, y: number, z: number): void - { - this._accelerationX = x; - this._accelerationY = y; - this._accelerationZ = z; - } - - /** - * モデル行列を取得する - * @return モデル行列 - */ - public getModelMatrix(): CubismModelMatrix - { - return this._modelMatrix; - } - - /** - * 不透明度の設定 - * @param a 不透明度 - */ - public setOpacity(a: number): void - { - this._opacity = a; - } - - /** - * 不透明度の取得 - * @return 不透明度 - */ - public getOpacity(): number - { - return this._opacity; - } - - /** - * モデルデータを読み込む - * - * @param buffer moc3ファイルが読み込まれているバッファ - */ - public loadModel(buffer: ArrayBuffer) - { - this._moc = CubismMoc.create(buffer); - this._model = this._moc.createModel(); - this._model.saveParameters(); - - if ((this._moc == null) || (this._model == null)) - { - CubismLogError("Failed to CreateModel()."); - return; - } - - this._modelMatrix = new CubismModelMatrix(this._model.getCanvasWidth(), this._model.getCanvasHeight()); - } - - /** - * モーションデータを読み込む - * @param buffer motion3.jsonファイルが読み込まれているバッファ - * @param size バッファのサイズ - * @param name モーションの名前 - * @return モーションクラス - */ - public loadMotion(buffer: ArrayBuffer, size: number, name: string): ACubismMotion - { - return CubismMotion.create(buffer, size); - } - - /** - * 表情データの読み込み - * @param buffer expファイルが読み込まれているバッファ - * @param size バッファのサイズ - * @param name 表情の名前 - */ - public loadExpression(buffer: ArrayBuffer, size: number, name: string): ACubismMotion - { - return CubismExpressionMotion.create(buffer, size); - } - - /** - * ポーズデータの読み込み - * @param buffer pose3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public loadPose(buffer: ArrayBuffer, size: number): void - { - this._pose = CubismPose.create(buffer, size); - } - - /** - * モデルに付属するユーザーデータを読み込む - * @param buffer userdata3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public loadUserData(buffer: ArrayBuffer, size: number): void - { - this._modelUserData = CubismModelUserData.create(buffer, size); - } - - /** - * 物理演算データの読み込み - * @param buffer physics3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public loadPhysics(buffer: ArrayBuffer, size: number): void - { - this._physics = CubismPhysics.create(buffer, size); - } - - /** - * 当たり判定の取得 - * @param drawableId 検証したいDrawableのID - * @param pointX X位置 - * @param pointY Y位置 - * @return true ヒットしている - * @return false ヒットしていない - */ - public isHit(drawableId: CubismIdHandle, pointX: number, pointY: number): boolean - { - const drawIndex: number = this._model.getDrawableIndex(drawableId); - - if(drawIndex < 0) - { - return false; // 存在しない場合はfalse - } - - const count: number = this._model.getDrawableVertexCount(drawIndex); - const vertices: Float32Array = this._model.getDrawableVertices(drawIndex); - - let left: number = vertices[0]; - let right: number = vertices[0]; - let top: number = vertices[1]; - let bottom: number = vertices[1]; - - for(let j: number = 1; j < count; ++j) - { - let x = vertices[Constant.vertexOffset + j * Constant.vertexStep]; - let y = vertices[Constant.vertexOffset + j * Constant.vertexStep + 1]; - - if(x < left) - { - left = x; // Min x - } - - if(x > right) - { - right = x; // Max x - } - - if(y < top) - { - top = y; // Min y - } - - if(y > bottom) - { - bottom = y; // Max y - } - } - - const tx: number = this._modelMatrix.invertTransformX(pointX); - const ty: number = this._modelMatrix.invertTransformY(pointY); - - return ((left <= tx) && (tx <= right) && (top <= ty) && (ty <= bottom)); - } - - /** - * モデルの取得 - * @return モデル - */ - public getModel(): CubismModel - { - return this._model; - } - - /** - * レンダラの取得 - * @return レンダラ - */ - public getRenderer(): CubismRenderer_WebGL - { - return this._renderer; - } - - /** - * レンダラを作成して初期化を実行する - */ - public createRenderer(): void - { - if(this._renderer) - { - this.deleteRenderer(); - } - - this._renderer = new CubismRenderer_WebGL(); - this._renderer.initialize(this._model); - } - - /** - * レンダラの解放 - */ - public deleteRenderer(): void - { - if(this._renderer) - { - this._renderer = void 0; - this._renderer = null; - } - } - - /** - * イベント発火時の標準処理 - * - * Eventが再生処理時にあった場合の処理をする。 - * 継承で上書きすることを想定している。 - * 上書きしない場合はログ出力をする。 - * - * @param eventValue 発火したイベントの文字列データ - */ - public motionEventFired(eventValue: csmString): void - { - CubismLogInfo("{0}", eventValue.s); - } - - /** - * イベント用のコールバック - * - * CubismMotionQueueManagerにイベント用に登録するためのCallback。 - * CubismUserModelの継承先のEventFiredを呼ぶ。 - * - * @param caller 発火したイベントを管理していたモーションマネージャー、比較用 - * @param eventValue 発火したイベントの文字列データ - * @param customData CubismUserModelを継承したインスタンスを想定 - */ - public static cubismDefaultMotionEventCallback(caller: CubismMotionQueueManager, eventValue: csmString, customData: CubismUserModel): void - { - let model: CubismUserModel = customData; - - if(model != null) - { - model.motionEventFired(eventValue); - } - } - - /** - * コンストラクタ - */ - public constructor() - { - // 各変数初期化 - this._moc = null; - this._model = null; - this._motionManager = null; - this._expressionManager = null; - this._eyeBlink = null; - this._breath = null; - this._modelMatrix = null; - this._pose = null; - this._dragManager = null; - this._physics = null; - this._modelUserData = null; - this._initialized = false; - this._updating = false; - this._opacity = 1.0; - this._lipsync = true; - this._lastLipSyncValue = 0.0; - this._dragX = 0.0; - this._dragY = 0.0; - this._accelerationX = 0.0; - this._accelerationY = 0.0; - this._accelerationZ = 0.0; - this._debugMode = false; - this._renderer = null; - - // モーションマネージャーを作成 - this._motionManager = new CubismMotionManager(); - this._motionManager.setEventCallback(CubismUserModel.cubismDefaultMotionEventCallback, this); - - // 表情マネージャーを作成 - this._expressionManager = new CubismMotionManager(); - - // ドラッグによるアニメーション - this._dragManager = new CubismTargetPoint(); - } - - /** - * デストラクタに相当する処理 - */ - public release() - { - this._motionManager.release(); - this._motionManager = void 0; - this._motionManager = null; - - this._expressionManager.release(); - this._expressionManager = void 0; - this._expressionManager = null; - - this._moc.deleteModel(this._model); - this._moc.release(); - this._moc = void 0; - this._moc = null; - - this._modelMatrix = void 0; - this._modelMatrix = null; - - CubismPose.delete(this._pose); - CubismEyeBlink.delete(this._eyeBlink); - CubismBreath.delete(this._breath); - - this._dragManager = void 0; - this._dragManager = null; - - CubismPhysics.delete(this._physics); - CubismModelUserData.delete(this._modelUserData); - this.deleteRenderer(); - - } - - protected _moc: CubismMoc; // Mocデータ - protected _model: CubismModel; // Modelインスタンス - - protected _motionManager: CubismMotionManager; // モーション管理 - protected _expressionManager: CubismMotionManager; // 表情管理 - protected _eyeBlink: CubismEyeBlink; // 自動まばたき - protected _breath: CubismBreath; // 呼吸 - protected _modelMatrix: CubismModelMatrix; // モデル行列 - protected _pose: CubismPose; // ポーズ管理 - protected _dragManager: CubismTargetPoint; // マウスドラッグ - protected _physics: CubismPhysics; // 物理演算 - protected _modelUserData: CubismModelUserData; // ユーザーデータ - - protected _initialized: boolean; // 初期化されたかどうか - protected _updating: boolean; // 更新されたかどうか - protected _opacity: number; // 不透明度 - protected _lipsync: boolean; // リップシンクするかどうか - protected _lastLipSyncValue: number; // 最後のリップシンクの制御地 - protected _dragX: number; // マウスドラッグのX位置 - protected _dragY: number; // マウスドラッグのY位置 - protected _accelerationX: number; // X軸方向の加速度 - protected _accelerationY: number; // Y軸方向の加速度 - protected _accelerationZ: number; // Z軸方向の加速度 - protected _debugMode: boolean; // デバッグモードかどうか - - private _renderer: CubismRenderer_WebGL; // レンダラ - } - -} \ No newline at end of file diff --git a/Framework/motion/acubismmotion.ts b/Framework/motion/acubismmotion.ts deleted file mode 100644 index e0bad58..0000000 --- a/Framework/motion/acubismmotion.ts +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismmath} from '../math/cubismmath'; -import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; -import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; -import {Live2DCubismFramework as csmstring} from '../type/csmstring'; -import {Live2DCubismFramework as csmvector} from '../type/csmvector'; -import { CSM_ASSERT } from '../utils/cubismdebug'; -import csmVector = csmvector.csmVector; -import csmString = csmstring.csmString; -import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; -import CubismModel = cubismmodel.CubismModel; -import CubismMath = cubismmath.CubismMath; - -export namespace Live2DCubismFramework -{ - /** - * モーションの抽象基底クラス - * - * モーションの抽象基底クラス。MotionQueueManagerによってモーションの再生を管理する。 - */ - export abstract class ACubismMotion - { - /** - * インスタンスの破棄 - */ - public static delete(motion: ACubismMotion): void - { - motion.release(); - motion = void 0; - motion = null; - } - - /** - * コンストラクタ - */ - public constructor() - { - this._fadeInSeconds = -1.0; - this._fadeOutSeconds = -1.0; - this._weight = 1.0; - this._offsetSeconds = 0.0; // 再生の開始時刻 - this._firedEventValues = new csmVector(); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - this._weight = 0.0; - } - - /** - * モデルのパラメータ - * @param model 対象のモデル - * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション - * @param userTimeSeconds デルタ時間の積算値[秒] - */ - public updateParameters(model: CubismModel, motionQueueEntry: CubismMotionQueueEntry, userTimeSeconds: number): void - { - if(!motionQueueEntry.isAvailable() || motionQueueEntry.isFinished()) - { - return; - } - - if(!motionQueueEntry.isStarted()) - { - motionQueueEntry.setIsStarted(true); - motionQueueEntry.setStartTime(userTimeSeconds - this._offsetSeconds); // モーションの開始時刻を記録 - motionQueueEntry.setFadeInStartTime(userTimeSeconds); // フェードインの開始時刻 - - const duration: number = this.getDuration(); - - if(motionQueueEntry.getEndTime() < 0) - { - // 開始していないうちに終了設定している場合がある。 - motionQueueEntry.setEndTime((duration <= 0) ? -1 : motionQueueEntry.getStartTime() + duration); - // duration == -1 の場合はループする - } - } - - let fadeWeight: number = this._weight; // 現在の値と掛け合わせる割合 - - //---- フェードイン・アウトの処理 ---- - // 単純なサイン関数でイージングする - const fadeIn: number = this._fadeInSeconds == 0.0 - ? 1.0 - : CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / this._fadeInSeconds); - - const fadeOut: number = (this._fadeOutSeconds == 0.0 || motionQueueEntry.getEndTime() < 0.0) - ? 1.0 - : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / this._fadeOutSeconds); - - fadeWeight = fadeWeight * fadeIn * fadeOut; - - motionQueueEntry.setState(userTimeSeconds, fadeWeight); - - CSM_ASSERT(0.0 <= fadeWeight && fadeWeight <= 1.0); - - //---- 全てのパラメータIDをループする ---- - this.doUpdateParameters(model, userTimeSeconds, fadeWeight, motionQueueEntry); - - // 後処理 - // 終了時刻を過ぎたら終了フラグを立てる(CubismMotionQueueManager) - if((motionQueueEntry.getEndTime() > 0) && (motionQueueEntry.getEndTime() < userTimeSeconds)) - { - motionQueueEntry.setIsFinished(true); // 終了 - } - } - - /** - * フェードインの時間を設定する - * @param fadeInSeconds フェードインにかかる時間[秒] - */ - public setFadeInTime(fadeInSeconds: number): void - { - this._fadeInSeconds = fadeInSeconds; - } - - /** - * フェードアウトの時間を設定する - * @param fadeOutSeconds フェードアウトにかかる時間[秒] - */ - public setFadeOutTime(fadeOutSeconds: number): void - { - this._fadeOutSeconds = fadeOutSeconds; - } - - /** - * フェードアウトにかかる時間の取得 - * @return フェードアウトにかかる時間[秒] - */ - public getFadeOutTime(): number - { - return this._fadeOutSeconds; - } - - /** - * フェードインにかかる時間の取得 - * @return フェードインにかかる時間[秒] - */ - public getFadeInTime(): number - { - return this._fadeInSeconds; - } - - /** - * モーション適用の重みの設定 - * @param weight 重み(0.0 - 1.0) - */ - public setWeight(weight: number): void - { - this._weight = weight; - } - - /** - * モーション適用の重みの取得 - * @return 重み(0.0 - 1.0) - */ - public getWeight(): number - { - return this._weight; - } - - /** - * モーションの長さの取得 - * @return モーションの長さ[秒] - * - * @note ループの時は「-1」。 - * ループでない場合は、オーバーライドする。 - * 正の値の時は取得される時間で終了する。 - * 「-1」の時は外部から停止命令がない限り終わらない処理となる。 - */ - public getDuration(): number - { - return -1.0; - } - - /** - * モーションのループ1回分の長さの取得 - * @return モーションのループ一回分の長さ[秒] - * - * @note ループしない場合は、getDuration()と同じ値を返す - * ループ一回分の長さが定義できない場合(プログラム的に動き続けるサブクラスなど)の場合は「-1」を返す - */ - public getLoopDuration(): number - { - return -1.0; - } - - /** - * モーション再生の開始時刻の設定 - * @param offsetSeconds モーション再生の開始時刻[秒] - */ - public setOffsetTime(offsetSeconds: number): void - { - this._offsetSeconds = offsetSeconds; - } - - /** - * モデルのパラメータ更新 - * - * イベント発火のチェック。 - * 入力する時間は呼ばれるモーションタイミングを0とした秒数で行う。 - * - * @param beforeCheckTimeSeconds 前回のイベントチェック時間[秒] - * @param motionTimeSeconds 今回の再生時間[秒] - */ - public getFiredEvent(beforeCheckTimeSeconds: number, motionTimeSeconds: number): csmVector - { - return this._firedEventValues; - } - - /** - * モーションを更新して、モデルにパラメータ値を反映する - * @param model 対象のモデル - * @param userTimeSeconds デルタ時間の積算値[秒] - * @param weight モーションの重み - * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション - * @return true モデルへパラメータ値の反映あり - * @return false モデルへのパラメータ値の反映なし(モーションの変化なし) - */ - public abstract doUpdateParameters(model: CubismModel, userTimeSeconds: number, weight: number, motionQueueEntry: CubismMotionQueueEntry): void; - - - public _fadeInSeconds: number; // フェードインにかかる時間[秒] - public _fadeOutSeconds: number; // フェードアウトにかかる時間[秒] - public _weight: number; // モーションの重み - public _offsetSeconds: number; // モーション再生の開始時間[秒] - - public _firedEventValues: csmVector; - } -} \ No newline at end of file diff --git a/Framework/motion/cubismexpressionmotion.ts b/Framework/motion/cubismexpressionmotion.ts deleted file mode 100644 index 1635150..0000000 --- a/Framework/motion/cubismexpressionmotion.ts +++ /dev/null @@ -1,189 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; -import {Live2DCubismFramework as cubismjson} from '../utils/cubismjson'; -import {Live2DCubismFramework as cubismid} from '../id/cubismid'; -import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; -import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; -import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; -import {Live2DCubismFramework as csmvector} from '../type/csmvector'; -import JsonFloat = cubismjson.JsonFloat; -import csmVector = csmvector.csmVector; -import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; -import CubismModel = cubismmodel.CubismModel; -import CubismFramework = cubismframework.CubismFramework; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismJson = cubismjson.CubismJson; -import Value = cubismjson.Value; -import ACubismMotion = acubismmotion.ACubismMotion; - -export namespace Live2DCubismFramework -{ - // exp3.jsonのキーとデフォルト - const ExpressionKeyFadeIn: string = "FadeInTime"; - const ExpressionKeyFadeOut: string = "FadeOutTime"; - const ExpressionKeyParameters: string = "Parameters"; - const ExpressionKeyId: string = "Id"; - const ExpressionKeyValue: string = "Value"; - const ExpressionKeyBlend: string = "Blend"; - const BlendValueAdd: string = "Add"; - const BlendValueMultiply: string = "Multiply"; - const BlendValueOverwrite: string = "Overwrite"; - const DefaultFadeTime: number = 1.0; - - /** - * 表情のモーション - * - * 表情のモーションクラス。 - */ - export class CubismExpressionMotion extends ACubismMotion - { - /** - * インスタンスを作成する。 - * @param buffer expファイルが読み込まれているバッファ - * @param size バッファのサイズ - * @return 作成されたインスタンス - */ - public static create(buffer: ArrayBuffer, size: number): CubismExpressionMotion - { - let expression: CubismExpressionMotion = new CubismExpressionMotion(); - - let json: CubismJson = CubismJson.create(buffer, size); - let root: Value = json.getRoot(); - - // typescriptではnullを許容していないため仮の値を入れる - if(root.getMap().getValue(ExpressionKeyFadeIn) == null) - { - root.getMap().setValue(ExpressionKeyFadeIn, new JsonFloat(DefaultFadeTime)); - } - if(root.getMap().getValue(ExpressionKeyFadeOut) == null) - { - root.getMap().setValue(ExpressionKeyFadeOut, new JsonFloat(DefaultFadeTime)); - } - - expression.setFadeInTime(root.getMap().getValue(ExpressionKeyFadeIn).toFloat(DefaultFadeTime)); // フェードイン - expression.setFadeOutTime(root.getMap().getValue(ExpressionKeyFadeOut).toFloat(DefaultFadeTime)); // フェードアウト - - // 各パラメータについて - const parameterCount = root.getMap().getValue(ExpressionKeyParameters).getSize(); - - for(let i: number = 0; i < parameterCount; ++i) - { - let param: Value = root.getMap().getValue(ExpressionKeyParameters).getVector().at(i); - const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(param.getMap().getValue(ExpressionKeyId).getRawString()); // パラメータID - - const value: number = param.getMap().getValue(ExpressionKeyValue).toFloat(); // 値 - - // 計算方法の設定 - let blendType: CubismExpressionMotion.ExpressionBlendType; - - if(param.getMap().getValue(ExpressionKeyBlend).isNull() || param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueAdd) - { - blendType = this.ExpressionBlendType.ExpressionBlendType_Add; - } - else if(param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueMultiply) - { - blendType = this.ExpressionBlendType.ExpressionBlendType_Multiply; - } - else if(param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueOverwrite) - { - blendType = this.ExpressionBlendType.ExpressionBlendType_Overwrite; - } - else - { - // その他 仕様にない値を設定した時は加算モードにすることで復旧 - blendType = this.ExpressionBlendType.ExpressionBlendType_Add; - } - - // 設定オブジェクトを作成してリストに追加する - let item: CubismExpressionMotion.ExpressionParameter = new CubismExpressionMotion.ExpressionParameter(); - - item.parameterId = parameterId; - item.blendType = blendType; - item.value = value; - - expression._parameters.pushBack(item); - } - - CubismJson.delete(json); // JSONデータは不要になったら削除する - return expression; - } - - /** - * モデルのパラメータの更新の実行 - * @param model 対象のモデル - * @param userTimeSeconds デルタ時間の積算値[秒] - * @param weight モーションの重み - * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション - */ - public doUpdateParameters(model: CubismModel, userTimeSeconds: number, weight: number, motionQueueEntry: CubismMotionQueueEntry): void - { - for(let i: number = 0; i < this._parameters.getSize(); ++i) - { - let parameter: CubismExpressionMotion.ExpressionParameter = this._parameters.at(i); - - switch(parameter.blendType) - { - case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Add: - { - model.addParameterValueById(parameter.parameterId, parameter.value, weight); - break; - } - case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Multiply: - { - model.multiplyParameterValueById(parameter.parameterId, parameter.value, weight); - break; - } - case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Overwrite: - { - model.setParameterValueById(parameter.parameterId, parameter.value, weight) - break; - } - default: - // 仕様にない値を設定した時はすでに加算モードになっている - break; - } - } - } - - /** - * コンストラクタ - */ - constructor() - { - super(); - - this._parameters = new csmVector(); - } - - _parameters: csmVector; // 表情のパラメータ情報リスト - } - - export namespace CubismExpressionMotion - { - /** - * 表情パラメータ値の計算方式 - */ - export enum ExpressionBlendType - { - ExpressionBlendType_Add = 0, // 加算 - ExpressionBlendType_Multiply = 1, // 乗算 - ExpressionBlendType_Overwrite = 2 // 上書き - } - - /** - * 表情のパラメータ情報 - */ - export class ExpressionParameter - { - parameterId: CubismIdHandle; // パラメータID - blendType: ExpressionBlendType; // パラメータの演算種類 - value: number; // 値 - } - } -} \ No newline at end of file diff --git a/Framework/motion/cubismmotion.ts b/Framework/motion/cubismmotion.ts deleted file mode 100644 index f113db5..0000000 --- a/Framework/motion/cubismmotion.ts +++ /dev/null @@ -1,805 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismmotionjson} from './cubismmotionjson'; -import {Live2DCubismFramework as cubismmotioninternal} from './cubismmotioninternal'; -import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; -import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; -import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; -import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; -import {Live2DCubismFramework as cubismmath} from '../math/cubismmath'; -import {Live2DCubismFramework as csmvector} from '../type/csmvector'; -import {Live2DCubismFramework as cubismid} from '../id/cubismid'; -import {Live2DCubismFramework as csmstring} from '../type/csmstring'; -import {CubismLogDebug, CSM_ASSERT} from '../utils/cubismdebug'; -import csmString = csmstring.csmString; -import CubismMotionData = cubismmotioninternal.CubismMotionData; -import CubismMotionSegment = cubismmotioninternal.CubismMotionSegment; -import CubismMotionPoint = cubismmotioninternal.CubismMotionPoint; -import CubismMotionEvent = cubismmotioninternal.CubismMotionEvent; -import CubismMotionSegmentType = cubismmotioninternal.CubismMotionSegmentType; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismMotionCurve = cubismmotioninternal.CubismMotionCurve; -import CubismMotionCurveTarget = cubismmotioninternal.CubismMotionCurveTarget; -import csmVector = csmvector.csmVector; -import CubismMath = cubismmath.CubismMath; -import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; -import CubismFramework = cubismframework.CubismFramework; -import CubismModel = cubismmodel.CubismModel; -import ACubismMotion = acubismmotion.ACubismMotion; -import CubismMotionJson = cubismmotionjson.CubismMotionJson; - -export namespace Live2DCubismFramework -{ - const EffectNameEyeBlink: string = "EyeBlink"; - const EffectNameLipSync: string = "LipSync"; - const TargetNameModel: string = "Model"; - const TargetNameParameter: string = "Parameter"; - const TargetNamePartOpacity: string = "PartOpacity"; - - function lerpPoints(a: CubismMotionPoint, b: CubismMotionPoint, t: number): CubismMotionPoint - { - let result: CubismMotionPoint = new CubismMotionPoint(); - - result.time = a.time + ((b.time - a.time) * t); - result.value = a.value + ((b.value - a.value) * t); - - return result; - } - - function linearEvaluate(points: CubismMotionPoint[], time: number): number - { - let t: number = (time - points[0].time) / (points[1].time - points[0].time); - - if (t < 0.0) - { - t = 0.0; - } - - return points[0].value + ((points[1].value - points[0].value) * t); - } - - function bezierEvaluate(points: CubismMotionPoint[], time: number): number - { - let t: number = (time - points[0].time) / (points[3].time - points[0].time); - - if (t < 0.0) - { - t = 0.0; - } - - const p01: CubismMotionPoint = lerpPoints(points[0], points[1], t); - const p12: CubismMotionPoint = lerpPoints(points[1], points[2], t); - const p23: CubismMotionPoint = lerpPoints(points[2], points[3], t); - - const p012: CubismMotionPoint = lerpPoints(p01, p12, t); - const p123: CubismMotionPoint = lerpPoints(p12, p23, t); - - return lerpPoints(p012, p123, t).value; - } - - function steppedEvaluate(points: CubismMotionPoint[], time: number): number - { - return points[0].value; - } - - function inverseSteppedEvaluate(points: CubismMotionPoint[], time: number): number - { - return points[1].value; - } - - function evaluateCurve(motionData: CubismMotionData, index: number, time: number): number - { - // Find segment to evaluate. - const curve: CubismMotionCurve = motionData.curves.at(index); - - let target: number = -1; - const totalSegmentCount: number = curve.baseSegmentIndex + curve.segmentCount; - let pointPosition: number = 0; - for (let i: number = curve.baseSegmentIndex; i < totalSegmentCount; ++i) - { - // Get first point of next segment. - pointPosition = motionData.segments.at(i).basePointIndex - + (motionData.segments.at(i).segmentType == CubismMotionSegmentType.CubismMotionSegmentType_Bezier - ? 3 - : 1); - - - // Break if time lies within current segment. - if (motionData.points.at(pointPosition).time > time) - { - target = i; - break; - } - } - - - if (target == -1) - { - return motionData.points.at(pointPosition).value; - } - - - const segment: CubismMotionSegment = motionData.segments.at(target); - - return segment.evaluate(motionData.points.get(segment.basePointIndex), time); - } - - /** - * モーションクラス - * - * モーションのクラス。 - */ - export class CubismMotion extends ACubismMotion - { - /** - * インスタンスを作成する - * - * @param buffer motion3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - * @return 作成されたインスタンス - */ - public static create(buffer: ArrayBuffer, size: number): CubismMotion - { - let ret: CubismMotion = new CubismMotion(); - - ret.parse(buffer, size); - ret._sourceFrameRate = ret._motionData.fps; - ret._loopDurationSeconds = ret._motionData.duration; - - // NOTE: Editorではループありのモーション書き出しは非対応 - // ret->_loop = (ret->_motionData->Loop > 0); - return ret; - } - - /** - * モデルのパラメータの更新の実行 - * @param model 対象のモデル - * @param userTimeSeconds 現在の時刻[秒] - * @param fadeWeight モーションの重み - * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション - */ - public doUpdateParameters(model: CubismModel, userTimeSeconds: number, fadeWeight: number, motionQueueEntry: CubismMotionQueueEntry): void - { - if (this._modelCurveIdEyeBlink == null) - { - this._modelCurveIdEyeBlink = CubismFramework.getIdManager().getId(EffectNameEyeBlink); - } - - if (this._modelCurveIdLipSync == null) - { - this._modelCurveIdLipSync = CubismFramework.getIdManager().getId(EffectNameLipSync); - } - - let timeOffsetSeconds: number = userTimeSeconds - motionQueueEntry.getStartTime(); - - if (timeOffsetSeconds < 0.0) - { - timeOffsetSeconds = 0.0; // エラー回避 - } - - let lipSyncValue: number = Number.MAX_VALUE; - let eyeBlinkValue: number = Number.MAX_VALUE; - - //まばたき、リップシンクのうちモーションの適用を検出するためのビット(maxFlagCount個まで - const MaxTargetSize = 64; - let lipSyncFlags = 0; - let eyeBlinkFlags = 0; - - //瞬き、リップシンクのターゲット数が上限を超えている場合 - if (this._eyeBlinkParameterIds.getSize() > MaxTargetSize) - { - CubismLogDebug("too many eye blink targets : {0}", this._eyeBlinkParameterIds.getSize()); - } - if (this._lipSyncParameterIds.getSize() > MaxTargetSize) - { - CubismLogDebug("too many lip sync targets : {0}", this._lipSyncParameterIds.getSize()); - } - - const tmpFadeIn: number = (this._fadeInSeconds <= 0.0) - ? 1.0 - : CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / this._fadeInSeconds); - - const tmpFadeOut: number = (this._fadeOutSeconds <= 0.0 || motionQueueEntry.getEndTime() < 0.0) - ? 1.0 - : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / this._fadeOutSeconds); - let value: number; - let c: number, parameterIndex: number; - - // 'Repeat' time as necessary. - let time: number = timeOffsetSeconds; - - if (this._isLoop) - { - while (time > this._motionData.duration) - { - time -= this._motionData.duration; - } - } - - let curves: csmVector = this._motionData.curves; - - // Evaluate model curves. - for (c = 0; c < this._motionData.curveCount && curves.at(c).type == CubismMotionCurveTarget.CubismMotionCurveTarget_Model; ++c) - { - // Evaluate curve and call handler. - value = evaluateCurve(this._motionData, c, time); - - if (curves.at(c).id == this._modelCurveIdEyeBlink) - { - eyeBlinkValue = value; - } - else if (curves.at(c).id == this._modelCurveIdLipSync) - { - lipSyncValue = value; - } - } - - let parameterMotionCurveCount: number = 0; - - for (; c < this._motionData.curveCount && curves.at(c).type == CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter; ++c) - { - parameterMotionCurveCount++; - - // Find parameter index. - parameterIndex = model.getParameterIndex(curves.at(c).id); - - // Skip curve evaluation if no value in sink. - if (parameterIndex == -1) - { - continue; - } - - const sourceValue: number = model.getParameterValueByIndex(parameterIndex); - - // Evaluate curve and apply value. - value = evaluateCurve(this._motionData, c, time); - - if (eyeBlinkValue != Number.MAX_VALUE) - { - for (let i: number = 0; i < this._eyeBlinkParameterIds.getSize() && i < MaxTargetSize; ++i) - { - if (this._eyeBlinkParameterIds.at(i) == curves.at(c).id) - { - value *= eyeBlinkValue; - eyeBlinkFlags |= 1 << i; - break; - } - } - } - - if(lipSyncValue != Number.MAX_VALUE) - { - for(let i: number = 0; i < this._lipSyncParameterIds.getSize() && i < MaxTargetSize; ++i) - { - if(this._lipSyncParameterIds.at(i) == curves.at(c).id) - { - value += lipSyncValue; - lipSyncFlags |= 1 << i; - break; - } - } - } - - let v: number; - - // パラメータごとのフェード - if(curves.at(c).fadeInTime < 0.0 && curves.at(c).fadeOutTime < 0.0) - { - // モーションのフェードを適用 - v = sourceValue + (value - sourceValue) * fadeWeight; - } - else - { - // パラメータに対してフェードインかフェードアウトが設定してある場合はそちらを適用 - let fin: number; - let fout: number; - - if(curves.at(c).fadeInTime < 0.0) - { - fin = tmpFadeIn; - } - else - { - fin = curves.at(c).fadeInTime == 0.0 - ? 1.0 - :CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / curves.at(c).fadeInTime); - } - - if(curves.at(c).fadeOutTime < 0.0) - { - fout = tmpFadeOut; - } - else - { - fout = (curves.at(c).fadeOutTime == 0.0 || motionQueueEntry.getEndTime() < 0.0) - ? 1.0 - : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / curves.at(c).fadeOutTime); - } - - const paramWeight: number = this._weight * fin * fout; - - // パラメータごとのフェードを適用 - v = sourceValue + (value - sourceValue) * paramWeight; - } - - model.setParameterValueByIndex(parameterIndex, v, 1.0); - } - - { - if(eyeBlinkValue != Number.MAX_VALUE) - { - for(let i: number = 0; i < this._eyeBlinkParameterIds.getSize() && i < MaxTargetSize; ++i) - { - const sourceValue: number = model.getParameterValueById(this._eyeBlinkParameterIds.at(i)); - - // モーションでの上書きがあった時にはまばたきは適用しない - if((eyeBlinkFlags >> i) & 0x01) - { - continue; - } - - const v: number = sourceValue + (eyeBlinkValue - sourceValue) * fadeWeight; - - model.setParameterValueById(this._eyeBlinkParameterIds.at(i), v); - } - } - - if(lipSyncValue != Number.MAX_VALUE) - { - for(let i: number = 0; i < this._lipSyncParameterIds.getSize() && i < MaxTargetSize; ++i) - { - const sourceValue: number = model.getParameterValueById(this._lipSyncParameterIds.at(i)); - - // モーションでの上書きがあった時にはリップシンクは適用しない - if((lipSyncFlags >> i) & 0x01) - { - continue; - } - - const v: number = sourceValue + (lipSyncValue - sourceValue) * fadeWeight; - - model.setParameterValueById(this._lipSyncParameterIds.at(i), v); - } - } - } - - for(; c < this._motionData.curveCount && curves.at(c).type == CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity; ++c) - { - // Find parameter index. - parameterIndex = model.getParameterIndex(curves.at(c).id); - - // Skip curve evaluation if no value in sink. - if(parameterIndex == -1) - { - continue; - } - - // Evaluate curve and apply value. - value = evaluateCurve(this._motionData, c, time); - - model.setParameterValueByIndex(parameterIndex, value); - } - - if(timeOffsetSeconds >= this._motionData.duration) - { - if(this._isLoop) - { - motionQueueEntry.setStartTime(userTimeSeconds); // 最初の状態へ - if(this._isLoopFadeIn) - { - // ループ内でループ用フェードインが有効の時は、フェードイン設定し直し - motionQueueEntry.setFadeInStartTime(userTimeSeconds); - } - } - else - { - motionQueueEntry.setIsFinished(true); - } - } - this._lastWeight = fadeWeight; - } - - /** - * ループ情報の設定 - * @param loop ループ情報 - */ - public setIsLoop(loop: boolean): void - { - this._isLoop = loop; - } - - /** - * ループ情報の取得 - * @return true ループする - * @return false ループしない - */ - public isLoop(): boolean - { - return this._isLoop; - } - - /** - * ループ時のフェードイン情報の設定 - * @param loopFadeIn ループ時のフェードイン情報 - */ - public setIsLoopFadeIn(loopFadeIn: boolean): void - { - this._isLoopFadeIn = loopFadeIn; - } - - /** - * ループ時のフェードイン情報の取得 - * - * @return true する - * @return false しない - */ - public isLoopFadeIn(): boolean - { - return this._isLoopFadeIn; - } - - /** - * モーションの長さを取得する。 - * - * @return モーションの長さ[秒] - */ - public getDuration(): number - { - return this._isLoop ? -1.0 : this._loopDurationSeconds; - } - - /** - * モーションのループ時の長さを取得する。 - * - * @return モーションのループ時の長さ[秒] - */ - public getLoopDuration(): number - { - return this._loopDurationSeconds; - } - - /** - * パラメータに対するフェードインの時間を設定する。 - * - * @param parameterId パラメータID - * @param value フェードインにかかる時間[秒] - */ - public setParameterFadeInTime(parameterId: CubismIdHandle, value: number): void - { - let curves: csmVector = this._motionData.curves; - - for (let i: number = 0; i < this._motionData.curveCount; ++i) - { - if (parameterId == curves.at(i).id) - { - curves.at(i).fadeInTime = value; - return; - } - } - } - - /** - * パラメータに対するフェードアウトの時間の設定 - * @param parameterId パラメータID - * @param value フェードアウトにかかる時間[秒] - */ - public setParameterFadeOutTime(parameterId: CubismIdHandle, value: number): void - { - let curves: csmVector = this._motionData.curves; - - for (let i: number = 0; i < this._motionData.curveCount; ++i) - { - if (parameterId == curves.at(i).id) - { - curves.at(i).fadeOutTime = value; - return; - } - } - } - - /** - * パラメータに対するフェードインの時間の取得 - * @param parameterId パラメータID - * @return フェードインにかかる時間[秒] - */ - public getParameterFadeInTime(parameterId: CubismIdHandle): number - { - let curves: csmVector = this._motionData.curves; - - for (let i: number = 0; i < this._motionData.curveCount; ++i) - { - if (parameterId == curves.at(i).id) - { - return curves.at(i).fadeInTime; - } - } - - return -1; - } - - /** - * パラメータに対するフェードアウトの時間を取得 - * - * @param parameterId パラメータID - * @return フェードアウトにかかる時間[秒] - */ - public getParameterFadeOutTime(parameterId: CubismIdHandle): number - { - let curves: csmVector = this._motionData.curves; - - for (let i: number = 0; i < this._motionData.curveCount; ++i) - { - if (parameterId == curves.at(i).id) - { - return curves.at(i).fadeOutTime; - } - } - - return -1; - } - - /** - * 自動エフェクトがかかっているパラメータIDリストの設定 - * @param eyeBlinkParameterIds 自動まばたきがかかっているパラメータIDのリスト - * @param lipSyncParameterIds リップシンクがかかっているパラメータIDのリスト - */ - public setEffectIds(eyeBlinkParameterIds: csmVector, lipSyncParameterIds: csmVector): void - { - this._eyeBlinkParameterIds = eyeBlinkParameterIds; - this._lipSyncParameterIds = lipSyncParameterIds; - } - - /** - * コンストラクタ - */ - public constructor() - { - super(); - this._sourceFrameRate = 30.0; - this._loopDurationSeconds = -1.0; - this._isLoop = false; // trueから false へデフォルトを変更 - this._isLoopFadeIn = true; // ループ時にフェードインが有効かどうかのフラグ - this._lastWeight = 0.0; - this._motionData = null; - this._modelCurveIdEyeBlink = null; - this._modelCurveIdLipSync = null; - this._eyeBlinkParameterIds = null; - this._lipSyncParameterIds = null; - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - this._motionData = void 0; - this._motionData = null; - } - - /** - * motion3.jsonをパースする。 - * - * @param motionJson motion3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public parse(motionJson: ArrayBuffer, size: number): void - { - this._motionData = new CubismMotionData(); - - let json: CubismMotionJson = new CubismMotionJson(motionJson, size); - - this._motionData.duration = json.getMotionDuration(); - this._motionData.loop = json.isMotionLoop(); - this._motionData.curveCount = json.getMotionCurveCount(); - this._motionData.fps = json.getMotionFps(); - this._motionData.eventCount = json.getEventCount(); - - if (json.isExistMotionFadeInTime()) - { - this._fadeInSeconds = (json.getMotionFadeInTime() < 0.0) - ? 1.0 - : json.getMotionFadeInTime(); - } - else - { - this._fadeInSeconds = 1.0; - } - - if (json.isExistMotionFadeOutTime()) - { - this._fadeOutSeconds = (json.getMotionFadeOutTime() < 0.0) - ? 1.0 - : json.getMotionFadeOutTime(); - } - else - { - this._fadeOutSeconds = 1.0; - } - - this._motionData.curves.updateSize(this._motionData.curveCount, CubismMotionCurve, true); - this._motionData.segments.updateSize(json.getMotionTotalSegmentCount(), CubismMotionSegment, true); - this._motionData.points.updateSize(json.getMotionTotalPointCount(), CubismMotionPoint, true); - this._motionData.events.updateSize(this._motionData.eventCount, CubismMotionEvent, true); - - let totalPointCount: number = 0; - let totalSegmentCount: number = 0; - - // Curves - for (let curveCount: number = 0; curveCount < this._motionData.curveCount; ++curveCount) - { - if (json.getMotionCurveTarget(curveCount) == TargetNameModel) - { - this._motionData.curves.at(curveCount).type = CubismMotionCurveTarget.CubismMotionCurveTarget_Model; - } - else if (json.getMotionCurveTarget(curveCount) == TargetNameParameter) - { - this._motionData.curves.at(curveCount).type = CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter; - } - else if (json.getMotionCurveTarget(curveCount) == TargetNamePartOpacity) - { - this._motionData.curves.at(curveCount).type = CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity; - } - - this._motionData.curves.at(curveCount).id = json.getMotionCurveId(curveCount); - - this._motionData.curves.at(curveCount).baseSegmentIndex = totalSegmentCount; - - this._motionData.curves.at(curveCount).fadeInTime = - (json.isExistMotionCurveFadeInTime(curveCount)) - ? json.getMotionCurveFadeInTime(curveCount) - : -1.0 ; - this._motionData.curves.at(curveCount).fadeOutTime = - (json.isExistMotionCurveFadeOutTime(curveCount)) - ? json.getMotionCurveFadeOutTime(curveCount) - : -1.0; - - // Segments - for (let segmentPosition: number = 0; segmentPosition < json.getMotionCurveSegmentCount(curveCount);) - { - if (segmentPosition == 0) - { - this._motionData.segments.at(totalSegmentCount).basePointIndex = totalPointCount; - - this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, segmentPosition); - this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, segmentPosition + 1); - - totalPointCount += 1; - segmentPosition += 2; - } - else - { - this._motionData.segments.at(totalSegmentCount).basePointIndex = totalPointCount - 1; - } - - const segment: number = json.getMotionCurveSegment(curveCount, segmentPosition); - switch (segment) - { - case CubismMotionSegmentType.CubismMotionSegmentType_Linear: - { - this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Linear; - this._motionData.segments.at(totalSegmentCount).evaluate = linearEvaluate; - - this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); - this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); - - totalPointCount += 1; - segmentPosition += 3; - - break; - } - case CubismMotionSegmentType.CubismMotionSegmentType_Bezier: - { - this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Bezier; - this._motionData.segments.at(totalSegmentCount).evaluate = bezierEvaluate; - - this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); - this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); - - this._motionData.points.at(totalPointCount + 1).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 3)); - this._motionData.points.at(totalPointCount + 1).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 4)); - - this._motionData.points.at(totalPointCount + 2).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 5)); - this._motionData.points.at(totalPointCount + 2).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 6)); - - totalPointCount += 3; - segmentPosition += 7; - - break; - } - - case CubismMotionSegmentType.CubismMotionSegmentType_Stepped: - { - this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Stepped; - this._motionData.segments.at(totalSegmentCount).evaluate = steppedEvaluate; - - this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); - this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); - - totalPointCount += 1; - segmentPosition += 3; - - break; - } - - case CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped: - { - this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped; - this._motionData.segments.at(totalSegmentCount).evaluate = inverseSteppedEvaluate; - - this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); - this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); - - totalPointCount += 1; - segmentPosition += 3; - - break; - } - default: - { - CSM_ASSERT(0); - break; - } - } - - ++this._motionData.curves.at(curveCount).segmentCount; - ++totalSegmentCount; - } - } - - for (let userdatacount: number = 0; userdatacount < json.getEventCount(); ++userdatacount) - { - this._motionData.events.at(userdatacount).fireTime = json.getEventTime(userdatacount); - this._motionData.events.at(userdatacount).value = json.getEventValue(userdatacount); - } - - json.release(); - json = void 0; - json = null; - } - - /** - * モデルのパラメータ更新 - * - * イベント発火のチェック。 - * 入力する時間は呼ばれるモーションタイミングを0とした秒数で行う。 - * - * @param beforeCheckTimeSeconds 前回のイベントチェック時間[秒] - * @param motionTimeSeconds 今回の再生時間[秒] - */ - public getFiredEvent(beforeCheckTimeSeconds: number, motionTimeSeconds: number): csmVector - { - this._firedEventValues.updateSize(0); - - // イベントの発火チェック - for (let u: number = 0; u < this._motionData.eventCount; ++u) - { - if ((this._motionData.events.at(u).fireTime > beforeCheckTimeSeconds) && - (this._motionData.events.at(u).fireTime <= motionTimeSeconds)) - { - this._firedEventValues.pushBack(new csmString(this._motionData.events.at(u).value.s)); - } - } - - return this._firedEventValues; - } - - public _sourceFrameRate: number; // ロードしたファイルのFPS。記述が無ければデフォルト値15fpsとなる - public _loopDurationSeconds: number; // mtnファイルで定義される一連のモーションの長さ - public _isLoop: boolean; // ループするか? - public _isLoopFadeIn: boolean; // ループ時にフェードインが有効かどうかのフラグ。初期値では有効。 - public _lastWeight: number; // 最後に設定された重み - - public _motionData: CubismMotionData; // 実際のモーションデータ本体 - - public _eyeBlinkParameterIds: csmVector; // 自動まばたきを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。 - public _lipSyncParameterIds: csmVector; // リップシンクを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。 - - public _modelCurveIdEyeBlink: CubismIdHandle; // モデルが持つ自動まばたき用パラメータIDのハンドル。 モデルとモーションを対応付ける。 - public _modelCurveIdLipSync: CubismIdHandle; // モデルが持つリップシンク用パラメータIDのハンドル。 モデルとモーションを対応付ける。 - } -} \ No newline at end of file diff --git a/Framework/motion/cubismmotioninternal.ts b/Framework/motion/cubismmotioninternal.ts deleted file mode 100644 index 8794aa0..0000000 --- a/Framework/motion/cubismmotioninternal.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismid} from '../id/cubismid'; -import {Live2DCubismFramework as csmstring} from '../type/csmstring'; -import {Live2DCubismFramework as csmvector} from '../type/csmvector'; -import csmVector = csmvector.csmVector; -import csmString = csmstring.csmString; -import CubismIdHandle = cubismid.CubismIdHandle; - -export namespace Live2DCubismFramework -{ - /** - * @brief モーションカーブの種類 - * - * モーションカーブの種類。 - */ - export enum CubismMotionCurveTarget - { - CubismMotionCurveTarget_Model, // モデルに対して - CubismMotionCurveTarget_Parameter, // パラメータに対して - CubismMotionCurveTarget_PartOpacity // パーツの不透明度に対して - }; - - - /** - * @brief モーションカーブのセグメントの種類 - * - * モーションカーブのセグメントの種類。 - */ - export enum CubismMotionSegmentType - { - CubismMotionSegmentType_Linear = 0, // リニア - CubismMotionSegmentType_Bezier = 1, // ベジェ曲線 - CubismMotionSegmentType_Stepped = 2, // ステップ - CubismMotionSegmentType_InverseStepped = 3 // インバースステップ - }; - - /** - * @brief モーションカーブの制御点 - * - * モーションカーブの制御点。 - */ - export class CubismMotionPoint - { - time: number = 0.0; // 時間[秒] - value: number = 0.0; // 値 - }; - - - /** - * モーションカーブのセグメントの評価関数 - * - * @param points モーションカーブの制御点リスト - * @param time 評価する時間[秒] - */ - export interface csmMotionSegmentEvaluationFunction - { - ( - points: CubismMotionPoint[], - time: number - ): number; - } - - /** - * @brief モーションカーブのセグメント - * - * モーションカーブのセグメント。 - */ - export class CubismMotionSegment - { - /** - * @brief コンストラクタ - * - * コンストラクタ。 - */ - public constructor() - { - this.evaluate = null; - this.basePointIndex = 0; - this.segmentType = 0; - } - - evaluate: csmMotionSegmentEvaluationFunction; // 使用する評価関数 - basePointIndex: number; // 最初のセグメントへのインデックス - segmentType: number; // セグメントの種類 - }; - - /** - * @brief モーションカーブ - * - * モーションカーブ。 - */ - export class CubismMotionCurve - { - public constructor() - { - this.type = CubismMotionCurveTarget.CubismMotionCurveTarget_Model; - this.segmentCount = 0; - this.baseSegmentIndex = 0; - this.fadeInTime = 0.0; - this.fadeOutTime = 0.0; - } - - type: CubismMotionCurveTarget; // カーブの種類 - id: CubismIdHandle; // カーブのID - segmentCount: number; // セグメントの個数 - baseSegmentIndex: number; // 最初のセグメントのインデックス - fadeInTime: number; // フェードインにかかる時間[秒] - fadeOutTime: number; // フェードアウトにかかる時間[秒] - }; - - /** - * イベント。 - */ - export class CubismMotionEvent - { - fireTime: number = 0.0; - value: csmString; - }; - - /** - * @brief モーションデータ - * - * モーションデータ。 - */ - export class CubismMotionData - { - public constructor() - { - this.duration = 0.0; - this.loop = false; - this.curveCount = 0; - this.eventCount = 0; - this.fps = 0.0; - - this.curves = new csmVector(); - this.segments = new csmVector(); - this.points = new csmVector(); - this.events = new csmVector(); - } - - duration: number; // モーションの長さ[秒] - loop: boolean; // ループするかどうか - curveCount: number; // カーブの個数 - eventCount: number; // UserDataの個数 - fps: number; // フレームレート - curves: csmVector; // カーブのリスト - segments: csmVector; // セグメントのリスト - points: csmVector; // ポイントのリスト - events: csmVector; // イベントのリスト - }; -} \ No newline at end of file diff --git a/Framework/motion/cubismmotionjson.ts b/Framework/motion/cubismmotionjson.ts deleted file mode 100644 index 8cc14cc..0000000 --- a/Framework/motion/cubismmotionjson.ts +++ /dev/null @@ -1,282 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismjson} from '../utils/cubismjson'; -import {Live2DCubismFramework as cubismid} from '../id/cubismid'; -import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; -import {Live2DCubismFramework as csmstring} from '../type/csmstring'; -import csmString = csmstring.csmString; -import CubismFramework = cubismframework.CubismFramework; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismJson = cubismjson.CubismJson; - -export namespace Live2DCubismFramework -{ - // JSON keys - const Meta: string = "Meta"; - const Duration: string = "Duration"; - const Loop: string = "Loop"; - const CurveCount: string = "CurveCount"; - const Fps: string = "Fps"; - const TotalSegmentCount: string = "TotalSegmentCount"; - const TotalPointCount: string = "TotalPointCount"; - const Curves: string = "Curves"; - const Target: string = "Target"; - const Id: string = "Id"; - const FadeInTime: string = "FadeInTime"; - const FadeOutTime: string = "FadeOutTime"; - const Segments: string = "Segments"; - const UserData: string = "UserData"; - const UserDataCount: string = "UserDataCount"; - const TotalUserDataSize: string = "TotalUserDataSize"; - const Time: string = "Time"; - const Value: string = "Value"; - - /** - * motion3.jsonのコンテナ。 - */ - export class CubismMotionJson - { - /** - * コンストラクタ - * @param buffer motion3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public constructor(buffer: ArrayBuffer, size: number) - { - this._json = CubismJson.create(buffer, size); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - CubismJson.delete(this._json); - } - - /** - * モーションの長さを取得する - * @return モーションの長さ[秒] - */ - public getMotionDuration(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(Duration).toFloat(); - } - - /** - * モーションのループ情報の取得 - * @return true ループする - * @return false ループしない - */ - public isMotionLoop(): boolean - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(Loop).toBoolean(); - } - - /** - * モーションカーブの個数の取得 - * @return モーションカーブの個数 - */ - public getMotionCurveCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(CurveCount).toInt(); - } - - /** - * モーションのフレームレートの取得 - * @return フレームレート[FPS] - */ - public getMotionFps(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(Fps).toFloat(); - } - - /** - * モーションのセグメントの総合計の取得 - * @return モーションのセグメントの取得 - */ - public getMotionTotalSegmentCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalSegmentCount).toInt(); - } - - /** - * モーションのカーブの制御店の総合計の取得 - * @return モーションのカーブの制御点の総合計 - */ - public getMotionTotalPointCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalPointCount).toInt(); - } - - /** - * モーションのフェードイン時間の存在 - * @return true 存在する - * @return false 存在しない - */ - public isExistMotionFadeInTime(): boolean - { - return this._json.getRoot().getMap().getValue(Meta).getMap().isExist(FadeInTime); - } - - /** - * モーションのフェードアウト時間の存在 - * @return true 存在する - * @return false 存在しない - */ - public isExistMotionFadeOutTime(): boolean - { - return this._json.getRoot().getMap().getValue(Meta).getMap().isExist(FadeOutTime); - } - - /** - * モーションのフェードイン時間の取得 - * @return フェードイン時間[秒] - */ - public getMotionFadeInTime(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(FadeInTime).toFloat(); - } - - /** - * モーションのフェードアウト時間の取得 - * @return フェードアウト時間[秒] - */ - public getMotionFadeOutTime(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(FadeOutTime).toFloat(); - } - - /** - * モーションのカーブの種類の取得 - * @param curveIndex カーブのインデックス - * @return カーブの種類 - */ - public getMotionCurveTarget(curveIndex: number): string - { - return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Target).getRawString(); - } - - /** - * モーションのカーブのIDの取得 - * @param curveIndex カーブのインデックス - * @return カーブのID - */ - public getMotionCurveId(curveIndex: number): CubismIdHandle - { - return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Id).getRawString()); - } - - /** - * モーションのカーブのフェードイン時間の存在 - * @param curveIndex カーブのインデックス - * @return true 存在する - * @return false 存在しない - */ - public isExistMotionCurveFadeInTime(curveIndex: number): boolean - { - return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().isExist(FadeInTime); - } - - /** - * モーションのカーブのフェードアウト時間の存在 - * @param curveIndex カーブのインデックス - * @return true 存在する - * @return false 存在しない - */ - public isExistMotionCurveFadeOutTime(curveIndex: number): boolean - { - return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().isExist(FadeOutTime); - } - - /** - * モーションのカーブのフェードイン時間の取得 - * @param curveIndex カーブのインデックス - * @return フェードイン時間[秒] - */ - public getMotionCurveFadeInTime(curveIndex: number): number - { - return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(FadeInTime).toFloat(); - } - - /** - * モーションのカーブのフェードアウト時間の取得 - * @param curveIndex カーブのインデックス - * @return フェードアウト時間[秒] - */ - public getMotionCurveFadeOutTime(curveIndex: number): number - { - return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(FadeOutTime).toFloat(); - } - - /** - * モーションのカーブのセグメントの個数を取得する - * @param curveIndex カーブのインデックス - * @return モーションのカーブのセグメントの個数 - */ - public getMotionCurveSegmentCount(curveIndex: number): number - { - return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Segments).getVector().getSize(); - } - - /** - * モーションのカーブのセグメントの値の取得 - * @param curveIndex カーブのインデックス - * @param segmentIndex セグメントのインデックス - * @return セグメントの値 - */ - public getMotionCurveSegment(curveIndex: number, segmentIndex: number): number - { - return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Segments).getVector().at(segmentIndex).toFloat(); - } - - /** - * イベントの個数の取得 - * @return イベントの個数 - */ - public getEventCount(): number - { - if(!this._json.getRoot().getMap().getValue(Meta).getMap().isExist(UserDataCount)) - { - return 0; - } - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(UserDataCount).toInt(); - } - - /** - * イベントの総文字数の取得 - * @return イベントの総文字数 - */ - public getTotalEventValueSize(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalUserDataSize).toInt(); - } - - /** - * イベントの時間の取得 - * @param userDataIndex イベントのインデックス - * @return イベントの時間[秒] - */ - public getEventTime(userDataIndex: number): number - { - return this._json.getRoot().getMap().getValue(UserData).getVector().at(userDataIndex).getMap().getValue(Time).toInt(); - } - - /** - * イベントの取得 - * @param userDataIndex イベントのインデックス - * @return イベントの文字列 - */ - public getEventValue(userDataIndex: number): csmString - { - return new csmString(this._json.getRoot().getMap().getValue(UserData).getVector().at(userDataIndex).getMap().getValue(Value).getRawString()); - } - - _json: CubismJson; // motion3.jsonのデータ - } -} \ No newline at end of file diff --git a/Framework/motion/cubismmotionmanager.ts b/Framework/motion/cubismmotionmanager.ts deleted file mode 100644 index 9299351..0000000 --- a/Framework/motion/cubismmotionmanager.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismmotionqueuemanager} from "./cubismmotionqueuemanager"; -import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; -import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; -import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle; -import CubismModel = cubismmodel.CubismModel; -import ACubismMotion = acubismmotion.ACubismMotion; -import CubismMotionQueueManager = cubismmotionqueuemanager.CubismMotionQueueManager; - -export namespace Live2DCubismFramework -{ - /** - * モーションの管理 - * - * モーションの管理を行うクラス - */ - export class CubismMotionManager extends CubismMotionQueueManager - { - /** - * コンストラクタ - */ - public constructor() - { - super(); - this._currentPriority = 0; - this._reservePriority = 0; - } - - /** - * 再生中のモーションの優先度の取得 - * @return モーションの優先度 - */ - public getCurrentPriority(): number - { - return this._currentPriority; - } - - /** - * 予約中のモーションの優先度を取得する。 - * @return モーションの優先度 - */ - public getReservePriority(): number - { - return this._reservePriority; - } - - /** - * 予約中のモーションの優先度を設定する。 - * @param val 優先度 - */ - public setReservePriority(val: number): void - { - this._reservePriority = val; - } - - /** - * 優先度を設定してモーションを開始する。 - * - * @param motion モーション - * @param autoDelete 再生が狩猟したモーションのインスタンスを削除するならtrue - * @param priority 優先度 - * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 - */ - public startMotionPriority(motion: ACubismMotion, autoDelete: boolean, priority: number): CubismMotionQueueEntryHandle - { - if(priority == this._reservePriority) - { - this._reservePriority = 0; // 予約を解除 - } - - this._currentPriority = priority; // 再生中モーションの優先度を設定 - - return super.startMotion(motion, autoDelete, this._userTimeSeconds); - } - - /** - * モーションを更新して、モデルにパラメータ値を反映する。 - * - * @param model 対象のモデル - * @param deltaTimeSeconds デルタ時間[秒] - * @return true 更新されている - * @return false 更新されていない - */ - public updateMotion(model: CubismModel, deltaTimeSeconds: number): boolean - { - this._userTimeSeconds += deltaTimeSeconds; - - const updated: boolean = super.doUpdateMotion(model, this._userTimeSeconds); - - if(this.isFinished()) - { - this._currentPriority = 0; // 再生中のモーションの優先度を解除 - } - - return updated; - } - - /** - * モーションを予約する。 - * - * @param priority 優先度 - * @return true 予約できた - * @return false 予約できなかった - */ - public reserveMotion(priority: number): boolean - { - if((priority <= this._reservePriority) || (priority <= this._currentPriority)) - { - return false; - } - - this._reservePriority = priority; - - return true; - } - - _currentPriority: number; // 現在再生中のモーションの優先度 - _reservePriority: number; // 再生予定のモーションの優先度。再生中は0になる。モーションファイルを別スレッドで読み込むときの機能。 - } - -} \ No newline at end of file diff --git a/Framework/motion/cubismmotionqueueentry.ts b/Framework/motion/cubismmotionqueueentry.ts deleted file mode 100644 index a34b779..0000000 --- a/Framework/motion/cubismmotionqueueentry.ts +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; -import {Live2DCubismFramework as cubismmotionqueuemanager} from './cubismmotionqueuemanager'; -import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle; -import ACubismMotion = acubismmotion.ACubismMotion; - -export namespace Live2DCubismFramework -{ - /** - * CubismMotionQueueManagerで再生している各モーションの管理クラス。 - */ - export class CubismMotionQueueEntry - { - /** - * コンストラクタ - */ - public constructor() - { - this._autoDelete = false; - this._motion = null; - this._available = true; - this._finished = false; - this._started = false; - this._startTimeSeconds = -1.0; - this._fadeInStartTimeSeconds = 0.0; - this._endTimeSeconds = -1.0; - this._stateTimeSeconds = 0.0; - this._stateWeight = 0.0; - this._lastEventCheckSeconds = 0.0; - this._motionQueueEntryHandle = this; - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - if(this._autoDelete && this._motion) - { - ACubismMotion.delete(this._motion); // - } - } - - /** - * フェードアウトの開始 - * @param fadeOutSeconds フェードアウトにかかる時間[秒] - * @param userTimeSeconds デルタ時間の積算値[秒] - */ - public startFadeout(fadeoutSeconds: number, userTimeSeconds: number): void - { - const newEndTimeSeconds: number = userTimeSeconds + fadeoutSeconds; - - if(this._endTimeSeconds < 0.0 || newEndTimeSeconds < this._endTimeSeconds) - { - this._endTimeSeconds = newEndTimeSeconds; - } - } - - /** - * モーションの終了の確認 - * - * @return true モーションが終了した - * @return false 終了していない - */ - public isFinished(): boolean - { - return this._finished; - } - - /** - * モーションの開始の確認 - * @return true モーションが開始した - * @return false 開始していない - */ - public isStarted(): boolean - { - return this._started; - } - - /** - * モーションの開始時刻の取得 - * @return モーションの開始時刻[秒] - */ - public getStartTime(): number - { - return this._startTimeSeconds; - } - - /** - * フェードインの開始時刻の取得 - * @return フェードインの開始時刻[秒] - */ - public getFadeInStartTime(): number - { - return this._fadeInStartTimeSeconds; - } - - /** - * フェードインの終了時刻の取得 - * @return フェードインの終了時刻の取得 - */ - public getEndTime(): number - { - return this._endTimeSeconds; - } - - /** - * モーションの開始時刻の設定 - * @param startTime モーションの開始時刻 - */ - public setStartTime(startTime: number): void - { - this._startTimeSeconds = startTime; - } - - /** - * フェードインの開始時刻の設定 - * @param startTime フェードインの開始時刻[秒] - */ - public setFadeInStartTime(startTime: number): void - { - this._fadeInStartTimeSeconds = startTime; - } - - /** - * フェードインの終了時刻の設定 - * @param endTime フェードインの終了時刻[秒] - */ - public setEndTime(endTime: number): void - { - this._endTimeSeconds = endTime; - } - - /** - * モーションの終了の設定 - * @param f trueならモーションの終了 - */ - public setIsFinished(f: boolean): void - { - this._finished = f; - } - - /** - * モーション開始の設定 - * @param f trueならモーションの開始 - */ - public setIsStarted(f: boolean): void - { - this._started = f; - } - - /** - * モーションの有効性の確認 - * @return true モーションは有効 - * @return false モーションは無効 - */ - public isAvailable(): boolean - { - return this._available; - } - - /** - * モーションの有効性の設定 - * @param v trueならモーションは有効 - */ - public setIsAvailable(v: boolean): void - { - this._available = v; - } - - /** - * モーションの状態の設定 - * @param timeSeconds 現在時刻[秒] - * @param weight モーション尾重み - */ - public setState(timeSeconds: number, weight: number): void - { - this._stateTimeSeconds = timeSeconds; - this._stateWeight = weight; - } - - /** - * モーションの現在時刻の取得 - * @return モーションの現在時刻[秒] - */ - public getStateTime(): number - { - return this._stateTimeSeconds; - } - - /** - * モーションの重みの取得 - * @return モーションの重み - */ - public getStateWeight(): number - { - return this._stateWeight; - } - - /** - * 最後にイベントの発火をチェックした時間を取得 - * - * @return 最後にイベントの発火をチェックした時間[秒] - */ - public getLastCheckEventTime(): number - { - return this._lastEventCheckSeconds; - } - - /** - * 最後にイベントをチェックした時間を設定 - * @param checkTime 最後にイベントをチェックした時間[秒] - */ - public setLastCheckEventTime(checkTime: number): void - { - this._lastEventCheckSeconds = checkTime; - } - - _autoDelete: boolean; // 自動削除 - _motion: ACubismMotion; // モーション - - _available: boolean; // 有効化フラグ - _finished: boolean; // 終了フラグ - _started: boolean; // 開始フラグ - _startTimeSeconds: number; // モーション再生開始時刻[秒] - _fadeInStartTimeSeconds: number; // フェードイン開始時刻(ループの時は初回のみ)[秒] - _endTimeSeconds: number; // 終了予定時刻[秒] - _stateTimeSeconds: number; // 時刻の状態[秒] - _stateWeight: number;  // 重みの状態 - _lastEventCheckSeconds: number; // 最終のMotion側のチェックした時間 - - _motionQueueEntryHandle: CubismMotionQueueEntryHandle; // インスタンスごとに一意の値を持つ識別番号 - } -} \ No newline at end of file diff --git a/Framework/motion/cubismmotionqueuemanager.ts b/Framework/motion/cubismmotionqueuemanager.ts deleted file mode 100644 index 0166dd7..0000000 --- a/Framework/motion/cubismmotionqueuemanager.ts +++ /dev/null @@ -1,342 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; -import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; -import {Live2DCubismFramework as csmvector} from '../type/csmvector'; -import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; -import {Live2DCubismFramework as csmstring} from '../type/csmstring'; -import csmString = csmstring.csmString; -import CubismModel = cubismmodel.CubismModel; -import csmVector = csmvector.csmVector; -import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; -import ACubismMotion = acubismmotion.ACubismMotion; - -export namespace Live2DCubismFramework -{ - /** - * モーション再生の管理 - * - * モーション再生の管理用クラス。CubismMotionモーションなどACubismMotionのサブクラスを再生するために使用する。 - * - * @note 再生中に別のモーションが StartMotion()された場合は、新しいモーションに滑らかに変化し旧モーションは中断する。 - * 表情用モーション、体用モーションなどを分けてモーション化した場合など、 - * 複数のモーションを同時に再生させる場合は、複数のCubismMotionQueueManagerインスタンスを使用する。 - */ - export class CubismMotionQueueManager - { - /** - * コンストラクタ - */ - public constructor() - { - this._userTimeSeconds = 0.0; - this._eventCallBack = null; - this._eventCustomData = null; - this._motions = new csmVector(); - } - - /** - * デストラクタ - */ - public release(): void - { - for(let i: number = 0; i < this._motions.getSize(); ++i) - { - if(this._motions.at(i)) - { - this._motions.at(i).release(); - this._motions.set(i, void 0); - this._motions.set(i, null); - } - } - - this._motions = null; - } - - /** - * 指定したモーションの開始 - * - * 指定したモーションを開始する。同じタイプのモーションが既にある場合は、既存のモーションに終了フラグを立て、フェードアウトを開始させる。 - * - * @param motion 開始するモーション - * @param autoDelete 再生が終了したモーションのインスタンスを削除するなら true - * @param userTimeSeconds デルタ時間の積算値[秒] - * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 - */ - public startMotion(motion: ACubismMotion, autoDelete: boolean, userTimeSeconds: number): CubismMotionQueueEntryHandle - { - if(motion == null) - { - return InvalidMotionQueueEntryHandleValue; - } - - let motionQueueEntry: CubismMotionQueueEntry = null; - - // 既にモーションがあれば終了フラグを立てる - for(let i: number = 0; i < this._motions.getSize(); ++i) - { - motionQueueEntry = this._motions.at(i); - if(motionQueueEntry == null) - { - continue; - } - - motionQueueEntry.startFadeout(motionQueueEntry._motion.getFadeOutTime(), userTimeSeconds); // フェードアウトを開始し終了する - } - - motionQueueEntry = new CubismMotionQueueEntry(); // 終了時に破棄する - motionQueueEntry._autoDelete = autoDelete; - motionQueueEntry._motion = motion; - - this._motions.pushBack(motionQueueEntry); - - return motionQueueEntry._motionQueueEntryHandle; - } - - /** - * 全てのモーションの終了の確認 - * @return true 全て終了している - * @return false 終了していない - */ - public isFinished(): boolean - { - // ------- 処理を行う ------- - // 既にモーションがあれば終了フラグを立てる - - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) - { - let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); - - if(motionQueueEntry == null) - { - ite = this._motions.erase(ite); // 削除 - continue; - } - - let motion: ACubismMotion = motionQueueEntry._motion; - - if(motion == null) - { - motionQueueEntry.release(); - motionQueueEntry = void 0; - motionQueueEntry = null; - ite = this._motions.erase(ite); // 削除 - continue; - } - - // ----- 終了済みの処理があれば削除する ------ - if(!motionQueueEntry.isFinished()) - { - return false; - } - else - { - ite.preIncrement(); - } - } - - return true; - } - - /** - * 指定したモーションの終了の確認 - * @param motionQueueEntryNumber モーションの識別番号 - * @return true 全て終了している - * @return false 終了していない - */ - public isFinishedByHandle(motionQueueEntryNumber: CubismMotionQueueEntryHandle): boolean - { - // 既にモーションがあれば終了フラグを立てる - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());ite.increment()) - { - let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); - - if(motionQueueEntry == null) - { - continue; - } - - if(motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber && !motionQueueEntry.isFinished()) - { - return false; - } - } - return true; - } - - /** - * 全てのモーションを停止する - */ - public stopAllMotions(): void - { - // ------- 処理を行う ------- - // 既にモーションがあれば終了フラグを立てる - - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) - { - let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); - - if(motionQueueEntry == null) - { - ite = this._motions.erase(ite); - - continue; - } - - // ----- 終了済みの処理があれば削除する ------ - motionQueueEntry.release(); - motionQueueEntry = void 0; - motionQueueEntry = null; - ite = this._motions.erase(ite); // 削除 - } - } - - /** - * 指定したCubismMotionQueueEntryの取得 - - * @param motionQueueEntryNumber モーションの識別番号 - * @return 指定したCubismMotionQueueEntry - * @return null 見つからなかった - */ - public getCubismMotionQueueEntry(motionQueueEntryNumber: any): CubismMotionQueueEntry - { - //------- 処理を行う ------- - // 既にモーションがあれば終了フラグを立てる - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end()); ite.preIncrement()) - { - let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); - - if(motionQueueEntry == null) - { - continue; - } - - if(motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber) - { - return motionQueueEntry; - } - } - - return null; - } - - /** - * イベントを受け取るCallbackの登録 - * - * @param callback コールバック関数 - * @param customData コールバックに返されるデータ - */ - public setEventCallback(callback: CubismMotionEventFunction, customData: any = null): void - { - this._eventCallBack = callback; - this._eventCustomData = customData; - } - - /** - * モーションを更新して、モデルにパラメータ値を反映する。 - * - * @param model 対象のモデル - * @param userTimeSeconds デルタ時間の積算値[秒] - * @return true モデルへパラメータ値の反映あり - * @return false モデルへパラメータ値の反映なし(モーションの変化なし) - */ - public doUpdateMotion(model: CubismModel, userTimeSeconds: number): boolean - { - let updated: boolean = false; - - // ------- 処理を行う -------- - // 既にモーションがあれば終了フラグを立てる - - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) - { - let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); - - if(motionQueueEntry == null) - { - ite = this._motions.erase(ite); // 削除 - continue; - } - - let motion: ACubismMotion = motionQueueEntry._motion; - - if(motion == null) - { - motionQueueEntry.release(); - motionQueueEntry = void 0; - motionQueueEntry = null; - ite = this._motions.erase(ite); // 削除 - - continue; - } - - // ------ 値を反映する ------ - motion.updateParameters(model, motionQueueEntry, userTimeSeconds); - updated = true; - - // ------ ユーザトリガーイベントを検査する ---- - const firedList: csmVector = motion.getFiredEvent( - motionQueueEntry.getLastCheckEventTime() - motionQueueEntry.getStartTime(), - userTimeSeconds - motionQueueEntry.getStartTime() - ); - - for(let i: number = 0; i < firedList.getSize(); ++i) - { - this._eventCallBack(this, firedList.at(i), this._eventCustomData); - } - - motionQueueEntry.setLastCheckEventTime(userTimeSeconds); - - // ------ 終了済みの処理があれば削除する ------ - if(motionQueueEntry.isFinished()) - { - motionQueueEntry.release(); - motionQueueEntry = void 0; - motionQueueEntry = null; - ite = this._motions.erase(ite); // 削除 - } - else - { - ite.preIncrement(); - } - } - - return updated; - } - _userTimeSeconds: number; // デルタ時間の積算値[秒] - - _motions: csmVector; // モーション - _eventCallBack: CubismMotionEventFunction; // コールバック関数 - _eventCustomData: any; // コールバックに戻されるデータ - } - - - /** - * イベントのコールバック関数を定義 - * - * イベントのコールバックに登録できる関数の型情報 - * @param caller 発火したイベントを再生させたCubismMotionQueueManager - * @param eventValue 発火したイベントの文字列データ - * @param customData コールバックに返される登録時に指定されたデータ - */ - export interface CubismMotionEventFunction - { - ( - caller: CubismMotionQueueManager, - eventValue: csmString, - customData: any - ): void; - } - - /** - * モーションの識別番号 - * - * モーションの識別番号の定義 - */ - export declare type CubismMotionQueueEntryHandle = any; - export const InvalidMotionQueueEntryHandleValue: CubismMotionQueueEntryHandle = -1; -} \ No newline at end of file diff --git a/Framework/physics/cubismphysics.ts b/Framework/physics/cubismphysics.ts deleted file mode 100644 index 4a7f6ad..0000000 --- a/Framework/physics/cubismphysics.ts +++ /dev/null @@ -1,826 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismphysicsinternal} from './cubismphysicsinternal'; -import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; -import {Live2DCubismFramework as cubismvector2} from '../math/cubismvector2'; -import {Live2DCubismFramework as cubismmath} from '../math/cubismmath'; -import {Live2DCubismFramework as cubismphysicsjson} from './cubismphysicsjson'; -import CubismPhysicsJson = cubismphysicsjson.CubismPhysicsJson; -import CubismMath = cubismmath.CubismMath; -import CubismPhysicsRig = cubismphysicsinternal.CubismPhysicsRig; -import CubismPhysicsSubRig = cubismphysicsinternal.CubismPhysicsSubRig; -import CubismPhysicsInput = cubismphysicsinternal.CubismPhysicsInput; -import CubismPhysicsOutput = cubismphysicsinternal.CubismPhysicsOutput; -import CubismPhysicsParticle = cubismphysicsinternal.CubismPhysicsParticle; -import CubismPhysicsSource = cubismphysicsinternal.CubismPhysicsSource; -import CubismPhysicsTargetType = cubismphysicsinternal.CubismPhysicsTargetType; -import CubismPhysicsNormalization = cubismphysicsinternal.CubismPhysicsNormalization; -import CubismVector2 = cubismvector2.CubismVector2; -import CubismModel = cubismmodel.CubismModel; - -export namespace Live2DCubismFramework -{ - - /// physics types tags. - const PhysicsTypeTagX: string = "X"; - const PhysicsTypeTagY: string = "Y"; - const PhysicsTypeTagAngle: string = "Angle"; - - /// Constant of air resistance. - const AirResistance: number = 5.0; - - /// Constant of maximum weight of input and output ratio. - const MaximumWeight: number = 100.0; - - /// Constant of threshold of movement. - const MovementThreshold: number = 0.001; - - /** - * 物理演算クラス - */ - export class CubismPhysics - { - /** - * インスタンスの作成 - * @param buffer physics3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - * @return 作成されたインスタンス - */ - public static create(buffer: ArrayBuffer, size: number): CubismPhysics - { - let ret: CubismPhysics = new CubismPhysics(); - - ret.parse(buffer, size); - ret._physicsRig.gravity.y = 0; - - return ret; - } - - /** - * インスタンスを破棄する - * @param physics 破棄するインスタンス - */ - public static delete(physics: CubismPhysics): void - { - physics.release(); - physics = void 0; - physics = null; - } - - /** - * 物理演算の評価 - * @param model 物理演算の結果を適用するモデル - * @param deltaTimeSeconds デルタ時間[秒] - */ - public evaluate(model: CubismModel, deltaTimeSeconds: number): void - { - let totalAngle: {angle: number}; - let weight: number; - let radAngle: number; - let outputValue: number; - let totalTranslation: CubismVector2 = new CubismVector2(); - let currentSetting: CubismPhysicsSubRig; - let currentInput: CubismPhysicsInput[]; - let currentOutput: CubismPhysicsOutput[]; - let currentParticles: CubismPhysicsParticle[]; - - let parameterValue: Float32Array; - let parameterMaximumValue: Float32Array; - let parameterMinimumValue: Float32Array; - let parameterDefaultValue: Float32Array; - - parameterValue = model.getModel().parameters.values; - parameterMaximumValue = model.getModel().parameters.maximumValues; - parameterMinimumValue = model.getModel().parameters.minimumValues; - parameterDefaultValue = model.getModel().parameters.defaultValues; - - for(let settingIndex: number = 0; settingIndex < this._physicsRig.subRigCount; ++settingIndex) - { - totalAngle = {angle: 0.0}; - totalTranslation.x = 0.0; - totalTranslation.y = 0.0; - currentSetting = this._physicsRig.settings.at(settingIndex); - currentInput = this._physicsRig.inputs.get(currentSetting.baseInputIndex); - currentOutput = this._physicsRig.outputs.get(currentSetting.baseOutputIndex); - currentParticles = this._physicsRig.particles.get(currentSetting.baseParticleIndex); - - // Load input parameters - for(let i: number = 0; i < currentSetting.inputCount; ++i) - { - weight = currentInput[i].weight / MaximumWeight; - - if(currentInput[i].sourceParameterIndex == -1) - { - currentInput[i].sourceParameterIndex = model.getParameterIndex(currentInput[i].source.id); - } - - currentInput[i].getNormalizedParameterValue( - totalTranslation, - totalAngle, - parameterValue[currentInput[i].sourceParameterIndex], - parameterMinimumValue[currentInput[i].sourceParameterIndex], - parameterMaximumValue[currentInput[i].sourceParameterIndex], - parameterDefaultValue[currentInput[i].sourceParameterIndex], - currentSetting.normalizationPosition, - currentSetting.normalizationAngle, - currentInput[0].reflect, - weight - ); - } - - radAngle = CubismMath.degreesToRadian(-totalAngle.angle); - - totalTranslation.x = (totalTranslation.x * CubismMath.cos(radAngle) - totalTranslation.y * CubismMath.sin(radAngle)); - totalTranslation.y = (totalTranslation.x * CubismMath.sin(radAngle) + totalTranslation.y * CubismMath.cos(radAngle)); - - // Calculate particles position. - updateParticles( - currentParticles, - currentSetting.particleCount, - totalTranslation, - totalAngle.angle, - this._options.wind, - MovementThreshold * currentSetting.normalizationPosition.maximum, - deltaTimeSeconds, - AirResistance - ); - - // Update output parameters. - for (let i: number = 0; i < currentSetting.outputCount; ++i) - { - let particleIndex = currentOutput[i].vertexIndex; - - if(particleIndex < 1 || particleIndex >= currentSetting.particleCount) - { - break; - } - - if(currentOutput[i].destinationParameterIndex == -1) - { - currentOutput[i].destinationParameterIndex = model.getParameterIndex(currentOutput[i].destination.id); - } - - let translation: CubismVector2 = new CubismVector2(); - translation.x = currentParticles[particleIndex].position.x - currentParticles[particleIndex - 1].position.x; - translation.y = currentParticles[particleIndex].position.y - currentParticles[particleIndex - 1].position.y; - - outputValue = currentOutput[i].getValue( - translation, - currentParticles, - particleIndex, - currentOutput[i].reflect, - this._options.gravity - ); - - let destinationParameterIndex = currentOutput[i].destinationParameterIndex; - let outParameterValue = parameterValue.slice(destinationParameterIndex); - - updateOutputParameterValue( - outParameterValue, - parameterMinimumValue[destinationParameterIndex], - parameterMaximumValue[destinationParameterIndex], - outputValue, - currentOutput[i] - ); - - // 値を反映 - for(let offset: number = destinationParameterIndex, outParamIndex: number = 0; offset < parameterValue.length; offset++, outParamIndex++) - { - parameterValue[offset] = outParameterValue[outParamIndex]; - } - } - } - } - - /** - * オプションの設定 - * @param options オプション - */ - public setOptions(options: CubismPhysics.Options): void - { - this._options = options; - } - - /** - * オプションの取得 - * @return オプション - */ - public getOption(): CubismPhysics.Options - { - return this._options; - } - - /** - * コンストラクタ - */ - public constructor() - { - this._physicsRig = null; - - // set default options - this._options = new CubismPhysics.Options(); - this._options.gravity.y = -1.0; - this._options.gravity.x = 0; - this._options.wind.x = 0; - this._options.wind.y = 0; - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - this._physicsRig = void 0; - this._physicsRig = null; - } - - /** - * physics3.jsonをパースする。 - * @param physicsJson physics3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public parse(physicsJson: ArrayBuffer, size: number): void - { - this._physicsRig = new CubismPhysicsRig(); - - let json: CubismPhysicsJson = new CubismPhysicsJson(physicsJson, size); - - this._physicsRig.gravity = json.getGravity(); - this._physicsRig.wind = json.getWind(); - this._physicsRig.subRigCount = json.getSubRigCount(); - - this._physicsRig.settings.updateSize(this._physicsRig.subRigCount, CubismPhysicsSubRig, true); - this._physicsRig.inputs.updateSize(json.getTotalInputCount(), CubismPhysicsInput, true); - this._physicsRig.outputs.updateSize(json.getTotalOutputCount(), CubismPhysicsOutput, true); - this._physicsRig.particles.updateSize(json.getVertexCount(), CubismPhysicsParticle, true); - - let inputIndex: number = 0, outputIndex: number = 0, particleIndex: number = 0; - - for(let i: number = 0; i < this._physicsRig.settings.getSize(); ++i) - { - this._physicsRig.settings.at(i).normalizationPosition.minimum = json.getNormalizationPositionMinimumValue(i); - this._physicsRig.settings.at(i).normalizationPosition.maximum = json.getNormalizationPositionMaximumValue(i); - this._physicsRig.settings.at(i).normalizationPosition.defalut = json.getNormalizationPositionDefaultValue(i); - - this._physicsRig.settings.at(i).normalizationAngle.minimum = json.getNormalizationAngleMinimumValue(i); - this._physicsRig.settings.at(i).normalizationAngle.maximum = json.getNormalizationAngleMaximumValue(i); - this._physicsRig.settings.at(i).normalizationAngle.defalut = json.getNormalizationAngleDefaultValue(i); - - // Input - this._physicsRig.settings.at(i).inputCount = json.getInputCount(i); - this._physicsRig.settings.at(i).baseInputIndex = inputIndex; - - for(let j: number = 0; j < this._physicsRig.settings.at(i).inputCount; ++j) - { - this._physicsRig.inputs.at(inputIndex + j).sourceParameterIndex = -1; - this._physicsRig.inputs.at(inputIndex + j).weight = json.getInputWeight(i, j); - this._physicsRig.inputs.at(inputIndex + j).reflect = json.getInputReflect(i, j); - - if(json.getInputType(i, j) == PhysicsTypeTagX) - { - this._physicsRig.inputs.at(inputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_X; - this._physicsRig.inputs.at(inputIndex + j).getNormalizedParameterValue = getInputTranslationXFromNormalizedParameterValue; - } - else if(json.getInputType(i, j) == PhysicsTypeTagY) - { - this._physicsRig.inputs.at(inputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Y; - this._physicsRig.inputs.at(inputIndex + j).getNormalizedParameterValue = getInputTranslationYFromNormalizedParamterValue; - } - else if(json.getInputType(i, j) == PhysicsTypeTagAngle) - { - this._physicsRig.inputs.at(inputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Angle; - this._physicsRig.inputs.at(inputIndex + j).getNormalizedParameterValue = getInputAngleFromNormalizedParameterValue; - } - - this._physicsRig.inputs.at(inputIndex + j).source.targetType = CubismPhysicsTargetType.CubismPhysicsTargetType_Parameter; - this._physicsRig.inputs.at(inputIndex + j).source.id = json.getInputSourceId(i, j); - } - inputIndex += this._physicsRig.settings.at(i).inputCount; - - // Output - this._physicsRig.settings.at(i).outputCount = json.getOutputCount(i); - this._physicsRig.settings.at(i).baseOutputIndex = outputIndex; - - for(let j: number = 0; j < this._physicsRig.settings.at(i).outputCount; ++j) - { - this._physicsRig.outputs.at(outputIndex + j).destinationParameterIndex = -1; - this._physicsRig.outputs.at(outputIndex + j).vertexIndex = json.getOutputVertexIndex(i, j); - this._physicsRig.outputs.at(outputIndex + j).angleScale = json.getOutputAngleScale(i, j); - this._physicsRig.outputs.at(outputIndex + j).weight = json.getOutputWeight(i, j); - this._physicsRig.outputs.at(outputIndex + j).destination.targetType = CubismPhysicsTargetType.CubismPhysicsTargetType_Parameter; - - this._physicsRig.outputs.at(outputIndex + j).destination.id = json.getOutputDestinationId(i, j); - - if(json.getOutputType(i, j) == PhysicsTypeTagX) - { - this._physicsRig.outputs.at(outputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_X; - this._physicsRig.outputs.at(outputIndex + j).getValue = getOutputTranslationX; - this._physicsRig.outputs.at(outputIndex + j).getScale = getOutputScaleTranslationX; - } - else if(json.getOutputType(i, j) == PhysicsTypeTagY) - { - this._physicsRig.outputs.at(outputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Y; - this._physicsRig.outputs.at(outputIndex + j).getValue = getOutputTranslationY; - this._physicsRig.outputs.at(outputIndex + j).getScale = getOutputScaleTranslationY; - } - else if(json.getOutputType(i, j) == PhysicsTypeTagAngle) - { - this._physicsRig.outputs.at(outputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Angle; - this._physicsRig.outputs.at(outputIndex + j).getValue = getOutputAngle; - this._physicsRig.outputs.at(outputIndex + j).getScale = getOutputScaleAngle; - } - - this._physicsRig.outputs.at(outputIndex + j).reflect = json.getOutputReflect(i, j); - } - outputIndex += this._physicsRig.settings.at(i).outputCount; - - // Particle - this._physicsRig.settings.at(i).particleCount = json.getParticleCount(i); - this._physicsRig.settings.at(i).baseParticleIndex = particleIndex; - - for(let j: number = 0; j < this._physicsRig.settings.at(i).particleCount; ++j) - { - this._physicsRig.particles.at(particleIndex + j).mobility = json.getParticleMobility(i, j); - this._physicsRig.particles.at(particleIndex + j).delay = json.getParticleDelay(i, j); - this._physicsRig.particles.at(particleIndex + j).acceleration = json.getParticleAcceleration(i, j); - this._physicsRig.particles.at(particleIndex + j).radius = json.getParticleRadius(i, j); - this._physicsRig.particles.at(particleIndex + j).position = json.getParticlePosition(i, j); - } - - particleIndex += this._physicsRig.settings.at(i).particleCount; - } - - this.initialize(); - - json.release(); - json = void 0; - json = null; - } - - /** - * 初期化する - */ - public initialize(): void - { - let strand: CubismPhysicsParticle[]; - let currentSetting: CubismPhysicsSubRig; - let radius: CubismVector2; - - for (let settingIndex: number = 0; settingIndex < this._physicsRig.subRigCount; ++settingIndex) - { - currentSetting = this._physicsRig.settings.at(settingIndex); - strand = this._physicsRig.particles.get(currentSetting.baseParticleIndex); - - // Initialize the top of particle. - strand[0].initialPosition = new CubismVector2(0.0, 0.0); - strand[0].lastPosition = new CubismVector2(strand[0].initialPosition.x, strand[0].initialPosition.y); - strand[0].lastGravity = new CubismVector2(0.0, -1.0); - strand[0].lastGravity.y *= -1.0; - strand[0].velocity = new CubismVector2(0.0, 0.0); - strand[0].force = new CubismVector2(0.0, 0.0); - - // Initialize paritcles. - for (let i: number = 1; i < currentSetting.particleCount; ++i) - { - radius = new CubismVector2(0.0, 0.0); - radius.y = strand[i].radius; - strand[i].initialPosition = new CubismVector2(strand[i - 1].initialPosition.x + radius.x, strand[i - 1].initialPosition.y + radius.y); - strand[i].position = new CubismVector2(strand[i].initialPosition.x, strand[i].initialPosition.y); - strand[i].lastPosition = new CubismVector2(strand[i].initialPosition.x, strand[i].initialPosition.y); - strand[i].lastGravity = new CubismVector2(0.0, -1.0); - strand[i].lastGravity.y *= -1.0; - strand[i].velocity = new CubismVector2(0.0, 0.0); - strand[i].force = new CubismVector2(0.0, 0.0); - } - } - } - - _physicsRig: CubismPhysicsRig; // 物理演算のデータ - _options: CubismPhysics.Options; // オプション - } - - export namespace CubismPhysics - { - /** - * 物理演算のオプション - */ - export class Options - { - constructor() - { - this.gravity = new CubismVector2(0, 0); - this.wind = new CubismVector2(0, 0); - } - - gravity: CubismVector2; // 重力方向 - wind: CubismVector2; // 風の方向 - } - - } - - /** - * Gets sign. - * - * @param value Evaluation target value. - * - * @return Sign of value. - */ - function sign(value: number): number - { - let ret: number = 0; - - if(value > 0.0) - { - ret = 1; - } - else if(value < 0.0) - { - ret = -1; - } - - return ret; - } - - function getInputTranslationXFromNormalizedParameterValue( - targetTranslation: CubismVector2, - targetAngle: {angle: number}, - value: number, - parameterMinimumValue: number, - parameterMaximumValue: number, - parameterDefaultValue: number, - normalizationPosition: CubismPhysicsNormalization, - normalizationAngle: CubismPhysicsNormalization, - isInverted: boolean, - weight: number): void - { - targetTranslation.x += normalizeParameterValue( - value, - parameterMinimumValue, - parameterMaximumValue, - parameterDefaultValue, - normalizationPosition.minimum, - normalizationPosition.maximum, - normalizationPosition.defalut, - isInverted - ) * weight; - } - - function getInputTranslationYFromNormalizedParamterValue( - targetTranslation: CubismVector2, - targetAngle: {angle: number}, - value: number, - parameterMinimumValue: number, - parameterMaximumValue: number, - parameterDefaultValue: number, - normalizationPosition: CubismPhysicsNormalization, - normalizationAngle: CubismPhysicsNormalization, - isInverted: boolean, - weight: number): void - { - targetTranslation.y += normalizeParameterValue( - value, - parameterMinimumValue, - parameterMaximumValue, - parameterDefaultValue, - normalizationPosition.minimum, - normalizationPosition.maximum, - normalizationPosition.defalut, - isInverted - ) * weight; - } - - function getInputAngleFromNormalizedParameterValue( - targetTranslation: CubismVector2, - targetAngle: {angle: number}, - value: number, - parameterMinimumValue: number, - parameterMaximumValue: number, - parameterDefaultValue: number, - normalizaitionPosition: CubismPhysicsNormalization, - normalizationAngle: CubismPhysicsNormalization, - isInverted: boolean, - weight: number): void - { - targetAngle.angle += normalizeParameterValue( - value, - parameterMinimumValue, - parameterMaximumValue, - parameterDefaultValue, - normalizationAngle.minimum, - normalizationAngle.maximum, - normalizationAngle.defalut, - isInverted, - ) * weight; - } - - function getOutputTranslationX( - translation: CubismVector2, - particles: CubismPhysicsParticle[], - particleIndex: number, - isInverted: boolean, - parentGravity: CubismVector2): number - { - let outputValue: number = translation.x; - - if(isInverted) - { - outputValue *= -1.0; - } - - return outputValue; - } - - function getOutputTranslationY( - translation: CubismVector2, - particles: CubismPhysicsParticle[], - particleIndex: number, - isInverted: boolean, - parentGravity: CubismVector2): number - { - let outputValue: number = translation.y; - - if(isInverted) - { - outputValue *= -1.0; - } - return outputValue; - } - - function getOutputAngle( - translation: CubismVector2, - particles: CubismPhysicsParticle[], - particleIndex: number, - isInverted: boolean, - parentGravity: CubismVector2): number - { - let outputValue: number; - - if(particleIndex >= 2) - { - parentGravity = particles[particleIndex - 1].position.substract(particles[particleIndex - 2].position); - } - else - { - parentGravity = parentGravity.multiplyByScaler(-1.0); - } - - outputValue = CubismMath.directionToRadian(parentGravity, translation); - - if(isInverted) - { - outputValue *= -1.0; - } - - return outputValue; - } - - function getRangeValue(min: number, max: number): number - { - let maxValue: number = CubismMath.max(min, max); - let minValue: number = CubismMath.min(min, max); - - return CubismMath.abs(maxValue - minValue); - } - - function getDefaultValue(min: number, max: number): number - { - const minValue: number = CubismMath.min(min, max); - return minValue + (getRangeValue(min, max) / 2.0); - } - - function getOutputScaleTranslationX(translationScale: CubismVector2, angleScale: number): number - { - return JSON.parse(JSON.stringify(translationScale.x)); - } - - function getOutputScaleTranslationY(translationScale: CubismVector2, angleScale: number): number - { - return JSON.parse(JSON.stringify(translationScale.y)); - } - - function getOutputScaleAngle(translationScale: CubismVector2, angleScale: number): number - { - return JSON.parse(JSON.stringify(angleScale)); - } - - - /** - * Updates particles. - * - * @param strand Target array of particle. - * @param strandCount Count of particle. - * @param totalTranslation Total translation value. - * @param totalAngle Total angle. - * @param windDirection Direction of Wind. - * @param thresholdValue Threshold of movement. - * @param deltaTimeSeconds Delta time. - * @param airResistance Air resistance. - */ - function updateParticles( - strand: CubismPhysicsParticle[], - strandCount: number, - totalTranslation: CubismVector2, - totalAngle: number, - windDirection: CubismVector2, - thresholdValue: number, - deltaTimeSeconds: number, - airResistance: number) - { - let totalRadian: number; - let delay: number; - let radian: number; - let currentGravity: CubismVector2; - let direction: CubismVector2 = new CubismVector2(0.0, 0.0); - let velocity: CubismVector2 = new CubismVector2(0.0, 0.0); - let force: CubismVector2 = new CubismVector2(0.0, 0.0); - let newDirection: CubismVector2 = new CubismVector2(0.0, 0.0); - - strand[0].position = new CubismVector2(totalTranslation.x, totalTranslation.y); - - totalRadian = CubismMath.degreesToRadian(totalAngle); - currentGravity = CubismMath.radianToDirection(totalRadian); - currentGravity.normalize(); - - for(let i: number = 1; i < strandCount; ++i) - { - strand[i].force = currentGravity.multiplyByScaler(strand[i].acceleration).add(windDirection); - - strand[i].lastPosition = new CubismVector2(strand[i].position.x, strand[i].position.y); - - delay = strand[i].delay * deltaTimeSeconds * 30.0; - - direction = strand[i].position.substract(strand[i - 1].position); - - radian = CubismMath.directionToRadian(strand[i].lastGravity, currentGravity) / airResistance; - - direction.x = ((CubismMath.cos(radian) * direction.x) - (direction.y * CubismMath.sin(radian))); - direction.y = ((CubismMath.sin(radian) * direction.x) + (direction.y * CubismMath.cos(radian))); - - strand[i].position = strand[i - 1].position.add(direction); - - velocity = strand[i].velocity.multiplyByScaler(delay); - force = strand[i].force.multiplyByScaler(delay).multiplyByScaler(delay); - - strand[i].position = strand[i].position.add(velocity).add(force); - - newDirection = strand[i].position.substract(strand[i - 1].position); - newDirection.normalize(); - - strand[i].position = strand[i - 1].position.add(newDirection.multiplyByScaler(strand[i].radius)); - - if (CubismMath.abs(strand[i].position.x) < thresholdValue) - { - strand[i].position.x = 0.0; - } - - if (delay != 0.0) - { - strand[i].velocity = strand[i].position.substract(strand[i].lastPosition); - strand[i].velocity = strand[i].velocity.divisionByScalar(delay); - strand[i].velocity = strand[i].velocity.multiplyByScaler(strand[i].mobility); - } - - strand[i].force = new CubismVector2(0.0, 0.0); - strand[i].lastGravity = new CubismVector2(currentGravity.x, currentGravity.y); - } - - } - - /** - * Updates output parameter value. - * @param parameterValue Target parameter value. - * @param parameterValueMinimum Minimum of parameter value. - * @param parameterValueMaximum Maximum of parameter value. - * @param translation Translation value. - */ - function updateOutputParameterValue( - parameterValue: Float32Array, - parameterValueMinimum: number, - parameterValueMaximum: number, - translation: number, - output: CubismPhysicsOutput): void - { - let outputScale: number; - let value: number; - let weight: number; - - outputScale = output.getScale(output.translationScale, output.angleScale); - - value = translation * outputScale; - - if (value < parameterValueMinimum) - { - if (value < output.valueBelowMinimum) - { - output.valueBelowMinimum = value; - } - - value = parameterValueMinimum; - } - else if (value > parameterValueMaximum) - { - if (value > output.valueExceededMaximum) - { - output.valueExceededMaximum = value; - } - - value = parameterValueMaximum; - } - - weight = (output.weight / MaximumWeight); - - if (weight >= 1.0) - { - parameterValue[0] = value; - } - else - { - value = (parameterValue[0] * (1.0 - weight)) + (value * weight); - parameterValue[0] = value; - } - } - - - function normalizeParameterValue( - value: number, - parameterMinimum: number, - parameterMaximum: number, - parameterDefault: number, - normalizedMinimum: number, - normalizedMaximum: number, - normalizedDefault: number, - isInverted: boolean) - { - let result: number = 0.0; - - const maxValue: number = CubismMath.max(parameterMaximum, parameterMinimum); - - if(maxValue < value) - { - return result; - } - - const minValue: number = CubismMath.min(parameterMaximum, parameterMinimum); - - if(minValue > value) - { - return result; - } - - const minNormValue: number = CubismMath.min(normalizedMinimum, normalizedMaximum); - const maxNormValue: number = CubismMath.max(normalizedMinimum, normalizedMaximum); - const middleNormValue: number = normalizedDefault; - - const middleValue: number = getDefaultValue(minValue, maxValue); - const paramValue: number = value - middleValue; - - switch(sign(paramValue)) - { - case 1: - { - const nLength: number = maxNormValue - middleNormValue; - const pLength: number = maxValue - middleValue; - - if(pLength != 0.0) - { - result = paramValue * (nLength / pLength); - result += middleNormValue; - } - - break; - } - case -1: - { - const nLength: number = minNormValue - middleNormValue; - const pLength: number = minValue - middleValue; - - if(pLength != 0.0) - { - result = paramValue * (nLength / pLength); - result += middleNormValue; - } - - break; - } - case 0: - { - result = middleNormValue; - - break; - } - default: - { - break; - } - } - - return (isInverted) - ? result - : (result * -1.0); - } -} \ No newline at end of file diff --git a/Framework/physics/cubismphysicsinternal.ts b/Framework/physics/cubismphysicsinternal.ts deleted file mode 100644 index de54c9c..0000000 --- a/Framework/physics/cubismphysicsinternal.ts +++ /dev/null @@ -1,248 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismvector2} from '../math/cubismvector2'; -import {Live2DCubismFramework as cubismid} from '../id/cubismid'; -import {Live2DCubismFramework as csmvector} from '../type/csmvector'; -import csmVector = csmvector.csmVector; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismVector2 = cubismvector2.CubismVector2; - -export namespace Live2DCubismFramework -{ - /** - * 物理演算の適用先の種類 - */ - export enum CubismPhysicsTargetType - { - CubismPhysicsTargetType_Parameter, // パラメータに対して適用 - } - - /** - * 物理演算の入力の種類 - */ - export enum CubismPhysicsSource - { - CubismPhysicsSource_X, // X軸の位置から - CubismPhysicsSource_Y, // Y軸の位置から - CubismPhysicsSource_Angle, // 角度から - } - - /** - * @brief 物理演算で使用する外部の力 - * - * 物理演算で使用する外部の力。 - */ - export class PhysicsJsonEffectiveForces - { - constructor() - { - this.gravity = new CubismVector2(0, 0); - this.wind = new CubismVector2(0, 0); - } - gravity: CubismVector2; ///< 重力 - wind: CubismVector2; ///< 風 - } - - /** - * 物理演算のパラメータ情報 - */ - export class CubismPhysicsParameter - { - id: CubismIdHandle; // パラメータ - targetType: CubismPhysicsTargetType; // 適用先の種類 - } - - /** - * 物理演算の正規化情報 - */ - export class CubismPhysicsNormalization - { - minimum: number; // 最大値 - maximum: number; // 最小値 - defalut: number; // デフォルト値 - } - - /** - * 物理演算の演算委使用する物理点の情報 - */ - export class CubismPhysicsParticle - { - constructor() - { - this.initialPosition = new CubismVector2(0, 0); - this.position = new CubismVector2(0, 0); - this.lastPosition = new CubismVector2(0, 0); - this.lastGravity = new CubismVector2(0, 0); - this.force = new CubismVector2(0, 0); - this.velocity = new CubismVector2(0, 0); - } - - initialPosition: CubismVector2; // 初期位置 - mobility: number; // 動きやすさ - delay: number; // 遅れ - acceleration: number; // 加速度 - radius: number; // 距離 - position: CubismVector2; // 現在の位置 - lastPosition: CubismVector2; // 最後の位置 - lastGravity: CubismVector2; // 最後の重力 - force: CubismVector2; // 現在かかっている力 - velocity: CubismVector2; // 現在の速度 - } - - /** - * 物理演算の物理点の管理 - */ - export class CubismPhysicsSubRig - { - constructor() - { - this.normalizationPosition = new CubismPhysicsNormalization(); - this.normalizationAngle = new CubismPhysicsNormalization(); - } - inputCount: number; // 入力の個数 - outputCount: number; // 出力の個数 - particleCount: number; // 物理点の個数 - baseInputIndex: number; // 入力の最初のインデックス - baseOutputIndex: number; // 出力の最初のインデックス - baseParticleIndex: number; // 物理点の最初のインデックス - normalizationPosition: CubismPhysicsNormalization; // 正規化された位置 - normalizationAngle: CubismPhysicsNormalization; // 正規化された角度 - } - - /** - * 正規化されたパラメータの取得関数の宣言 - * @param targetTranslation // 演算結果の移動値 - * @param targetAngle // 演算結果の角度 - * @param value // パラメータの値 - * @param parameterMinimunValue // パラメータの最小値 - * @param parameterMaximumValue // パラメータの最大値 - * @param parameterDefaultValue // パラメータのデフォルト値 - * @param normalizationPosition // 正規化された位置 - * @param normalizationAngle // 正規化された角度 - * @param isInverted // 値が反転されているか? - * @param weight // 重み - */ - export interface normalizedPhysicsParameterValueGetter - { - ( - targetTranslation: CubismVector2, - targetAngle: {angle: number}, - value: number, - parameterMinimunValue: number, - parameterMaximumValue: number, - parameterDefaultValue: number, - normalizationPosition: CubismPhysicsNormalization, - normalizationAngle: CubismPhysicsNormalization, - isInverted: boolean, - weight: number - ): void - } - - /** - * 物理演算の値の取得関数の宣言 - * @param translation 移動値 - * @param particles 物理点のリスト - * @param isInverted 値が反映されているか - * @param parentGravity 重力 - * @return 値 - */ - export interface physicsValueGetter - { - ( - translation: CubismVector2, - particles: CubismPhysicsParticle[], - particleIndex: number, - isInverted: boolean, - parentGravity: CubismVector2 - ): number - } - - /** - * 物理演算のスケールの取得関数の宣言 - * @param translationScale 移動値のスケール - * @param angleScale 角度のスケール - * @return スケール値 - */ - export interface physicsScaleGetter - { - ( - translationScale: CubismVector2, - angleScale: number - ): number; - } - - /** - * 物理演算の入力情報 - */ - export class CubismPhysicsInput - { - constructor() - { - this.source = new CubismPhysicsParameter(); - } - source: CubismPhysicsParameter; // 入力元のパラメータ - sourceParameterIndex: number; // 入力元のパラメータのインデックス - weight: number; // 重み - type: number; // 入力の種類 - reflect: boolean; // 値が反転されているかどうか - getNormalizedParameterValue: normalizedPhysicsParameterValueGetter; // 正規化されたパラメータ値の取得関数 - } - - /** - * @brief 物理演算の出力情報 - * - * 物理演算の出力情報。 - */ - export class CubismPhysicsOutput - { - constructor() - { - this.destination = new CubismPhysicsParameter(); - this.translationScale = new CubismVector2(0, 0); - } - - destination: CubismPhysicsParameter; ///< 出力先のパラメータ - destinationParameterIndex: number; ///< 出力先のパラメータのインデックス - vertexIndex: number; ///< 振り子のインデックス - translationScale: CubismVector2; ///< 移動値のスケール - angleScale: number; ///< 角度のスケール - weight: number; /// 重み - type: CubismPhysicsSource; ///< 出力の種類 - reflect: boolean; ///< 値が反転されているかどうか - valueBelowMinimum: number; ///< 最小値を下回った時の値 - valueExceededMaximum: number; ///< 最大値をこえた時の値 - getValue: physicsValueGetter; ///< 物理演算の値の取得関数 - getScale: physicsScaleGetter; ///< 物理演算のスケール値の取得関数 - } - - /** - * @brief 物理演算のデータ - * - * 物理演算のデータ。 - */ - export class CubismPhysicsRig - { - constructor() - { - this.settings = new csmVector(); - this.inputs = new csmVector(); - this.outputs = new csmVector(); - this.particles = new csmVector(); - this.gravity = new CubismVector2(0, 0); - this.wind = new CubismVector2(0, 0); - } - - subRigCount: number; ///< 物理演算の物理点の個数 - settings: csmVector; ///< 物理演算の物理点の管理のリスト - inputs: csmVector; ///< 物理演算の入力のリスト - outputs: csmVector; ///< 物理演算の出力のリスト - particles: csmVector; ///< 物理演算の物理点のリスト - gravity: CubismVector2; ///< 重力 - wind: CubismVector2; ///< 風 - }; -} \ No newline at end of file diff --git a/Framework/physics/cubismphysicsjson.ts b/Framework/physics/cubismphysicsjson.ts deleted file mode 100644 index bcb784f..0000000 --- a/Framework/physics/cubismphysicsjson.ts +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismjson} from '../utils/cubismjson'; -import {Live2DCubismFramework as cubismvector2} from '../math/cubismvector2'; -import {Live2DCubismFramework as cubismid} from '../id/cubismid'; -import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; -import CubismFramework = cubismframework.CubismFramework; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismVector2 = cubismvector2.CubismVector2; -import CubismJson = cubismjson.CubismJson; - -export namespace Live2DCubismFramework -{ - // JSON keys - const Position: string = "Position"; - const X: string = "X"; - const Y: string = "Y"; - const Angle: string = "Angle"; - const Type: string = "Type"; - const Id: string = "Id"; - - // Meta - const Meta: string = "Meta"; - const EffectiveForces: string = "EffectiveForces"; - const TotalInputCount: string = "TotalInputCount"; - const TotalOutputCount: string = "TotalOutputCount"; - const PhysicsSettingCount: string = "PhysicsSettingCount"; - const Gravity: string = "Gravity"; - const Wind: string = "Wind"; - const VertexCount: string = "VertexCount"; - - // PhysicsSettings - const PhysicsSettings: string = "PhysicsSettings"; - const Normalization: string = "Normalization"; - const Minimum: string = "Minimum"; - const Maximum: string = "Maximum"; - const Default: string = "Default"; - const Reflect: string = "Reflect"; - const Weight: string = "Weight"; - - // Input - const Input: string = "Input"; - const Source: string = "Source"; - - // Output - const Output: string = "Output"; - const Scale: string = "Scale"; - const VertexIndex: string = "VertexIndex"; - const Destination: string = "Destination"; - - // Particle - const Vertices: string = "Vertices"; - const Mobility: string = "Mobility"; - const Delay: string = "Delay"; - const Radius: string = "Radius"; - const Acceleration: string = "Acceleration"; - - /** - * physics3.jsonのコンテナ。 - */ - export class CubismPhysicsJson - { - /** - * コンストラクタ - * @param buffer physics3.jsonが読み込まれているバッファ - * @param size バッファのサイズ - */ - public constructor(buffer: ArrayBuffer, size: number) - { - this._json = CubismJson.create(buffer, size); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - CubismJson.delete(this._json); - } - - /** - * 重力の取得 - * @return 重力 - */ - public getGravity(): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(0, 0); - ret.x = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Gravity).getMap().getValue(X).toFloat(); - ret.y = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Gravity).getMap().getValue(Y).toFloat(); - return ret; - } - - /** - * 風の取得 - * @return 風 - */ - public getWind(): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(0, 0); - ret.x = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Wind).getMap().getValue(X).toFloat(); - ret.y = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Wind).getMap().getValue(Y).toFloat(); - return ret; - } - - /** - * 物理店の管理の個数の取得 - * @return 物理店の管理の個数 - */ - public getSubRigCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(PhysicsSettingCount).toInt(); - } - - /** - * 入力の総合計の取得 - * @return 入力の総合計 - */ - public getTotalInputCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalInputCount).toInt(); - } - - /** - * 出力の総合計の取得 - * @return 出力の総合計 - */ - public getTotalOutputCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalOutputCount).toInt(); - } - - /** - * 物理点の個数の取得 - * @return 物理点の個数 - */ - public getVertexCount(): number - { - return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(VertexCount).toInt(); - } - - /** - * 正規化された位置の最小値の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @return 正規化された位置の最小値 - */ - public getNormalizationPositionMinimumValue(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Position).getMap().getValue(Minimum).toFloat(); - } - - /** - * 正規化された位置の最大値の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @return 正規化された位置の最大値 - */ - public getNormalizationPositionMaximumValue(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Position).getMap().getValue(Maximum).toFloat(); - } - - /** - * 正規化された位置のデフォルト値の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @return 正規化された位置のデフォルト値 - */ - public getNormalizationPositionDefaultValue(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Position).getMap().getValue(Default).toFloat(); - } - - /** - * 正規化された角度の最小値の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @return 正規化された角度の最小値 - */ - public getNormalizationAngleMinimumValue(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Angle).getMap().getValue(Minimum).toFloat(); - } - - /** - * 正規化された角度の最大値の取得 - * @param physicsSettingIndex - * @return 正規化された角度の最大値 - */ - public getNormalizationAngleMaximumValue(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Angle).getMap().getValue(Maximum).toFloat(); - } - - /** - * 正規化された角度のデフォルト値の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @return 正規化された角度のデフォルト値 - */ - public getNormalizationAngleDefaultValue(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Angle).getMap().getValue(Default).toFloat(); - } - - /** - * 入力の個数の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @return 入力の個数 - */ - public getInputCount(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().getSize(); - } - - /** - * 入力の重みの取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param inputIndex 入力のインデックス - * @return 入力の重み - */ - public getInputWeight(physicsSettingIndex: number, inputIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Weight).toFloat(); - } - - /** - * 入力の反転の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param inputIndex 入力のインデックス - * @return 入力の反転 - */ - public getInputReflect(physicsSettingIndex: number, inputIndex: number): boolean - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Reflect).toBoolean(); - } - - /** - * 入力の種類の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param inputIndex 入力のインデックス - * @return 入力の種類 - */ - public getInputType(physicsSettingIndex: number, inputIndex: number): string - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Type).getRawString(); - } - - /** - * 入力元のIDの取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param inputIndex 入力のインデックス - * @return 入力元のID - */ - public getInputSourceId(physicsSettingIndex: number, inputIndex: number): CubismIdHandle - { - return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Source).getMap().getValue(Id).getRawString()); - } - - /** - * 出力の個数の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @return 出力の個数 - */ - public getOutputCount(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().getSize(); - } - - /** - * 出力の物理点のインデックスの取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param outputIndex 出力のインデックス - * @return 出力の物理点のインデックス - */ - public getOutputVertexIndex(physicsSettingIndex: number, outputIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(VertexIndex).toInt(); - } - - /** - * 出力の角度のスケールを取得する - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param outputIndex 出力のインデックス - * @return 出力の角度のスケール - */ - public getOutputAngleScale(physicsSettingIndex: number, outputIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Scale).toFloat(); - } - - /** - * 出力の重みの取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param outputIndex 出力のインデックス - * @return 出力の重み - */ - public getOutputWeight(physicsSettingIndex: number, outputIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Weight).toFloat(); - } - - /** - * 出力先のIDの取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param outputIndex 出力のインデックス - * @return 出力先のID - */ - public getOutputDestinationId(physicsSettingIndex: number, outputIndex: number): CubismIdHandle - { - return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Destination).getMap().getValue(Id).getRawString()); - } - - /** - * 出力の種類の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param outputIndex 出力のインデックス - * @return 出力の種類 - */ - public getOutputType(physicsSettingIndex: number, outputIndex: number): string - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Type).getRawString(); - } - - /** - * 出力の反転の取得 - * @param physicsSettingIndex 物理演算のインデックス - * @param outputIndex 出力のインデックス - * @return 出力の反転 - */ - public getOutputReflect(physicsSettingIndex: number, outputIndex: number): boolean - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Reflect).toBoolean(); - } - - /** - * 物理点の個数の取得 - * @param physicsSettingIndex 物理演算男設定のインデックス - * @return 物理点の個数 - */ - public getParticleCount(physicsSettingIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().getSize(); - } - - /** - * 物理点の動きやすさの取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param vertexIndex 物理点のインデックス - * @return 物理点の動きやすさ - */ - public getParticleMobility(physicsSettingIndex: number, vertexIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Mobility).toFloat(); - } - - /** - * 物理点の遅れの取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param vertexIndex 物理点のインデックス - * @return 物理点の遅れ - */ - public getParticleDelay(physicsSettingIndex: number, vertexIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Delay).toFloat(); - } - - /** - * 物理点の加速度の取得 - * @param physicsSettingIndex 物理演算の設定 - * @param vertexIndex 物理点のインデックス - * @return 物理点の加速度 - */ - public getParticleAcceleration(physicsSettingIndex: number, vertexIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Acceleration).toFloat(); - } - - /** - * 物理点の距離の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param vertexIndex 物理点のインデックス - * @return 物理点の距離 - */ - public getParticleRadius(physicsSettingIndex: number, vertexIndex: number): number - { - return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Radius).toInt(); - } - - /** - * 物理点の位置の取得 - * @param physicsSettingIndex 物理演算の設定のインデックス - * @param vertexInde 物理点のインデックス - * @return 物理点の位置 - */ - public getParticlePosition(physicsSettingIndex: number, vertexIndex: number): CubismVector2 - { - let ret: CubismVector2 = new CubismVector2(0, 0); - ret.x = this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Position).getMap().getValue(X).toFloat(); - ret.y = this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Position).getMap().getValue(Y).toFloat(); - return ret; - } - - _json: CubismJson; // physics3.jsonデータ - } - -} \ No newline at end of file diff --git a/Framework/rendering/cubismrenderer.ts b/Framework/rendering/cubismrenderer.ts deleted file mode 100644 index 5e8cf64..0000000 --- a/Framework/rendering/cubismrenderer.ts +++ /dev/null @@ -1,312 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismmatrix44} from '../math/cubismmatrix44'; -import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; -import CubismModel = cubismmodel.CubismModel; -import CubismMatrix44 = cubismmatrix44.CubismMatrix44; - -export namespace Live2DCubismFramework -{ - /** - * モデル描画を処理するレンダラ - * - * サブクラスに環境依存の描画命令を記述する。 - */ - export abstract class CubismRenderer - { - /** - * レンダラのインスタンスを生成して取得する - * - * @return レンダラのインスタンス - */ - public static create(): CubismRenderer - { - return null; - } - - /** - * レンダラのインスタンスを解放する - */ - public static delete(renderer: CubismRenderer): void - { - renderer = void 0; - renderer = null; - } - - /** - * レンダラが保持する静的なリソースを開放する - */ - public static StaticRelease(): void - { - //CubismRenderer_WebGL.doStaticRelease(); - } - - /** - * レンダラの初期化処理を実行する - * 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる - * @param model モデルのインスタンス - */ - public initialize(model: CubismModel): void - { - this._model = model; - } - - /** - * モデルを描画する - */ - public drawModel(): void - { - if(this.getModel() == null) return; - /** - * doDrawModelの描画前と描画後に以下の関数を呼んでください - * ・saveProfile(); - * ・restoreProfile(); - * これはレンダラの描画設定を保存復帰させることで、 - * モデル描画直前の状態に戻すための処理です。 - */ - - this.saveProfile(); - this.doDrawModel(); - this.restoreProfile(); - } - - /** - * Model-View-Projection 行列をセットする - * 配列は複製されるので、元の配列は外で破棄して良い - * @param matrix44 Model-View-Projection 行列 - */ - public setMvpMatrix(matrix44: CubismMatrix44): void - { - this._mvpMatrix4x4.setMatrix(matrix44.getArray()); - } - - /** - * Model-View-Projection 行列を取得する - * @return Model-View-Projection 行列 - */ - public getMvpMatrix(): CubismMatrix44 - { - return this._mvpMatrix4x4; - } - - /** - * モデルの色をセットする - * 各色0.0~1.0の間で指定する(1.0が標準の状態) - * @param red 赤チャンネルの値 - * @param green 緑チャンネルの値 - * @param blue 青チャンネルの値 - * @param alpha αチャンネルの値 - */ - public setModelColor(red: number, green: number, blue: number, alpha: number): void - { - if(red < 0.0) - { - red = 0.0; - } - else if(red > 1.0) - { - red = 1.0; - } - - if(green < 0.0) - { - green = 0.0; - } - else if(green > 1.0) - { - green = 1.0; - } - - if(blue < 0.0) - { - blue = 0.0; - } - else if(blue > 1.0) - { - blue = 1.0; - } - - if(alpha < 0.0) - { - alpha = 0.0; - } - else if(alpha > 1.0) - { - alpha = 1.0; - } - - this._modelColor.R = red; - this._modelColor.G = green; - this._modelColor.B = blue; - this._modelColor.A = alpha; - } - - /** - * モデルの色を取得する - * 各色0.0~1.0の間で指定する(1.0が標準の状態) - * - * @return RGBAのカラー情報 - */ - public getModelColor(): CubismRenderer.CubismTextureColor - { - return JSON.parse(JSON.stringify(this._modelColor)); - } - - /** - * 乗算済みαの有効・無効をセットする - * 有効にするならtrue、無効にするならfalseをセットする - */ - public setIsPremultipliedAlpha(enable: boolean): void - { - this._isPremultipliedAlpha = enable; - } - - /** - * 乗算済みαの有効・無効を取得する - * @return true 乗算済みのα有効 - * @return false 乗算済みのα無効 - */ - public isPremultipliedAlpha(): boolean - { - return this._isPremultipliedAlpha; - } - - /** - * カリング(片面描画)の有効・無効をセットする。 - * 有効にするならtrue、無効にするならfalseをセットする - */ - public setIsCulling(culling: boolean): void - { - this._isCulling = culling; - } - - /** - * カリング(片面描画)の有効・無効を取得する。 - * @return true カリング有効 - * @return false カリング無効 - */ - public isCulling(): boolean - { - return this._isCulling; - } - - /** - * テクスチャの異方性フィルタリングのパラメータをセットする - * パラメータ値の影響度はレンダラの実装に依存する - * @param n パラメータの値 - */ - public setAnisotropy(n: number): void - { - this._anisortopy = n; - } - - /** - * テクスチャの異方性フィルタリングのパラメータをセットする - * @return 異方性フィルタリングのパラメータ - */ - public getAnisotropy(): number - { - return this._anisortopy; - } - - /** - * レンダリングするモデルを取得する - * @return レンダリングするモデル - */ - public getModel(): CubismModel - { - return this._model; - } - - /** - * コンストラクタ - */ - protected constructor() - { - this._isCulling = false; - this._isPremultipliedAlpha = false; - this._anisortopy = 0.0; - this._model = null; - this._modelColor = new CubismRenderer.CubismTextureColor(); - - // 単位行列に初期化 - this._mvpMatrix4x4 = new CubismMatrix44(); - this._mvpMatrix4x4.loadIdentity(); - } - - /** - * モデル描画の実装 - */ - public abstract doDrawModel(): void; - - /** - * 描画オブジェクト(アートメッシュ)を描画する - * ポリゴンメッシュとテクスチャ番号をセットで渡す。 - * @param textureNo 描画するテクスチャ番号 - * @param indexCount 描画オブジェクトのインデックス値 - * @param vertexCount ポリゴンメッシュの頂点数 - * @param indexArray ポリゴンメッシュ頂点のインデックス配列 - * @param vertexArray ポリゴンメッシュの頂点配列 - * @param uvArray uv配列 - * @param opacity 不透明度 - * @param colorBlendMode カラーブレンディングのタイプ - */ - public abstract drawMesh(textureNo: number, indexCount: number, vertexCount: number, - indexArray: Uint16Array, vertexArray: Float32Array, uvArray: Float32Array, - opacity: number, colorBlendMode: CubismRenderer.CubismBlendMode): void; - - /** - * モデル描画直前のレンダラのステートを保持する - */ - public abstract saveProfile(): void; - - /** - * モデル描画直前のレンダラのステートを復帰させる - */ - public abstract restoreProfile(): void; - - protected _mvpMatrix4x4: CubismMatrix44; // Model-View-Projection 行列 - protected _modelColor: CubismRenderer.CubismTextureColor; // モデル自体のカラー(RGBA) - protected _isCulling: boolean; // カリングが有効ならtrue - protected _isPremultipliedAlpha: boolean; // 乗算済みαならtrue - protected _anisortopy: any; // テクスチャの異方性フィルタリングのパラメータ - protected _model: CubismModel; // レンダリング対象のモデル - } - - export namespace CubismRenderer - { - export enum CubismBlendMode - { - CubismBlendMode_Normal = 0, // 通常 - CubismBlendMode_Additive = 1, // 加算 - CubismBlendMode_Multiplicative = 2, // 乗算 - }; - - /** - * テクスチャの色をRGBAで扱うためのクラス - */ - export class CubismTextureColor - { - /** - * コンストラクタ - */ - constructor() - { - this.R = 1.0; - this.G = 1.0; - this.B = 1.0; - this.A = 1.0; - } - - R: number; // 赤チャンネル - G: number; // 緑チャンネル - B: number; // 青チャンネル - A: number; // αチャンネル - } - } -} \ No newline at end of file diff --git a/Framework/rendering/cubismrenderer_WebGL.ts b/Framework/rendering/cubismrenderer_WebGL.ts deleted file mode 100644 index b6e7395..0000000 --- a/Framework/rendering/cubismrenderer_WebGL.ts +++ /dev/null @@ -1,1986 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; -import {Live2DCubismFramework as csmrect} from "../type/csmrectf"; -import {Live2DCubismFramework as cubismrenderer} from "./cubismrenderer"; -import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; -import {Live2DCubismFramework as cubsimmatrix44} from "../math/cubismmatrix44"; -import {Live2DCubismFramework as csmmap} from "../type/csmmap"; -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {CubismLogError} from "../utils/cubismdebug"; -import Constant = cubismframework.Constant; -import CubismMatrix44 = cubsimmatrix44.CubismMatrix44; -import csmRect = csmrect.csmRect; -import csmMap = csmmap.csmMap; -import csmVector = csmvector.csmVector; -import CubismModel = cubismmodel.CubismModel; -import CubismRenderer = cubismrenderer.CubismRenderer; - -export namespace Live2DCubismFramework -{ - const ColorChannelCount: number = 4; // 実験時に1チャンネルの場合は1、RGBだけの場合は3、アルファも含める場合は4 - - const shaderCount: number = 13; // シェーダーの数 = マスク生成用 + (通常用 + 加算 + 乗算) * (マスク無 + マスク有 + マスク無の乗算済アルファ対応版 + マスク有の乗算済アルファ対応版) - let s_instance: CubismShader_WebGL; - - /** - * クリッピングマスクの処理を実行するクラス - */ - export class CubismClippingManager_WebGL - { - /** - * カラーチャンネル(RGBA)のフラグを取得する - * @param channelNo カラーチャンネル(RGBA)の番号(0:R, 1:G, 2:B, 3:A) - */ - public getChannelFlagAsColor(channelNo: number): CubismRenderer.CubismTextureColor - { - return this._channelColors.at(channelNo); - } - - /** - * テンポラリのレンダーテクスチャのアドレスを取得する - * FrameBufferObjectが存在しない場合、新しく生成する - * - * @return レンダーテクスチャのアドレス - */ - public getMaskRenderTexture(): WebGLFramebuffer - { - let ret: WebGLFramebuffer = 0; - - // テンポラリのRenderTextureを取得する - if(this._maskTexture && this._maskTexture.texture != 0) // 前回使ったものを返す - { - this._maskTexture.frameNo = this._currentFrameNo; - ret = this._maskTexture.texture; - } - - if(ret == 0) - { - // FrameBufferObjectが存在しない場合、新しく生成する - - // クリッピングバッファサイズを取得 - const size: number = this._clippingMaskBufferSize; - - this._colorBuffer = this.gl.createTexture(); - this.gl.bindTexture(this.gl.TEXTURE_2D, this._colorBuffer); - this.gl.texImage2D(this.gl.TEXTURE_2D, 0 ,this.gl.RGBA, size, size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); - this.gl.bindTexture(this.gl.TEXTURE_2D, null); - - let tmpFrameBufferObject: GLint; - tmpFrameBufferObject = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING); - - ret = this.gl.createFramebuffer(); - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, ret); - this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._colorBuffer, 0); - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, tmpFrameBufferObject); - - this._maskTexture = new CubismRenderTextureResource(this._currentFrameNo, ret); - } - - return ret; - } - - /** - * WebGLレンダリングコンテキストを設定する - * @param gl WebGLレンダリングコンテキスト - */ - public setGL(gl: WebGLRenderingContext): void - { - this.gl = gl; - } - - /** - * マスクされる描画オブジェクト群全体を囲む矩形(モデル座標系)を計算する - * @param model モデルのインスタンス - * @param clippingContext クリッピングマスクのコンテキスト - */ - public calcClippedDrawTotalBounds(model: CubismModel, clippingContext: CubismClippingContext): void - { - // 被クリッピングマスク(マスクされる描画オブジェクト)の全体の矩形 - let clippedDrawTotalMinX: number = Number.MAX_VALUE; - let clippedDrawTotalMinY: number = Number.MAX_VALUE; - let clippedDrawTotalMaxX: number = Number.MIN_VALUE; - let clippedDrawTotalMaxY: number = Number.MIN_VALUE; - - // このマスクが実際に必要か判定する - // このクリッピングを利用する「描画オブジェクト」がひとつでも使用可能であればマスクを生成する必要がある - const clippedDrawCount: number = clippingContext._clippedDrawableIndexList.length; - - for(let clippedDrawableIndex: number = 0; clippedDrawableIndex < clippedDrawCount; clippedDrawableIndex++) - { - // マスクを使用する描画オブジェクトの描画される矩形を求める - const drawableIndex: number = clippingContext._clippedDrawableIndexList[clippedDrawableIndex]; - - const drawableVertexCount: number = model.getDrawableVertexCount(drawableIndex); - let drawableVertexes: Float32Array = model.getDrawableVertices(drawableIndex); - - let minX: number = Number.MAX_VALUE; - let minY: number = Number.MAX_VALUE; - let maxX: number = Number.MIN_VALUE; - let maxY: number = Number.MIN_VALUE; - - let loop: number = drawableVertexCount * Constant.vertexStep; - for(let pi: number = Constant.vertexOffset; pi < loop; pi += Constant.vertexStep) - { - let x: number = drawableVertexes[pi]; - let y: number = drawableVertexes[pi + 1]; - - if(x < minX) - { - minX = x; - } - if(x > maxX) - { - maxX = x; - } - if(y < minY) - { - minY = y; - } - if(y > maxY) - { - maxY = y; - } - } - - // 有効な点が一つも取れなかったのでスキップ - if(minX == Number.MAX_VALUE) - { - continue; - } - - // 全体の矩形に反映 - if(minX < clippedDrawTotalMinX) - { - clippedDrawTotalMinX = minX; - } - if(minY < clippedDrawTotalMinY) - { - clippedDrawTotalMinY = minY; - } - if(maxX > clippedDrawTotalMaxX) - { - clippedDrawTotalMaxX = maxX; - } - if(maxY > clippedDrawTotalMaxY) - { - clippedDrawTotalMaxY = maxY; - } - - if(clippedDrawTotalMinX == Number.MAX_VALUE) - { - clippingContext._allClippedDrawRect.x = 0.0; - clippingContext._allClippedDrawRect.y = 0.0; - clippingContext._allClippedDrawRect.width = 0.0; - clippingContext._allClippedDrawRect.height = 0.0; - clippingContext._isUsing = false; - } - else - { - clippingContext._isUsing = true; - let w: number = clippedDrawTotalMaxX - clippedDrawTotalMinX; - let h: number = clippedDrawTotalMaxY - clippedDrawTotalMinY; - clippingContext._allClippedDrawRect.x = clippedDrawTotalMinX; - clippingContext._allClippedDrawRect.y = clippedDrawTotalMinY; - clippingContext._allClippedDrawRect.width = w; - clippingContext._allClippedDrawRect.height = h; - } - - } - } - - /** - * コンストラクタ - */ - public constructor() - { - this._maskRenderTexture = null; - this._colorBuffer = null; - this._currentFrameNo = 0; - this._clippingMaskBufferSize = 256; - this._clippingContextListForMask = new csmVector(); - this._clippingContextListForDraw = new csmVector(); - this._channelColors = new csmVector(); - this._tmpBoundsOnModel = new csmRect(); - this._tmpMatrix = new CubismMatrix44(); - this._tmpMatrixForMask = new CubismMatrix44(); - this._tmpMatrixForDraw = new CubismMatrix44(); - this._maskTexture = null; - ; - let tmp: CubismRenderer.CubismTextureColor = new CubismRenderer.CubismTextureColor(); - tmp.R = 1.0; - tmp.G = 0.0; - tmp.B = 0.0; - tmp.A = 0.0; - this._channelColors.pushBack(tmp); - - tmp = new CubismRenderer.CubismTextureColor(); - tmp.R = 0.0; - tmp.G = 1.0; - tmp.B = 0.0; - tmp.A = 0.0; - this._channelColors.pushBack(tmp); - - tmp = new CubismRenderer.CubismTextureColor(); - tmp.R = 0.0; - tmp.G = 0.0; - tmp.B = 1.0; - tmp.A = 0.0; - this._channelColors.pushBack(tmp); - - tmp = new CubismRenderer.CubismTextureColor(); - tmp.R = 0.0; - tmp.G = 0.0; - tmp.B = 0.0; - tmp.A = 1.0; - this._channelColors.pushBack(tmp); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - for(let i: number = 0; i < this._clippingContextListForMask.getSize(); i++) - { - if(this._clippingContextListForMask.at(i)) - { - this._clippingContextListForMask.at(i).release(); - this._clippingContextListForMask.set(i, void 0); - } - this._clippingContextListForMask.set(i, null); - } - this._clippingContextListForMask = null; - - // _clippingContextListForDrawは_clippingContextListForMaskにあるインスタンスを指している。上記の処理により要素ごとのDELETEha不要。 - for(let i: number = 0; i < this._clippingContextListForDraw.getSize(); i++) - { - this._clippingContextListForDraw.at(i).release(); - this._clippingContextListForDraw.set(i, null); - } - this._clippingContextListForDraw = null; - - if(this._maskTexture) - { - this.gl.deleteFramebuffer(this._maskTexture.texture); - - this._maskTexture = void 0; - this._maskTexture = null; - } - - for(let i: number = 0; i < this._channelColors.getSize(); i++) - { - if(this._channelColors.at(i)) - { - this._channelColors.set(i, void 0); - } - this._channelColors.set(i, null); - } - - this._channelColors = null; - } - - /** - * マネージャの初期化処理 - * クリッピングマスクを使う描画オブジェクトの登録を行う - * @param model モデルのインスタンス - * @param drawableCount 描画オブジェクトの数 - * @param drawableMasks 描画オブジェクトをマスクする描画オブジェクトのインデックスのリスト - * @param drawableCounts 描画オブジェクトをマスクする描画オブジェクトの数 - */ - public initialize(model: CubismModel, drawableCount: number, drawableMasks: Int32Array[], drawableMaskCounts: Int32Array): void - { - // クリッピングマスクを使う描画オブジェクトをすべて登録する - // クリッピングマスクは、通常数個程度に限定して使うものとする - for(let i: number = 0; i < drawableCount; i++) - { - if(drawableMaskCounts[i] <= 0) - { - // クリッピングマスクが使用されていないアートメッシュ(多くの場合使用しない) - this._clippingContextListForDraw.pushBack(null); - continue; - } - - // 既にあるClipContextと同じかチェックする - let clippingContext: CubismClippingContext = this.findSameClip(drawableMasks[i], drawableMaskCounts[i]); - if(clippingContext == null) - { - // 同一のマスクが存在していない場合は生成する - clippingContext = new CubismClippingContext(this, drawableMasks[i], drawableMaskCounts[i]); - this._clippingContextListForMask.pushBack(clippingContext); - } - - clippingContext.addClippedDrawable(i); - - this._clippingContextListForDraw.pushBack(clippingContext); - } - } - - /** - * クリッピングコンテキストを作成する。モデル描画時に実行する。 - * @param model モデルのインスタンス - * @param renderer レンダラのインスタンス - */ - public setupClippingContext(model: CubismModel, renderer: CubismRenderer_WebGL): void - { - this._currentFrameNo++; - - // 全てのクリッピングを用意する - // 同じクリップ(複数の場合はまとめて一つのクリップ)を使う場合は1度だけ設定する - let usingClipCount: number = 0; - for(let clipIndex = 0; clipIndex < this._clippingContextListForMask.getSize(); clipIndex++) - { - // 1つのクリッピングマスクに関して - let cc: CubismClippingContext = this._clippingContextListForMask.at(clipIndex); - - // このクリップを利用する描画オブジェクト群全体を囲む矩形を計算 - this.calcClippedDrawTotalBounds(model, cc); - - if(cc._isUsing) - { - usingClipCount++; // 使用中としてカウント - } - } - - // マスク作成処理 - if(usingClipCount > 0) - { - // 現在のビューポートの値を退避 - let viewport: number[] = new Array(4); - - // 現在のビューポートの値を退避 - viewport = this.gl.getParameter(this.gl.VIEWPORT); - - // 生成したFrameBufferと同じサイズでビューポートを設定 - this.gl.viewport(0, 0, this._clippingMaskBufferSize, this._clippingMaskBufferSize); - - // マスクactive切り替え前のFBOを退避 - let oldFBO: number; - oldFBO = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING); - - // マスクをactiveにする - this._maskRenderTexture = this.getMaskRenderTexture(); - - // モデル描画時にDrawMeshNowに渡される変換(モデルtoワールド座標変換) - let modelToWorldF: CubismMatrix44 = renderer.getMvpMatrix(); - - renderer.preDraw(); // バッファをクリアする - - // 各マスクのレイアウトを決定していく - this.setupLayoutBounds(usingClipCount); - - // ---------- マスク描画処理 ---------- - // マスク用RenderTextureをactiveにセット - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this._maskRenderTexture); - - // マスクをクリアする - // (仮仕様) 1が無効(描かれない)領域、0が有効(描かれる)領域。(シェーダーCd*Csで0に近い値をかけてマスクを作る。1をかけると何も起こらない) - this.gl.clearColor(1.0, 1.0, 1.0, 1.0); - this.gl.clear(this.gl.COLOR_BUFFER_BIT); - - // 実際にマスクを生成する - // 全てのマスクをどのようにレイアウトして描くかを決定し、ClipContext, ClippedDrawContextに記憶する - for(let clipIndex: number = 0; clipIndex < this._clippingContextListForMask.getSize(); clipIndex++) - { - // --- 実際に1つのマスクを描く --- - let clipContext: CubismClippingContext = this._clippingContextListForMask.at(clipIndex); - let allClipedDrawRect: csmRect = clipContext._allClippedDrawRect; // このマスクを使う、すべての描画オブジェクトの論理座標上の囲み矩形 - let layoutBoundsOnTex01: csmRect = clipContext._layoutBounds; // この中にマスクを収める - - // モデル座標上の矩形を、適宜マージンを付けて使う - const MARGIN: number = 0.05; - this._tmpBoundsOnModel.setRect(allClipedDrawRect); - this._tmpBoundsOnModel.expand(allClipedDrawRect.width * MARGIN, allClipedDrawRect.height * MARGIN); - //########## 本来は割り当てられた領域の全体を使わず必要最低限のサイズがよい - - // シェーダ用の計算式を求める。回転を考慮しない場合は以下のとおり - // movePeriod' = movePeriod * scaleX + offX [[ movePeriod' = (movePeriod - tmpBoundsOnModel.movePeriod)*scale + layoutBoundsOnTex01.movePeriod ]] - const scaleX: number = layoutBoundsOnTex01.width / this._tmpBoundsOnModel.width; - const scaleY: number = layoutBoundsOnTex01.height / this._tmpBoundsOnModel.height; - - // マスク生成時に使う行列を求める - { - // シェーダに渡す行列を求める <<<<<<<<<<<<<<<<<<<<<<<< 要最適化(逆順に計算すればシンプルにできる) - this._tmpMatrix.loadIdentity(); - { - // layout0..1 を -1..1に変換 - this._tmpMatrix.translateRelative(-1.0, -1.0); - this._tmpMatrix.scaleRelative(2.0, 2.0); - } - { - // view to layout0..1 - this._tmpMatrix.translateRelative(layoutBoundsOnTex01.x, layoutBoundsOnTex01.y); - this._tmpMatrix.scaleRelative(scaleX, scaleY); // new = [translate][scale] - this._tmpMatrix.translateRelative(-this._tmpBoundsOnModel.x, -this._tmpBoundsOnModel.y); - // new = [translate][scale][translate] - } - // tmpMatrixForMaskが計算結果 - this._tmpMatrixForMask.setMatrix(this._tmpMatrix.getArray()); - } - - //--------- draw時の mask 参照用行列を計算 - { - // シェーダに渡す行列を求める <<<<<<<<<<<<<<<<<<<<<<<< 要最適化(逆順に計算すればシンプルにできる) - this._tmpMatrix.loadIdentity(); - { - this._tmpMatrix.translateRelative(layoutBoundsOnTex01.x, layoutBoundsOnTex01.y); - this._tmpMatrix.scaleRelative(scaleX, scaleY); // new = [translate][scale] - this._tmpMatrix.translateRelative(-this._tmpBoundsOnModel.x, -this._tmpBoundsOnModel.y); - // new = [translate][scale][translate] - } - this._tmpMatrixForDraw.setMatrix(this._tmpMatrix.getArray()); - } - clipContext._matrixForMask.setMatrix(this._tmpMatrixForMask.getArray()); - clipContext._matrixForDraw.setMatrix(this._tmpMatrixForDraw.getArray()); - - const clipDrawCount: number = clipContext._clippingIdCount; - for(let i: number = 0; i < clipDrawCount; i++) - { - const clipDrawIndex: number = clipContext._clippingIdList[i]; - - // 頂点情報が更新されておらず、信頼性がない場合は描画をパスする - if(!model.getDrawableDynamicFlagVertexPositionsDidChange(clipDrawIndex)) - { - continue; - } - - renderer.setIsCulling(model.getDrawableCulling(clipDrawIndex) != false); - - // 今回専用の変換を適用して描く - // チャンネルも切り替える必要がある(A,R,G,B) - renderer.setClippingContextBufferForMask(clipContext); - renderer.drawMesh( - model.getDrawableTextureIndices(clipDrawIndex), - model.getDrawableVertexIndexCount(clipDrawIndex), - model.getDrawableVertexCount(clipDrawIndex), - model.getDrawableVertexIndices(clipDrawIndex), - model.getDrawableVertices(clipDrawIndex), - model.getDrawableVertexUvs(clipDrawIndex), - model.getDrawableOpacity(clipDrawIndex), - CubismRenderer.CubismBlendMode.CubismBlendMode_Normal // クリッピングは通常描画を強制 - ); - } - } - - // --- 後処理 --- - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, oldFBO); // 描画対象を戻す - renderer.setClippingContextBufferForMask(null); - - this.gl.viewport(viewport[0], viewport[1], viewport[2], viewport[3]); - } - } - - /** - * 既にマスクを作っているかを確認 - * 作っている様であれば該当するクリッピングマスクのインスタンスを返す - * 作っていなければNULLを返す - * @param drawableMasks 描画オブジェクトをマスクする描画オブジェクトのリスト - * @param drawableMaskCounts 描画オブジェクトをマスクする描画オブジェクトの数 - * @return 該当するクリッピングマスクが存在すればインスタンスを返し、なければNULLを返す - */ - public findSameClip(drawableMasks: Int32Array, drawableMaskCounts: number): CubismClippingContext - { - // 作成済みClippingContextと一致するか確認 - for(let i: number = 0; i < this._clippingContextListForMask.getSize(); i++) - { - let clippingContext: CubismClippingContext = this._clippingContextListForMask.at(i); - const count: number = clippingContext._clippingIdCount; - - // 個数が違う場合は別物 - if(count != drawableMaskCounts) - { - continue; - } - - let sameCount = 0; - - // 同じIDを持つか確認。配列の数が同じなので、一致した個数が同じなら同じ物を持つとする - for(let j: number = 0; j < count; j++) - { - const clipId: number = clippingContext._clippingIdList[j]; - - for(let k: number = 0; k < count; k++) - { - if(drawableMasks[k] == clipId) - { - sameCount++; - break; - } - } - } - - if(sameCount == count) - { - return clippingContext; - } - } - - return null; // 見つからなかった - } - - /** - * クリッピングコンテキストを配置するレイアウト - * 一つのレンダーテクスチャを極力いっぱいに使ってマスクをレイアウトする - * マスクグループの数が4以下ならRGBA各チャンネルに一つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する。 - * - * @param usingClipCount 配置するクリッピングコンテキストの数 - */ - public setupLayoutBounds(usingClipCount: number): void - { - // ひとつのRenderTextureを極力いっぱいに使ってマスクをレイアウトする - // マスクグループの数が4以下ならRGBA各チャンネルに1つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する - - // RGBAを順番に使っていく - let div: number = usingClipCount / ColorChannelCount; // 1チャンネルに配置する基本のマスク - let mod: number = usingClipCount % ColorChannelCount; // 余り、この番号のチャンネルまでに一つずつ配分する - - // 小数点は切り捨てる - div = ~~div; - mod = ~~mod; - - // RGBAそれぞれのチャンネルを用意していく(0:R, 1:G, 2:B, 3:A) - let curClipIndex: number = 0; // 順番に設定していく - - for(let channelNo: number = 0; channelNo < ColorChannelCount; channelNo++) - { - // このチャンネルにレイアウトする数 - let layoutCount: number = div + (channelNo < mod ? 1 : 0); - - // 分割方法を決定する - if(layoutCount == 0) - { - // 何もしない - } - else if(layoutCount == 1) - { - // 全てをそのまま使う - let clipContext: CubismClippingContext = this._clippingContextListForMask.at(curClipIndex++); - clipContext._layoutChannelNo = channelNo; - clipContext._layoutBounds.x = 0.0; - clipContext._layoutBounds.y = 0.0; - clipContext._layoutBounds.width = 1.0; - clipContext._layoutBounds.height = 1.0; - } - else if(layoutCount == 2) - { - for(let i: number = 0; i < layoutCount; i++) - { - let xpos: number = i % 2; - - // 小数点は切り捨てる - xpos = ~~xpos; - - let cc: CubismClippingContext = this._clippingContextListForMask.at(curClipIndex++); - cc._layoutChannelNo = channelNo; - - cc._layoutBounds.x = xpos * 0.5; - cc._layoutBounds.y = 0.0; - cc._layoutBounds.width = 0.5; - cc._layoutBounds.height = 1.0; - // UVを2つに分解して使う - } - } - else if(layoutCount <= 4) - { - // 4分割して使う - for(let i: number = 0; i < layoutCount; i++) - { - let xpos: number = i % 2; - let ypos: number = i / 2; - - // 小数点は切り捨てる - xpos = ~~xpos; - ypos = ~~ypos; - - let cc = this._clippingContextListForMask.at(curClipIndex++); - cc._layoutChannelNo = channelNo; - - cc._layoutBounds.x = xpos * 0.5; - cc._layoutBounds.y = ypos * 0.5; - cc._layoutBounds.width = 0.5; - cc._layoutBounds.height = 0.5; - } - } - else if(layoutCount <= 9) - { - // 9分割して使う - for(let i: number = 0; i < layoutCount; i++) - { - let xpos = i % 3; - let ypos = i / 3; - - // 小数点は切り捨てる - xpos = ~~xpos; - ypos = ~~ypos; - - let cc: CubismClippingContext = this._clippingContextListForMask.at(curClipIndex++); - cc._layoutChannelNo = channelNo; - - cc._layoutBounds.x = xpos / 3.0; - cc._layoutBounds.y = ypos / 3.0; - cc._layoutBounds.width = 1.0 / 3.0; - cc._layoutBounds.height = 1.0 / 3.0; - } - } - else - { - CubismLogError("not supported mask count : {0}", layoutCount); - } - } - - } - - /** - * カラーバッファを取得する - * @return カラーバッファ - */ - public getColorBuffer(): WebGLTexture - { - return this._colorBuffer; - } - - /** - * 画面描画に使用するクリッピングマスクのリストを取得する - * @return 画面描画に使用するクリッピングマスクのリスト - */ - public getClippingContextListForDraw(): csmVector - { - return this._clippingContextListForDraw; - } - - /** - * クリッピングマスクバッファのサイズを設定する - * @param size クリッピングマスクバッファのサイズ - */ - public setClippingMaskBufferSize(size: number): void - { - this._clippingMaskBufferSize = size; - } - - /** - * クリッピングマスクバッファのサイズを取得する - * @return クリッピングマスクバッファのサイズ - */ - public getClippingMaskBufferSize(): number - { - return this._clippingMaskBufferSize; - } - - public _maskRenderTexture: WebGLFramebuffer; // マスク用レンダーテクスチャのアドレス - public _colorBuffer: WebGLTexture; // マスク用カラーバッファーのアドレス - public _currentFrameNo: number; // マスクテクスチャに与えるフレーム番号 - - public _channelColors: csmVector; - public _maskTexture: CubismRenderTextureResource; // マスク用のテクスチャリソースのリスト - public _clippingContextListForMask: csmVector; // マスク用クリッピングコンテキストのリスト - public _clippingContextListForDraw: csmVector; // 描画用クリッピングコンテキストのリスト - public _clippingMaskBufferSize: number; // クリッピングマスクのバッファサイズ(初期値:256) - - private _tmpMatrix: CubismMatrix44; // マスク計算用の行列 - private _tmpMatrixForMask: CubismMatrix44; // マスク計算用の行列 - private _tmpMatrixForDraw: CubismMatrix44; // マスク計算用の行列 - private _tmpBoundsOnModel: csmRect; // マスク配置計算用の矩形 - - gl: WebGLRenderingContext; // WebGLレンダリングコンテキスト - } - - /** - * レンダーテクスチャのリソースを定義する構造体 - * クリッピングマスクで使用する - */ - export class CubismRenderTextureResource - { - /** - * 引数付きコンストラクタ - * @param frameNo レンダラーのフレーム番号 - * @param texture テクスチャのアドレス - */ - public constructor(frameNo: number, texture: WebGLFramebuffer) - { - this.frameNo = frameNo; - this.texture = texture; - } - - public frameNo: number; // レンダラのフレーム番号 - public texture: WebGLFramebuffer; // テクスチャのアドレス - } - - /** - * クリッピングマスクのコンテキスト - */ - export class CubismClippingContext - { - /** - * 引数付きコンストラクタ - */ - public constructor(manager: CubismClippingManager_WebGL, clippingDrawableIndices: Int32Array, clipCount: number) - { - this._owner = manager; - - // クリップしている(=マスク用の)Drawableのインデックスリスト - this._clippingIdList = clippingDrawableIndices; - - // マスクの数 - this._clippingIdCount = clipCount; - - this._allClippedDrawRect = new csmRect(); - this._layoutBounds = new csmRect(); - - this._clippedDrawableIndexList = new Array(); - - this._matrixForMask = new CubismMatrix44(); - this._matrixForDraw = new CubismMatrix44(); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - if(this._layoutBounds != null) - { - this._layoutBounds = void 0; - this._layoutBounds = null; - } - - if(this._allClippedDrawRect != null) - { - this._allClippedDrawRect = void 0; - this._allClippedDrawRect = null; - } - - if(this._clippedDrawableIndexList != null) - { - this._clippedDrawableIndexList = void 0; - this._clippedDrawableIndexList = null; - } - } - - /** - * このマスクにクリップされる描画オブジェクトを追加する - * - * @param drawableIndex クリッピング対象に追加する描画オブジェクトのインデックス - */ - public addClippedDrawable(drawableIndex: number) - { - this._clippedDrawableIndexList.push(drawableIndex); - } - - /** - * このマスクを管理するマネージャのインスタンスを取得する - * @return クリッピングマネージャのインスタンス - */ - public getClippingManager(): CubismClippingManager_WebGL - { - return this._owner; - } - - public setGl(gl: WebGLRenderingContext): void - { - this._owner.setGL(gl); - } - - public _isUsing: boolean; // 現在の描画状態でマスクの準備が必要ならtrue - public readonly _clippingIdList: Int32Array; // クリッピングマスクのIDリスト - public _clippingIdCount: number; // クリッピングマスクの数 - public _layoutChannelNo: number; // RGBAのいずれのチャンネルにこのクリップを配置するか(0:R, 1:G, 2:B, 3:A) - public _layoutBounds: csmRect; // マスク用チャンネルのどの領域にマスクを入れるか(View座標-1~1, UVは0~1に直す) - public _allClippedDrawRect: csmRect; // このクリッピングで、クリッピングされるすべての描画オブジェクトの囲み矩形(毎回更新) - public _matrixForMask: CubismMatrix44; // マスクの位置計算結果を保持する行列 - public _matrixForDraw: CubismMatrix44; // 描画オブジェクトの位置計算結果を保持する行列 - public _clippedDrawableIndexList: number[]; // このマスクにクリップされる描画オブジェクトのリスト - - private _owner: CubismClippingManager_WebGL; // このマスクを管理しているマネージャのインスタンス - } - - /** - * WebGL用のシェーダープログラムを生成・破棄するクラス - * シングルトンなクラスであり、CubismShader_WebGL.getInstanceからアクセスする。 - */ - export class CubismShader_WebGL - { - /** - * インスタンスを取得する(シングルトン) - * @return インスタンス - */ - public static getInstance(): CubismShader_WebGL - { - if(s_instance == null) - { - s_instance = new CubismShader_WebGL(); - - return s_instance; - } - return s_instance; - } - - /** - * インスタンスを開放する(シングルトン) - */ - public static deleteInstance(): void - { - if(s_instance) - { - s_instance.release(); - s_instance = void 0; - s_instance = null; - } - } - - /** - * privateなコンストラクタ - */ - private constructor() - { - this._shaderSets = new csmVector(); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - this.releaseShaderProgram(); - } - - /** - * シェーダープログラムの一連のセットアップを実行する - * @param renderer レンダラのインスタンス - * @param textureId GPUのテクスチャID - * @param vertexCount ポリゴンメッシュの頂点数 - * @param vertexArray ポリゴンメッシュの頂点配列 - * @param indexArray インデックスバッファの頂点配列 - * @param uvArray uv配列 - * @param opacity 不透明度 - * @param colorBlendMode カラーブレンディングのタイプ - * @param baseColor ベースカラー - * @param isPremultipliedAlpha 乗算済みアルファかどうか - * @param matrix4x4 Model-View-Projection行列 - */ - public setupShaderProgram(renderer: CubismRenderer_WebGL, - textureId: WebGLTexture, - vertexCount: number, - vertexArray: Float32Array, - indexArray: Uint16Array, - uvArray: Float32Array, - opacity: number, - colorBlendMode: CubismRenderer.CubismBlendMode, - baseColor: CubismRenderer.CubismTextureColor, - isPremultipliedAlpha: boolean, - matrix4x4: CubismMatrix44): void - { - if(this._shaderSets.getSize() == 0) - { - this.generateShaders(); - } - - let vertexBuffer = null; - let uvBuffer = null; - let indexBuffer = null; - - // Blending - let SRC_COLOR: number; - let DST_COLOR: number; - let SRC_ALPHA: number; - let DST_ALPHA: number; - - if(renderer.getClippingContextBufferForMask() != null) // マスク生成時 - { - let shaderSet: CubismShader_WebGL.CubismShaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_SetupMask); - this.gl.useProgram(shaderSet.shaderProgram); - - // テクスチャ設定 - this.gl.activeTexture(this.gl.TEXTURE0); - this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); - this.gl.uniform1i(shaderSet.samplerTexture0Location, 0); - - // 頂点配列の設定(VBO) - if(vertexBuffer == null) - { - vertexBuffer = this.gl.createBuffer(); - } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer); - this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); - this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); - this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); - - // テクスチャ頂点の設定 - if(uvBuffer == null) - { - uvBuffer = this.gl.createBuffer(); - } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer); - this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); - this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); - this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); - - // チャンネル - const channelNo: number = renderer.getClippingContextBufferForMask()._layoutChannelNo; - let colorChannel: CubismRenderer.CubismTextureColor = renderer.getClippingContextBufferForMask().getClippingManager().getChannelFlagAsColor(channelNo); - this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); - - this.gl.uniformMatrix4fv(shaderSet.uniformClipMatrixLocation, false, renderer.getClippingContextBufferForMask()._matrixForMask.getArray()); - - let rect: csmRect = renderer.getClippingContextBufferForMask()._layoutBounds; - - this.gl.uniform4f( - shaderSet.uniformBaseColorLocation, - rect.x * 2.0 - 1.0, - rect.y * 2.0 - 1.0, - rect.getRight() * 2.0 - 1.0, - rect.getBottom() * 2.0 - 1.0 - ); - - SRC_COLOR = this.gl.ZERO; - DST_COLOR = this.gl.ONE_MINUS_SRC_COLOR; - SRC_ALPHA = this.gl.ZERO; - DST_ALPHA = this.gl.ONE_MINUS_SRC_ALPHA; - } - else // マスク生成以外の場合 - { - const masked: boolean = renderer.getClippingContextBufferForDraw() != null; // この描画オブジェクトはマスク対象か - const offset: number = (masked ? 1 : 0) + (isPremultipliedAlpha ? 2 : 0); - - let shaderSet: CubismShader_WebGL.CubismShaderSet = new CubismShader_WebGL.CubismShaderSet(); - - switch(colorBlendMode) - { - case CubismRenderer.CubismBlendMode.CubismBlendMode_Normal: - default: - shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Normal + offset); - SRC_COLOR = this.gl.ONE; - DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; - SRC_ALPHA = this.gl.ONE; - DST_ALPHA = this.gl.ONE_MINUS_SRC_ALPHA; - break; - - case CubismRenderer.CubismBlendMode.CubismBlendMode_Additive: - shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Add + offset); - SRC_COLOR = this.gl.ONE; - DST_COLOR = this.gl.ONE; - SRC_ALPHA = this.gl.ZERO; - DST_ALPHA = this.gl.ONE; - break; - - case CubismRenderer.CubismBlendMode.CubismBlendMode_Multiplicative: - shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Mult + offset); - SRC_COLOR = this.gl.DST_COLOR; - DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; - SRC_ALPHA = this.gl.ZERO; - DST_ALPHA = this.gl.ONE; - break; - } - - this.gl.useProgram(shaderSet.shaderProgram); - - // 頂点配列の設定 - if(vertexBuffer == null) - { - vertexBuffer = this.gl.createBuffer(); - } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer); - this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); - this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); - this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); - - // テクスチャ頂点の設定 - if(uvBuffer == null) - { - uvBuffer = this.gl.createBuffer(); - } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer); - this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); - this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); - this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); - - if(masked) - { - this.gl.activeTexture(this.gl.TEXTURE1); - let tex: WebGLTexture = renderer.getClippingContextBufferForDraw().getClippingManager().getColorBuffer(); - this.gl.bindTexture(this.gl.TEXTURE_2D, tex); - this.gl.uniform1i(shaderSet.samplerTexture1Location, 1); - - // view座標をClippingContextの座標に変換するための行列を設定 - this.gl.uniformMatrix4fv(shaderSet.uniformClipMatrixLocation, false,renderer.getClippingContextBufferForDraw()._matrixForDraw.getArray()); - - // 使用するカラーチャンネルを設定 - const channelNo: number = renderer.getClippingContextBufferForDraw()._layoutChannelNo; - let colorChannel: CubismRenderer.CubismTextureColor = renderer.getClippingContextBufferForDraw().getClippingManager().getChannelFlagAsColor(channelNo); - this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); - } - - // テクスチャ設定 - this.gl.activeTexture(this.gl.TEXTURE0); - this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); - this.gl.uniform1i(shaderSet.samplerTexture0Location, 0); - - // 座標変換 - this.gl.uniformMatrix4fv(shaderSet.uniformMatrixLocation, false, matrix4x4.getArray()); - - this.gl.uniform4f(shaderSet.uniformBaseColorLocation, baseColor.R, baseColor.G, baseColor.B, baseColor.A); - } - - // IBOを作成し、データを転送(OpenGLにはなかったが、これがないとdrawElenmentが使用できない) - if(indexBuffer == null) - { - indexBuffer = this.gl.createBuffer(); - } - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer); - this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, indexArray, this.gl.DYNAMIC_DRAW); - this.gl.blendFuncSeparate(SRC_COLOR, DST_COLOR, SRC_ALPHA, DST_ALPHA); - } - - /** - * シェーダープログラムを解放する - */ - public releaseShaderProgram(): void - { - for(let i: number = 0; i < this._shaderSets.getSize(); i++) - { - this.gl.deleteProgram(this._shaderSets.at(i).shaderProgram); - this._shaderSets.at(i).shaderProgram = 0; - this._shaderSets.set(i, void 0); - this._shaderSets.set(i, null); - } - } - - /** - * シェーダープログラムを初期化する - * @param vertShaderSrc 頂点シェーダのソース - * @param fragShaderSrc フラグメントシェーダのソース - */ - public generateShaders(): void - { - for(let i: number = 0; i < shaderCount; i++) - { - this._shaderSets.pushBack(new CubismShader_WebGL.CubismShaderSet()); - } - - this._shaderSets.at(0).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcSetupMask, CubismShader_WebGL.fragmentShaderSrcsetupMask); - - this._shaderSets.at(1).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrc, CubismShader_WebGL.fragmentShaderSrc); - this._shaderSets.at(2).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcMasked, CubismShader_WebGL.fragmentShaderSrcMask); - this._shaderSets.at(3).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrc, CubismShader_WebGL.fragmentShaderSrcPremultipliedAlpha); - this._shaderSets.at(4).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcMasked, CubismShader_WebGL.fragmentShaderSrcMaskPremultipliedAlpha); - - // 加算も通常と同じシェーダーを利用する - this._shaderSets.at(5).shaderProgram = this._shaderSets.at(1).shaderProgram; - this._shaderSets.at(6).shaderProgram = this._shaderSets.at(2).shaderProgram; - this._shaderSets.at(7).shaderProgram = this._shaderSets.at(3).shaderProgram; - this._shaderSets.at(8).shaderProgram = this._shaderSets.at(4).shaderProgram; - - // 乗算も通常と同じシェーダーを利用する - this._shaderSets.at(9).shaderProgram = this._shaderSets.at(1).shaderProgram; - this._shaderSets.at(10).shaderProgram = this._shaderSets.at(2).shaderProgram; - this._shaderSets.at(11).shaderProgram = this._shaderSets.at(3).shaderProgram; - this._shaderSets.at(12).shaderProgram = this._shaderSets.at(4).shaderProgram; - - // SetupMask - this._shaderSets.at(0).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(0).shaderProgram, "a_position"); - this._shaderSets.at(0).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(0).shaderProgram, "a_texCoord"); - this._shaderSets.at(0).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "s_texture0"); - this._shaderSets.at(0).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(0).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_channelFlag"); - this._shaderSets.at(0).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_baseColor"); - - // 通常 - this._shaderSets.at(1).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(1).shaderProgram, "a_position"); - this._shaderSets.at(1).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(1).shaderProgram, "a_texCoord"); - this._shaderSets.at(1).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "s_texture0"); - this._shaderSets.at(1).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "u_matrix"); - this._shaderSets.at(1).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "u_baseColor"); - - // 通常(クリッピング) - this._shaderSets.at(2).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(2).shaderProgram, "a_position"); - this._shaderSets.at(2).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(2).shaderProgram, "a_texCoord"); - this._shaderSets.at(2).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "s_texture0"); - this._shaderSets.at(2).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "s_texture1"); - this._shaderSets.at(2).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_matrix"); - this._shaderSets.at(2).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(2).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_channelFlag"); - this._shaderSets.at(2).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_baseColor"); - - // 通常(PremultipliedAlpha) - this._shaderSets.at(3).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(3).shaderProgram, "a_position"); - this._shaderSets.at(3).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(3).shaderProgram, "a_texCoord"); - this._shaderSets.at(3).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "s_texture0"); - this._shaderSets.at(3).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "u_matrix"); - this._shaderSets.at(3).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "u_baseColor"); - - // 通常(クリッピング、PremultipliedAlpha) - this._shaderSets.at(4).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(4).shaderProgram, "a_position"); - this._shaderSets.at(4).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(4).shaderProgram, "a_texCoord"); - this._shaderSets.at(4).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "s_texture0"); - this._shaderSets.at(4).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "s_texture1"); - this._shaderSets.at(4).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_matrix"); - this._shaderSets.at(4).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(4).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_channelFlag"); - this._shaderSets.at(4).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_baseColor"); - - // 加算 - this._shaderSets.at(5).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(5).shaderProgram, "a_position"); - this._shaderSets.at(5).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(5).shaderProgram, "a_texCoord"); - this._shaderSets.at(5).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "s_texture0"); - this._shaderSets.at(5).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "u_matrix"); - this._shaderSets.at(5).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "u_baseColor"); - // 加算(クリッピング) - this._shaderSets.at(6).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(6).shaderProgram, "a_position"); - this._shaderSets.at(6).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(6).shaderProgram, "a_texCoord"); - this._shaderSets.at(6).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "s_texture0"); - this._shaderSets.at(6).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "s_texture1"); - this._shaderSets.at(6).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_matrix"); - this._shaderSets.at(6).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(6).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_channelFlag"); - this._shaderSets.at(6).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_baseColor"); - - // 加算(PremultipliedAlpha) - this._shaderSets.at(7).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(7).shaderProgram, "a_position"); - this._shaderSets.at(7).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(7).shaderProgram, "a_texCoord"); - this._shaderSets.at(7).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "s_texture0"); - this._shaderSets.at(7).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "u_matrix"); - this._shaderSets.at(7).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "u_baseColor"); - - // 加算(クリッピング、PremultipliedAlpha) - this._shaderSets.at(8).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(8).shaderProgram, "a_position"); - this._shaderSets.at(8).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(8).shaderProgram, "a_texCoord"); - this._shaderSets.at(8).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "s_texture0"); - this._shaderSets.at(8).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "s_texture1"); - this._shaderSets.at(8).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_matrix"); - this._shaderSets.at(8).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(8).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_channelFlag"); - this._shaderSets.at(8).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_baseColor"); - - // 乗算 - this._shaderSets.at(9).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(9).shaderProgram, "a_position"); - this._shaderSets.at(9).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(9).shaderProgram, "a_texCoord"); - this._shaderSets.at(9).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "s_texture0"); - this._shaderSets.at(9).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "u_matrix"); - this._shaderSets.at(9).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "u_baseColor"); - - // 乗算(クリッピング) - this._shaderSets.at(10).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(10).shaderProgram, "a_position"); - this._shaderSets.at(10).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(10).shaderProgram, "a_texCoord"); - this._shaderSets.at(10).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "s_texture0"); - this._shaderSets.at(10).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "s_texture1"); - this._shaderSets.at(10).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_matrix"); - this._shaderSets.at(10).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(10).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_channelFlag"); - this._shaderSets.at(10).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_baseColor"); - - // 乗算(PremultipliedAlpha) - this._shaderSets.at(11).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(11).shaderProgram, "a_position"); - this._shaderSets.at(11).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(11).shaderProgram, "a_texCoord"); - this._shaderSets.at(11).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "s_texture0"); - this._shaderSets.at(11).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "u_matrix"); - this._shaderSets.at(11).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "u_baseColor"); - - // 乗算(クリッピング、PremultipliedAlpha) - this._shaderSets.at(12).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(12).shaderProgram, "a_position"); - this._shaderSets.at(12).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(12).shaderProgram, "a_texCoord"); - this._shaderSets.at(12).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "s_texture0"); - this._shaderSets.at(12).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "s_texture1"); - this._shaderSets.at(12).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_matrix"); - this._shaderSets.at(12).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(12).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_channelFlag"); - this._shaderSets.at(12).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_baseColor"); - } - - /** - * シェーダプログラムをロードしてアドレスを返す - * @param vertexShaderSource 頂点シェーダのソース - * @param fragmentShaderSource フラグメントシェーダのソース - * @return シェーダプログラムのアドレス - */ - public loadShaderProgram(vertexShaderSource: string, fragmentShaderSource: string): WebGLProgram - { - // Create Shader Program - let shaderProgram: WebGLProgram = this.gl.createProgram(); - - let vertShader = this.compileShaderSource(this.gl.VERTEX_SHADER, vertexShaderSource); - - if(!vertShader) - { - CubismLogError("Vertex shader compile error!"); - return 0; - } - - let fragShader = this.compileShaderSource(this.gl.FRAGMENT_SHADER, fragmentShaderSource); - if(!fragShader) - { - CubismLogError("Vertex shader compile error!"); - return 0; - } - - // Attach vertex shader to program - this.gl.attachShader(shaderProgram, vertShader); - - // Attach fragment shader to program - this.gl.attachShader(shaderProgram, fragShader); - - // link program - this.gl.linkProgram(shaderProgram) - let linkStatus = this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS); - - // リンクに失敗したらシェーダーを削除 - if(!linkStatus) - { - CubismLogError("Failed to link program: {0}", shaderProgram); - - this.gl.deleteShader(vertShader); - vertShader = 0; - - this.gl.deleteShader(fragShader); - fragShader = 0; - - if(shaderProgram) - { - this.gl.deleteProgram(shaderProgram); - shaderProgram = 0; - } - - return 0; - } - - // Release vertex and fragment shaders. - this.gl.detachShader(shaderProgram, vertShader); - this.gl.deleteShader(vertShader); - - this.gl.detachShader(shaderProgram, fragShader); - this.gl.deleteShader(fragShader); - - return shaderProgram; - } - - /** - * シェーダープログラムをコンパイルする - * @param shaderType シェーダタイプ(Vertex/Fragment) - * @param shaderSource シェーダソースコード - * - * @return コンパイルされたシェーダープログラム - */ - public compileShaderSource(shaderType: GLenum, shaderSource: string): WebGLProgram - { - const source: string = shaderSource; - - let shader: WebGLProgram = this.gl.createShader(shaderType); - this.gl.shaderSource(shader, source); - this.gl.compileShader(shader); - - if(!shader) - { - let log: string = this.gl.getShaderInfoLog(shader); - CubismLogError("Shader compile log: {0} ", log); - } - - let status: any = this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS); - if(!status) - { - this.gl.deleteShader(shader); - return null; - } - - return shader; - } - - public setGl(gl: WebGLRenderingContext): void - { - this.gl = gl; - } - - _shaderSets: csmVector; // ロードしたシェーダープログラムを保持する変数 - gl: WebGLRenderingContext; // webglコンテキスト - } - - /** - * CubismShader_WebGLのインナークラス - */ - export namespace CubismShader_WebGL - { - export class CubismShaderSet - { - shaderProgram: WebGLProgram; // シェーダープログラムのアドレス - attributePositionLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(Position) - attributeTexCoordLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(TexCoord) - uniformMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Matrix) - uniformClipMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ClipMatrix) - samplerTexture0Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture0) - samplerTexture1Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture1) - uniformBaseColorLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(BaseColor) - uniformChannelFlagLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ChannelFlag) - } - - export enum ShaderNames - { - // SetupMask - ShaderNames_SetupMask, - - // Normal - ShaderNames_Normal, - ShaderNames_NormalMasked, - ShaderNames_NormalPremultipliedAlpha, - ShaderNames_NormalMaskedPremultipliedAlpha, - - // Add - ShaderNames_Add, - ShaderNames_AddMasked, - ShaderNames_AddPremultipliedAlpha, - ShaderNames_AddMaskedPremultipledAlpha, - - // Mult - ShaderNames_Mult, - ShaderNames_MultMasked, - ShaderNames_MultPremultipliedAlpha, - ShaderNames_MultMaskedPremultipliedAlpha, - }; - - export const vertexShaderSrcSetupMask = - "attribute vec4 a_position;" + - "attribute vec2 a_texCoord;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_myPos;" + - "uniform mat4 u_clipMatrix;" + - "void main()" + - "{" + - " gl_Position = u_clipMatrix * a_position;" + - " v_myPos = u_clipMatrix * a_position;" + - " v_texCoord = a_texCoord;" + - " v_texCoord.y = 1.0 - v_texCoord.y;" + - "}"; - export const fragmentShaderSrcsetupMask = - "precision mediump float;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_myPos;" + - "uniform sampler2D s_texture0;" + - "uniform vec4 u_channelFlag;" + - "uniform vec4 u_baseColor;" + - "void main()" + - "{" + - " float isInside = " + - " step(u_baseColor.x, v_myPos.x/v_myPos.w)" + - " * step(u_baseColor.y, v_myPos.y/v_myPos.w)" + - " * step(v_myPos.x/v_myPos.w, u_baseColor.z)" + - " * step(v_myPos.y/v_myPos.w, u_baseColor.w);" + - " gl_FragColor = u_channelFlag * texture2D(s_texture0, v_texCoord).a * isInside;" + - "}"; - - //----- バーテックスシェーダプログラム ----- - // Normal & Add & Mult 共通 - export const vertexShaderSrc = - "attribute vec4 a_position;" + //v.vertex - "attribute vec2 a_texCoord;" + //v.texcoord - "varying vec2 v_texCoord;" + //v2f.texcoord - "uniform mat4 u_matrix;" + - "void main()" + - "{" + - " gl_Position = u_matrix * a_position;" + - " v_texCoord = a_texCoord;" + - " v_texCoord.y = 1.0 - v_texCoord.y;" + - "}"; - - // Normal & Add & Mult 共通(クリッピングされたものの描画用) - export const vertexShaderSrcMasked = - "attribute vec4 a_position;" + - "attribute vec2 a_texCoord;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_clipPos;" + - "uniform mat4 u_matrix;" + - "uniform mat4 u_clipMatrix;" + - "void main()" + - "{" + - " gl_Position = u_matrix * a_position;" + - " v_clipPos = u_clipMatrix * a_position;" + - " v_texCoord = a_texCoord;" + - " v_texCoord.y = 1.0 - v_texCoord.y;" + - "}"; - - //----- フラグメントシェーダプログラム ----- - // Normal & Add & Mult 共通 - export const fragmentShaderSrc = - "precision mediump float;" + - "varying vec2 v_texCoord;" + //v2f.texcoord - "uniform sampler2D s_texture0;" + //_MainTex - "uniform vec4 u_baseColor;" + //v2f.color - "void main()" + - "{" + - " vec4 color = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - " gl_FragColor = vec4(color.rgb * color.a, color.a);" + - "}"; - - // Normal & Add & Mult 共通 (PremultipliedAlpha) - export const fragmentShaderSrcPremultipliedAlpha = - "precision mediump float;" + - "varying vec2 v_texCoord;" + //v2f.texcoord - "uniform sampler2D s_texture0;" + //_MainTex - "uniform vec4 u_baseColor;" + //v2f.color - "void main()" + - "{" + - " gl_FragColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - "}"; - - // Normal & Add & Mult 共通(クリッピングされたものの描画用) - export const fragmentShaderSrcMask = - "precision mediump float;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_clipPos;" + - "uniform sampler2D s_texture0;" + - "uniform sampler2D s_texture1;" + - "uniform vec4 u_channelFlag;" + - "uniform vec4 u_baseColor;" + - "void main()" + - "{" + - " vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - " col_formask.rgb = col_formask.rgb * col_formask.a ;" + - " vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" + - " float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" + - " col_formask = col_formask * maskVal;" + - " gl_FragColor = col_formask;" + - "}"; - - // Normal (クリッピングされたものの描画用、PremultipliedAlpha兼用) - export const fragmentShaderSrcMaskPremultipliedAlpha = - "precision mediump float;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_clipPos;" + - "uniform sampler2D s_texture0;" + - "uniform sampler2D s_texture1;" + - "uniform vec4 u_channelFlag;" + - "uniform vec4 u_baseColor;" + - "void main()" + - "{" + - " vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - " vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" + - " float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" + - " col_formask = col_formask * maskVal;" + - " gl_FragColor = col_formask;" + - "}"; - - //テクスチャを使わないデバッグ用の表示 - export const vertexShaderSrcDebug = - "varying lowp vec4 colorVarying;" + - "void main()" + - "{" + - " gl_Position = a_position;vec4 diffuseColor = vec4(0.0, 0.0 , 1.0, 0.5);" + - " colorVarying = diffuseColor ;" + - "}"; - - export const fragmentShaderSrcDebug = - "precision mediump float;" + - "varying lowp vec4 colorVarying;" + - "void main()" + - "{" + - " gl_FragColor = colorVarying;" + - "}"; - } - - /** - * Cubismモデルを描画する直前のWebGLのステートを保持・復帰させるクラス - */ - export class CubismRendererProfile_WebGL - { - - /** - * コンストラクタ - */ - public constructor() - { - this._lastVertexAttribArrayEnabled = new Array(4); - this._lastColorMask = new Array(4); - this._lastBlending = new Array(4); - } - - /** - * WebGLのステートを保持する - */ - public save(): void - { - //-- push state -- - this._lastArrayBufferBinding = this.gl.getParameter(this.gl.ARRAY_BUFFER_BINDING); - this._lastElementArrayBufferBinding = this.gl.getParameter(this.gl.ELEMENT_ARRAY_BUFFER_BINDING); - this._lastProgram = this.gl.getParameter(this.gl.CURRENT_PROGRAM); - - this._lastActiveTexture = this.gl.getParameter(this.gl.ACTIVE_TEXTURE); - this.gl.activeTexture(this.gl.TEXTURE1); // テクスチャユニット1をアクティブに(以降の設定対象とする) - this._lastTexture1Binding2D = this.gl.getParameter(this.gl.TEXTURE_BINDING_2D); - - this.gl.activeTexture(this.gl.TEXTURE0); // テクスチャユニット0をアクティブに(以降の設定対象とする) - this._lastTexture0Binding2D = this.gl.getParameter(this.gl.TEXTURE_BINDING_2D); - - this._lastVertexAttribArrayEnabled[0] = this.gl.getVertexAttrib(0, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - this._lastVertexAttribArrayEnabled[1] = this.gl.getVertexAttrib(1, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - this._lastVertexAttribArrayEnabled[2] = this.gl.getVertexAttrib(2, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - this._lastVertexAttribArrayEnabled[3] = this.gl.getVertexAttrib(3, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - - this._lastScissorTest = this.gl.isEnabled(this.gl.SCISSOR_TEST); - this._lastStencilTest = this.gl.isEnabled(this.gl.STENCIL_TEST); - this._lastDepthTest = this.gl.isEnabled(this.gl.DEPTH_TEST); - this._lastCullFace = this.gl.isEnabled(this.gl.CULL_FACE); - this._lastBlend = this.gl.isEnabled(this.gl.BLEND); - - this._lastFrontFace = this.gl.getParameter(this.gl.FRONT_FACE); - - this._lastColorMask = this.gl.getParameter(this.gl.COLOR_WRITEMASK); - - // backup blending - this._lastBlending[0] = this.gl.getParameter(this.gl.BLEND_SRC_RGB); - this._lastBlending[1] = this.gl.getParameter(this.gl.BLEND_DST_RGB); - this._lastBlending[2] = this.gl.getParameter(this.gl.BLEND_SRC_ALPHA); - this._lastBlending[3] = this.gl.getParameter(this.gl.BLEND_DST_ALPHA); - } - - /** - * 保持したWebGLのステートを復帰させる - */ - public restore(): void - { - this.gl.useProgram(this._lastProgram); - - this.setGLEnableVertexAttribArray(0, this._lastVertexAttribArrayEnabled[0]); - this.setGLEnableVertexAttribArray(1, this._lastVertexAttribArrayEnabled[1]); - this.setGLEnableVertexAttribArray(2, this._lastVertexAttribArrayEnabled[2]); - this.setGLEnableVertexAttribArray(3, this._lastVertexAttribArrayEnabled[3]); - - this.setGLEnable(this.gl.SCISSOR_TEST, this._lastScissorTest); - this.setGLEnable(this.gl.STENCIL_TEST, this._lastStencilTest); - this.setGLEnable(this.gl.DEPTH_TEST, this._lastDepthTest); - this.setGLEnable(this.gl.CULL_FACE, this._lastCullFace); - this.setGLEnable(this.gl.BLEND, this._lastBlend); - - this.gl.frontFace(this._lastFrontFace); - - this.gl.colorMask(this._lastColorMask[0], this._lastColorMask[1], this._lastColorMask[2], this._lastColorMask[3]); - - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._lastArrayBufferBinding); // 前にバッファがバインドされていたら破棄する必要がある - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._lastElementArrayBufferBinding); - - this.gl.activeTexture(this.gl.TEXTURE1); // テクスチャユニット1を復元 - this.gl.bindTexture(this.gl.TEXTURE_2D, this._lastTexture1Binding2D); - - this.gl.activeTexture(this.gl.TEXTURE0); // テクスチャユニット0を復元 - this.gl.bindTexture(this.gl.TEXTURE_2D, this._lastTexture0Binding2D); - - this.gl.activeTexture(this._lastActiveTexture); - - // restore blending - this.gl.blendFuncSeparate(this._lastBlending[0], this._lastBlending[1], this._lastBlending[2], this._lastBlending[3]); - } - - /** - * WebGLの機能の有効・無効をセットする - * @param index 有効・無効にする機能 - * @param enabled trueなら有効にする - */ - private setGLEnable(index: GLenum, enabled: GLboolean): void - { - if(enabled == true) - { - this.gl.enable(index); - } - else - { - this.gl.disable(index); - } - } - - /** - * WebGLのVertex Attribute Array機能の有効・無効をセットする - * - * @param index 有効・無効にする機能 - * @param enabled trueなら有効にする - */ - private setGLEnableVertexAttribArray(index: GLuint, enabled: GLint): void - { - if(enabled) - { - this.gl.enableVertexAttribArray(index); - } - else - { - this.gl.disableVertexAttribArray(index); - } - } - - /** - * glの設定 - */ - public setGl(gl: WebGLRenderingContext): void - { - this.gl = gl; - } - - _lastArrayBufferBinding: GLint; // モデル描画直前の頂点バッファ - _lastElementArrayBufferBinding: GLint; // モデル描画直前のElementバッファ - _lastProgram: GLint; // モデル描画直前のシェーダプログラムバッファ - _lastActiveTexture: GLint; // モデル描画直前のアクティブなテクスチャ - _lastTexture0Binding2D: GLint; // モデル描画直前のテクスチャユニット0 - _lastTexture1Binding2D: GLint; // モデル描画直前のテクスチャユニット1 - _lastVertexAttribArrayEnabled: GLint[]; // モデル描画直前のGL_VERTEX_ATTRIB_ARRAY_ENABLEDパラメータ - _lastScissorTest: GLboolean; // モデル描画直前のGL_SCISSOR_TESTパラメータ - _lastBlend: GLboolean; // モデル描画直前のGL_BLENDパラメータ - _lastStencilTest: GLboolean; // モデル描画直前のGL_STENCIL_TESTパラメータ - _lastDepthTest: GLboolean; // モデル描画直前のGL_DEPTH_TESTパラメータ - _lastCullFace: GLboolean; // モデル描画直前のGL_CULL_FACEパラメータ - _lastFrontFace: GLint; // モデル描画直前のGL_FRONT_FACEパラメータ - _lastColorMask: GLboolean[]; // モデル描画直前のCOLOR_WRITEMASKパラメータ - _lastBlending: GLint[]; // モデル描画直前のカラーブレンディングパラメータ - - gl: WebGLRenderingContext; - } - - /** - * WebGL用の描画命令を実装したクラス - */ - export class CubismRenderer_WebGL extends CubismRenderer - { - /** - * レンダラの初期化処理を実行する - * 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる - * - * @param model モデルのインスタンス - */ - public initialize(model: CubismModel): void - { - if(model.isUsingMasking()) - { - this._clippingManager = new CubismClippingManager_WebGL(); // クリッピングマスク・バッファ前処理方式を初期化 - this._clippingManager.initialize( - model, - model.getDrawableCount(), - model.getDrawableMasks(), - model.getDrawableMaskCounts() - ); - } - - this._sortedDrawableIndexList.resize(model.getDrawableCount(), 0); - - super.initialize(model); // 親クラスの処理を呼ぶ - } - - /** - * WebGLテクスチャのバインド処理 - * CubismRendererにテクスチャを設定し、CubismRenderer内でその画像を参照するためのIndex値を戻り値とする - * @param modelTextureNo セットするモデルテクスチャの番号 - * @param glTextureNo WebGLテクスチャの番号 - */ - public bindTexture(modelTextureNo: number, glTexture: WebGLTexture): void - { - this._textures.setValue(modelTextureNo, glTexture); - } - - /** - * WebGLにバインドされたテクスチャのリストを取得する - * @return テクスチャのリスト - */ - public getBindedTextures(): csmMap - { - return this._textures; - } - - /** - * クリッピングマスクバッファのサイズを設定する - * マスク用のFrameBufferを破棄、再作成する為処理コストは高い - * @param size クリッピングマスクバッファのサイズ - */ - public setClippingMaskBufferSize(size: number) - { - // FrameBufferのサイズを変更するためにインスタンスを破棄・再作成する - this._clippingManager.release(); - this._clippingManager = void 0; - this._clippingManager = null; - - this._clippingManager = new CubismClippingManager_WebGL(); - - this._clippingManager.setClippingMaskBufferSize(size); - - this._clippingManager.initialize( - this.getModel(), - this.getModel().getDrawableCount(), - this.getModel().getDrawableMasks(), - this.getModel().getDrawableMaskCounts() - ); - } - - /** - * クリッピングマスクバッファのサイズを取得する - * @return クリッピングマスクバッファのサイズ - */ - public getClippingMaskBufferSize(): number - { - return this._clippingManager.getClippingMaskBufferSize(); - } - - /** - * コンストラクタ - */ - public constructor() - { - super(); - this._clippingContextBufferForMask = null; - this._clippingContextBufferForDraw = null; - this._clippingManager = new CubismClippingManager_WebGL(); - this.firstDraw = true; - this._rendererProfile = new CubismRendererProfile_WebGL(); - this._textures = new csmMap(); - this._sortedDrawableIndexList = new csmVector(); - - // テクスチャ対応マップの容量を確保しておく - this._textures.prepareCapacity(32, true); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - this._clippingManager.release(); - this._clippingManager = void 0; - this._clippingManager = null; - } - - /** - * モデルを描画する実際の処理 - */ - public doDrawModel(): void - { - //------------ クリッピングマスク・バッファ前処理方式の場合 ------------ - if(this._clippingManager != null) - { - this.preDraw(); - this._clippingManager.setupClippingContext(this.getModel(), this); - } - - // 上記クリッピング処理内でも一度PreDrawを呼ぶので注意!! - this.preDraw(); - - const drawableCount: number = this.getModel().getDrawableCount(); - const renderOrder: Int32Array = this.getModel().getDrawableRenderOrders(); - - // インデックスを描画順でソート - for(let i: number = 0; i < drawableCount; ++i) - { - const order: number = renderOrder[i]; - this._sortedDrawableIndexList.set(order, i); - } - - // 描画 - for(let i: number = 0; i < drawableCount; ++i) - { - const drawableIndex: number = this._sortedDrawableIndexList.at(i); - - // Drawableが表示状態でなければ処理をパスする - if(!this.getModel().getDrawableDynamicFlagIsVisible(drawableIndex)) - { - continue; - } - - // クリッピングマスクをセットする - this.setClippingContextBufferForDraw( - (this._clippingManager != null) - ? (this._clippingManager.getClippingContextListForDraw()).at(drawableIndex) - : null - ); - - this.setIsCulling(this.getModel().getDrawableCulling(drawableIndex)); - - this.drawMesh( - this.getModel().getDrawableTextureIndices(drawableIndex), - this.getModel().getDrawableVertexIndexCount(drawableIndex), - this.getModel().getDrawableVertexCount(drawableIndex), - this.getModel().getDrawableVertexIndices(drawableIndex), - this.getModel().getDrawableVertices(drawableIndex), - this.getModel().getDrawableVertexUvs(drawableIndex), - this.getModel().getDrawableOpacity(drawableIndex), - this.getModel().getDrawableBlendMode(drawableIndex) - ); - } - } - - /** - * [オーバーライド] - * 描画オブジェクト(アートメッシュ)を描画する。 - * ポリゴンメッシュとテクスチャ番号をセットで渡す。 - * @param textureNo 描画するテクスチャ番号 - * @param indexCount 描画オブジェクトのインデックス値 - * @param vertexCount ポリゴンメッシュの頂点数 - * @param indexArray ポリゴンメッシュのインデックス配列 - * @param vertexArray ポリゴンメッシュの頂点配列 - * @param uvArray uv配列 - * @param opacity 不透明度 - * @param colorBlendMode カラー合成タイプ - */ - public drawMesh(textureNo: number, indexCount: number, vertexCount: number, - indexArray: Uint16Array, vertexArray: Float32Array, uvArray: Float32Array, - opacity: number, colorBlendMode: CubismRenderer.CubismBlendMode): void - { - // 裏面描画の有効・無効 - if(this.isCulling()) - { - this.gl.enable(this.gl.CULL_FACE); - } - else - { - this.gl.disable(this.gl.CULL_FACE); - } - - this.gl.frontFace(this.gl.CCW); // Cubism3 OpenGLはマスク・アートメッシュ共にCCWが表面 - - let modelColorRGBA: CubismRenderer.CubismTextureColor = this.getModelColor(); - - if(this.getClippingContextBufferForMask() == null) // マスク生成時以外 - { - modelColorRGBA.A *= opacity; - if(this.isPremultipliedAlpha()) - { - modelColorRGBA.R *= modelColorRGBA.A; - modelColorRGBA.G *= modelColorRGBA.A; - modelColorRGBA.B *= modelColorRGBA.A; - } - } - - let drawtexture: WebGLTexture; // シェーダに渡すテクスチャ - - // テクスチャマップからバインド済みテクスチャIDを取得 - // バインドされていなければダミーのテクスチャIDをセットする - if(this._textures.getValue(textureNo) != null) - { - drawtexture = this._textures.getValue(textureNo); - } - else - { - drawtexture = null; - } - - CubismShader_WebGL.getInstance().setupShaderProgram( - this, drawtexture, vertexCount, vertexArray, indexArray, uvArray, - opacity, colorBlendMode, modelColorRGBA, this.isPremultipliedAlpha(), - this.getMvpMatrix() - ); - - // ポリゴンメッシュを描画する - this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_SHORT, 0); - - // 後処理 - this.gl.useProgram(null); - this.setClippingContextBufferForDraw(null); - this.setClippingContextBufferForMask(null); - } - - /** - * レンダラが保持する静的なリソースを解放する - * WebGLの静的なシェーダープログラムを解放する - */ - public static doStaticRelease(): void - { - CubismShader_WebGL.deleteInstance(); - } - - /** - * 描画開始時の追加処理 - * モデルを描画する前にクリッピングマスクに必要な処理を実装している - */ - public preDraw(): void - { - if(this.firstDraw) - { - this.firstDraw = false; - - // 拡張機能を有効にする - this._anisortopy = this.gl.getExtension("EXT_texture_filter_anisotropic") || - this.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic") || - this.gl.getExtension("MOZ_EXT_texture_filter_anisotropic"); - } - - this.gl.disable(this.gl.SCISSOR_TEST); - this.gl.disable(this.gl.STENCIL_TEST); - this.gl.disable(this.gl.DEPTH_TEST); - - // カリング(1.0beta3) - this.gl.frontFace(this.gl.CW); - - this.gl.enable(this.gl.BLEND); - this.gl.colorMask(true, true, true, true); - - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null); // 前にバッファがバインドされていたら破棄する必要がある - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null); - } - - /** - * モデル描画直前のWebGLのステートを保持する - */ - public saveProfile(): void - { - this._rendererProfile.save(); - } - - /** - * モデル描画直前のWebGLのステートを保持する - */ - public restoreProfile(): void - { - this._rendererProfile.restore(); - } - - /** - * マスクテクスチャに描画するクリッピングコンテキストをセットする - */ - public setClippingContextBufferForMask(clip: CubismClippingContext) - { - this._clippingContextBufferForMask = clip; - } - - /** - * マスクテクスチャに描画するクリッピングコンテキストを取得する - * @return マスクテクスチャに描画するクリッピングコンテキスト - */ - public getClippingContextBufferForMask(): CubismClippingContext - { - return this._clippingContextBufferForMask; - } - - /** - * 画面上に描画するクリッピングコンテキストをセットする - */ - public setClippingContextBufferForDraw(clip: CubismClippingContext): void - { - this._clippingContextBufferForDraw = clip; - } - - /** - * 画面上に描画するクリッピングコンテキストを取得する - * @return 画面上に描画するクリッピングコンテキスト - */ - public getClippingContextBufferForDraw(): CubismClippingContext - { - return this._clippingContextBufferForDraw; - } - - /** - * glの設定 - */ - public startUp(gl: WebGLRenderingContext): void - { - this.gl = gl; - this._rendererProfile.setGl(gl); - this._clippingManager.setGL(gl); - CubismShader_WebGL.getInstance().setGl(gl); - } - - _textures: csmMap; // モデルが参照するテクスチャとレンダラでバインドしているテクスチャとのマップ - _sortedDrawableIndexList: csmVector; // 描画オブジェクトのインデックスを描画順に並べたリスト - _rendererProfile: CubismRendererProfile_WebGL; // WebGLのステートを保持するオブジェクト - _clippingManager: CubismClippingManager_WebGL; // クリッピングマスク管理オブジェクト - _clippingContextBufferForMask: CubismClippingContext; // マスクテクスチャに描画するためのクリッピングコンテキスト - _clippingContextBufferForDraw: CubismClippingContext; // 画面上描画するためのクリッピングコンテキスト - firstDraw: boolean; - gl: WebGLRenderingContext; // webglコンテキスト - } - -} \ No newline at end of file diff --git a/Framework/tsconfig.json b/Framework/tsconfig.json deleted file mode 100644 index 2bc7bcc..0000000 --- a/Framework/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "sourceMap": true, - "target": "es5", - "module": "es2015", - "moduleResolution": "node", - "lib": [ - "dom", - "es2018" - ], - "noImplicitAny": true - } -} \ No newline at end of file diff --git a/Framework/type/csmmap.ts b/Framework/type/csmmap.ts deleted file mode 100644 index 6dad45f..0000000 --- a/Framework/type/csmmap.ts +++ /dev/null @@ -1,360 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import { CubismLogDebug } from "../utils/cubismdebug"; - -export namespace Live2DCubismFramework -{ - /** - * Key-Valueのペアを定義するクラス - * csmMapクラスの内部データで使用する。 - */ - export class csmPair<_KeyT, _ValT> - { - /** - * コンストラクタ - * @param key Keyとしてセットする値 - * @param value Valueとしてセットする値 - */ - public constructor(key?: _KeyT, value?: _ValT) - { - this.first = (key == undefined) - ? null - : key; - - this.second = (value == undefined) - ? null - : value; - } - - public first: _KeyT; // keyとして用いる変数 - public second: _ValT; // valueとして用いる変数 - } - - /** - * マップ型 - */ - export class csmMap<_KeyT, _ValT> - { - /** - * 引数付きコンストラクタ - * @param size 初期化時点で確保するサイズ - */ - public constructor(size?: number) - { - if(size != undefined) - { - if(size < 1) - { - this._keyValues = new Array(); - this._dummyValue = null; - this._size = 0; - } - else - { - this._keyValues = new Array(size); - this._size = size; - } - } - else - { - this._keyValues = new Array(); - this._dummyValue = null; - this._size = 0; - } - } - - /** - * デストラクタ - */ - public release() - { - this.clear(); - } - - /** - * キーを追加する - * @param key 新たに追加するキー - */ - public appendKey(key: _KeyT): void - { - // 新しくKey/Valueのペアを作る - this.prepareCapacity(this._size + 1, false); // 1つ以上入る隙間を作る - // 新しいkey/valueのインデックスは_size - - this._keyValues[this._size] = new csmPair<_KeyT, _ValT>(key); - this._size += 1; - } - - /** - * 添字演算子[key]のオーバーロード(get) - * @param key 添字から特定されるValue値 - */ - public getValue(key: _KeyT): _ValT - { - let found = -1; - - for(let i: number = 0; i < this._size; i++) - { - if(this._keyValues[i].first == key) - { - found = i; - break; - } - } - - if(found >= 0) - { - return this._keyValues[found].second; - } - else - { - this.appendKey(key); // 新規キーを追加 - return this._keyValues[this._size - 1].second; - } - } - - /** - * 添字演算子[key]のオーバーロード(set) - * @param key 添字から特定されるValue値 - * @param value 代入するValue値 - */ - public setValue(key: _KeyT, value: _ValT): void - { - let found = -1; - - for(let i: number = 0; i < this._size; i++) - { - if(this._keyValues[i].first == key) - { - found = i; - break; - } - } - - if(found >= 0) - { - this._keyValues[found].second = value; - } - else - { - this.appendKey(key); // 新規キーを追加 - this._keyValues[this._size - 1].second = value; - } - } - - /** - * 引数で渡したKeyを持つ要素が存在するか - * @param key 存在を確認するkey - * @return true 引数で渡したkeyを持つ要素が存在する - * @return false 引数で渡したkeyを持つ要素が存在しない - */ - public isExist(key: _KeyT): boolean - { - for(let i: number = 0; i < this._size; i++) - { - if(this._keyValues[i].first == key) - { - return true; - } - } - return false; - } - - /** - * keyValueのポインタを全て解放する - */ - public clear(): void - { - this._keyValues = void 0; - this._keyValues = null; - this._keyValues = new Array(); - - this._size = 0; - } - - /** - * コンテナのサイズを取得する - * - * @return コンテナのサイズ - */ - public getSize(): number - { - return this._size; - } - - /** - * コンテナのキャパシティを確保する - * @param newSize 新たなキャパシティ。引数の値が現在のサイズ未満の場合は何もしない。 - * @param fitToSize trueなら指定したサイズに合わせる。falseならサイズを2倍確保しておく。 - */ - public prepareCapacity(newSize: number, fitToSize: boolean): void - { - if(newSize > this._keyValues.length) - { - if(this._keyValues.length == 0) - { - if(!fitToSize && newSize < csmMap.DefaultSize) newSize = csmMap.DefaultSize; - this._keyValues.length = newSize; - } - else - { - if(!fitToSize && newSize < this._keyValues.length * 2) newSize = this._keyValues.length * 2; - this._keyValues.length = newSize; - } - } - } - - /** - * コンテナの先頭要素を返す - */ - public begin(): csmMap.iterator<_KeyT, _ValT> - { - let ite: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, 0); - return ite; - } - - /** - * コンテナの終端要素を返す - */ - public end(): csmMap.iterator<_KeyT, _ValT> - { - let ite: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, this._size); // 終了 - return ite; - } - - /** - * コンテナから要素を削除する - * - * @param ite 削除する要素 - */ - public erase(ite: csmMap.iterator<_KeyT, _ValT>): csmMap.iterator<_KeyT, _ValT> - { - let index: number = ite._index; - if(index < 0 || this._size <= index) - { - return ite; // 削除範囲外 - } - - // 削除 - this._keyValues.splice(index, 1); - --this._size; - - let ite2: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, index); // 終了 - return ite2; - } - - /** - * コンテナの値を32ビット符号付き整数型でダンプする - */ - public dumpAsInt() - { - for(let i = 0; i < this._size; i++) - { - CubismLogDebug("{0} ,", this._keyValues[i]); - CubismLogDebug("\n"); - } - } - - public static readonly DefaultSize = 10; // コンテナの初期化のデフォルトサイズ - public _keyValues: csmPair<_KeyT, _ValT>[];// key-valueペアの配列 - public _dummyValue: _ValT; // 空の値を返す為のダミー - public _size: number; // コンテナの要素数 - } - - export namespace csmMap - { - /** - * csmMapのイテレータ - */ - export class iterator<_KeyT, _ValT> - { - /** - * コンストラクタ - */ - constructor(v?: csmMap<_KeyT, _ValT>, idx?: number) - { - this._map = (v != undefined) - ? v - : new csmMap<_KeyT, _ValT>(); - - this._index = (idx != undefined) - ? idx - : 0; - } - - /** - * =演算子のオーバーロード - */ - public set(ite: iterator<_KeyT, _ValT>): iterator<_KeyT, _ValT> - { - this._index = ite._index; - this._map = ite._map; - return this; - } - - /** - * 前置き++演算子のオーバーロード - */ - public preIncrement(): iterator<_KeyT, _ValT> - { - ++this._index; - return this; - } - - /** - * 前置き--演算子のオーバーロード - */ - public preDecrement(): iterator<_KeyT, _ValT> - { - --this._index; - return this; - } - - /** - * 後置き++演算子のオーバーロード - */ - public increment(): iterator<_KeyT, _ValT> - { - let iteold = new iterator<_KeyT, _ValT>(this._map, this._index++); // 古い値を保存 - this._map = iteold._map; - this._index = iteold._index; - return this; - } - - /** - * 後置き--演算子のオーバーロード - */ - public decrement(): iterator<_KeyT, _ValT> - { - let iteold = new iterator<_KeyT, _ValT>(this._map, this._index); // 古い値を保存 - this._map = iteold._map; - this._index = iteold._index; - return this; - } - - /** - * *演算子のオーバーロード - */ - public ptr(): csmPair<_KeyT, _ValT> - { - return this._map._keyValues[this._index]; - } - - /** - * !=演算 - */ - public notEqual(ite: iterator<_KeyT, _ValT>): boolean - { - return (this._index != ite._index) || (this._map != ite._map); - } - - _index: number; // コンテナのインデックス値 - _map: csmMap<_KeyT, _ValT>; // コンテナ - } - } -} \ No newline at end of file diff --git a/Framework/type/csmrectf.ts b/Framework/type/csmrectf.ts deleted file mode 100644 index 0c8e30d..0000000 --- a/Framework/type/csmrectf.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -export namespace Live2DCubismFramework -{ - /** - * 矩形形状(座標・長さはfloat値)を定義するクラス - */ - export class csmRect - { - /** - * コンストラクタ - * @param x 左端X座標 - * @param y 上端Y座標 - * @param w 幅 - * @param h 高さ - */ - public constructor(x?: number, y?: number, w?: number, h?: number) - { - this.x = x; - this.y = y; - this.width = w; - this.height = h; - } - - /** - * 矩形中央のX座標を取得する - */ - public getCenterX(): number - { - return this.x + 0.5 * this.width; - } - - /** - * 矩形中央のY座標を取得する - */ - public getCenterY(): number - { - return this.y + 0.5 * this.height; - } - - /** - * 右側のX座標を取得する - */ - public getRight(): number - { - return this.x + this.width; - } - - /** - * 下端のY座標を取得する - */ - public getBottom(): number - { - return this.y + this.height; - } - - /** - * 矩形に値をセットする - * @param r 矩形のインスタンス - */ - public setRect(r: csmRect): void - { - this.x = r.x; - this.y = r.y; - this.width = r.width; - this.height = r.height; - } - - /** - * 矩形中央を軸にして縦横を拡縮する - * @param w 幅方向に拡縮する量 - * @param h 高さ方向に拡縮する量 - */ - public expand(w: number, h: number) - { - this.x -= w; - this.y -= h; - this.width += w * 2.0; - this.height += h * 2.0; - } - - public x: number; // 左端X座標 - public y: number; // 上端Y座標 - public width: number; // 幅 - public height: number; // 高さ - } -} \ No newline at end of file diff --git a/Framework/type/csmstring.ts b/Framework/type/csmstring.ts deleted file mode 100644 index 23bc018..0000000 --- a/Framework/type/csmstring.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -export namespace Live2DCubismFramework -{ - /** - * 文字列クラス。 - */ - export class csmString - { - /** - * 文字列を後方に追加する - * - * @param c 追加する文字列 - * @return 更新された文字列 - */ - public append(c: string, length?: number): csmString - { - this.s += (length !== undefined) - ? c.substr(0, length) - : c; - - return this; - } - - /** - * 文字サイズを拡張して文字を埋める - * @param length 拡張する文字数 - * @param v 埋める文字 - * @return 更新された文字列 - */ - public expansion(length: number, v: string): csmString - { - let ret: csmString = this; - - for(let i = 0; i < length; i++) - { - ret.append(v); - } - - return ret; - } - - /** - * 文字列の長さをバイト数で取得する - */ - public getBytes(): number - { - return encodeURIComponent(this.s) .replace(/%../g, "x").length; - } - - /** - * 文字列の長さを返す - */ - public getLength(): number - { - return this.s.length; - } - - /** - * 文字列比較 < - * @param s 比較する文字列 - * @return true: 比較する文字列より小さい - * @return false: 比較する文字列より大きい - */ - public isLess(s: csmString): boolean - { - return this.s < s.s; - } - - /** - * 文字列比較 > - * @param s 比較する文字列 - * @return true: 比較する文字列より大きい - * @return false: 比較する文字列より小さい - */ - public isGreat(s: csmString): boolean - { - return this.s > s.s; - } - - /** - * 文字列比較 == - * @param s 比較する文字列 - * @return true: 比較する文字列と等しい - * @return false: 比較する文字列と異なる - */ - public isEqual(s: string): boolean - { - return this.s == s; - } - - /** - * 文字列が空かどうか - * @return true: 空の文字列 - * @return false: 値が設定されている - */ - public isEmpty(): boolean - { - return this.s.length == 0; - } - - /** - * 引数付きコンストラクタ - */ - public constructor(s: string) - { - this.s = s; - } - - s: string; - } -} \ No newline at end of file diff --git a/Framework/type/csmvector.ts b/Framework/type/csmvector.ts deleted file mode 100644 index 746d0a8..0000000 --- a/Framework/type/csmvector.ts +++ /dev/null @@ -1,396 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -export namespace Live2DCubismFramework -{ - /** - * ベクター型(可変配列型) - */ - export class csmVector - { - /** - * 引数付きコンストラクタ - * @param iniitalCapacity 初期化後のキャパシティ。データサイズは_capacity * sizeof(T) - * @param zeroClear trueなら初期化時に確保した領域を0で埋める - */ - constructor(initialCapacity: number = 0) - { - if(initialCapacity < 1) - { - this._ptr = new Array(); - this._capacity = 0; - this._size = 0; - } - else - { - this._ptr = new Array(initialCapacity); - this._capacity = initialCapacity; - this._size = 0; - } - } - - /** - * インデックスで指定した要素を返す - */ - public at(index: number): T - { - return this._ptr[index]; - } - - /** - * 要素をセット - * @param index 要素をセットするインデックス - * @param value セットする要素 - */ - public set(index: number, value: T): void - { - this._ptr[index] = value; - } - - /** - * コンテナを取得する - */ - public get(offset: number = 0): T[] - { - let ret: T[] = new Array(); - for(let i = offset; i < this._size; i++) - { - ret.push(this._ptr[i]); - } - return ret; - } - - /** - * pushBack処理、コンテナに新たな要素を追加する - * @param value PushBack処理で追加する値 - */ - public pushBack(value: T): void - { - if(this._size >= this._capacity) - { - this.prepareCapacity(this._capacity == 0 ? csmVector.s_defaultSize : this._capacity * 2); - } - - this._ptr[this._size++] = value; - } - - /** - * コンテナの全要素を解放する - */ - public clear(): void - { - this._ptr.length = 0; - this._size = 0; - } - - /** - * コンテナの要素数を返す - * @return コンテナの要素数 - */ - public getSize(): number - { - return this._size; - } - - /** - * コンテナの全要素に対して代入処理を行う - * @param newSize 代入処理後のサイズ - * @param value 要素に代入する値 - */ - public assign(newSize: number, value: T): void - { - let curSize = this._size; - - if(curSize < newSize) - { - this.prepareCapacity(newSize); // capacity更新 - } - - for(let i: number = 0; i < newSize; i++) - { - this._ptr[i] = value; - } - - this._size = newSize; - } - - /** - * サイズ変更 - */ - public resize(newSize: number, value: T = null): void - { - this.updateSize(newSize, value, true); - } - - /** - * サイズ変更 - */ - public updateSize(newSize: number, value: any = null, callPlacementNew: boolean = true): void - { - let curSize: number = this._size; - - if(curSize < newSize) - { - this.prepareCapacity(newSize); // capacity更新 - - if(callPlacementNew) - { - for(let i: number = this._size; i < newSize; i++) - { - if(typeof value == 'function') // new - { - this._ptr[i] = JSON.parse(JSON.stringify(new value())); - } - else // プリミティブ型なので値渡し - { - this._ptr[i] = value; - } - } - } - else - { - for(let i: number = this._size; i < newSize; i++) - { - this._ptr[i] = value; - } - } - } - else - { - // newSize <= this._size - //--- - let sub = this._size - newSize; - this._ptr.splice(this._size - sub, sub); // 不要なので破棄する - } - this._size = newSize; - } - - /** - * コンテナにコンテナ要素を挿入する - * @param position 挿入する位置 - * @param begin 挿入するコンテナの開始位置 - * @param end 挿入するコンテナの終端位置 - */ - public insert(position: csmVector.iterator, begin: csmVector.iterator, end: csmVector.iterator): void - { - let dstSi: number = position._index; - let srcSi: number = begin._index; - let srcEi: number = end._index; - - let addCount: number = srcEi - srcSi; - - this.prepareCapacity(this._size + addCount); - - // 挿入用の既存データをシフトして隙間を作る - let addSize = this._size - dstSi; - if(addSize > 0) - { - for(let i: number = 0; i < addSize; i++) - { - this._ptr.splice(dstSi + i, 0, null); - } - } - - for(let i: number = srcSi; i < srcEi; i++, dstSi++) - { - this._ptr[dstSi] = begin._vector._ptr[i]; - } - - this._size = this._size + addCount; - } - - /** - * コンテナからインデックスで指定した要素を削除する - * @param index インデックス値 - * @return true 削除実行 - * @return false 削除範囲外 - */ - public remove(index: number): boolean - { - if(index < 0 || this._size <= index) - { - return false; // 削除範囲外 - } - - this._ptr.splice(index, 1); - --this._size; - - return true; - } - - /** - * コンテナから要素を削除して他の要素をシフトする - * @param ite 削除する要素 - */ - public erase(ite: csmVector.iterator): csmVector.iterator - { - let index: number = ite._index; - if(index < 0 || this._size <= index) - { - return ite; // 削除範囲外 - } - - // 削除 - this._ptr.splice(index, 1); - --this._size; - - let ite2: csmVector.iterator = new csmVector.iterator(this, index); // 終了 - return ite2; - } - - /** - * コンテナのキャパシティを確保する - * @param newSize 新たなキャパシティ。引数の値が現在のサイズ未満の場合は何もしない. - */ - public prepareCapacity(newSize: number): void - { - if(newSize > this._capacity) - { - if(this._capacity == 0) - { - this._ptr = new Array(newSize); - this._capacity = newSize; - } - else - { - this._ptr.length = newSize; - this._capacity = newSize; - } - } - } - - /** - * コンテナの先頭要素を返す - */ - public begin(): csmVector.iterator - { - let ite: csmVector.iterator = (this._size == 0) - ? this.end() - : new csmVector.iterator(this, 0); - return ite; - } - - /** - * コンテナの終端要素を返す - */ - public end(): csmVector.iterator - { - let ite: csmVector.iterator = new csmVector.iterator(this, this._size); - return ite; - } - - public getOffset(offset: number): csmVector - { - let newVector = new csmVector(); - newVector._ptr = this.get(offset); - newVector._size = this.get(offset).length; - newVector._capacity = this.get(offset).length; - - return newVector; - } - - _ptr: T[]; // コンテナの先頭アドレス - _size: number; // コンテナの要素数 - _capacity: number; // コンテナのキャパシティ - - static readonly s_defaultSize = 10; // コンテナ初期化のデフォルトサイズ - } - - export namespace csmVector - { - export class iterator - { - /** - * コンストラクタ - */ - public constructor(v?: csmVector, index?: number) - { - this._vector = (v != undefined) ? v : null; - this._index = (index != undefined) ? index : 0; - } - - /** - * 代入 - */ - public set(ite: iterator): iterator - { - this._index = ite._index; - this._vector = ite._vector; - return this; - } - - /** - * 前置き++演算 - */ - public preIncrement(): iterator - { - ++this._index; - return this; - } - - /** - * 前置き--演算 - */ - public preDecrement(): iterator - { - --this._index; - return this; - } - - /** - * 後置き++演算子 - */ - public increment(): iterator - { - let iteold = new iterator(this._vector, this._index++); - this._vector = iteold._vector; - this._index = iteold._index; - return this; - } - - /** - * 後置き--演算子 - */ - public decrement(): iterator - { - let iteold = new iterator(this._vector, this._index--); // 古い値を保存 - this._vector = iteold._vector; - this._index = iteold._index; - return this; - } - - /** - * ptr - */ - public ptr(): T - { - return this._vector._ptr[this._index]; - } - - /** - * =演算子のオーバーロード - */ - public substitution(ite: iterator): iterator - { - this._index = ite._index; - this._vector = ite._vector; - return this; - } - - /** - * !=演算子のオーバーロード - */ - public notEqual(ite: iterator): boolean - { - return (this._index != ite._index) || (this._vector != ite._vector); - } - - _index: number; // コンテナのインデックス値 - _vector: csmVector; // コンテナ - } - } -} \ No newline at end of file diff --git a/Framework/utils/cubismdebug.ts b/Framework/utils/cubismdebug.ts deleted file mode 100644 index e8e8f4a..0000000 --- a/Framework/utils/cubismdebug.ts +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as live2dcubismframework, Option} from "../live2dcubismframework"; -import CubismFramework = live2dcubismframework.CubismFramework; -import { CSM_LOG_LEVEL, CSM_LOG_LEVEL_VERBOSE, CSM_LOG_LEVEL_DEBUG, CSM_LOG_LEVEL_INFO, CSM_LOG_LEVEL_WARNING, CSM_LOG_LEVEL_ERROR } from "../cubismframeworkconfig"; - -export const CubismLogPrint = (level: Option.LogLevel, fmt: string, ... args: any[]) => -{ - Live2DCubismFramework.CubismDebug.print(level, "[CSM]" + fmt, args); -} - -export const CubismLogPrintIn = (level: Option.LogLevel, fmt: string, ... args: any[]) => -{ - CubismLogPrint(level, fmt + "\n", args); -} - -export let CSM_ASSERT = (expr: any) => -{ - console.assert(expr); -}; - - -export let CubismLogVerbose = (fmt: string, ... args: any[]) => {}; -export let CubismLogDebug = (fmt: string, ... args: any[]) => {}; -export let CubismLogInfo = (fmt: string, ... args: any[]) => {}; -export let CubismLogWarning = (fmt: string, ... args: any[]) => {}; -export let CubismLogError = (fmt: string, ... args: any[]) => {}; - -if(CSM_LOG_LEVEL <= CSM_LOG_LEVEL_VERBOSE) -{ - CubismLogVerbose = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Verbose, "[V]" + fmt, args); - }; - - CubismLogDebug = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Debug, "[D]" + fmt, args); - }; - - CubismLogInfo = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); - }; - - CubismLogWarning = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); - }; - - CubismLogError = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); - }; -} -else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_DEBUG) -{ - CubismLogDebug = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Debug, "[D]" + fmt, args); - }; - - CubismLogInfo = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); - }; - - CubismLogWarning = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); - }; - - CubismLogError = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); - }; -} -else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_INFO) -{ - CubismLogInfo = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); - }; - - CubismLogWarning = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); - }; - - CubismLogError = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); - }; -} -else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_WARNING) -{ - CubismLogWarning = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); - }; - - CubismLogError = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); - }; -} -else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_ERROR) -{ - CubismLogError = (fmt: string, ... args: any[]) => - { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); - }; -} - -//------------ LIVE2D NAMESPACE ------------ -export namespace Live2DCubismFramework -{ - - /** - * デバッグ用のユーティリティクラス。 - * ログの出力、バイトのダンプなど - */ - export class CubismDebug - { - /** - * ログを出力する。第一引数にログレベルを設定する。 - * CubismFramework.initialize()時にオプションで設定されたログ出力レベルを下回る場合はログに出さない。 - * - * @param logLevel ログレベルの設定 - * @param format 書式付き文字列 - * @param ... args 可変長引数 - */ - public static print(logLevel: Option.LogLevel, format: string, ... args: any[]): void - { - // オプションで設定されたログ出力レベルを下回る場合はログに出さない - // if(logLevel < CubismFramework.getLoggingLevel()) - // { - // return; - // } - - // TODO - // const Core::csmLogFunction logPrint = CubismFramework::CoreLogFunction; - - // if (!logPrint) - // return; - - let buffer: string = format; - buffer = buffer.replace( - /\{(\d+)\}/g, - (m, k) => // m="{0}", k="0" - { - return args[k]; - } - ); - - // logPrint(buffer); - } - - /** - * データから指定した長さだけダンプ出力する。 - * CubismFramework.initialize()時にオプションで設定されたログ出力レベルを下回る場合はログに出さない。 - * - * @param logLevel ログレベルの設定 - * @param data ダンプするデータ - * @param length ダンプする長さ - */ - public static dumpBytes(logLevel: Option.LogLevel, data: Uint8Array, length: number): void - { - for (let i: number = 0; i < length; i++) - { - if (i % 16 == 0 && i > 0) this.print(logLevel, "\n"); - else if (i % 8 == 0 && i > 0) this.print(logLevel, " "); - this.print(logLevel, "{0} ", (data[i] & 0xFF)); - } - - this.print(logLevel, "\n"); - } - - /** - * private コンストラクタ - */ - private constructor() - { - - } - } -} - -//------------ LIVE2D NAMESPACE ------------ \ No newline at end of file diff --git a/Framework/utils/cubismjson.ts b/Framework/utils/cubismjson.ts deleted file mode 100644 index f28dfaf..0000000 --- a/Framework/utils/cubismjson.ts +++ /dev/null @@ -1,1249 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -import {Live2DCubismFramework as csmstring} from "../type/csmstring"; -import {Live2DCubismFramework as csmmap} from "../type/csmmap"; -import {Live2DCubismFramework as csmvector} from "../type/csmvector"; -import {CubismLogInfo} from "./cubismdebug"; -import {strtod} from "../live2dcubismframework"; -import csmVector = csmvector.csmVector; -import csmMap = csmmap.csmMap; -import csmString = csmstring.csmString; - -export namespace Live2DCubismFramework -{ - // StaticInitializeNotForClientCall()で初期化する - const CSM_JSON_ERROR_TYPE_MISMATCH: string = "Error: type mismatch"; - const CSM_JSON_ERROR_INDEX_OF_BOUNDS: string = "Error: index out of bounds"; - - /** - * パースしたJSONエレメントの要素の基底クラス。 - */ - export abstract class Value - { - /** - * コンストラクタ - */ - public constructor() - { - - } - - /** - * 要素を文字列型で返す(csmString型) - */ - public abstract getString(defaultValue?: string, indent?: string): string; - - /** - * 要素を文字列型で返す(string) - */ - public getRawString(defaultValue?: string, indent?: string): string - { - return this.getString(defaultValue, indent); - } - - /** - * 要素を数値型で返す(number) - */ - public toInt(defaultValue: number = 0): number - { - return defaultValue; - } - - /** - * 要素を数値型で返す(number) - */ - public toFloat(defaultValue: number = 0): number - { - return defaultValue; - } - - /** - * 要素を真偽値で返す(boolean) - */ - public toBoolean(defaultValue: boolean = false): boolean - { - return defaultValue; - } - - /** - * サイズを返す - */ - public getSize(): number - { - return 0; - } - - /** - * 要素を配列で返す(Value[]) - */ - public getArray(defaultValue: Value[] = null): Value[] - { - return defaultValue; - } - - /** - * 要素をコンテナで返す(array) - */ - public getVector(defaultValue?: csmVector): csmVector - { - return defaultValue; - } - - /** - * 要素をマップで返す(csmMap) - */ - public getMap(defaultValue?: csmMap): csmMap - { - return defaultValue; - } - - /** - * マップのキー一覧をコンテナで返す - * - * @return マップのキーの一覧 - */ - public getKeys(): csmVector - { - return Value.s_dummyKeys; - } - - /** - * Valueの種類がエラー値ならtrue - */ - public isError(): boolean - { - return false; - } - - /** - * Valueの種類がnullならtrue - */ - public isNull(): boolean - { - return false; - } - - /** - * Valueの種類が真偽値ならtrue - */ - public isBool(): boolean - { - return false; - } - - /** - * Valueの種類が数値型ならtrue - */ - public isFloat(): boolean - { - return false; - } - - /** - * Valueの種類が文字列ならtrue - */ - public isString(): boolean - { - return false; - } - - /** - * Valueの種類が配列ならtrue - */ - public isArray(): boolean - { - return false; - } - - /** - * Valueの種類がマップ型ならtrue - */ - public isMap(): boolean - { - return false; - } - - /** - * 引数の値と等しければtrue - */ - public equals(value: csmString): boolean; - public equals(value: string): boolean; - public equals(value: number): boolean; - public equals(value: boolean): boolean; - public equals(value: any):boolean - { - return false; - } - - /** - * Valueの値が静的ならtrue、静的なら解放しない - */ - public isStatic(): boolean - { - return false; - } - - /** - * Valueにエラー値をセットする - */ - public setErrorNotForClientCall(errorStr: string): Value - { - return Value.errorValue; - } - - /** - * 初期化用メソッド - */ - public static staticInitializeNotForClientCall(): void - { - JsonBoolean.trueValue = new JsonBoolean(true); - JsonBoolean.falseValue = new JsonBoolean(false); - - JsonError.errorValue = new JsonError("ERROR", true); - this.nullValue = new JsonNullvalue(); - - Value.s_dummyKeys = new csmVector(); - } - - /** - * リリース用メソッド - */ - public static staticReleaseNotForClientCall(): void - { - JsonBoolean.trueValue = void 0; - JsonBoolean.falseValue = void 0; - JsonError.errorValue = void 0; - Value.nullValue = void 0; - Value.s_dummyKeys = void 0; - - JsonBoolean.trueValue = null; - JsonBoolean.falseValue = null; - JsonError.errorValue = null; - Value.nullValue = null; - Value.s_dummyKeys = null; - } - - protected _stringBuffer: string; // 文字列バッファ - - private static s_dummyKeys: csmVector; // ダミーキー - - public static errorValue: Value; // 一時的な返り値として返すエラー。 CubismFramework::Disposeするまではdeleteしない - public static nullValue: Value; // 一時的な返り値として返すNULL。 CubismFramework::Disposeするまではdeleteしない - } - - /** - * Ascii文字のみ対応した最小限の軽量JSONパーサ。 - * 仕様はJSONのサブセットとなる。 - * 設定ファイル(model3.json)などのロード用 - * - * [未対応項目] - * ・日本語などの非ASCII文字 - * ・eによる指数表現 - */ - export class CubismJson - { - /** - * コンストラクタ - */ - public constructor(buffer?: ArrayBuffer, length?: number) - { - this._error = null; - this._lineCount = 0; - this._root = null; - - if(buffer != undefined) - { - this.parseBytes(buffer, length); - } - } - - /** - * バイトデータから直接ロードしてパースする - * - * @param buffer バッファ - * @param size バッファサイズ - * @return CubismJsonクラスのインスタンス。失敗したらNULL - */ - public static create(buffer: ArrayBuffer, size: number) - { - let json = new CubismJson(); - const succeeded: boolean = json.parseBytes(buffer, size); - - if(!succeeded) - { - CubismJson.delete(json); - console.log("parseBytes is failed"); - return null; - } - else - { - return json; - } - } - - /** - * パースしたJSONオブジェクトの解放処理 - * - * @param instance CubismJsonクラスのインスタンス - */ - public static delete(instance: CubismJson) - { - instance = void 0; - instance = null; - } - - /** - * パースしたJSONのルート要素を返す - */ - public getRoot(): Value - { - return this._root; - } - - /** - * JSONのパースを実行する - * @param buffer パース対象のデータバイト - * @param size データバイトのサイズ - * return true : 成功 - * return false: 失敗 - */ - public parseBytes(buffer: ArrayBuffer, size: number): boolean - { - let endPos: number[] = new Array(1); // 参照渡しにするため配列 - let decodeBuffer: string = new TextDecoder('utf-8').decode(buffer); - this._root = this.parseValue(decodeBuffer, size, 0, endPos); - - if(this._error) - { - console.log(this._error); - let strbuf: string = '\0'; - strbuf = "Json parse error : @line " + (this._lineCount + 1) + "\n"; - this._root = new JsonString(strbuf); - - CubismLogInfo("{0}", this._root.getRawString()); - return false; - } - else if(this._root == null) - { - this._root = new JsonError(new csmString(this._error), false); // rootは解放されるのでエラーオブジェクトを別途作成する - return false; - } - return true; - } - - /** - * パース時のエラー値を返す - */ - public getParseError(): string - { - return this._error; - } - - /** - * ルート要素の次の要素がファイルの終端だったらtrueを返す - */ - public checkEndOfFile(): boolean - { - return this._root.getArray()[1].equals("EOF"); - } - - /** - * JSONエレメントからValue(float,String,Value*,Array,null,true,false)をパースする - * エレメントの書式に応じて内部でParseString(), ParseObject(), ParseArray()を呼ぶ - * - * @param buffer JSONエレメントのバッファ - * @param length パースする長さ - * @param begin パースを開始する位置 - * @param outEndPos パース終了時の位置 - * @return パースから取得したValueオブジェクト - */ - protected parseValue(buffer: string, length: number, begin: number, outEndPos: number[]) - { - if (this._error) return null; - - let o: Value = null; - let i: number = begin; - let f: number; - - for (; i < length; i++) - { - let c: string = buffer[i]; - switch(c) - { - case '-': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - let afterString: string[] = new Array(1); // 参照渡しにするため - f = strtod(buffer.slice(i), afterString); - outEndPos[0] = buffer.indexOf(afterString[0]); - return new JsonFloat(f); - } - case '\"': - return new JsonString(this.parseString(buffer, length, i + 1, outEndPos)); // \"の次の文字から - case '[': - o = this.parseArray(buffer, length, i + 1, outEndPos); - return o; - case '{': - o = this.parseObject(buffer, length, i + 1, outEndPos); - return o; - case 'n': // null以外にない - if(i + 3 < length) - { - o = new JsonNullvalue(); // 解放できるようにする - outEndPos[0] = i + 4; - } - else - { - this._error = "parse null"; - } - return o; - case 't': // true以外にない - if(i + 3 < length) - { - o = JsonBoolean.trueValue; - outEndPos[0] = i + 4; - } - else - { - this._error = "parse true"; - } - return o; - case 'f': // false以外にない - if(i + 4 < length) - { - o = JsonBoolean.falseValue; - outEndPos[0] = i + 5; - } - else - { - this._error = "illegal ',' position"; - } - return o; - case ',': // Array separator - this._error = "illegal ',' position"; - return null; - case ']': // 不正な}だがスキップする。配列の最後に不要な , があると思われる - outEndPos[0] = i; // 同じ文字を再処理 - return null; - case '\n': - this._lineCount++; - case ' ': - case '\t': - case '\r': - default: // スキップ - break; - } - } - - this._error = "illegal end of value"; - return null; - } - - /** - * 次の「"」までの文字列をパースする。 - * - * @param string -> パース対象の文字列 - * @param length -> パースする長さ - * @param begin -> パースを開始する位置 - * @param outEndPos -> パース終了時の位置 - * @return パースした文F字列要素 - */ - protected parseString(string: string, length: number, begin: number, outEndPos: number[]): string - { - if (this._error) return null; - - let i = begin; - let c: string, c2: string; - let ret: csmString = new csmString(""); - let bufStart: number = begin; // sbufに登録されていない文字の開始位置 - - for (; i < length; i++) - { - c = string[i]; - - switch(c) - { - case '\"': // 終端の”、エスケープ文字は別に処理されるのでここに来ない - { - outEndPos[0] = i + 1; // ”の次の文字 - ret.append(string.slice(bufStart), (i - bufStart)); // 前の文字までを登録する - return ret.s; - } - case '//': // エスケープの場合 - { - i++; // 2文字をセットで扱う - - if(i - 1 > bufStart) - { - ret.append(string.slice(bufStart), (i - bufStart)); // 前の文字までを登録する - } - bufStart = i + 1; // エスケープ(2文字)の次の文字から - - if (i < length) - { - c2 = string[i]; - - switch(c2) - { - case '\\': - ret.expansion(1, '\\'); - break; - case '\"': - ret.expansion(1, '\"'); - break; - case '/': - ret.expansion(1, '/'); - break; - case 'b': - ret.expansion(1, '\b'); - break; - case 'f': - ret.expansion(1, '\f'); - break; - case 'n': - ret.expansion(1, '\n'); - break; - case 'r': - ret.expansion(1, '\r'); - break; - case 't': - ret.expansion(1, '\t'); - break; - case 'u': - this._error = "parse string/unicord escape not supported"; - break; - default: - break; - } - } - else - { - this._error = "parse string/escape error"; - } - } - default: - { - break; - } - } - } - - this._error = "parse string/illegal end"; - return null; - } - - /** - * JSONのオブジェクトエレメントをパースしてValueオブジェクトを返す - * - * @param buffer JSONエレメントのバッファ - * @param length パースする長さ - * @param begin パースを開始する位置 - * @param outEndPos パース終了時の位置 - * @return パースから取得したValueオブジェクト - */ - protected parseObject(buffer: string, length: number, begin: number, outEndPos: number[]): Value - { - if(this._error) return null; - let ret: JsonMap = new JsonMap(); - - // Key: Value - let key: string = ""; - let i: number = begin; - let c: string = ""; - let localRetEndPos2: number[] = Array(1); - let ok: boolean = false; - - // , が続く限りループ - for(; i < length; i++) - { - FOR_LOOP: for(; i < length; i++) - { - c = buffer[i]; - - switch(c) - { - case '\"': - key = this.parseString(buffer, length, i + 1, localRetEndPos2); - if(this._error) - { - return null; - } - - i = localRetEndPos2[0]; - ok = true; - break FOR_LOOP; //-- loopから出る - case '}': // 閉じカッコ - outEndPos[0] = i + 1; - return ret; // 空 - case ':': - this._error = "illegal ':' position"; - break; - case '\n': - this._lineCount++; - default: - break; // スキップする文字 - } - } - if(!ok) - { - this._error = "key not found"; - return null; - } - - ok = false; - - // : をチェック - FOR_LOOP2: for(; i < length; i++) - { - c = buffer[i]; - - switch(c) - { - case ':': - ok = true; - i++; - break FOR_LOOP2; - case '}': - this._error = "illegal '}' position"; - break; - case '\n': this._lineCount++; - // case ' ': case '\t' : case '\r': - default: - break; // スキップする文字 - } - } - - if(!ok) - { - this._error = "':' not found"; - return null; - } - - // 値をチェック - let value: Value = this.parseValue(buffer, length, i, localRetEndPos2); - if(this._error) - { - return null; - } - - i = localRetEndPos2[0]; - - // ret.put(key, value); - ret.put(key, value); - - FOR_LOOP3: for(; i < length; i++) - { - c = buffer[i]; - - switch(c) - { - case ',': - break FOR_LOOP3; - case '}': - outEndPos[0] = i + 1; - return ret; // 正常終了 - case '\n': - this._lineCount++; - default: - break; // スキップ - } - } - } - - this._error = "illegal end of perseObject"; - return null; - } - - /** - * 次の「"」までの文字列をパースする。 - * @param buffer JSONエレメントのバッファ - * @param length パースする長さ - * @param begin パースを開始する位置 - * @param outEndPos パース終了時の位置 - * @return パースから取得したValueオブジェクト - */ - protected parseArray(buffer: string, length: number, begin: number, outEndPos: number[]): Value - { - if(this._error) return null; - let ret:JsonArray = new JsonArray(); - - // key : value - let i: number = begin; - let c: string; - let localRetEndpos2: number[] = new Array(1); - - // , が続く限りループ - for(; i < length; i++) - { - // : をチェック - let value: Value = this.parseValue(buffer, length, i, localRetEndpos2); - - if(this._error) - { - return null; - } - i = localRetEndpos2[0]; - - if(value) - { - ret.add(value); - } - - // FOR_LOOP3: - // boolean breakflag = false; - FOR_LOOP: for(; i < length; i++) - { - c = buffer[i]; - - switch(c) - { - case ',': - // breakflag = true; - // break; // 次のKEY, VAlUEへ - break FOR_LOOP; - case ']': - outEndPos[0] = i + 1; - return ret; // 終了 - case '\n': - ++this._lineCount; - //case ' ': case '\t': case '\r': - default: - break; // スキップ - } - } - } - - ret = void 0; - this._error = "illegal end of parseObject"; - return null; - } - - _error: string; // パース時のエラー - _lineCount: number; // エラー報告に用いる行数カウント - _root: Value; // パースされたルート要素 - } - - /** - * パースしたJSONの要素をfloat値として扱う - */ - export class JsonFloat extends Value - { - /** - * コンストラクタ - */ - constructor(v: number) - { - super(); - - this._value = v; - } - - /** - * Valueの種類が数値型ならtrue - */ - public isFloat(): boolean - { - return true; - } - - /** - * 要素を文字列で返す(csmString型) - */ - public getString(defaultValue: string, indent: string): string - { - let strbuf: string = '\0'; - this._value = parseFloat(strbuf); - this._stringBuffer = strbuf; - - return this._stringBuffer; - } - - /** - * 要素を数値型で返す(number) - */ - public toInt(defaultValue: number = 0): number - { - return parseInt(this._value.toString()); - } - - /** - * 要素を数値型で返す(number) - */ - public toFloat(defaultValue: number = 0.0): number - { - return this._value; - } - - /** - * 引数の値と等しければtrue - */ - public equals(value: csmString): boolean; - public equals(value: string): boolean; - public equals(value: number): boolean; - public equals(value: boolean): boolean; - public equals(value: any):boolean - { - if ('number' === typeof(value)) - { - // int - if (Math.round(value)) - { - return false; - } - // float - else - { - return value == this._value; - } - } - return false; - } - - private _value: number; // JSON要素の値 - } - - /** - * パースしたJSONの要素を真偽値として扱う - */ - export class JsonBoolean extends Value - { - - /** - * Valueの種類が真偽値ならtrue - */ - public isBool(): boolean - { - return true; - } - - /** - * 要素を真偽値で返す(boolean) - */ - public toBoolean(defaultValue: boolean = false): boolean - { - return this._boolValue; - } - - /** - * 要素を文字列で返す(csmString型) - */ - public getString(defaultValue: string, indent: string): string - { - this._stringBuffer = this._boolValue - ? "true" - : "false"; - - return this._stringBuffer; - } - - /** - * 引数の値と等しければtrue - */ - public equals(value: csmString): boolean; - public equals(value: string): boolean; - public equals(value: number): boolean; - public equals(value: boolean): boolean; - public equals(value: any):boolean - { - if ('boolean' === typeof(value)) - { - return value == this._boolValue; - } - return false; - } - - /** - * Valueの値が静的ならtrue, 静的なら解放しない - */ - public isStatic(): boolean - { - return true; - } - - /** - * 引数付きコンストラクタ - */ - public constructor(v: boolean) - { - super(); - - this._boolValue = v; - } - - static trueValue: JsonBoolean; // true - static falseValue: JsonBoolean; // false - - private _boolValue: boolean; // JSON要素の値 - } - - /** - * パースしたJSONの要素を文字列として扱う - */ - export class JsonString extends Value - { - /** - * 引数付きコンストラクタ - */ - public constructor(s: string); - public constructor(s: csmString) - public constructor(s: any) - { - super(); - - if('string' === typeof(s)) - { - this._stringBuffer = s; - } - - if(s instanceof csmString) - { - this._stringBuffer = s.s; - } - } - - /** - * Valueの種類が文字列ならtrue - */ - public isString(): boolean - { - return true; - } - - /** - * 要素を文字列で返す(csmString型) - */ - public getString(defaultValue: string, indent: string): string - { - return this._stringBuffer; - } - - /** - * 引数の値と等しければtrue - */ - public equals(value: csmString): boolean; - public equals(value: string): boolean; - public equals(value: number): boolean; - public equals(value: boolean): boolean; - public equals(value: any):boolean - { - if ('string' === typeof(value)) - { - return this._stringBuffer == value; - } - - if (value instanceof csmString) - { - return (this._stringBuffer == value.s); - } - - return false; - } - } - - /** - * JSONパース時のエラー結果。文字列型のようにふるまう - */ - export class JsonError extends JsonString - { - /** - * Valueの値が静的ならtrue、静的なら解放しない - */ - public isStatic(): boolean - { - return this._isStatic; - } - - /** - * エラー情報をセットする - */ - public setErrorNotForClientCall(s: string): Value - { - this._stringBuffer = s; - return this; - } - - /** - * 引数付きコンストラクタ - */ - public constructor(s: csmString|string, isStatic: boolean) - { - if("string" === typeof(s)) - { - super(s); - } - else - { - super(s); - } - this._isStatic = isStatic; - } - - /** - * Valueの種類がエラー値ならtrue - */ - public isError(): boolean - { - return true; - } - - - protected _isStatic: boolean; // 静的なValueかどうか - } - - /** - * パースしたJSONの要素をNULL値として持つ - */ - export class JsonNullvalue extends Value - { - /** - * Valueの種類がNULL値ならtrue - */ - public isNull(): boolean - { - return true; - } - - /** - * 要素を文字列で返す(csmString型) - */ - public getString(defaultValue: string, indent: string): string - { - return this._stringBuffer; - } - - /** - * Valueの値が静的ならtrue, 静的なら解放しない - */ - public isStatic(): boolean - { - return true; - } - - /** - * コンストラクタ - */ - public constructor() - { - super(); - - this._stringBuffer = "NullValue"; - } - - } - - /** - * パースしたJSONの要素を配列として持つ - */ - export class JsonArray extends Value - { - /** - * コンストラクタ - */ - public constructor() - { - super(); - this._array = new csmVector(); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - for(let ite: csmVector.iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.preIncrement()) - { - let v: Value = ite.ptr(); - - if(v && !v.isStatic()) - { - v = void 0; - v = null; - } - } - } - - /** - * Valueの種類が配列ならtrue - */ - public isArray(): boolean - { - return true; - } - - /** - * 要素を文字列で返す(csmString型) - */ - public getString(defaultValue: string, indent: string): string - { - let stringBuffer: string = indent + "[\n"; - - for(let ite: csmVector.iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.increment()) - { - let v: Value = ite.ptr(); - this._stringBuffer += indent + "" + v.getString(indent + " ") + "\n"; - } - - this._stringBuffer = stringBuffer + indent + "]\n"; - - return this._stringBuffer; - } - - /** - * 配列要素を追加する - * @param v 追加する要素 - */ - public add(v: Value): void - { - this._array.pushBack(v); - } - - /** - * 要素をコンテナで返す(csmVector) - */ - public getVector(defaultValue: csmVector = null): csmVector - { - return this._array; - } - - /** - * 要素の数を返す - */ - public getSize(): number - { - return this._array.getSize(); - } - - private _array: csmVector; // JSON要素の値 - } - - /** - * パースしたJSONの要素をマップとして持つ - */ - export class JsonMap extends Value - { - /** - * コンストラクタ - */ - public constructor() - { - super(); - //this._keys = new csmVector(); - this._map = new csmMap(); - } - - /** - * デストラクタ相当の処理 - */ - public release(): void - { - const ite: csmMap.iterator = this._map.begin(); - - while(ite.notEqual(this._map.end())) - { - let v: Value = ite.ptr().second; - - if(v && !v.isStatic()) - { - v = void 0; - v = null; - } - - ite.preIncrement(); - } - } - - /** - * Valueの値がMap型ならtrue - */ - public isMap(): boolean - { - return true; - } - - /** - * 要素を文字列で返す(csmString型) - */ - public getString(defaultValue: string, indent: string) - { - this._stringBuffer = indent + "{\n"; - - const ite: csmMap.iterator = this._map.begin(); - while(ite.notEqual(this._map.end())) - { - const key = ite.ptr().first; - let v: Value = ite.ptr().second; - - this._stringBuffer += indent + " " + key + " : " + v.getString(indent + " ") + " \n"; - ite.preIncrement(); - } - - this._stringBuffer += indent + "}\n"; - - return this._stringBuffer; - } - - /** - * 要素をMap型で返す - */ - public getMap(defaultValue?: csmMap): csmMap - { - return this._map; - } - - /** - * Mapに要素を追加する - */ - public put(key: string, v: Value): void - { - this._map.setValue(key, v); - } - - /** - * Mapからキーのリストを取得する - */ - public getKeys(): csmVector - { - if (!this._keys) - { - this._keys = new csmVector(); - - const ite: csmMap.iterator = this._map.begin(); - - while(ite.notEqual(this._map.end())) - { - const key: string = ite.ptr().first; - this._keys.pushBack(key); - ite.preIncrement(); - } - } - return this._keys; - } - - /** - * Mapの要素数を取得する - */ - public getSize(): number - { - return this._keys.getSize(); - } - - - private _map: csmMap; // JSON要素の値 - private _keys: csmVector; // JSON要素の値 - } -} \ No newline at end of file diff --git a/Framework/utils/cubismstring.ts b/Framework/utils/cubismstring.ts deleted file mode 100644 index fefcb03..0000000 --- a/Framework/utils/cubismstring.ts +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -export namespace Live2DCubismFramework -{ - export class CubismString - { - /** - * 標準出力の書式を適用した文字列を取得する。 - * @param format 標準出力の書式指定文字列 - * @param ...args 書式指定文字列に渡す文字列 - * @return 書式を適用した文字列 - */ - public static getFormatedString(format: string, ... args: any[]): string - { - let ret: string = format; - return ret.replace( - /\{(\d+)\}/g, - (m, k) => // m="{0}", k="0" - { - return args[k]; - } - ); - } - - /** - * textがstartWordで始まっているかどうかを返す - * @param test 検査対象の文字列 - * @param startWord 比較対象の文字列 - * @return true textがstartWordで始まっている - * @return false textがstartWordで始まっていない - */ - public static isStartWith(text: string, startWord: string): boolean - { - let textIndex = 0; - let startWordIndex = 0; - while(startWord[startWordIndex] != '\0') - { - if(text[textIndex] == '\0' || text[textIndex++] != startWord[startWordIndex++]) - { - return false; - } - } - return false; - } - - /** - * position位置の文字から数字を解析する。 - * - * @param string 文字列 - * @param length 文字列の長さ - * @param position 解析したい文字の位置 - * @param outEndPos 一文字も読み込まなかった場合はエラー値(-1)が入る - * @return 解析結果の数値 - */ - public static stringToFloat(string: string, length: number, position: number, outEndPos: number[]): number - { - let i: number = position; - let minus: boolean = false; // マイナスフラグ - let period: boolean = false; - let v1: number = 0; - - //負号の確認 - let c: number = parseInt(string[i]); - if (c < 0) - { - minus = true; - i++; - } - - //整数部の確認 - for (; i < length; i++) - { - let c = string[i]; - if (0 <= parseInt(c) && parseInt(c) <= 9) - { - v1 = v1 * 10 + (parseInt(c) - 0); - } - else if (c == '.') - { - period = true; - i++; - break; - } - else - { - break; - } - } - - //小数部の確認 - if (period) - { - let mul: number = 0.1; - for (; i < length; i++) - { - c = parseFloat(string[i]) & 0xFF; - if (0 <= c && c <= 9) - { - v1 += mul * (c - 0); - } - else - { - break; - } - mul *= 0.1; //一桁下げる - if (!c) break; - } - } - - if (i == position) - { - //一文字も読み込まなかった場合 - outEndPos[0] = -1; //エラー値が入るので呼び出し元で適切な処理を行う - return 0; - } - - if (minus) v1 = -v1; - - outEndPos[0] = i; - return v1; - } - - /** - * コンストラクタ呼び出し不可な静的クラスにする。 - */ - private constructor() - { - - } - } -} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappdefine.ts b/Sample/TypeScript/Demo/src/lappdefine.ts deleted file mode 100644 index df53e09..0000000 --- a/Sample/TypeScript/Demo/src/lappdefine.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as live2dcubismframework, Option} from "../../../../Framework/live2dcubismframework"; -import Csm_CubismFramework_Option = Option; - -/** - * Sample Appで使用する定数 - */ -export namespace LAppDefine -{ - // 画面 - export const ViewMaxScale: number = 2.0; - export const ViewMinScale: number = 0.8; - - export const ViewLogicalLeft: number = -1.0; - export const ViewLogicalRight: number = 1.0; - - export const ViewLogicalMaxLeft: number = -2.0; - export const ViewLogicalMaxRight: number = 2.0; - export const ViewLogicalMaxBottom: number = -2.0; - export const ViewLogicalMaxTop: number = 2.0; - - // 相対パス - export const ResourcesPath: string = "./Resources/"; - - // モデルの後ろにある背景の画像ファイル - export const BackImageName: string = "back_class_normal.png"; - - // 歯車 - export const GearImageName: string = "icon_gear.png"; - - // 終了ボタン - export const PowerImageName: string = "CloseNormal.png"; - - // モデル定義--------------------------------------------- - // モデルを配置したディレクトリ名の配列 - // ディレクトリ名とmodel3.jsonの名前を一致させておくこと - export const ModelDir: string[] = [ - "Haru", - "Hiyori", - "Mark" - ] - export const ModelDirSize: number = ModelDir.length; - - // 外部定義ファイル(json)と合わせる - export const MotionGroupIdle: string = "Idle"; // アイドリング - export const MotionGroupTapBody: string = "TapBody"; // 体をタップしたとき - - // 外部定義ファイル(json)と合わせる - export const HitAreaNameHead: string = "Head"; - export const HitAreaNameBody: string = "Body"; - - // モーションの優先度定数 - export const PriorityNone: number = 0; - export const PriorityIdle: number = 1; - export const PriorityNormal: number = 2; - export const PriorityForce: number = 3; - - // デバッグ用ログの表示オプション - export const DebugLogEnable: boolean = true; - export const DebugTouchLogEnable: boolean = false; - - // Frameworkから出力するログのレベル設定 - export const CubismLoggingLevel: Csm_CubismFramework_Option.LogLevel = Csm_CubismFramework_Option.LogLevel.LogLevel_Verbose; -} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappdelegate.ts b/Sample/TypeScript/Demo/src/lappdelegate.ts deleted file mode 100644 index 69e2f58..0000000 --- a/Sample/TypeScript/Demo/src/lappdelegate.ts +++ /dev/null @@ -1,340 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as live2dcubismframework, Option} from "../../../../Framework/live2dcubismframework"; -import {Live2DCubismFramework as cubismmatrix44} from "../../../../Framework/math/cubismmatrix44"; -import Csm_CubismMatrix44 = cubismmatrix44.CubismMatrix44; -import Csm_CubismFramework = live2dcubismframework.CubismFramework; -import Csm_Option = Option; -import { LAppView } from "./lappview"; -import { LAppPal } from "./lapppal"; -import { LAppTextureManager } from "./lapptexturemanager"; -import { LAppLive2DManager } from "./lapplive2dmanager"; - -export let canvas: HTMLCanvasElement = null; -export let s_instance: LAppDelegate = null; -export let gl: WebGLRenderingContext = null; - -/** - * アプリケーションクラス。 - * Cubism3の管理を行う。 - */ -export class LAppDelegate -{ - /** - * クラスのインスタンス(シングルトン)を返す。 - * インスタンスが生成されていない場合は内部でインスタンスを生成する。 - * - * @return クラスのインスタンス - */ - public static getInstance(): LAppDelegate - { - if(s_instance == null) - { - s_instance = new LAppDelegate(); - } - - return s_instance; - } - - /** - * クラスのインスタンス(シングルトン)を解放する。 - */ - public static releaseInstance(): void - { - if(s_instance != null) - { - s_instance = void 0; - } - - s_instance = null; - } - - /** - * APPに必要な物を初期化する。 - */ - public initialize(): boolean - { - // キャンバスの取得 - canvas = document.getElementById("SAMPLE"); - - // glコンテキストを初期化 - gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); - - if(!gl) - { - alert("WebGLを初期化できません。ブラウザはサポートしていないようです。"); - gl = null; - - // gl初期化失敗 - return false; - } - - // 透過設定 - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - - // マウス関連コールバック関数登録 - canvas.onmousedown = onClickBegan; - canvas.onmousemove = onMouseMoved; - canvas.onmouseup = onClickEnded; - - // AppViewの初期化 - this._view.initialize(); - - // Cubism3の初期化 - this.initializeCubism(); - - return true; - } - - /** - * 解放する。 - */ - public release(): void - { - this._textureManager = void 0; - this._view = void 0; - - // リソースを解放 - LAppLive2DManager.releaseInstance(); - - // Cubism3の解放 - Csm_CubismFramework.dispose(); - } - - /** - * 実行処理。 - */ - public run(): void - { - // メインループ - let loop = () => - { - // 時間更新 - LAppPal.updateTime(); - - // 画面の初期化 - gl.clearColor(0.0, 0.0, 0.0, 1.0); - - // 深度テストを有効化 - gl.enable(gl.DEPTH_TEST); - - // 近くにある物体は、遠くにある物体を覆い隠す - gl.depthFunc(gl.LEQUAL); - - // カラーバッファや深度バッファをクリアする - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - - gl.clearDepth(1.0); - - this._view.initializeSprite(); - - // 描画更新 - this._view.render(); - - // ループのために再帰呼び出し - setTimeout(loop, 1000.0/60); - }; - loop(); - } - - /** - * シェーダーを登録する。 - */ - public createShader(): WebGLProgram - { - // バーテックスシェーダーのコンパイル - let vertexShaderId = gl.createShader(gl.VERTEX_SHADER); - - if(vertexShaderId == null) - { - console.log("failed to create vertexShader"); - return null; - } - - const vertexShader: string = - "precision mediump float;" + - "attribute vec3 position;" + - "attribute vec2 uv;" + - "varying vec2 vuv;" + - "void main(void)" + - "{" + - " gl_Position = vec4(position, 1.0);" + - " vuv = uv;" + - "}"; - - gl.shaderSource(vertexShaderId, vertexShader); - gl.compileShader(vertexShaderId); - - // フラグメントシェーダのコンパイル - let fragmentShaderId = gl.createShader(gl.FRAGMENT_SHADER); - - if(fragmentShaderId == null) - { - console.log("failed to create fragmentShader"); - return null; - } - - const fragmentShader: string = - "precision mediump float;" + - "varying vec2 vuv;" + - "uniform sampler2D texture;" + - "void main(void)" + - "{" + - " gl_FragColor = texture2D(texture, vuv);" + - "}"; - - gl.shaderSource(fragmentShaderId, fragmentShader); - gl.compileShader(fragmentShaderId); - - // プログラムオブジェクトの作成 - let programId = gl.createProgram(); - gl.attachShader(programId, vertexShaderId); - gl.attachShader(programId, fragmentShaderId); - - // リンク - gl.linkProgram(programId); - - gl.useProgram(programId); - - return programId; - } - - /** - * View情報を取得する。 - */ - public getView(): LAppView - { - return this._view; - } - - /** - * アプリケーションを終了するかどうか。 - */ - public getIsEnd(): boolean - { - return this._isEnd; - } - - /** - * アプリケーションを終了する。 - */ - public appEnd(): void - { - this._isEnd = true; - } - - public getTextureManager(): LAppTextureManager - { - return this._textureManager; - } - - /** - * コンストラクタ - */ - constructor() - { - this._captured = false; - this._mouseX = 0.0; - this._mouseY = 0.0; - this._isEnd = false; - - this._cubismOption = new Csm_Option(); - this._view = new LAppView(); - this._textureManager = new LAppTextureManager(); - } - - /** - * Cubism3の初期化 - */ - public initializeCubism(): void - { - // setup cubism - Csm_CubismFramework.startUp(); - - // initialize cubism - Csm_CubismFramework.initialize(); - - // load model - LAppLive2DManager.getInstance(); - - // default proj - let projection: Csm_CubismMatrix44 = new Csm_CubismMatrix44(); - - LAppPal.updateTime(); - } - - _cubismOption: Csm_Option; // Cubism3 Option - _view: LAppView; // View情報 - _captured: boolean; // クリックしているか - _mouseX: number; // マウスX座標 - _mouseY: number; // マウスY座標 - _isEnd: boolean; // APP終了しているか - _textureManager: LAppTextureManager;// テクスチャマネージャー -} - - - -/** - * クリックしたときに呼ばれる。 - */ -function onClickBegan(e: MouseEvent): void -{ - LAppDelegate.getInstance()._captured = true; - if(!LAppDelegate.getInstance()._view) - { - console.log("view notfound"); - return; - } - - let posX: number = e.pageX; - let posY: number = e.pageY; - - LAppDelegate.getInstance()._view.onTouchesBegan(posX, posY); -} - -/** - * マウスポインタが動いたら呼ばれる。 - */ -function onMouseMoved(e: MouseEvent): void -{ - let rect = e.toElement.getBoundingClientRect(); - let posX: number = e.clientX - rect.left; - let posY: number = e.clientY - rect.top; - - if(!LAppDelegate.getInstance()._captured) - { - return; - } - - if(!LAppDelegate.getInstance()._view) - { - console.log("view notfound"); - return; - } - - LAppDelegate.getInstance()._view.onTouchesMoved(posX, posY); -} - -/** - * クリックが終了したら呼ばれる。 - */ -function onClickEnded(e: MouseEvent): void -{ - LAppDelegate.getInstance()._captured = false; - let rect = e.toElement.getBoundingClientRect(); - let posX: number = e.clientX - rect.left; - let posY: number = e.clientY - rect.top; - - if(!LAppDelegate.getInstance()._view) - { - console.log("view notfound"); - return; - } - LAppDelegate.getInstance()._view.onTouchesEnded(posX, posY); -} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lapplive2dmanager.ts b/Sample/TypeScript/Demo/src/lapplive2dmanager.ts deleted file mode 100644 index 2a1e12c..0000000 --- a/Sample/TypeScript/Demo/src/lapplive2dmanager.ts +++ /dev/null @@ -1,218 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as cubismmatrix44} from "../../../../Framework/math/cubismmatrix44"; -import {Live2DCubismFramework as csmvector} from "../../../../Framework/type/csmvector"; -import Csm_csmVector = csmvector.csmVector; -import Csm_CubismMatrix44 = cubismmatrix44.CubismMatrix44; - -import { LAppModel } from "./lappmodel"; -import { LAppDefine } from "./lappdefine"; -import { LAppPal } from "./lapppal"; -import { canvas } from "./lappdelegate"; - - -export let s_instance: LAppLive2DManager = null; - -/** - * サンプルアプリケーションにおいてCubismModelを管理するクラス - * モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。 - */ -export class LAppLive2DManager -{ - /** - * クラスのインスタンス(シングルトン)を返す。 - * インスタンスが生成されていない場合は内部でインスタンスを生成する。 - * - * @return クラスのインスタンス - */ - public static getInstance(): LAppLive2DManager - { - if(s_instance == null) - { - s_instance = new LAppLive2DManager(); - } - - return s_instance; - } - - /** - * クラスのインスタンス(シングルトン)を解放する。 - */ - public static releaseInstance(): void - { - if(s_instance != null) - { - s_instance = void 0; - } - - s_instance = null; - } - - /** - * 現在のシーンで保持しているモデルを返す。 - * - * @param no モデルリストのインデックス値 - * @return モデルのインスタンスを返す。インデックス値が範囲外の場合はNULLを返す。 - */ - public getModel(no: number): LAppModel - { - if(no < this._models.getSize()) - { - return this._models.at(no); - } - - return null; - } - - /** - * 現在のシーンで保持しているすべてのモデルを解放する - */ - public releaseAllModel(): void - { - for(let i: number = 0; i < this._models.getSize(); i++) - { - this._models.set(i, void 0); - } - - this._models.clear(); - } - - /** - * 画面をドラッグした時の処理 - * - * @param x 画面のX座標 - * @param y 画面のY座標 - */ - public onDrag(x: number, y: number): void - { - for(let i: number = 0; i < this._models.getSize(); i++) - { - let model: LAppModel = this.getModel(i); - - if(model) - { - model.setDragging(x, y); - } - } - } - - /** - * 画面をタップした時の処理 - * - * @param x 画面のX座標 - * @param y 画面のY座標 - */ - public onTap(x: number, y: number): void - { - if(LAppDefine.DebugLogEnable) - { - LAppPal.printLog("[APP]tap point: {x: {0} y: {1}}", x.toFixed(2), y.toFixed(2)); - } - - for(let i: number = 0; i < this._models.getSize(); i++) - { - if(this._models.at(i).hitTest(LAppDefine.HitAreaNameHead, x, y)) - { - if(LAppDefine.DebugLogEnable) - { - LAppPal.printLog("[APP]hit area: [{0}]", LAppDefine.HitAreaNameHead); - } - this._models.at(i).setRandomExpression(); - } - else if(this._models.at(i).hitTest(LAppDefine.HitAreaNameBody, x, y)) - { - if(LAppDefine.DebugLogEnable) - { - LAppPal.printLog("[APP]hit area: [{0}]", LAppDefine.HitAreaNameBody); - } - this._models.at(i).startRandomMotion(LAppDefine.MotionGroupTapBody, LAppDefine.PriorityNormal); - } - } - } - - /** - * 画面を更新するときの処理 - * モデルの更新処理及び描画処理を行う - */ - public onUpdate(): void - { - let projection: Csm_CubismMatrix44 = new Csm_CubismMatrix44(); - - let width: number, height: number; - width = canvas.width; - height = canvas.height; - projection.scale(1.0, width / height); - - if(this._viewMatrix != null) - { - projection.multiplyByMatrix(this._viewMatrix); - } - - const saveProjection: Csm_CubismMatrix44 = projection; - let modelCount: number = this._models.getSize(); - - for(let i: number = 0; i < modelCount; ++i) - { - let model: LAppModel = this.getModel(i); - projection = saveProjection; - - model.update(); - model.draw(projection); // 参照渡しなのでprojectionは変質する。 - } - } - - /** - * 次のシーンに切りかえる - * サンプルアプリケーションではモデルセットの切り替えを行う。 - */ - public nextScene(): void - { - let no: number = (this._sceneIndex + 1) % LAppDefine.ModelDirSize; - this.changeScene(no); - } - - /** - * シーンを切り替える - * サンプルアプリケーションではモデルセットの切り替えを行う。 - */ - public changeScene(index: number): void - { - this._sceneIndex = index; - if(LAppDefine.DebugLogEnable) - { - LAppPal.printLog("[APP]model index: {0}", this._sceneIndex); - } - - // ModelDir[]に保持したディレクトリ名から - // model3.jsonのパスを決定する。 - // ディレクトリ名とmodel3.jsonの名前を一致させておくこと。 - let model: string = LAppDefine.ModelDir[index]; - let modelPath: string = LAppDefine.ResourcesPath + model + "/"; - let modelJsonName: string = LAppDefine.ModelDir[index]; - modelJsonName += ".model3.json"; - - this.releaseAllModel(); - this._models.pushBack(new LAppModel()); - this._models.at(0).loadAssets(modelPath, modelJsonName); - } - - /** - * コンストラクタ - */ - constructor() - { - this._viewMatrix = new Csm_CubismMatrix44(); - this._models = new Csm_csmVector(); - this._sceneIndex = 0; - this.changeScene(this._sceneIndex); - } - - _viewMatrix: Csm_CubismMatrix44; // モデル描画に用いるview行列 - _models: Csm_csmVector; // モデルインスタンスのコンテナ - _sceneIndex: number; // 表示するシーンのインデックス値 -} diff --git a/Sample/TypeScript/Demo/src/lappmodel.ts b/Sample/TypeScript/Demo/src/lappmodel.ts deleted file mode 100644 index 4fcfff7..0000000 --- a/Sample/TypeScript/Demo/src/lappmodel.ts +++ /dev/null @@ -1,993 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as live2dcubismframework} from "../../../../Framework/live2dcubismframework"; -import {Live2DCubismFramework as cubismid} from "../../../../Framework/id/cubismid"; -import {Live2DCubismFramework as cubismusermodel} from "../../../../Framework/model/cubismusermodel"; -import {Live2DCubismFramework as icubismmodelsetting} from "../../../../Framework/icubismmodelsetting"; -import {Live2DCubismFramework as cubismmodelsettingjson} from "../../../../Framework/cubismmodelsettingjson"; -import {Live2DCubismFramework as cubismdefaultparameterid} from "../../../../Framework/cubismdefaultparameterid"; -import {Live2DCubismFramework as acubismmotion} from "../../../../Framework/motion/acubismmotion"; -import {Live2DCubismFramework as cubismeyeblink} from "../../../../Framework/effect/cubismeyeblink"; -import {Live2DCubismFramework as cubismbreath} from "../../../../Framework/effect/cubismbreath"; -import {Live2DCubismFramework as csmvector} from "../../../../Framework/type/csmvector"; -import {Live2DCubismFramework as csmmap} from "../../../../Framework/type/csmmap"; -import {Live2DCubismFramework as cubismmatrix44} from "../../../../Framework/math/cubismmatrix44"; -import {Live2DCubismFramework as cubismstring} from "../../../../Framework/utils/cubismstring"; -import {Live2DCubismFramework as cubismmotion} from "../../../../Framework/motion/cubismmotion"; -import {Live2DCubismFramework as cubismmotionqueuemanager} from "../../../../Framework/motion/cubismmotionqueuemanager"; -import {Live2DCubismFramework as csmstring} from "../../../../Framework/type/csmstring"; -import {Live2DCubismFramework as csmrect} from "../../../../Framework/type/csmrectf"; -import {CubismLogInfo} from "../../../../Framework/utils/cubismdebug"; -import csmRect = csmrect.csmRect; -import csmString = csmstring.csmString; -import InvalidMotionQueueEntryHandleValue = cubismmotionqueuemanager.InvalidMotionQueueEntryHandleValue; -import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle; -import CubismMotion = cubismmotion.CubismMotion; -import CubismString = cubismstring.CubismString; -import CubismMatrix44 = cubismmatrix44.CubismMatrix44; -import csmMap = csmmap.csmMap; -import csmVector = csmvector.csmVector; -import CubismBreath = cubismbreath.CubismBreath; -import CubismEyeBlink = cubismeyeblink.CubismEyeBlink; -import ACubismMotion = acubismmotion.ACubismMotion; -import CubismFramework = live2dcubismframework.CubismFramework; -import CubismIdHandle = cubismid.CubismIdHandle; -import CubismUserModel = cubismusermodel.CubismUserModel; -import ICubismModelSetting = icubismmodelsetting.ICubismModelSetting; -import CubismModelSettingJson = cubismmodelsettingjson.CubismModelSettingJson; -import CubismDefaultParameterId = cubismdefaultparameterid; - -import {LAppDefine} from "./lappdefine"; -import {LAppPal} from "./lapppal"; -import {gl} from "./lappdelegate"; - -function createBuffer(path: string, callBack: any): void -{ - LAppPal.loadFileAsBytes(path, callBack); -} - -function deleteBuffer(buffer: ArrayBuffer, path: string = "") -{ - LAppPal.releaseBytes(buffer); -} - -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 - { - this._modelHomeDir = dir; - - const path: string = dir + fileName; - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - let buffer: ArrayBuffer = arrayBuffer; - let size = buffer.byteLength; - let setting: ICubismModelSetting = new CubismModelSettingJson(buffer, size); - - // ステートを更新 - 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; - - let buffer: ArrayBuffer; - let size: number; - - // CubismModel - if (this._modelSetting.getModelFileName() != "") - { - let path: string = this._modelSetting.getModelFileName(); - path = this._modelHomeDir + path; - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - buffer = arrayBuffer; - this.loadModel(buffer); - deleteBuffer(buffer, path); - this._state = LoadStep.LoadExpression; - - // callback - loadCubismExpression(); - } - ); - - this._state = LoadStep.WaitLoadModel; - } - else - { - console.log("ModelData is not exist"); - } - - // Expression - let loadCubismExpression = () => - { - if(this._modelSetting.getExpressionCount() > 0) - { - const count: number = this._modelSetting.getExpressionCount(); - - for(let i: number = 0; i < count; i++) - { - let name: string = this._modelSetting.getExpressionName(i); - let path: string = this._modelSetting.getExpressionFileName(i); - path = this._modelHomeDir + path; - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - let buffer: ArrayBuffer = arrayBuffer; - let size: number = buffer.byteLength; - - let motion: ACubismMotion = this.loadExpression(buffer, size, name); - - if(this._expressions.getValue(name) != null) - { - ACubismMotion.delete(this._expressions.getValue(name)); - this._expressions.setValue(name, null); - } - - this._expressions.setValue(name, motion); - - deleteBuffer(buffer, path); - - this._expressionCount++; - - if(this._expressionCount >= count) - { - this._state = LoadStep.LoadPhysics; - - // callback - loadCubismPhysics(); - } - } - ); - } - this._state = LoadStep.WaitLoadExpression; - } - else - { - this._state = LoadStep.LoadPhysics; - - // callback - loadCubismPhysics(); - } - }; - - // Physics - let loadCubismPhysics = () => - { - if(this._modelSetting.getPhysicsFileName() != "") - { - let path: string = this._modelSetting.getPhysicsFileName(); - path = this._modelHomeDir + path; - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - let buffer: ArrayBuffer = arrayBuffer; - let size: number = buffer.byteLength; - - this.loadPhysics(buffer, size); - deleteBuffer(buffer, path); - - this._state = LoadStep.LoadPose; - - // callback - loadCubismPose(); - } - ); - this._state = LoadStep.WaitLoadPhysics; - } - else - { - this._state = LoadStep.LoadPose; - - // callback - loadCubismPose(); - } - }; - - // Pose - let loadCubismPose = () => - { - if(this._modelSetting.getPoseFileName() != "") - { - let path: string = this._modelSetting.getPoseFileName(); - path = this._modelHomeDir + path; - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - let buffer: ArrayBuffer = arrayBuffer; - let size: number = buffer.byteLength; - - this.loadPose(buffer, size); - deleteBuffer(buffer, path); - - this._state = LoadStep.SetupEyeBlink; - - // callback - setupEyeBlink(); - } - ); - this._state = LoadStep.WaitLoadPose; - } - else - { - this._state = LoadStep.SetupEyeBlink; - - // callback - setupEyeBlink(); - } - }; - - // EyeBlink - let setupEyeBlink = () => - { - if(this._modelSetting.getEyeBlinkParameterCount() > 0) - { - this._eyeBlink = CubismEyeBlink.create(this._modelSetting); - this._state = LoadStep.SetupBreath; - - } - - // callback - setupBreath(); - }; - - // Breath - let setupBreath = () => - { - this._breath = CubismBreath.create(); - - let breathParameters: csmVector = new csmVector(); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleX, 0.0, 15.0, 6.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleY, 0.0, 8.0, 3.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleZ, 0.0, 10.0, 5.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamBodyAngleX, 0.0, 4.0, 15.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.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 - let loadUserData = () => - { - if(this._modelSetting.getUserDataFile() != "") - { - let path: string = this._modelSetting.getUserDataFile(); - path = this._modelHomeDir + path; - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - let buffer: ArrayBuffer = arrayBuffer; - let size: number = buffer.byteLength; - - this.loadUserData(buffer, size); - deleteBuffer(buffer, path); - - this._state = LoadStep.SetupEyeBlinkIds; - - // callback - setupEyeBlinkIds(); - } - ); - - this._state = LoadStep.WaitLoadUserData; - } - else - { - this._state = LoadStep.SetupEyeBlinkIds; - - // callback - setupEyeBlinkIds(); - } - }; - - // EyeBlinkIds - let setupEyeBlinkIds = () => - { - let eyeBlinkIdCount: number = this._modelSetting.getEyeBlinkParameterCount(); - - for(let i: number = 0; i < eyeBlinkIdCount; ++i) - { - this._eyeBlinkIds.pushBack(this._modelSetting.getEyeBlinkParameterId(i)); - } - - this._state = LoadStep.SetupLipSyncIds; - - // callback - setupLipSyncIds(); - }; - - // LipSyncIds - let setupLipSyncIds = () => - { - let lipSyncIdCount = this._modelSetting.getLipSyncParameterCount(); - - for(let i: number = 0; i < lipSyncIdCount; ++i) - { - this._lipSyncIds.pushBack(this._modelSetting.getLipSyncParameterId(i)); - } - this._state = LoadStep.SetupLayout; - - // callback - setupLayout(); - }; - - // Layout - let setupLayout = () => - { - let layout: csmMap = new csmMap(); - this._modelSetting.getLayoutMap(layout); - this._modelMatrix.setupFromLayout(layout); - this._state = LoadStep.LoadMotion; - - // callback - loadCubismMotion(); - }; - - // Motion - let loadCubismMotion = () => - { - this._state = LoadStep.WaitLoadMotion; - this._model.saveParameters(); - this._allMotionCount = 0; - this._motionCount = 0; - let group: string[] = []; - - let motionGroupCount: number = this._modelSetting.getMotionGroupCount(); - - // モーションの総数を求める - for(let i: number = 0; i < motionGroupCount; i++) - { - group[i] = this._modelSetting.getMotionGroupName(i); - this._allMotionCount += this._modelSetting.getMotionCount(group[i]); - } - - // モーションの読み込み - for(let i: number = 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 - { - if(this._state == LoadStep.LoadTexture) - { - // テクスチャ読み込み用 - let textureCount: number = this._modelSetting.getTextureCount(); - let img: HTMLImageElement[] = new Array(textureCount); - - for(let modelTextureNumber = 0; modelTextureNumber < textureCount; modelTextureNumber++) - { - // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ - if(this._modelSetting.getTextureFileName(modelTextureNumber) == "") - { - console.log("getTextureFileName null"); - continue; - } - - // WebGLのテクスチャユニットにテクスチャをロードする - let texturePath = this._modelSetting.getTextureFileName(modelTextureNumber); - texturePath = this._modelHomeDir + texturePath; - - // データのオンロードをトリガーにする - img[modelTextureNumber] = new Image(); - img[modelTextureNumber].onload = () => - { - // テクスチャオブジェクトの作成 - let tex: WebGLTexture = gl.createTexture(); - - // テクスチャを選択 - gl.bindTexture(gl.TEXTURE_2D, tex); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - // テクスチャにピクセルを書き込む - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[modelTextureNumber]); - - // ミップマップを生成 - gl.generateMipmap(gl.TEXTURE_2D); - - this.getRenderer().bindTexture(modelTextureNumber, tex); - - this._textureCount++; - - if(this._textureCount >= textureCount) - { - // ロード完了 - this._state = LoadStep.CompleteSetup; - } - } - img[modelTextureNumber].src = texturePath; - - this.getRenderer().setIsPremultipliedAlpha(false); - } - - 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); - - } - 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) - { - let value: number = 0; // リアルタイムでリップシンクを行う場合、システムから音量を取得して、0~1の範囲で値を入力します。 - - for(let i: number = 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 優先度 - * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するisFinished()の引数で使用する。開始できない時は[-1] - */ - public startMotion(group: string, no: number, priority: number): CubismMotionQueueEntryHandle - { - if(priority == LAppDefine.PriorityForce) - { - this._motionManager.setReservePriority(priority); - } - else if(!this._motionManager.reserveMotion(priority)) - { - if(this._debugMode) - { - LAppPal.printLog("[APP]can't start motion."); - } - return InvalidMotionQueueEntryHandleValue; - } - - const fileName: string = this._modelSetting.getMotionFileName(group, no); - - // ex) idle_0 - let name: string = CubismString.getFormatedString("{0}_{1}", group, no); - let motion: CubismMotion = this._motions.getValue(name); - let autoDelete: boolean = false; - - if(motion == null) - { - let path: string = fileName; - path = this._modelHomeDir + path; - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - let buffer: ArrayBuffer = arrayBuffer; - let size = buffer.byteLength; - - motion = this.loadMotion(buffer, size, null); - 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; // 終了時にメモリから削除 - - deleteBuffer(buffer, path); - } - ); - } - - if(this._debugMode) - { - LAppPal.printLog("[APP]start motion: [{0}_{1}", group, no); - } - return this._motionManager.startMotionPriority(motion, autoDelete, priority); - } - - /** - * ランダムに選ばれたモーションの再生を開始する。 - * @param group モーショングループ名 - * @param priority 優先度 - * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するisFinished()の引数で使用する。開始できない時は[-1] - */ - public startRandomMotion(group: string, priority: number): CubismMotionQueueEntryHandle - { - if(this._modelSetting.getMotionCount(group) == 0) - { - return InvalidMotionQueueEntryHandleValue; - } - - let no: number = Math.floor(Math.random() * this._modelSetting.getMotionCount(group)); - - return this.startMotion(group, no, priority); - } - - /** - * 引数で指定した表情モーションをセットする - * - * @param expressionId 表情モーションのID - */ - public setExpression(expressionId: string): void - { - let motion: ACubismMotion = this._expressions.getValue(expressionId); - - if(this._debugMode) - { - LAppPal.printLog("[APP]expression: [{0}]", expressionId); - } - - if(motion != null) - { - this._expressionManager.startMotionPriority(motion, false, LAppDefine.PriorityForce); - } - else - { - if(this._debugMode) - { - LAppPal.printLog("[APP]expression[{0}] is null", expressionId); - } - } - } - - /** - * ランダムに選ばれた表情モーションをセットする - */ - public setRandomExpression(): void - { - if(this._expressions.getSize() == 0) - { - return; - } - - let no: number = Math.floor(Math.random() * this._expressions.getSize()); - - for(let i: number = 0; i < this._expressions.getSize(); i++) - { - if(i == no) - { - let 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の頂点リストから矩形を計算し、座標をが矩形範囲内か判定する。 - * - * @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: number = 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から取得する。 - * - * @param group モーションデータのグループ名 - */ - public preLoadMotionGroup(group: string): void - { - for(let i: number = 0; i < this._modelSetting.getMotionCount(group); i++) - { - // ex) idle_0 - let name: string = CubismString.getFormatedString("{0}_{1}", group, i); - let path = this._modelSetting.getMotionFileName(group, i); - path = this._modelHomeDir + path; - - if(this._debugMode) - { - LAppPal.printLog("[APP]load motion: {0} => [{1}_{2}]", path, group, i); - } - - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - let buffer: ArrayBuffer = arrayBuffer; - let size = buffer.byteLength; - - let tmpMotion: CubismMotion = this.loadMotion(buffer, size, 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); - - deleteBuffer(buffer, path); - - this._motionCount++; - if(this._motionCount >= this._allMotionCount) - { - this._state = LoadStep.LoadTexture; - - // 全てのモーションを停止する - this._motionManager.stopAllMotions(); - - this._updating = false; - this._initialized = true; - - this.createRenderer(); - this.setupTextures(); - this.getRenderer().startUp(gl); - } - } - ); - } - } - - /** - * すべてのモーションデータを解放する。 - */ - public releaseMotions(): void - { - this._motions.clear(); - } - - /** - * 全ての表情データを解放する。 - */ - public releaseExpressions(): void - { - this._expressions.clear(); - } - - /** - * モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。 - */ - public doDraw(): void - { - if(this._model == null) return; - - 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; // モーション総数 -} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lapppal.ts b/Sample/TypeScript/Demo/src/lapppal.ts deleted file mode 100644 index fa5d819..0000000 --- a/Sample/TypeScript/Demo/src/lapppal.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -/** - * プラットフォーム依存機能を抽象化する Cubism Platform Abstraction Layer. - * - * ファイル読み込みや時刻取得等のプラットフォームに依存する関数をまとめる。 - */ -export class LAppPal -{ - /** - * ファイルをバイトデータとして読みこむ - * - * @param filePath 読み込み対象ファイルのパス - * @return - * { - * buffer, 読み込んだバイトデータ - * size ファイルサイズ - * } - */ - public static loadFileAsBytes(filePath: string, callback: any): void - { - //filePath;// - const path: string = filePath; - - let size = 0; - fetch(path).then( - (response) => - { - return response.arrayBuffer(); - } - ).then( - (arrayBuffer) => - { - size = arrayBuffer.byteLength; - callback(arrayBuffer, size); - } - ); - } - - /** - * バイトデータを解放する - * @param byteData 解放したいバイトデータ - */ - public static releaseBytes(byteData: ArrayBuffer): void - { - byteData = void 0; - } - - /** - * デルタ時間(前回フレームとの差分)を取得する - * @return デルタ時間[ms] - */ - public static getDeltaTime(): number - { - return this.s_deltaTime; - } - - public static updateTime(): void - { - this.s_currentFrame = Date.now(); - this.s_deltaTime = (this.s_currentFrame - this.s_lastFrame) / 1000; - this.s_lastFrame = this.s_currentFrame; - } - - /** - * ログを出力する - * @param format 書式付き文字列 - * @param ... args(可変長引数)文字列 - */ - public static printLog(format: string, ... args: any[]): void - { - console.log( - format.replace( - /\{(\d+)\}/g, - (m, k) => - { - return args[k]; - } - ) - ); - } - - /** - * メッセージを出力する - * @param message 文字列 - */ - public static printMessage(message: string): void - { - this.printLog(message); - } - - static lastUpdate = Date.now(); - - static s_currentFrame = 0.0; - static s_lastFrame = 0.0; - static s_deltaTime = 0.0; -} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappsprite.ts b/Sample/TypeScript/Demo/src/lappsprite.ts deleted file mode 100644 index 7a7f37a..0000000 --- a/Sample/TypeScript/Demo/src/lappsprite.ts +++ /dev/null @@ -1,137 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import { gl, canvas } from "./lappdelegate"; - -/** - * スプライトを実装するクラス - * - * テクスチャID、Rectの管理 - */ - export class LAppSprite - { - /** - * コンストラクタ - * @param x x座標 - * @param y y座標 - * @param width 横幅 - * @param height 高さ - * @param textureId テクスチャ - */ - constructor(x: number, y: number, width: number, height: number, textureId: WebGLTexture) - { - this._rect = new Rect(); - this._rect.left = (x - width * 0.5); - this._rect.right = (x + width * 0.5); - this._rect.up = (y + height * 0.5); - this._rect.down = (y - height * 0.5); - this._texture = textureId; - } - - /** - * テクスチャを返す - */ - public getTexture(): WebGLTexture - { - return this._texture; - } - - /** - * 描画する。 - * @param programId シェーダープログラム - * @param canvas 描画するキャンパス情報 - */ - public render(programId: WebGLProgram): void - { - if(!this._texture) - { - return; - } - - // 何番目のattribute変数か - let positionLocation = gl.getAttribLocation(programId, "position"); - let uvLocation = gl.getAttribLocation(programId, "uv"); - - let textureLocation: WebGLUniformLocation = null; - textureLocation = gl.getUniformLocation(programId, "texture"); - - // attribute属性を有効にする - gl.enableVertexAttribArray(positionLocation); - gl.enableVertexAttribArray(uvLocation); - - // uniform属性の登録 - gl.uniform1i(textureLocation, 0); - - const uvVertex: Float32Array = new Float32Array([ - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0 - ]); - let vuv: WebGLBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, vuv); - gl.bufferData(gl.ARRAY_BUFFER, uvVertex, gl.STATIC_DRAW); - - // attribute属性を登録 - gl.vertexAttribPointer(uvLocation, 2, gl.FLOAT, false, 0, 0); - - // 画面サイズを取得する。 - let maxWidth, maxHeight; - maxWidth = canvas.width; - maxHeight = canvas.height; - - // 頂点データ - let positionVertex: Float32Array = new Float32Array([ - (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), - (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), - (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5), - (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5) - ]); - - let vposition: WebGLBuffer = gl.createBuffer(); - gl.activeTexture(gl.TEXTURE0); - gl.bindBuffer(gl.ARRAY_BUFFER, vposition); - gl.bufferData(gl.ARRAY_BUFFER, positionVertex, gl.STATIC_DRAW); - - // attribute属性を登録 - gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); - - // モデルの描画 - gl.bindTexture(gl.TEXTURE_2D, this._texture); - gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); - } - - /** - * 当たり判定 - * @param pointX x座標 - * @param pointY y座標 - */ - public isHit(pointX: number, pointY: number): boolean - { - // 画面サイズを取得する。 - let maxWidth, maxHeight; - maxWidth = canvas.width; - maxHeight = canvas.height; - - // Y座標は変換する必要あり - let y = maxHeight - pointY; - - return (pointX >= this._rect.left && pointX <= this._rect.right && y <= this._rect.up && y >= this._rect.down); - } - - _texture: WebGLTexture; // テクスチャ - _rect: Rect; // 矩形 - } - - - export class Rect - { - public left: number; // 左辺 - public right: number; // 右辺 - public up: number; // 上辺 - public down: number; // 下辺 - } \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lapptexturemanager.ts b/Sample/TypeScript/Demo/src/lapptexturemanager.ts deleted file mode 100644 index 5731b60..0000000 --- a/Sample/TypeScript/Demo/src/lapptexturemanager.ts +++ /dev/null @@ -1,168 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as csmvector} from "../../../../Framework/type/csmvector"; -import Csm_csmVector = csmvector.csmVector; -import { gl } from "./lappdelegate"; - -/** - * テクスチャ管理クラス - * 画像読み込み、管理を行うクラス。 - */ -export class LAppTextureManager -{ - /** - * コンストラクタ - */ - constructor() - { - this._textures = new Csm_csmVector(); - } - - /** - * プリマルチプライ処理 - * @param red 画像のRed値 - * @param green 画像のGreen値 - * @param blue 画像のBlue値 - * @param alpha 画像のAlpha値 - */ - public premultiply(red: number, green: number, blue: number, alpha: number): number - { - return ( - (red * (alpha + 1) >> 8) | - ((green * (alpha + 1) >> 8) << 8) | - ((blue * (alpha + 1) >> 8) << 16) | - (((alpha)) << 24) - ); - } - - /** - * 画像読み込み - * - * @param fileName 読み込む画像ファイルパス名 - * @return 画像情報、読み込み失敗時はnullを返す - */ - public createTextureFromPngFile(fileName: string, callback: any): TextureInfo - { - // search loaded texture already - for(let i: number = 0; i < this._textures.getSize(); i++) - { - if(this._textures.at(i).fileName == fileName) - { - return this._textures.at(i); - } - } - - // データのオンロードをトリガーにする - let img = new Image(); - img.onload = () => - { - // テクスチャオブジェクトの作成 - let tex: WebGLTexture = gl.createTexture(); - - // テクスチャを選択 - gl.bindTexture(gl.TEXTURE_2D, tex); - - // テクスチャにピクセルを書き込む - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - - // テクスチャにピクセルを書き込む - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); - - // ミップマップを生成 - gl.generateMipmap(gl.TEXTURE_2D); - - // テクスチャをバインド - gl.bindTexture(gl.TEXTURE_2D, tex); - - let textureInfo: TextureInfo = new TextureInfo(); - - if(textureInfo != null) - { - textureInfo.fileName = fileName; - textureInfo.width = img.width; - textureInfo.height = img.height; - textureInfo.id = tex; - this._textures.pushBack(textureInfo); - } - - callback(textureInfo); - } - img.src = fileName; - - return null; - } - - /** - * 画像の解放 - * - * 配列に存在する画像全てを解放する。 - */ - public releaseTextures(): void - { - for(let i: number = 0; i < this._textures.getSize(); i++) - { - this._textures.set(i, void 0); - } - - this._textures.clear(); - } - - /** - * 画像の解放 - * - * 指定したテクスチャの画像を解放する。 - * @param texture 解放するテクスチャ - */ - public releaseTextureByTexture(texture: WebGLTexture) - { - for(let i: number = 0; i < this._textures.getSize(); i++) - { - if(this._textures.at(i).id != texture) - { - continue; - } - - this._textures.set(i, void 0); - this._textures.remove(i); - break; - } - } - - /** - * 画像の解放 - * - * 指定した名前の画像を解放する。 - * @param fileName 解放する画像ファイルパス名 - */ - public releaseTextureByFilePath(fileName: string): void - { - for(let i: number = 0; i < this._textures.getSize(); i++) - { - if(this._textures.at(i).fileName == fileName) - { - this._textures.set(i, void 0); - this._textures.remove(i); - break; - } - } - } - - _textures: Csm_csmVector; -} - -/** - * 画像情報構造体 - */ -export class TextureInfo -{ - id: WebGLTexture = null; // テクスチャ - width: number = 0; // 横幅 - height: number = 0; // 高さ - fileName: string; // ファイル名 -} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappview.ts b/Sample/TypeScript/Demo/src/lappview.ts deleted file mode 100644 index 697f51f..0000000 --- a/Sample/TypeScript/Demo/src/lappview.ts +++ /dev/null @@ -1,290 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import {Live2DCubismFramework as cubismMatrix44} from "../../../../Framework/math/cubismmatrix44"; -import {Live2DCubismFramework as cubismviewmatrix} from "../../../../Framework/math/cubismviewmatrix"; -import Csm_CubismViewMatrix = cubismviewmatrix.CubismViewMatrix; -import Csm_CubismMatrix44 = cubismMatrix44.CubismMatrix44; -import { TouchManager } from "./touchmanager"; -import { LAppDefine } from "./lappdefine"; -import { LAppLive2DManager } from "./lapplive2dmanager"; -import { LAppDelegate, canvas} from "./lappdelegate"; -import { LAppSprite } from "./lappsprite"; -import { TextureInfo } from "./lapptexturemanager"; -import { LAppPal } from "./lapppal"; - -enum LoadStep -{ - BackImage, - GearImage, - PowerImage, - CompleteLoad -} - -/** - * 描画クラス。 - */ -export class LAppView -{ - /** - * コンストラクタ - */ - constructor() - { - this._loadStep = LoadStep.BackImage; - - this._programId = null; - this._back = null; - this._gear = null; - - // タッチ関係のイベント管理 - this._touchManager = new TouchManager(); - - // デバイス座標からスクリーン座標に変換するための - this._deviceToScreen = new Csm_CubismMatrix44(); - - // 画面の表示の拡大縮小や移動の変換を行う行列 - this._viewMatrix = new Csm_CubismViewMatrix(); - } - - /** - * 初期化する。 - */ - public initialize(): void - { - let width: number, height: number; - width = canvas.width; - height = canvas.height; - - let ratio: number = height / width; - let left: number = LAppDefine.ViewLogicalLeft; - let right: number = LAppDefine.ViewLogicalRight; - let bottom: number = -ratio; - let top: number = ratio; - - this._viewMatrix.setScreenRect(left, right, bottom, top); // デバイスに対応する画面の範囲。 Xの左端、Xの右端、Yの下端、Yの上端 - - let screenW: number = Math.abs(left - right); - this._deviceToScreen.scaleRelative(screenW / width, -screenW / width); - this._deviceToScreen.translateRelative(-width * 0.5, -height * 0.5); - - // 表示範囲の設定 - this._viewMatrix.setMaxScale(LAppDefine.ViewMaxScale); // 限界拡張率 - this._viewMatrix.setMinScale(LAppDefine.ViewMinScale); // 限界縮小率 - - // 表示できる最大範囲 - this._viewMatrix.setMaxScreenRect( - LAppDefine.ViewLogicalMaxLeft, - LAppDefine.ViewLogicalMaxRight, - LAppDefine.ViewLogicalMaxBottom, - LAppDefine.ViewLogicalMaxTop - ); - } - - /** - * 描画する。 - */ - public render(): void - { - if(this._loadStep != LoadStep.CompleteLoad) - { - return; - } - - if(this._back) - { - this._back.render(this._programId); - } - if(this._gear) - { - this._gear.render(this._programId); - } - - let live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance(); - - live2DManager.onUpdate(); - } - - /** - * 画像の初期化を行う。 - */ - public initializeSprite(): void - { - let width: number, height: number; - width = canvas.width; - height = canvas.height; - - let textureManager = LAppDelegate.getInstance().getTextureManager(); - const resourcesPath = LAppDefine.ResourcesPath; - - let imageName: string = ""; - - // 背景画像初期化 - if(this._loadStep == LoadStep.BackImage) - { - imageName = LAppDefine.BackImageName; - - // 非同期なのでコールバック関数を作成 - let initBackGroundTexture = (textureInfo: TextureInfo): void => - { - let x: number = width * 0.5; - let y: number = height * 0.5; - - let fwidth = textureInfo.width * 2.0; - let fheight = height * 0.95; - this._back = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); - this._loadStep = LoadStep.GearImage; - } - let backGroundTexture: TextureInfo = textureManager.createTextureFromPngFile(resourcesPath + imageName, initBackGroundTexture); - - // 既に画像があれば直接初期化 - if(backGroundTexture != null) - { - initBackGroundTexture(backGroundTexture); - } - } - - // 歯車画像初期化 - if(this._loadStep == LoadStep.GearImage) - { - imageName = LAppDefine.GearImageName; - let initGearTexture = (textureInfo: TextureInfo): void => - { - let x = width - textureInfo.width * 0.5; - let y = height - textureInfo.height * 0.5; - let fwidth = textureInfo.width; - let fheight = textureInfo.height; - this._gear = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); - - this._loadStep = LoadStep.CompleteLoad; - } - let gearTexture: TextureInfo = textureManager.createTextureFromPngFile(resourcesPath + imageName, initGearTexture); - - // 既に画像があれば直接初期化 - if(gearTexture != null) - { - initGearTexture(gearTexture); - } - } - - if(this._loadStep == LoadStep.CompleteLoad) - { - this._programId = LAppDelegate.getInstance().createShader(); - } - } - - /** - * タッチされた時に呼ばれる。 - * - * @param pointX スクリーンX座標 - * @param pointY スクリーンY座標 - */ - public onTouchesBegan(pointX: number, pointY: number): void - { - this._touchManager.touchesBegan(pointX, pointY); - } - - /** - * タッチしているときにポインタが動いたら呼ばれる。 - * - * @param pointX スクリーンX座標 - * @param pointY スクリーンY座標 - */ - public onTouchesMoved(pointX: number, pointY: number): void - { - let viewX: number = this.transformViewX(this._touchManager.getX()); - let viewY: number = this.transformViewY(this._touchManager.getY()); - - this._touchManager.touchesMoved(pointX, pointY); - - let live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance(); - live2DManager.onDrag(viewX, viewY); - } - - /** - * タッチが終了したら呼ばれる。 - * - * @param pointX スクリーンX座標 - * @param pointY スクリーンY座標 - */ - public onTouchesEnded(pointX: number, pointY: number): void - { - // タッチ終了 - let live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance(); - live2DManager.onDrag(0.0, 0.0); - - { - // シングルタップ - let x: number = this._deviceToScreen.transformX(this._touchManager.getX()); // 論理座標変換した座標を取得。 - let y: number = this._deviceToScreen.transformY(this._touchManager.getY()); // 論理座標変化した座標を取得。 - - if(LAppDefine.DebugTouchLogEnable) - { - LAppPal.printLog("[APP]touchesEnded x: {0} y: {1}", x, y); - } - live2DManager.onTap(x, y); - - // 歯車にタップしたか - if(this._gear.isHit(pointX, pointY)) - { - live2DManager.nextScene(); - } - } - } - - /** - * X座標をView座標に変換する。 - * - * @param deviceX デバイスX座標 - */ - public transformViewX(deviceX: number): number - { - let screenX: number = this._deviceToScreen.transformX(deviceX); // 論理座標変換した座標を取得。 - return this._viewMatrix.invertTransformX(screenX); // 拡大、縮小、移動後の値。 - } - - /** - * Y座標をView座標に変換する。 - * - * @param deviceY デバイスY座標 - */ - public transformViewY(deviceY: number): number - { - let screenY: number = this._deviceToScreen.transformY(deviceY); // 論理座標変換した座標を取得。 - return this._viewMatrix.invertTransformY(screenY); - } - - /** - * X座標をScreen座標に変換する。 - * @param deviceX デバイスX座標 - */ - public transformScreenX(deviceX: number): number - { - return this._deviceToScreen.transformX(deviceX); - } - - /** - * Y座標をScreen座標に変換する。 - * - * @param deviceY デバイスY座標 - */ - public transformScreenY(deviceY: number): number - { - return this._deviceToScreen.transformY(deviceY); - } - - _touchManager: TouchManager; // タッチマネージャー - _deviceToScreen: Csm_CubismMatrix44; // デバイスからスクリーンへの行列 - _viewMatrix: Csm_CubismViewMatrix; // viewMatrix - _programId: WebGLProgram; // シェーダID - _back: LAppSprite; // 背景画像 - _gear: LAppSprite; // ギア画像 - _changeModel: boolean; // モデル切り替えフラグ - _isClick: boolean; // クリック中 - - _loadStep: number; -} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/main.ts b/Sample/TypeScript/Demo/src/main.ts deleted file mode 100644 index b587f2d..0000000 --- a/Sample/TypeScript/Demo/src/main.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -import { LAppDelegate } from "./lappdelegate"; - -let main: any = () => -{ - // create the application instance - if(LAppDelegate.getInstance().initialize() == false) - { - console.log("application iniitalize"); - return; - } - - LAppDelegate.getInstance().run(); -} - - -main(); - -/** - * 終了時の処理 - */ -window.onbeforeunload = () => -{ - LAppDelegate.getInstance().release(); - LAppDelegate.releaseInstance(); -}; diff --git a/Sample/TypeScript/Demo/src/touchmanager.ts b/Sample/TypeScript/Demo/src/touchmanager.ts deleted file mode 100644 index 96006a1..0000000 --- a/Sample/TypeScript/Demo/src/touchmanager.ts +++ /dev/null @@ -1,199 +0,0 @@ -/* -* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. -*/ - -export class TouchManager -{ - /** - * コンストラクタ - */ - constructor() - { - this._startX = 0.0; - this._startY = 0.0; - this._lastX = 0.0; - this._lastY = 0.0; - this._lastX1 = 0.0; - this._lastY1 = 0.0; - this._lastX2 = 0.0; - this._lastY2 = 0.0; - this._lastTouchDistance = 0.0; - this._deltaX = 0.0; - this._deltaY = 0.0; - this._scale = 1.0; - this._touchSingle = false; - this._flipAvailable = false; - } - - public getCenterX(): number - { - return this._lastX; - } - - public getCenterY(): number - { - return this._lastY; - } - - public getDeltaX(): number - { - return this._deltaX; - } - - public getDeltaY(): number - { - return this._deltaY; - } - - public getStartX(): number - { - return this._startX; - } - - public getStartY(): number - { - return this._startY; - } - - public getScale(): number - { - return this._scale; - } - - public getX(): number - { - return this._lastX; - } - - public getY(): number - { - return this._lastY; - } - - public getX1(): number - { - return this._lastX1; - } - - public getY1(): number - { - return this._lastY1; - } - - public getX2(): number - { - return this._lastX2; - } - - public getY2(): number - { - return this._lastY2; - } - - public isSingleTouch(): boolean - { - return this._touchSingle; - } - - public isFlickAvailable(): boolean - { - return this._flipAvailable; - } - - public disableFlick(): void - { - this._flipAvailable = false; - } - - /** - * タッチ開始時イベント - * @param deviceX タッチした画面のxの値 - * @param deviceY タッチした画面のyの値 - */ - public touchesBegan(deviceX: number, deviceY: number): void - { - this._lastX = deviceX; - this._lastY = deviceY; - this._startX = deviceX; - this._startY = deviceY; - this._lastTouchDistance = -1.0; - this._flipAvailable = true; - this._touchSingle = true; - } - - /** - * ドラッグ時のイベント - * @param deviceX タッチした画面のxの値 - * @param deviceY タッチした画面のyの値 - */ - public touchesMoved(deviceX: number, deviceY: number): void - { - this._lastX = deviceX; - this._lastY = deviceY; - this._lastTouchDistance = -1.0; - this._touchSingle = true; - } - - /** - * フリックの距離測定 - * @return フリック距離 - */ - public getFlickDistance(): number - { - return this.calculateDistance(this._startX, this._startY, this._lastX, this._lastY) - } - - /** - * 点1から点2への距離を求める - * - * @param x1 1つ目のタッチした画面のxの値 - * @param y1 1つ目のタッチした画面のyの値 - * @param x2 2つ目のタッチした画面のxの値 - * @param y2 2つ目のタッチした画面のyの値 - */ - public calculateDistance(x1: number, y1: number, x2: number, y2: number): number - { - return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); - } - - /** - * 2つ目の値から、移動量を求める。 - * 違う方向の場合は移動量0。同じ方向の場合は、絶対値が小さい方の値を参照する。 - * - * @param v1 1つ目の移動量 - * @param v2 2つ目の移動量 - * - * @return 小さい方の移動量 - */ - public calculateMovingAmount(v1: number, v2: number): number - { - if ((v1 > 0.0) != (v2 > 0.0)) - { - return 0.0; - } - - let sign: number = v1 > 0.0 ? 1.0 : -1.0; - let absoluteValue1 = Math.abs(v1); - let absoluteValue2 = Math.abs(v2); - return sign * ((absoluteValue1 < absoluteValue2) ? absoluteValue1: absoluteValue2); - } - - - _startY: number; // タッチを開始した時のxの値 - _startX: number; // タッチを開始した時のyの値 - _lastX: number; // シングルタッチ時のxの値 - _lastY: number; // シングルタッチ時のyの値 - _lastX1: number; // ダブルタッチ時の一つ目のxの値 - _lastY1: number; // ダブルタッチ時の一つ目のyの値 - _lastX2: number; // ダブルタッチ時の二つ目のxの値 - _lastY2: number; // ダブルタッチ時の二つ目のyの値 - _lastTouchDistance: number; // 2本以上でタッチしたときの指の距離 - _deltaX: number; // 前回の値から今回の値へのxの移動距離。 - _deltaY: number; // 前回の値から今回の値へのyの移動距離。 - _scale: number; // このフレームで掛け合わせる拡大率。拡大操作中以外は1。 - _touchSingle: boolean; // シングルタッチ時はtrue - _flipAvailable: boolean; // フリップが有効かどうか -} \ No newline at end of file From 751d11388721b682618d647e1136f7b62ba68dae Mon Sep 17 00:00:00 2001 From: cubism-dev Date: Thu, 25 Oct 2018 17:08:47 +0900 Subject: [PATCH 3/4] Linefeed code LF unified. --- Framework/cubismdefaultparameterid.ts | 66 + Framework/cubismframeworkconfig.ts | 32 + Framework/cubismmodelsettingjson.ts | 681 ++++++ Framework/effect/cubismbreath.ts | 140 ++ Framework/effect/cubismeyeblink.ts | 238 ++ Framework/effect/cubismpose.ts | 416 ++++ Framework/icubismallcator.ts | 47 + Framework/icubismmodelsetting.ts | 193 ++ Framework/id/cubismid.ts | 90 + Framework/id/cubismidmanager.ts | 131 ++ Framework/live2dcubismframework.ts | 283 +++ Framework/math/cubismmath.ts | 226 ++ Framework/math/cubismmatrix44.ts | 279 +++ Framework/math/cubismmodelmatrix.ts | 263 +++ Framework/math/cubismtargetpoint.ts | 172 ++ Framework/math/cubismvector2.ts | 180 ++ Framework/math/cubismviewmatrix.ts | 312 +++ Framework/model/cubismmoc.ts | 106 + Framework/model/cubismmodel.ts | 803 +++++++ Framework/model/cubismmodeluserdata.ts | 139 ++ Framework/model/cubismmodeluserdatajson.ts | 99 + Framework/model/cubismusermodel.ts | 466 ++++ Framework/motion/acubismmotion.ts | 239 ++ Framework/motion/cubismexpressionmotion.ts | 189 ++ Framework/motion/cubismmotion.ts | 805 +++++++ Framework/motion/cubismmotioninternal.ts | 157 ++ Framework/motion/cubismmotionjson.ts | 282 +++ Framework/motion/cubismmotionmanager.ts | 127 ++ Framework/motion/cubismmotionqueueentry.ts | 240 ++ Framework/motion/cubismmotionqueuemanager.ts | 342 +++ Framework/physics/cubismphysics.ts | 826 +++++++ Framework/physics/cubismphysicsinternal.ts | 248 ++ Framework/physics/cubismphysicsjson.ts | 407 ++++ Framework/rendering/cubismrenderer.ts | 312 +++ Framework/rendering/cubismrenderer_WebGL.ts | 1986 +++++++++++++++++ Framework/tsconfig.json | 13 + Framework/type/csmmap.ts | 360 +++ Framework/type/csmrectf.ts | 92 + Framework/type/csmstring.ts | 117 + Framework/type/csmvector.ts | 396 ++++ Framework/utils/cubismdebug.ts | 194 ++ Framework/utils/cubismjson.ts | 1249 +++++++++++ Framework/utils/cubismstring.ts | 136 ++ Sample/TypeScript/Demo/src/lappdefine.ts | 70 + Sample/TypeScript/Demo/src/lappdelegate.ts | 340 +++ .../TypeScript/Demo/src/lapplive2dmanager.ts | 218 ++ Sample/TypeScript/Demo/src/lappmodel.ts | 993 +++++++++ Sample/TypeScript/Demo/src/lapppal.ts | 102 + Sample/TypeScript/Demo/src/lappsprite.ts | 137 ++ .../TypeScript/Demo/src/lapptexturemanager.ts | 168 ++ Sample/TypeScript/Demo/src/lappview.ts | 290 +++ Sample/TypeScript/Demo/src/main.ts | 32 + Sample/TypeScript/Demo/src/touchmanager.ts | 199 ++ 53 files changed, 16628 insertions(+) create mode 100644 Framework/cubismdefaultparameterid.ts create mode 100644 Framework/cubismframeworkconfig.ts create mode 100644 Framework/cubismmodelsettingjson.ts create mode 100644 Framework/effect/cubismbreath.ts create mode 100644 Framework/effect/cubismeyeblink.ts create mode 100644 Framework/effect/cubismpose.ts create mode 100644 Framework/icubismallcator.ts create mode 100644 Framework/icubismmodelsetting.ts create mode 100644 Framework/id/cubismid.ts create mode 100644 Framework/id/cubismidmanager.ts create mode 100644 Framework/live2dcubismframework.ts create mode 100644 Framework/math/cubismmath.ts create mode 100644 Framework/math/cubismmatrix44.ts create mode 100644 Framework/math/cubismmodelmatrix.ts create mode 100644 Framework/math/cubismtargetpoint.ts create mode 100644 Framework/math/cubismvector2.ts create mode 100644 Framework/math/cubismviewmatrix.ts create mode 100644 Framework/model/cubismmoc.ts create mode 100644 Framework/model/cubismmodel.ts create mode 100644 Framework/model/cubismmodeluserdata.ts create mode 100644 Framework/model/cubismmodeluserdatajson.ts create mode 100644 Framework/model/cubismusermodel.ts create mode 100644 Framework/motion/acubismmotion.ts create mode 100644 Framework/motion/cubismexpressionmotion.ts create mode 100644 Framework/motion/cubismmotion.ts create mode 100644 Framework/motion/cubismmotioninternal.ts create mode 100644 Framework/motion/cubismmotionjson.ts create mode 100644 Framework/motion/cubismmotionmanager.ts create mode 100644 Framework/motion/cubismmotionqueueentry.ts create mode 100644 Framework/motion/cubismmotionqueuemanager.ts create mode 100644 Framework/physics/cubismphysics.ts create mode 100644 Framework/physics/cubismphysicsinternal.ts create mode 100644 Framework/physics/cubismphysicsjson.ts create mode 100644 Framework/rendering/cubismrenderer.ts create mode 100644 Framework/rendering/cubismrenderer_WebGL.ts create mode 100644 Framework/tsconfig.json create mode 100644 Framework/type/csmmap.ts create mode 100644 Framework/type/csmrectf.ts create mode 100644 Framework/type/csmstring.ts create mode 100644 Framework/type/csmvector.ts create mode 100644 Framework/utils/cubismdebug.ts create mode 100644 Framework/utils/cubismjson.ts create mode 100644 Framework/utils/cubismstring.ts create mode 100644 Sample/TypeScript/Demo/src/lappdefine.ts create mode 100644 Sample/TypeScript/Demo/src/lappdelegate.ts create mode 100644 Sample/TypeScript/Demo/src/lapplive2dmanager.ts create mode 100644 Sample/TypeScript/Demo/src/lappmodel.ts create mode 100644 Sample/TypeScript/Demo/src/lapppal.ts create mode 100644 Sample/TypeScript/Demo/src/lappsprite.ts create mode 100644 Sample/TypeScript/Demo/src/lapptexturemanager.ts create mode 100644 Sample/TypeScript/Demo/src/lappview.ts create mode 100644 Sample/TypeScript/Demo/src/main.ts create mode 100644 Sample/TypeScript/Demo/src/touchmanager.ts diff --git a/Framework/cubismdefaultparameterid.ts b/Framework/cubismdefaultparameterid.ts new file mode 100644 index 0000000..ad7514b --- /dev/null +++ b/Framework/cubismdefaultparameterid.ts @@ -0,0 +1,66 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +/** + * @brief パラメータIDのデフォルト値を保持する定数
+ * デフォルト値の仕様は以下のマニュアルに基づく
+ * http://docs.live2d.com/cubism-editor-manual/standard-parametor-list/ + */ +export namespace Live2DCubismFramework +{ + // パーツID + export const HitAreaPrefix: string = "HitArea"; + export const HitAreaHead: string = "Head"; + export const HitAreaBody: string = "Body"; + export const PartsIdCore: string = "Parts01Core"; + export const PartsArmPrefix: string = "Parts01Arm_"; + export const PartsArmLPrefix: string = "Parts01ArmL_"; + export const PartsArmRPrefix: string = "Parts01ArmR_"; + + // パラメータID + export const ParamAngleX: string = "ParamAngleX"; + export const ParamAngleY: string = "ParamAngleY"; + export const ParamAngleZ: string = "ParamAngleZ"; + export const ParamEyeLOpen: string = "ParamEyeLOpen"; + export const ParamEyeLSmile: string = "ParamEyeLSmile"; + export const ParamEyeROpen: string = "ParamEyeROpen"; + export const ParamEyeRSmile: string = "ParamEyeRSmile"; + export const ParamEyeBallX: string = "ParamEyeBallX"; + export const ParamEyeBallY: string = "ParamEyeBallY"; + export const ParamEyeBallForm: string = "ParamEyeBallForm"; + export const ParamBrowLY: string = "ParamBrowLY"; + export const ParamBrowRY: string = "ParamBrowRY"; + export const ParamBrowLX: string = "ParamBrowLX"; + export const ParamBrowRX: string = "ParamBrowRX"; + export const ParamBrowLAngle: string = "ParamBrowLAngle"; + export const ParamBrowRAngle: string = "ParamBrowRAngle"; + export const ParamBrowLForm: string = "ParamBrowLForm"; + export const ParamBrowRForm: string = "ParamBrowRForm"; + export const ParamMouthForm: string = "ParamMouthForm"; + export const ParamMouthOpenY: string = "ParamMouthOpenY"; + export const ParamCheek: string = "ParamCheek"; + export const ParamBodyAngleX: string = "ParamBodyAngleX"; + export const ParamBodyAngleY: string = "ParamBodyAngleY"; + export const ParamBodyAngleZ: string = "ParamBodyAngleZ"; + export const ParamBreath: string = "ParamBreath"; + export const ParamArmLA: string = "ParamArmLA"; + export const ParamArmRA: string = "ParamArmRA"; + export const ParamArmLB: string = "ParamArmLB"; + export const ParamArmRB: string = "ParamArmRB"; + export const ParamHandL: string = "ParamHandL"; + export const ParamHandR: string = "ParamHandR"; + export const ParamHairFront: string = "ParamHairFront"; + export const ParamHairSide: string = "ParamHairSide"; + export const ParamHairBack: string = "ParamHairBack"; + export const ParamHairFluffy: string = "ParamHairFluffy"; + export const ParamShoulderY: string = "ParamShoulderY"; + export const ParamBustX: string = "ParamBustX"; + export const ParamBustY: string = "ParamBustY"; + export const ParamBaseX: string = "ParamBaseX"; + export const ParamBaseY: string = "ParamBaseY"; + export const ParamNONE: string = "NONE:"; +} \ No newline at end of file diff --git a/Framework/cubismframeworkconfig.ts b/Framework/cubismframeworkconfig.ts new file mode 100644 index 0000000..b6edc37 --- /dev/null +++ b/Framework/cubismframeworkconfig.ts @@ -0,0 +1,32 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +//======================================================== +// ログ出力関数の設定 +//======================================================== + +//---------- ログ出力レベル 選択項目 定義 ---------- +/// 詳細ログ出力設定 +export const CSM_LOG_LEVEL_VERBOSE: number = 0; +/// デバッグログ出力設定 +export const CSM_LOG_LEVEL_DEBUG: number = 1; +/// Infoログ出力設定 +export const CSM_LOG_LEVEL_INFO: number = 2; +/// 警告ログ出力設定 +export const CSM_LOG_LEVEL_WARNING: number = 3; +/// エラーログ出力設定 +export const CSM_LOG_LEVEL_ERROR: number = 4; +/// ログ出力オフ設定 +export const CSM_LOG_LEVEL_OFF: number = 5; + +/** +* ログ出力レベル設定。 +* +* 強制的にログ出力レベルを変える時に定義を有効にする。 +* CSM_LOG_LEVEL_VERBOSE ~ CSM_LOG_LEVEL_OFF を選択する。 +*/ +export const CSM_LOG_LEVEL: number = CSM_LOG_LEVEL_VERBOSE; \ No newline at end of file diff --git a/Framework/cubismmodelsettingjson.ts b/Framework/cubismmodelsettingjson.ts new file mode 100644 index 0000000..b0bed8e --- /dev/null +++ b/Framework/cubismmodelsettingjson.ts @@ -0,0 +1,681 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismframework} from "./live2dcubismframework"; +import {Live2DCubismFramework as icubismmodelsetting} from "./icubismmodelsetting"; +import {Live2DCubismFramework as cubismid} from "./id/cubismid"; +import {Live2DCubismFramework as cubismjson} from "./utils/cubismjson"; +import {Live2DCubismFramework as csmmap} from"./type/csmmap"; +import csmMap = csmmap.csmMap; +import CubismFramework = cubismframework.CubismFramework; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismJson = cubismjson.CubismJson; +import Value = cubismjson.Value; +import ICubismModelSetting = icubismmodelsetting.ICubismModelSetting; + + +export namespace Live2DCubismFramework +{ + /** + * Model3Jsonのキー文字列 + */ + + // JSON Keys + const Version: string = "Version"; + const FileReferences: string = "FileReferences"; + const Groups: string = "Groups"; + const Layout: string = "Layout"; + const HitAreas: string = "HitAreas"; + + const Moc: string = "Moc"; + const Textures: string = "Textures"; + const Physics: string = "Physics"; + const Pose: string = "Pose"; + const Expressions: string = "Expressions"; + const Motions: string = "Motions"; + + const UserData: string = "UserData"; + const Name: string = "Name"; + const FilePath: string = "File"; + const Id: string = "Id"; + const Ids: string = "Ids"; + const Target: string = "Target"; + + // Motions + const Idle: string = "Idle"; + const TapBody: string = "TapBody"; + const PinchIn: string = "PinchIn"; + const PinchOut: string = "PinchOut"; + const Shake: string = "Shake"; + const FlickHead: string = "FlickHead"; + const Parameter: string = "Parameter"; + + const SoundPath: string = "Sound"; + const FadeInTime: string = "FadeInTime"; + const FadeOutTime: string = "FadeOutTime"; + + // Layout + const CenterX: string = "CenterX"; + const CenterY: string = "CenterY"; + const X: string = "X"; + const Y: string = "Y"; + const Width: string = "Width"; + const Height: string = "Height"; + + const LipSync: string = "LipSync"; + const EyeBlink: string = "EyeBlink"; + + const InitParameter: string = "init_param"; + const InitPartsVisible: string = "init_parts_visible"; + const Val: string = "val"; + + + /** + * Model3Jsonパーサー + * + * model3.jsonファイルをパースして値を取得する + */ + export class CubismModelSettingJson extends ICubismModelSetting + { + /** + * 引数付きコンストラクタ + * + * @param buffer Model3Jsonをバイト配列として読み込んだデータバッファ + * @param size Model3Jsonのデータサイズ + */ + public constructor(buffer: ArrayBuffer, size: number) + { + super(); + this._json = CubismJson.create(buffer, size); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + CubismJson.delete(this._json); + } + + /** + * CubismJsonオブジェクトを取得する + * + * @return CubismJson + */ + public GetJson(): CubismJson + { + return this._json; + } + + /** + * Mocファイルの名前を取得する + * @return Mocファイルの名前 + */ + public getModelFileName(): string + { + if(!this.isExistModelFile()) + { + return ""; + } + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Moc).getRawString(); + } + + /** + * モデルが使用するテクスチャの数を取得する + * テクスチャの数 + */ + public getTextureCount(): number + { + if(!this.isExistTextureFiles()) + { + return 0; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Textures).getSize(); + } + + /** + * テクスチャが配置されたディレクトリの名前を取得する + * @return テクスチャが配置されたディレクトリの名前 + */ + public getTextureDirectory(): string + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Textures).getRawString(); + } + + /** + * モデルが使用するテクスチャの名前を取得する + * @param index 配列のインデックス値 + * @return テクスチャの名前 + */ + public getTextureFileName(index: number): string + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Textures).getVector().at(index).getRawString(); + } + + /** + * モデルに設定された当たり判定の数を取得する + * @return モデルに設定された当たり判定の数 + */ + public getHitAreasCount(): number + { + if(!this.isExistHitAreas()) + { + return 0; + } + + return this._json.getRoot().getMap().getValue(HitAreas).getSize(); + } + + /** + * 当たり判定に設定されたIDを取得する + * + * @param index 配列のindex + * @return 当たり判定に設定されたID + */ + public getHitAreaId(index: number): CubismIdHandle + { + return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(HitAreas).getVector().at(index).getMap().getValue(Id).getRawString()); + } + + /** + * 当たり判定に設定された名前を取得する + * @param index 配列のインデックス値 + * @return 当たり判定に設定された名前 + */ + public getHitAreaName(index: number): string + { + return this._json.getRoot().getMap().getValue(HitAreas).getVector().at(index).getMap().getValue(Name).getRawString(); + } + + /** + * 物理演算設定ファイルの名前を取得する + * @return 物理演算設定ファイルの名前 + */ + public getPhysicsFileName(): string + { + if(!this.isExistPhysicsFile()) + { + return ""; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Physics).getRawString(); + } + + /** + * パーツ切り替え設定ファイルの名前を取得する + * @return パーツ切り替え設定ファイルの名前 + */ + public getPoseFileName(): string + { + if(!this.isExistPoseFile()) + { + return ""; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Pose).getRawString(); + } + + /** + * 表情設定ファイルの数を取得する + * @return 表情設定ファイルの数 + */ + public getExpressionCount(): number + { + if(!this.isExistExpressionFile()) + { + return 0; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Expressions).getSize(); + } + + /** + * 表情設定ファイルを識別する名前(別名)を取得する + * @param index 配列のインデックス値 + * @return 表情の名前 + */ + public getExpressionName(index: number): string + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Expressions).getVector().at(index).getMap().getValue(Name).getRawString(); + } + + /** + * 表情設定ファイルの名前を取得する + * @param index 配列のインデックス値 + * @return 表情設定ファイルの名前 + */ + public getExpressionFileName(index: number): string + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Expressions).getVector().at(index).getMap().getValue(FilePath).getRawString(); + } + + /** + * モーショングループの数を取得する + * @return モーショングループの数 + */ + public getMotionGroupCount(): number + { + if(!this.isExistMotionGroups()) + { + return 0; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getSize(); + } + + /** + * モーショングループの名前を取得する + * @param index 配列のインデックス値 + * @return モーショングループの名前 + */ + public getMotionGroupName(index: number): string + { + if(!this.isExistMotionGroups()) + { + return null; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getKeys().at(index); + } + + /** + * モーショングループに含まれるモーションの数を取得する + * @param groupName モーショングループの名前 + * @return モーショングループの数 + */ + public getMotionCount(groupName: string): number + { + if(!this.isExistMotionGroupName(groupName)) + { + return 0; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getSize(); + } + + /** + * グループ名とインデックス値からモーションファイル名を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return モーションファイルの名前 + */ + public getMotionFileName(groupName: string, index: number): string + { + if(!this.isExistMotionGroupName(groupName)) + { + return ""; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(FilePath).getRawString(); + } + + /** + * モーションに対応するサウンドファイルの名前を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return サウンドファイルの名前 + */ + public getMotionSoundFileName(groupName: string, index: number): string + { + if(!this.isExistMotionSoundFile(groupName, index)) + { + return ""; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(SoundPath).getRawString(); + } + + /** + * モーション開始時のフェードイン処理時間を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return フェードイン処理時間[秒] + */ + public getMotionFadeInTimeValue(groupName: string, index: number): number + { + if(!this.isExistMotionFadeIn(groupName, index)) + { + return -1.0; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(FadeInTime).toFloat(); + } + + /** + * モーション終了時のフェードアウト処理時間を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return フェードアウト処理時間[秒] + */ + public getMotionFadeOutTimeValue(groupName: string, index: number): number + { + if(!this.isExistMotionFadeOut(groupName, index)) + { + return -1.0; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().getValue(FadeOutTime).toFloat(); + } + + /** + * ユーザーデータのファイル名を取得する + * @return ユーザーデータのファイル名 + */ + public getUserDataFile(): string + { + if(!this.isExistUserDataFile()) + { + return ""; + } + + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(UserData).getRawString(); + } + + /** + * レイアウト情報を取得する + * @param outLayoutMap csmMapクラスのインスタンス + * @return true レイアウト情報が存在する + * @return false レイアウト情報が存在しない + */ + public getLayoutMap(outLayoutMap: csmMap): boolean + { + // 存在しない要素にアクセスするとエラーになるためValueがnullの場合はnullを代入する + let map: csmMap = (this._json.getRoot().getMap().isExist(Layout)) + ? this._json.getRoot().getMap().getValue(Layout).getMap() + : null; + + if(map == null) + { + return false; + } + + let ret: boolean = false; + + for(const ite: csmMap.iterator = map.begin(); ite.notEqual(map.end()); ite.preIncrement()) + { + outLayoutMap.setValue(ite.ptr().first, ite.ptr().second.toFloat()); + ret = true; + } + + return ret; + } + + /** + * 目パチに関連付けられたパラメータの数を取得する + * @return 目パチに関連付けられたパラメータの数 + */ + public getEyeBlinkParameterCount(): number + { + if (!this.isExistEyeBlinkParameters()) + { + return 0; + } + + let num: number = 0; + for (let i = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) + { + if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == EyeBlink) + { + num = this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().getSize(); + break; + } + } + + return num; + } + + /** + * 目パチに関連付けられたパラメータのIDを取得する + * @param index 配列のインデックス値 + * @return パラメータID + */ + public getEyeBlinkParameterId(index: number): CubismIdHandle + { + if (!this.isExistEyeBlinkParameters()) + { + return null; + } + + for (let i = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) + { + if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == EyeBlink) + { + return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().at(index).getRawString()); + } + } + return null; + } + + /** + * リップシンクに関連付けられたパラメータの数を取得する + * @return リップシンクに関連付けられたパラメータの数 + */ + public getLipSyncParameterCount(): number + { + if (!this.isExistLipSyncParameters()) + { + return 0; + } + + let num: number = 0; + for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) + { + if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == LipSync) + { + num = this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().getSize(); + break; + } + } + + return num; + } + + /** + * リップシンクに関連付けられたパラメータの数を取得する + * @param index 配列のインデックス値 + * @return パラメータID + */ + public getLipSyncParameterId(index: number): CubismIdHandle + { + if (!this.isExistLipSyncParameters()) + { + return null; + } + + for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); i++) + { + if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == LipSync) + { + return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Ids).getVector().at(index).getRawString()); + } + } + return null; + } + + /** + * モデルファイルのキーが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistModelFile(): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Moc); + } + + /** + * テクスチャファイルのキーが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistTextureFiles(): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Textures); + } + + /** + * 当たり判定のキーが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistHitAreas(): boolean + { + return this._json.getRoot().getMap().isExist(HitAreas); + } + + /** + * 物理演算ファイルのキーが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistPhysicsFile(): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Physics); + } + + /** + * ポーズ設定ファイルのキーが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistPoseFile(): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Pose); + } + + /** + * 表情設定ファイルのキーが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistExpressionFile(): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Expressions); + } + + /** + * モーショングループのキーが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistMotionGroups(): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Motions); + } + + /** + * 引数で指定したモーショングループのキーが存在するかどうかを確認する + * @param groupName グループ名 + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistMotionGroupName(groupName: string): boolean + { + if(!this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(Motions)) + { + return false; + } + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().isExist(groupName); + } + + /** + * 引数で指定したモーションに対応するサウンドファイルのキーが存在するかどうかを確認する + * @param groupName グループ名 + * @param index 配列のインデックス値 + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistMotionSoundFile(groupName: string, index: number): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().isExist(SoundPath); + } + + /** + * 引数で指定したモーションに対応するフェードイン時間のキーが存在するかどうかを確認する + * @param groupName グループ名 + * @param index 配列のインデックス値 + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistMotionFadeIn(groupName: string, index: number): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().isExist(FadeInTime); + } + + /** + * 引数で指定したモーションに対応するフェードアウト時間のキーが存在するかどうかを確認する + * @param groupName グループ名 + * @param index 配列のインデックス値 + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistMotionFadeOut(groupName: string, index: number): boolean + { + return this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(Motions).getMap().getValue(groupName).getVector().at(index).getMap().isExist(FadeOutTime); + } + + /** + * UserDataのファイル名が存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistUserDataFile(): boolean + { + if(!this._json.getRoot().getMap().getValue(FileReferences).getMap().isExist(UserData)) + { + return false; + } + return !this._json.getRoot().getMap().getValue(FileReferences).getMap().getValue(UserData).isNull(); + } + + /** + * 目ぱちに対応付けられたパラメータが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistEyeBlinkParameters(): boolean + { + if(!this._json.getRoot().getMap().isExist(Groups)) + { + return false; + } + for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); ++i) + { + if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == EyeBlink) + { + return true; + } + } + + return false; + } + + /** + * リップシンクに対応付けられたパラメータが存在するかどうかを確認する + * @return true キーが存在する + * @return false キーが存在しない + */ + private isExistLipSyncParameters(): boolean + { + if(!this._json.getRoot().getMap().isExist(Groups)) + { + return false; + } + for (let i: number = 0; i < this._json.getRoot().getMap().getValue(Groups).getSize(); ++i) + { + if (this._json.getRoot().getMap().getValue(Groups).getVector().at(i).getMap().getValue(Name).getRawString() == LipSync) + { + return true; + } + } + return false; + } + + + private _json: CubismJson; + } +} \ No newline at end of file diff --git a/Framework/effect/cubismbreath.ts b/Framework/effect/cubismbreath.ts new file mode 100644 index 0000000..2a2a407 --- /dev/null +++ b/Framework/effect/cubismbreath.ts @@ -0,0 +1,140 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; +import {Live2DCubismFramework as cubismid} from "../id/cubismid"; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismModel = cubismmodel.CubismModel; +import csmVector = csmvector.csmVector; + + +export namespace Live2DCubismFramework +{ + /** + * 呼吸機能 + * + * 呼吸機能を提供する。 + */ + export class CubismBreath + { + + /** + * インスタンスの作成 + */ + public static create(): CubismBreath + { + return new CubismBreath(); + } + + /** + * インスタンスの破棄 + * @param instance 対象のCubismBreath + */ + public static delete(instance: CubismBreath): void + { + instance = void 0; + instance = null; + } + + /** + * 呼吸のパラメータの紐づけ + * @param breathParameters 呼吸を紐づけたいパラメータのリスト + */ + public setParameters(breathParameters: csmVector): void + { + this._breathParameters = breathParameters; + } + + /** + * 呼吸に紐づいているパラメータの取得 + * @return 呼吸に紐づいているパラメータのリスト + */ + public getParameters(): csmVector + { + return this._breathParameters; + } + + /** + * モデルのパラメータの更新 + * @param model 対象のモデル + * @param deltaTimeSeconds デルタ時間[秒] + */ + public updateParameters(model: CubismModel, deltaTimeSeconds: number): void + { + this._currentTime += deltaTimeSeconds; + + const t: number = this._currentTime * 2.0 * 3.14159; + + for(let i: number = 0; i < this._breathParameters.getSize(); ++i) + { + let data: CubismBreath.BreathParameterData = this._breathParameters.at(i); + + model.addParameterValueById( + data.parameterId, + data.offset + (data.peak * Math.sin(t / data.cycle)), + data.weight + ); + } + } + + + /** + * コンストラクタ + */ + public constructor() + { + this._currentTime = 0.0; + } + + _breathParameters: csmVector; // 呼吸にひもづいているパラメータのリスト + _currentTime: number; // 積算時間[秒] + } + + export namespace CubismBreath + { + /** + * 呼吸のパラメータ情報 + */ + export class BreathParameterData + { + /** + * コンストラクタ + * @param parameterId 呼吸をひもづけるパラメータID + * @param offset 呼吸を正弦波としたときの、波のオフセット + * @param peak 呼吸を正弦波としたときの、波の高さ + * @param cycle 呼吸を正弦波としたときの、波の周期 + * @param weight パラメータへの重み + */ + constructor(parameterId?: CubismIdHandle, offset?: number, peak?: number, cycle?: number, weight?: number) + { + this.parameterId = (parameterId == undefined) + ? null + : parameterId; + this.offset = (offset == undefined) + ? 0.0 + : offset; + this.peak = (peak == undefined) + ? 0.0 + : peak; + this.cycle = (cycle == undefined) + ? 0.0 + : cycle; + this.weight = (weight == undefined) + ? 0.0 + : weight; + } + + parameterId: CubismIdHandle; // 呼吸をひもづけるパラメータID\ + offset: number; // 呼吸を正弦波としたときの、波のオフセット + peak: number; // 呼吸を正弦波としたときの、波の高さ + cycle: number; // 呼吸を正弦波としたときの、波の周期 + weight: number; // パラメータへの重み + } + + } +} \ No newline at end of file diff --git a/Framework/effect/cubismeyeblink.ts b/Framework/effect/cubismeyeblink.ts new file mode 100644 index 0000000..15fb7ac --- /dev/null +++ b/Framework/effect/cubismeyeblink.ts @@ -0,0 +1,238 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {Live2DCubismFramework as icubismmodelsetting} from "../icubismmodelsetting"; +import {Live2DCubismFramework as cubismid} from "../id/cubismid"; +import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; +import CubismModel = cubismmodel.CubismModel; +import CubismIdHandle = cubismid.CubismIdHandle; +import ICubismModelSetting = icubismmodelsetting.ICubismModelSetting; +import csmVector = csmvector.csmVector; + +export namespace Live2DCubismFramework +{ + /** + * 自動まばたき機能 + * + * 自動まばたき機能を提供する。 + */ + export class CubismEyeBlink + { + /** + * インスタンスを作成する + * @param modelSetting モデルの設定情報 + * @return 作成されたインスタンス + * @note 引数がNULLの場合、パラメータIDが設定されていない空のインスタンスを作成する。 + */ + public static create(modelSetting: ICubismModelSetting = null): CubismEyeBlink + { + return new CubismEyeBlink(modelSetting); + } + + /** + * インスタンスの破棄 + * @param eyeBlink 対象のCubismEyeBlink + */ + public static delete(eyeBlink: CubismEyeBlink): void + { + eyeBlink = void 0; + eyeBlink = null; + } + + /** + * まばたきの間隔の設定 + * @param blinkingInterval まばたきの間隔の時間[秒] + */ + public setBlinkingInterval(blinkingInterval: number): void + { + this._blinkingIntervalSeconds = blinkingInterval; + } + + /** + * まばたきのモーションの詳細設定 + * @param closing まぶたを閉じる動作の所要時間[秒] + * @param closed まぶたを閉じている動作の所要時間[秒] + * @param opening まぶたを開く動作の所要時間[秒] + */ + public setBlinkingSetting(closing: number, closed: number, opening: number): void + { + this._closingSeconds = closing; + this._closedSeconds = closed; + this._openingSeconds = opening; + } + + /** + * まばたきさせるパラメータIDのリストの設定 + * @param parameterIds パラメータのIDのリスト + */ + public setParameterIds(parameterIds: csmVector): void + { + this._parameterIds = parameterIds; + } + + /** + * まばたきさせるパラメータIDのリストの取得 + * @return パラメータIDのリスト + */ + public getParameterIds(): csmVector + { + return this._parameterIds; + } + + /** + * モデルのパラメータの更新 + * @param model 対象のモデル + * @param deltaTimeSeconds デルタ時間[秒] + */ + public updateParameters(model: CubismModel, deltaTimeSeconds: number): void + { + this._userTimeSeconds += deltaTimeSeconds; + let parameterValue: number; + let t: number = 0.0; + + switch(this._blinkingState) + { + case CubismEyeBlink.EyeState.EyeState_Closing: + t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._closingSeconds); + + if(t >= 1.0) + { + t = 1.0; + this._blinkingState = CubismEyeBlink.EyeState.EyeState_Closed; + this._stateStartTimeSeconds = this._userTimeSeconds; + } + + parameterValue = 1.0 - t; + + break; + case CubismEyeBlink.EyeState.EyeState_Closed: + t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._closedSeconds); + + if(t >= 1.0) + { + this._blinkingState = CubismEyeBlink.EyeState.EyeState_Opening; + this._stateStartTimeSeconds = this._userTimeSeconds; + } + + parameterValue = 0.0; + + break; + case CubismEyeBlink.EyeState.EyeState_Opening: + t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._openingSeconds); + + if(t >= 1.0) + { + t = 1.0; + this._blinkingState = CubismEyeBlink.EyeState.EyeState_Interval; + this._nextBlinkingTime = this.determinNextBlinkingTiming(); + } + + parameterValue = t; + + break; + case CubismEyeBlink.EyeState.EyeState_Interval: + if(this._nextBlinkingTime < this._userTimeSeconds) + { + this._blinkingState = CubismEyeBlink.EyeState.EyeState_Closing; + this._stateStartTimeSeconds = this._userTimeSeconds; + } + + parameterValue = 1.0; + + break; + case CubismEyeBlink.EyeState.EyeState_First: + default: + this._blinkingState = CubismEyeBlink.EyeState.EyeState_Interval; + this._nextBlinkingTime = this.determinNextBlinkingTiming(); + + parameterValue = 1.0; + break; + } + + if(!CubismEyeBlink.CloseIfZero) + { + parameterValue = -parameterValue; + } + + for(let i: number = 0; i < this._parameterIds.getSize(); ++i) + { + model.setParameterValueById(this._parameterIds.at(i), parameterValue); + } + } + + /** + * コンストラクタ + * @param modelSetting モデルの設定情報 + */ + public constructor(modelSetting: ICubismModelSetting) + { + this._blinkingState = CubismEyeBlink.EyeState.EyeState_First; + this._nextBlinkingTime = 0.0; + this._stateStartTimeSeconds = 0.0; + this._blinkingIntervalSeconds = 4.0; + this._closingSeconds = 0.1; + this._closedSeconds = 0.05; + this._openingSeconds = 0.15; + this._userTimeSeconds = 0.0; + this._parameterIds = new csmVector(); + + if(modelSetting == null) + { + return; + } + + for(let i: number = 0; i < modelSetting.getEyeBlinkParameterCount(); ++i) + { + this._parameterIds.pushBack(modelSetting.getEyeBlinkParameterId(i)); + } + } + + /** + * 次の瞬きのタイミングの決定 + * + * @return 次のまばたきを行う時刻[秒] + */ + public determinNextBlinkingTiming(): number + { + const r: number = Math.random(); + return this._userTimeSeconds + (r * (2.0 * this._blinkingIntervalSeconds - 1.0)); + } + + _blinkingState: number; // 現在の状態 + _parameterIds: csmVector; // 操作対象のパラメータのIDのリスト + _nextBlinkingTime: number; // 次のまばたきの時刻[秒] + _stateStartTimeSeconds: number; // 現在の状態が開始した時刻[秒] + _blinkingIntervalSeconds: number; // まばたきの間隔[秒] + _closingSeconds: number; // まぶたを閉じる動作の所要時間[秒] + _closedSeconds: number; // まぶたを閉じている動作の所要時間[秒] + _openingSeconds: number; // まぶたを開く動作の所要時間[秒] + _userTimeSeconds: number; // デルタ時間の積算値[秒] + } + + export namespace CubismEyeBlink + { + /** + * まばたきの状態 + * + * まばたきの状態を表す列挙型 + */ + export enum EyeState + { + EyeState_First = 0, // 初期状態 + EyeState_Interval, // まばたきしていない状態 + EyeState_Closing, // まぶたが閉じていく途中の状態 + EyeState_Closed, // まぶたが閉じている状態 + EyeState_Opening // まぶたが開いていく途中の状態 + } + + /** + * IDで指定された目のパラメータが、0のときに閉じるなら true 、1の時に閉じるなら false 。 + */ + export const CloseIfZero = true; + } +} \ No newline at end of file diff --git a/Framework/effect/cubismpose.ts b/Framework/effect/cubismpose.ts new file mode 100644 index 0000000..cd4aff6 --- /dev/null +++ b/Framework/effect/cubismpose.ts @@ -0,0 +1,416 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismid} from "../id/cubismid"; +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; +import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; +import {Live2DCubismFramework as cubismjson} from "../utils/cubismjson"; +import CubismIdHandle = cubismid.CubismIdHandle; +import csmVector = csmvector.csmVector; +import CubismModel = cubismmodel.CubismModel; +import CubismFramework = cubismframework.CubismFramework; +import CubismJson = cubismjson.CubismJson; +import Value = cubismjson.Value; + + +export namespace Live2DCubismFramework +{ + const Epsilon: number = 0.001; + const DefaultFadeInSeconds: number = 0.5; + + // Pose.jsonのタグ + const FadeIn: string = "FadeInTime"; + const Link: string = "Link"; + const Groups: string = "Groups"; + const Id: string = "Id"; + + + /** + * パーツの不透明度の設定 + * + * パーツの不透明度の管理と設定を行う。 + */ + export class CubismPose + { + /** + * インスタンスの作成 + * @param pose3json pose3.jsonのデータ + * @param size pose3.jsonのデータのサイズ[byte] + * @return 作成されたインスタンス + */ + public static create(pose3json: ArrayBuffer, size: number): CubismPose + { + let ret: CubismPose = new CubismPose(); + let json: CubismJson = CubismJson.create(pose3json, size); + let root: Value = json.getRoot(); + + // フェード時間の指定 + if(root.getMap().isExist(FadeIn)) + { + ret._fadeTimeSeconds = root.getMap().getValue(FadeIn).toFloat(DefaultFadeInSeconds); + + if(ret._fadeTimeSeconds <= 0.0) + { + ret._fadeTimeSeconds = DefaultFadeInSeconds; + } + } + + // パーツグループ + let poseListInfo: Value = root.getMap().getValue(Groups); + const poseCount: number = poseListInfo.getSize(); + + for(let poseIndex: number = 0; poseIndex < poseCount; ++poseIndex) + { + let idListInfo: Value = poseListInfo.getVector().at(poseIndex); + const idCount: number = idListInfo.getSize(); + let groupCount: number = 0; + + for(let groupIndex: number = 0; groupIndex < idCount; ++groupIndex) + { + let partInfo: Value = idListInfo.getVector().at(groupIndex); + let partData: CubismPose.PartData = new CubismPose.PartData(); + const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(partInfo.getMap().getValue(Id).getRawString()); + + partData.partId = parameterId; + + // リンクするパーツの設定 + if(partInfo.getMap().isExist(Link)) + { + let linkListInfo: Value = partInfo.getMap().getValue(Link); + const linkCount: number = linkListInfo.getSize(); + + for(let linkIndex: number = 0; linkIndex < linkCount; ++linkIndex) + { + let linkPart: CubismPose.PartData = new CubismPose.PartData(); + const linkId: CubismIdHandle = CubismFramework.getIdManager().getId(linkListInfo.getVector().at(linkIndex).getString()); + + linkPart.partId = linkId; + + partData.link.pushBack(linkPart); + } + } + + ret._partGroups.pushBack(partData.clone()); + + ++groupCount; + } + + ret._partGroupCounts.pushBack(groupCount); + } + + CubismJson.delete(json); + + return ret; + } + + /** + * インスタンスを破棄する + * @param pose 対象のCubismPose + */ + public static delete(pose: CubismPose): void + { + pose = void 0; + pose = null; + } + + /** + * モデルのパラメータの更新 + * @param model 対象のモデル + * @param deltaTimeSeconds デルタ時間[秒] + */ + public updateParameters(model: CubismModel, deltaTimeSeconds: number): void + { + // 前回のモデルと同じでない場合は初期化が必要 + if(model != this._lastModel) + { + // パラメータインデックスの初期化 + this.reset(model); + } + + this._lastModel = model; + + // 設定から時間を変更すると、経過時間がマイナスになる事があるので、経過時間0として対応 + if(deltaTimeSeconds < 0.0) + { + deltaTimeSeconds = 0.0; + } + + let beginIndex: number = 0; + + for(let i = 0; i < this._partGroupCounts.getSize(); i++) + { + const partGroupCount: number = this._partGroupCounts.at(i); + + this.doFade(model, deltaTimeSeconds, beginIndex, partGroupCount); + + beginIndex += partGroupCount; + } + + this.copyPartOpacities(model); + } + + /** + * 表示を初期化 + * @param model 対象のモデル + * @note 不透明度の初期値が0でないパラメータは、不透明度を1に設定する + */ + public reset(model: CubismModel): void + { + let beginIndex: number = 0; + + for(let i: number = 0; i < this._partGroupCounts.getSize(); ++i) + { + const groupCount: number = this._partGroupCounts.at(i); + + for(let j: number = beginIndex; j < beginIndex + groupCount; ++j) + { + this._partGroups.at(j).initialize(model); + + const partsIndex: number = this._partGroups.at(j).partIndex; + const paramIndex: number = this._partGroups.at(j).parameterIndex; + + if(partsIndex < 0) + { + continue; + } + + model.setPartOpacityByIndex(partsIndex, (j == beginIndex ? 1.0 : 0.0)); + model.setParameterValueByIndex(paramIndex, (j == beginIndex ? 1.0: 0.0)); + + for(let k: number = 0; k < this._partGroups.at(j).link.getSize(); ++k) + { + this._partGroups.at(j).link.at(k).initialize(model); + } + } + + beginIndex += groupCount; + } + } + + /** + * パーツの不透明度をコピー + * + * @param model 対象のモデル + */ + public copyPartOpacities(model: CubismModel): void + { + for(let groupIndex: number = 0; groupIndex < this._partGroups.getSize(); ++groupIndex) + { + let partData: CubismPose.PartData = this._partGroups.at(groupIndex); + + if(partData.link.getSize() == 0) + { + continue; // 連動するパラメータはない + } + + const partIndex: number = this._partGroups.at(groupIndex).partIndex; + const opacity: number = model.getPartOpacityByIndex(partIndex); + + for(let linkIndex: number = 0; linkIndex < partData.link.getSize(); ++linkIndex) + { + let linkPart: CubismPose.PartData = partData.link.at(linkIndex); + const linkPartIndex: number = linkPart.partIndex; + + if(linkPartIndex < 0) + { + continue; + } + + model.setPartOpacityByIndex(linkPartIndex, opacity); + } + } + } + + /** + * パーツのフェード操作を行う。 + * @param model 対象のモデル + * @param deltaTimeSeconds デルタ時間[秒] + * @param beginIndex フェード操作を行うパーツグループの先頭インデックス + * @param partGroupCount フェード操作を行うパーツグループの個数 + */ + public doFade(model: CubismModel, deltaTimeSeconds: number, beginIndex: number, partGroupCount: number): void + { + let visiblePartIndex: number = -1; + let newOpacity: number = 1.0; + + const phi: number = 0.5; + const backOpacityThreshold: number = 0.15; + + // 現在、表示状態になっているパーツを取得 + for(let i: number = beginIndex; i < beginIndex + partGroupCount; ++i) + { + const partIndex: number = this._partGroups.at(i).partIndex; + const paramIndex: number = this._partGroups.at(i).parameterIndex; + + if(model.getParameterValueByIndex(paramIndex) > Epsilon) + { + if(visiblePartIndex >= 0) + { + break; + } + + visiblePartIndex = i; + newOpacity = model.getPartOpacityByIndex(partIndex); + + // 新しい不透明度を計算 + newOpacity += (deltaTimeSeconds / this._fadeTimeSeconds); + + if(newOpacity > 1.0) + { + newOpacity = 1.0; + } + } + } + + if(visiblePartIndex < 0) + { + visiblePartIndex = 0; + newOpacity = 1.0; + } + + // 表示パーツ、非表示パーツの不透明度を設定する + for(let i: number = beginIndex; i < beginIndex + partGroupCount; ++i) + { + const partsIndex: number = this._partGroups.at(i).partIndex; + + // 表示パーツの設定 + if(visiblePartIndex == i) + { + model.setPartOpacityByIndex(partsIndex, newOpacity); // 先に設定 + } + // 非表示パーツの設定 + else + { + let opacity: number = model.getPartOpacityByIndex(partsIndex); + let a1: number; // 計算によって求められる不透明度 + + if(newOpacity < phi) + { + a1 = newOpacity * (phi - 1) / phi + 1.0; // (0,1),(phi,phi)を通る直線式 + } + else + { + a1 = (1 - newOpacity) * phi / (1.0 - phi); // (1,0),(phi,phi)を通る直線式 + } + + // 背景の見える割合を制限する場合 + const backOpacity: number = (1.0 - a1) * (1.0 - newOpacity); + + if(backOpacity > backOpacityThreshold) + { + a1 = 1.0 - backOpacityThreshold / (1.0 - newOpacity); + } + + if(opacity > a1) + { + opacity = a1; // 計算の不透明度よりも大きければ(濃ければ)不透明度を上げる + } + + model.setPartOpacityByIndex(partsIndex, opacity); + } + } + } + + /** + * コンストラクタ + */ + public constructor() + { + this._fadeTimeSeconds = DefaultFadeInSeconds; + this._lastModel = null; + this._partGroups = new csmVector(); + this._partGroupCounts = new csmVector(); + } + + _partGroups: csmVector; // パーツグループ + _partGroupCounts: csmVector; // それぞれのパーツグループの個数 + _fadeTimeSeconds: number; // フェード時間[秒] + _lastModel: CubismModel; // 前回操作したモデル + } + + export namespace CubismPose + { + /** + * パーツにまつわるデータを管理 + */ + export class PartData + { + /** + * コンストラクタ + */ + constructor(v?: PartData) + { + this.parameterIndex = 0; + this.partIndex = 0; + this.link = new csmVector(); + + if(v != undefined) + { + this.partId = v.partId; + + for(const ite: csmVector.iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) + { + this.link.pushBack(ite.ptr().clone()); + } + } + } + + /** + * =演算子のオーバーロード + */ + public assignment(v: PartData): PartData + { + this.partId = v.partId; + + for(const ite: csmVector.iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) + { + this.link.pushBack(ite.ptr().clone()); + } + + return this; + } + + /** + * 初期化 + * @param model 初期化に使用するモデル + */ + public initialize(model: CubismModel): void + { + this.parameterIndex = model.getParameterIndex(this.partId); + this.partIndex = model.getPartIndex(this.partId); + + model.setParameterValueByIndex(this.parameterIndex, 1); + } + + /** + * オブジェクトのコピーを生成する + */ + public clone(): PartData + { + let clonePartData: PartData = new PartData(); + + clonePartData.partId = this.partId; + clonePartData.parameterIndex = this.parameterIndex; + clonePartData.partIndex = this.partIndex; + clonePartData.link = new csmVector(); + + for(let ite: csmVector.iterator = this.link.begin(); ite.notEqual(this.link.end()); ite.increment()) + { + clonePartData.link.pushBack(ite.ptr().clone()); + } + + return clonePartData; + } + + partId: CubismIdHandle; // パーツID + parameterIndex: number; // パラメータのインデックス + partIndex: number; // パーツのインデックス + link: csmVector; // 連動するパラメータ + } + } +} \ No newline at end of file diff --git a/Framework/icubismallcator.ts b/Framework/icubismallcator.ts new file mode 100644 index 0000000..93fd333 --- /dev/null +++ b/Framework/icubismallcator.ts @@ -0,0 +1,47 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +export namespace Live2DCubismFramework +{ + /** + * メモリアロケーションを抽象化したクラス + * + * メモリ確保・解放処理をプラットフォーム側で実装して + * フレームワークから呼び出すためのインターフェース + */ + export abstract class ICubismAllocator + { + /** + * アラインメント制約なしのヒープ・メモリーを確保します + * + * @param size 確保するバイト数 + * @return 成功すると割り当てられたメモリのアドレス。そうでなければ'0'を返す + */ + public abstract allocate(size: number): any; + + /** + * アラインメント制約なしのヒープ・メモリーを解放します。 + * + * @param memory 解放するメモリのアドレス + */ + public abstract deallocate(memory: any): void; + + /** + * アラインメント制約有のヒープ・メモリーを確保します。 + * @param size 確保するバイト数 + * @param alignment メモリーブロックのアラインメント幅 + * @return 成功すると割り当てられたメモリのアドレス。そうでなければ'0'を返す + */ + public abstract allocateAligned(size: number, alignment: number): any; + + /** + * アラインメント制約ありのヒープ・メモリーを解放します。 + * @param alignedMemory 解放するメモリのアドレス + */ + public abstract deallocateAligned(alignedMemory: any): void; + } +} diff --git a/Framework/icubismmodelsetting.ts b/Framework/icubismmodelsetting.ts new file mode 100644 index 0000000..943838b --- /dev/null +++ b/Framework/icubismmodelsetting.ts @@ -0,0 +1,193 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismid} from './id/cubismid'; +import {Live2DCubismFramework as csmmap} from './type/csmmap'; +import csmMap = csmmap.csmMap; +import CubismIdHandle = cubismid.CubismIdHandle; + +export namespace Live2DCubismFramework +{ + /** + * モデル設定情報を取り扱う関数を宣言した純粋仮想クラス。 + * + * このクラスを継承することで、モデル設定情報を取り扱うクラスになる。 + */ + export abstract class ICubismModelSetting + { + /** + * Mocファイルの名前を取得する + * @return Mocファイルの名前 + */ + public abstract getModelFileName(): string; + + /** + * モデルが使用するテクスチャの数を取得する + * テクスチャの数 + */ + public abstract getTextureCount(): number; + + /** + * テクスチャが配置されたディレクトリの名前を取得する + * @return テクスチャが配置されたディレクトリの名前 + */ + public abstract getTextureDirectory(): string; + + /** + * モデルが使用するテクスチャの名前を取得する + * @param index 配列のインデックス値 + * @return テクスチャの名前 + */ + public abstract getTextureFileName(index: number): string; + + /** + * モデルに設定された当たり判定の数を取得する + * @return モデルに設定された当たり判定の数 + */ + public abstract getHitAreasCount(): number; + + /** + * 当たり判定に設定されたIDを取得する + * + * @param index 配列のindex + * @return 当たり判定に設定されたID + */ + public abstract getHitAreaId(index: number): CubismIdHandle; + + /** + * 当たり判定に設定された名前を取得する + * @param index 配列のインデックス値 + * @return 当たり判定に設定された名前 + */ + public abstract getHitAreaName(index: number): string; + + /** + * 物理演算設定ファイルの名前を取得する + * @return 物理演算設定ファイルの名前 + */ + public abstract getPhysicsFileName(): string; + + /** + * パーツ切り替え設定ファイルの名前を取得する + * @return パーツ切り替え設定ファイルの名前 + */ + public abstract getPoseFileName(): string; + + /** + * 表情設定ファイルの数を取得する + * @return 表情設定ファイルの数 + */ + public abstract getExpressionCount(): number; + + /** + * 表情設定ファイルを識別する名前(別名)を取得する + * @param index 配列のインデックス値 + * @return 表情の名前 + */ + public abstract getExpressionName(index: number): string; + + /** + * 表情設定ファイルの名前を取得する + * @param index 配列のインデックス値 + * @return 表情設定ファイルの名前 + */ + public abstract getExpressionFileName(index: number): string; + + /** + * モーショングループの数を取得する + * @return モーショングループの数 + */ + public abstract getMotionGroupCount(): number; + + /** + * モーショングループの名前を取得する + * @param index 配列のインデックス値 + * @return モーショングループの名前 + */ + public abstract getMotionGroupName(index: number): string; + + /** + * モーショングループに含まれるモーションの数を取得する + * @param groupName モーショングループの名前 + * @return モーショングループの数 + */ + public abstract getMotionCount(groupName: string): number; + + /** + * グループ名とインデックス値からモーションファイル名を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return モーションファイルの名前 + */ + public abstract getMotionFileName(groupName: string, index: number): string; + + /** + * モーションに対応するサウンドファイルの名前を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return サウンドファイルの名前 + */ + public abstract getMotionSoundFileName(groupName: string, index: number): string; + + /** + * モーション開始時のフェードイン処理時間を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return フェードイン処理時間[秒] + */ + public abstract getMotionFadeInTimeValue(groupName: string, index: number): number; + + /** + * モーション終了時のフェードアウト処理時間を取得する + * @param groupName モーショングループの名前 + * @param index 配列のインデックス値 + * @return フェードアウト処理時間[秒] + */ + public abstract getMotionFadeOutTimeValue(groupName: string, index: number): number; + + /** + * ユーザーデータのファイル名を取得する + * @return ユーザーデータのファイル名 + */ + public abstract getUserDataFile(): string; + + /** + * レイアウト情報を取得する + * @param outLayoutMap csmMapクラスのインスタンス + * @return true レイアウト情報が存在する + * @return false レイアウト情報が存在しない + */ + public abstract getLayoutMap(outLayoutMap: csmMap): boolean; + + + /** + * 目パチに関連付けられたパラメータの数を取得する + * @return 目パチに関連付けられたパラメータの数 + */ + public abstract getEyeBlinkParameterCount(): number; + + /** + * 目パチに関連付けられたパラメータのIDを取得する + * @param index 配列のインデックス値 + * @return パラメータID + */ + public abstract getEyeBlinkParameterId(index: number): CubismIdHandle; + + /** + * リップシンクに関連付けられたパラメータの数を取得する + * @return リップシンクに関連付けられたパラメータの数 + */ + public abstract getLipSyncParameterCount(): number; + + /** + * リップシンクに関連付けられたパラメータの数を取得する + * @param index 配列のインデックス値 + * @return パラメータID + */ + public abstract getLipSyncParameterId(index: number): CubismIdHandle; + } +} \ No newline at end of file diff --git a/Framework/id/cubismid.ts b/Framework/id/cubismid.ts new file mode 100644 index 0000000..3ab56fb --- /dev/null +++ b/Framework/id/cubismid.ts @@ -0,0 +1,90 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as csmstring} from "../type/csmstring"; +import csmString = csmstring.csmString; + +export namespace Live2DCubismFramework +{ + /** + * パラメータ名・パーツ名・Drawable名を保持 + * + * パラメータ名・パーツ名・Drawable名を保持するクラス。 + */ + export class CubismId + { + /** + * ID名を取得する + */ + public getString(): csmString + { + return this._id; + } + + /** + * コンストラクタ + */ + public constructor(id: string | csmString) + { + if(typeof(id) === 'string') + { + this._id = new csmString(id); + return; + } + + this._id = id; + } + + /** + * idを比較 + * @param c 比較するid + * @return 同じならばtrue,異なっていればfalseを返す + */ + public isEqual(c: string | csmString | CubismId): boolean + { + if (typeof(c) === 'string') + { + return this._id.isEqual(c); + } + else if (c instanceof csmString) + { + return this._id.isEqual(c.s); + } + else if (c instanceof CubismId) + { + return this._id.isEqual(c._id.s); + } + return false; + } + + /** + * idを比較 + * @param c 比較するid + * @return 同じならばtrue,異なっていればfalseを返す + */ + public isNotEqual(c: string | csmString | CubismId): boolean + { + if (typeof(c) == 'string') + { + return !this._id.isEqual(c); + } + else if (c instanceof csmString) + { + return !this._id.isEqual(c.s); + } + else if (c instanceof CubismId) + { + return !this._id.isEqual(c._id.s); + } + return false; + } + + private _id: csmString; // ID名 + } + + export declare type CubismIdHandle = CubismId; +} \ No newline at end of file diff --git a/Framework/id/cubismidmanager.ts b/Framework/id/cubismidmanager.ts new file mode 100644 index 0000000..012c70f --- /dev/null +++ b/Framework/id/cubismidmanager.ts @@ -0,0 +1,131 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {Live2DCubismFramework as cubismid} from "./cubismid"; +import {Live2DCubismFramework as csmstring} from "../type/csmstring"; +import csmString = csmstring.csmString; +import CubismId = cubismid.CubismId; +import csmVector = csmvector.csmVector; + +export namespace Live2DCubismFramework +{ + /** + * ID名の管理 + * + * ID名を管理する。 + */ + export class CubismIdManager + { + /** + * コンストラクタ + */ + public constructor() + { + this._ids = new csmVector(); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + for(let i: number = 0; i < this._ids.getSize(); ++i) + { + this._ids.set(i, void 0); + } + this._ids = null; + } + + /** + * ID名をリストから登録 + * + * @param ids ID名リスト + * @param count IDの個数 + */ + public registerIds(ids: string[] | csmString[]): void + { + for(let i: number = 0; i < ids.length; i++) + { + this.registerId(ids[i]); + } + } + + /** + * ID名を登録 + * + * @param id ID名 + */ + public registerId(id: string | csmString): CubismId + { + let result: CubismId = null; + + if ('string' == typeof(id)) + { + if ((result = this.findId(id)) != null) + { + return result; + } + + result = new CubismId(id); + this._ids.pushBack(result); + } + else + { + return this.registerId(id.s); + } + + return result; + } + + /** + * ID名からIDを取得する + * + * @param id ID名 + */ + public getId(id: csmString | string): CubismId + { + return this.registerId(id); + } + + /** + * ID名からIDの確認 + * + * @return true 存在する + * @return false 存在しない + */ + public isExist(id: csmString | string): boolean + { + if ('string' == typeof(id)) + { + return (this.findId(id) != null); + } + return this.isExist(id.s); + } + + /** + * ID名からIDを検索する。 + * + * @param id ID名 + * @return 登録されているID。なければNULL。 + */ + private findId(id: string): CubismId + { + for(let i: number = 0; i < this._ids.getSize(); ++i) + { + if(this._ids.at(i).getString().isEqual(id)) + { + return this._ids.at(i); + } + } + + return null; + } + + private _ids: csmVector; // 登録されているIDのリスト + } +} \ No newline at end of file diff --git a/Framework/live2dcubismframework.ts b/Framework/live2dcubismframework.ts new file mode 100644 index 0000000..692acbe --- /dev/null +++ b/Framework/live2dcubismframework.ts @@ -0,0 +1,283 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismjson} from "./utils/cubismjson"; +import {Live2DCubismFramework as cubismidmanager} from "./id/cubismidmanager"; +import {Live2DCubismFramework as cubismrenderer} from "./rendering/cubismrenderer"; +import {CubismLogInfo, CubismLogWarning, CSM_ASSERT} from "./utils/cubismdebug"; +import Value = cubismjson.Value; +import CubismIdManager = cubismidmanager.CubismIdManager; +import CubismRenderer = cubismrenderer.CubismRenderer; + +export function strtod(s: string, endPtr: string[]): number +{ + let index: number = 0; + for(let i: number = 1; ; i++) + { + let testC: string = s.slice(i - 1, i); + + // 指数・マイナスの可能性があるのでスキップする + if(testC=='e' || testC=='-' || testC == 'E') + { + continue; + } + +    // 文字列の範囲を広げていく + let test: string = s.substring(0, i); + let number: number = Number(test); + if(isNaN(number)) + { +     // 数値として認識できなくなったので終了 + break; + } + +    // 最後に数値としてできたindexを格納しておく + index = i; + } + let d = parseFloat(s); // パースした数値 + + if(isNaN(d)) + { +     // 数値として認識できなくなったので終了 + d = NaN; + } + + endPtr[0] = s.slice(index); // 後続の文字列 + + return d; +} + +export namespace Live2DCubismFramework +{ + // ファイルスコープの変数を初期化 + + let s_isStarted: boolean = false; + let s_isInitialized: boolean = false; + let s_option: Option = null; + let s_cubismIdManager: CubismIdManager = null; + + /** + * Framework内で使う定数の宣言 + */ + export namespace Constant + { + export const vertexOffset: number = 0; // メッシュ頂点のオフセット値 + export const vertexStep: number = 2; // メッシュ頂点のステップ値 + } + + export function csmDelete(address: T): void + { + if(!address) + { + return; + } + + address = void 0; + } + + /** + * Live2D Cubism3 Original Workflow SDKのエントリポイント + * 利用開始時はCubismFramework.initialize()を呼び、CubismFramework.dispose()で終了する。 + */ + export class CubismFramework + { + /** + * @brief Cubism FrameworkのAPIを使用可能にする。
+ * APIを実行する前に必ずこの関数を実行すること。
+ * 引数に必ずメモリアロケータを渡してください。
+ * 一度準備が完了して以降は、再び実行しても内部処理がスキップされます。 + * + * @param allocator ICubismAllocatorクラスのインスタンス + * @param option Optionクラスのインスタンス + * + * @return 準備処理が完了したらtrueが返ります。 + */ + public static startUp(option: Option = null): boolean + { + if(s_isStarted) + { + CubismLogInfo("CubismFramework::StartUp() is already done."); + return s_isStarted; + } + + s_option = option; + + if(s_option != null) + { + // TODO Core::csmSetLogFunction(s_option->LogFunction); + } + + s_isStarted = true; + + // Live2D Cubism Coreバージョン情報を表示 + if(s_isStarted) + { + const version: number = 1; // TODO Core::csmGetVersion() + const major: number = ((version & 0xFF000000) >> 24); + const minor: number = ((version & 0x00FF0000) >> 16); + const patch: number = ((version & 0x0000FFFF)); + const versionNumber: number = version; + + CubismLogInfo("Live2D Cubism Core version: %02d.%02d.%04d (%d)", major, minor, patch, versionNumber); + } + + CubismLogInfo("CubismFramework::StartUp() is complete."); + + return s_isStarted; + } + + /** + * StartUp()で初期化したCubismFrameworkの各パラメータをクリアします。 + * Dispose()したCubismFrameworkを再利用する際に利用してください。 + */ + public static cleanUp(): void + { + s_isStarted = false; + s_isInitialized = false; + s_option = null; + s_cubismIdManager = null; + } + + /** + * Cubism Framework内のリソースを初期化してモデルを表示可能な状態にします。
+ * 再度Initialize()するには先にDispose()を実行する必要があります。 + */ + public static initialize(): void + { + CSM_ASSERT(s_isStarted); + if(!s_isStarted) + { + CubismLogWarning("CubismFramework is not started."); + return; + } + + // --- s_isInitializedによる連続初期化ガード --- + // 連続してリソース確保が行われないようにする。 + // 再度Initialize()するには先にDispose()を実行する必要がある。 + if (s_isInitialized) + { + CubismLogWarning("CubismFramework::Initialize() skipped, already initialized."); + return; + } + + //---- static 初期化 ---- + Value.staticInitializeNotForClientCall(); + + s_cubismIdManager = new CubismIdManager(); + + s_isInitialized = true; + + CubismLogInfo("CubismFramework::Initialize() is complete."); + } + + /** + * Cubism Framework内の全てのリソースを解放します。 + * ただし、外部で確保されたリソースについては解放しません。 + * 外部で適切に破棄する必要があります。 + */ + public static dispose(): void + { + CSM_ASSERT(s_isStarted); + if(!s_isStarted) + { + CubismLogWarning("CubismFramework is not started."); + return; + } + + // --- s_isInitializedによる未初期化解放ガード --- + // dispose()するには先にinitialize()を実行する必要がある。 + if(!s_isInitialized) // false...リソース未確保の場合 + { + CubismLogWarning("CubismFramework::Dispose() skipped, not initialized."); + return; + } + + Value.staticReleaseNotForClientCall(); + + s_cubismIdManager.release(); + s_cubismIdManager = void 0; + + // レンダラの静的リソース(シェーダプログラム他)を解放する + CubismRenderer.StaticRelease(); + + s_isInitialized = false; + + CubismLogInfo("CubismFramework::Dispose() is complete."); + } + + /** + * 現在のログ出力レベル設定の値を返す。 + * + * @return 現在のログ出力レベル設定の値 + */ + public static getLoggingLevel(): Option.LogLevel + { + if (s_option != null) + { + return s_option.loggingLevel; + } + return Option.LogLevel.LogLevel_Off; + } + + /** + * Cubism FrameworkのAPIを使用する準備が完了したかどうか + * @return APIを使用する準備が完了していればtrueが返ります。 + */ + public static isStarted(): boolean + { + return s_isStarted; + } + + /** + * Cubism Frameworkのリソース初期化がすでに行われているかどうか + * @return リソース確保が完了していればtrueが返ります + */ + public static isInitialized(): boolean + { + return s_isInitialized; + } + + /** + * IDマネージャのインスタンスを取得する + * @return CubismManagerクラスのインスタンス + */ + public static getIdManager(): CubismIdManager + { + return s_cubismIdManager; + } + + /** + * 静的クラスとして使用する + * インスタンス化させない + */ + private constructor() + { + + } + } +} + +export class Option +{ + loggingLevel: Option.LogLevel; // ログ出力レベルの設定 +} + +/** + * ログ出力のレベル + */ +export namespace Option +{ + export enum LogLevel + { + LogLevel_Verbose = 0, // 詳細ログ + LogLevel_Debug, // デバッグログ + LogLevel_Info, // Infoログ + LogLevel_Warning, // 警告ログ + LogLevel_Error, // エラーログ + LogLevel_Off // ログ出力無効 + } +} diff --git a/Framework/math/cubismmath.ts b/Framework/math/cubismmath.ts new file mode 100644 index 0000000..6e62b58 --- /dev/null +++ b/Framework/math/cubismmath.ts @@ -0,0 +1,226 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismvector2} from "./cubismvector2"; +import CubismVector2 = cubismvector2.CubismVector2; + +export namespace Live2DCubismFramework +{ + /** + * 数値計算などに使用するユーティリティクラス + */ + export class CubismMath + { + /** + * 第一引数の値を最小値と最大値の範囲に収めた値を返す + * + * @param value 収められる値 + * @param min 範囲の最小値 + * @param max 範囲の最大値 + * @return 最小値と最大値の範囲に収めた値 + */ + static range(value: number, min: number, max: number): number + { + if (value < min) + { + value = min; + } + else if (value > max) + { + value = max; + } + + return value; + } + + /** + * サイン関数の値を求める + * + * @param x 角度値(ラジアン) + * @return サイン関数sin(x)の値 + */ + static sin(x: number): number + { + return Math.sin(x); + } + + /** + * コサイン関数の値を求める + * + * @param x 角度値(ラジアン) + * @return コサイン関数cos(x)の値 + */ + static cos(x: number): number + { + return Math.cos(x); + } + + /** + * 値の絶対値を求める + * + * @param x 絶対値を求める値 + * @return 値の絶対値 + */ + static abs(x: number): number + { + return Math.abs(x); + } + + /** + * 平方根(ルート)を求める + * @param x -> 平方根を求める値 + * @return 値の平方根 + */ + static sqrt(x: number): number + { + return Math.sqrt(x); + } + + /** + * イージング処理されたサインを求める + * フェードイン・アウト時のイージングに利用できる + * + * @param value イージングを行う値 + * @return イージング処理されたサイン値 + */ + static getEasingSine(value: number): number + { + if (value < 0.0) + { + return 0.0; + } + else if (value > 1.0) + { + return 1.0; + } + + return 0.5 - 0.5 * this.cos(value * Math.PI); + } + + /** + * 大きい方の値を返す + * + * @param left 左辺の値 + * @param right 右辺の値 + * @return 大きい方の値 + */ + static max(left: number, right: number): number + { + return (left > right) + ? left + : right; + } + + /** + * 小さい方の値を返す + * + * @param left 左辺の値 + * @param right 右辺の値  + * @return 小さい方の値 + */ + static min(left: number, right: number): number + { + return (left > right) + ? right + : left; + } + + /** + * 角度値をラジアン値に変換する + * + * @param degrees 角度値 + * @return 角度値から変換したラジアン値 + */ + static degreesToRadian(degrees: number): number + { + return (degrees / 180.0) * Math.PI; + } + + /** + * ラジアン値を角度値に変換する + * + * @param radian ラジアン値 + * @return ラジアン値から変換した角度値 + */ + static radianToDegrees(radian: number): number + { + return (radian * 180.0) / Math.PI; + } + + /** + * 2つのベクトルからラジアン値を求める + * + * @param from 始点ベクトル + * @param to 終点ベクトル + * @return ラジアン値から求めた方向ベクトル + */ + static directionToRadian(from: CubismVector2, to: CubismVector2): number + { + const q1: number = Math.atan2(to.y, to.x); + const q2: number = Math.atan2(from.y, from.x); + + let ret: number = q1 - q2; + + while(ret < -Math.PI) + { + ret += Math.PI * 2.0; + } + + while(ret > Math.PI) + { + ret -= Math.PI * 2.0; + } + + return ret; + } + + /** + * 2つのベクトルから角度値を求める + * + * @param from 始点ベクトル + * @param to 終点ベクトル + * @return 角度値から求めた方向ベクトル + */ + static directionToDegrees(from: CubismVector2, to: CubismVector2): number + { + const radian: number = this.directionToRadian(from, to); + let degree: number = this.radianToDegrees(radian); + + if ((to.x - from.x) > 0.0) + { + degree = -degree; + } + + return degree; + } + + /** + * ラジアン値を方向ベクトルに変換する。 + * + * @param totalAngle ラジアン値 + * @return ラジアン値から変換した方向ベクトル + */ + + static radianToDirection(totalAngle: number): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(); + + ret.x = this.sin(totalAngle); + ret.y = this.cos(totalAngle); + + return ret; + } + + /** + * コンストラクタ + */ + private constructor() + { + + } + } +} \ No newline at end of file diff --git a/Framework/math/cubismmatrix44.ts b/Framework/math/cubismmatrix44.ts new file mode 100644 index 0000000..bef0756 --- /dev/null +++ b/Framework/math/cubismmatrix44.ts @@ -0,0 +1,279 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +export namespace Live2DCubismFramework +{ + /** + * 4x4の行列 + * + * 4x4行列の便利クラス。 + */ + export class CubismMatrix44 + { + /** + * コンストラクタ + */ + public constructor() + { + this._tr = new Float32Array(16); // 4 * 4のサイズ + this.loadIdentity(); + } + + /** + * 受け取った2つの行列の乗算を行う。 + * + * @param a 行列a + * @param b 行列b + * @return 乗算結果の行列 + */ + public static multiply(a: Float32Array, b: Float32Array, dst: Float32Array): void + { + let c: Float32Array = new Float32Array( + [ + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0 + ] + ); + + let n: number = 4; + + for (let i: number = 0; i < n; ++i) + { + for(let j: number = 0; j < n; ++j) + { + for(let k: number = 0; k < n; ++k) + { + c[j + i * 4] += a[k + i * 4] * b[j + k * 4]; + } + } + } + + for(let i: number = 0; i < 16; ++i) + { + dst[i] = c[i]; + } + } + + /** + * 単位行列に初期化する + */ + public loadIdentity(): void + { + let c: Float32Array = new Float32Array( + [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ] + ); + + this.setMatrix(c); + } + + /** + * 行列を設定 + * + * @param tr 16個の浮動小数点数で表される4x4の行列 + */ + public setMatrix(tr: Float32Array): void + { + for(let i = 0; i < 16; ++i) + { + this._tr[i] = tr[i]; + } + } + + /** + * 行列を浮動小数点数の配列で取得 + * + * @return 16個の浮動小数点数で表される4x4の行列 + */ + public getArray(): Float32Array + { + return this._tr; + } + + /** + * X軸の拡大率を取得 + * @return X軸の拡大率 + */ + public getScaleX(): number + { + return this._tr[0]; + } + + /** + * Y軸の拡大率を取得する + * + * @return Y軸の拡大率 + */ + public getScaleY(): number + { + return this._tr[5]; + } + + /** + * X軸の移動量を取得 + * @return X軸の移動量 + */ + public getTranslateX(): number + { + return this._tr[12]; + } + + /** + * Y軸の移動量を取得 + * @return Y軸の移動量 + */ + public getTranslateY(): number + { + return this._tr[13]; + } + + /** + * X軸の値を現在の行列で計算 + * + * @param src X軸の値 + * @return 現在の行列で計算されたX軸の値 + */ + public transformX(src: number): number + { + return this._tr[0] * src + this._tr[12]; + } + + /** + * Y軸の値を現在の行列で計算 + * + * @param src Y軸の値 + * @return 現在の行列で計算されたY軸の値 + */ + public transformY(src: number): number + { + return this._tr[5] * src + this._tr[13]; + } + + /** + * X軸の値を現在の行列で逆計算 + */ + public invertTransformX(src: number): number + { + return (src - this._tr[12]) / this._tr[0]; + } + + /** + * Y軸の値を現在の行列で逆計算 + */ + public invertTransformY(src: number): number + { + return (src - this._tr[13]) / this._tr[5]; + } + + /** + * 現在の行列の位置を起点にして移動 + * + * 現在の行列の位置を起点にして相対的に移動する。 + * + * @param x X軸の移動量 + * @param y Y軸の移動量 + */ + public translateRelative(x: number, y: number): void + { + let tr1: Float32Array = new Float32Array( + [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + x, y, 0.0, 1.0 + ] + ); + + CubismMatrix44.multiply(tr1, this._tr, this._tr); + } + + /** + * 現在の行列の位置を移動 + * + * 現在の行列の位置を指定した位置へ移動する + * + * @param x X軸の移動量 + * @param y y軸の移動量 + */ + public translate(x: number, y: number): void + { + this._tr[12] = x; + this._tr[13] = y; + } + + /** + * 現在の行列のX軸の位置を指定した位置へ移動する + * + * @param x X軸の移動量 + */ + public translateX(x: number): void + { + this._tr[12] = x; + } + + /** + * 現在の行列のY軸の位置を指定した位置へ移動する + * + * @param y Y軸の移動量 + */ + public translateY(y: number): void + { + this._tr[13] = y; + } + + + /** + * 現在の行列の拡大率を相対的に設定する + * + * @param x X軸の拡大率 + * @param y Y軸の拡大率 + */ + public scaleRelative(x: number, y:number): void + { + let tr1: Float32Array = new Float32Array( + [ + x, 0.0, 0.0, 0.0, + 0.0, y, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ] + ); + + CubismMatrix44.multiply(tr1, this._tr, this._tr); + } + + /** + * 現在の行列の拡大率を指定した倍率に設定する + * + * @param x X軸の拡大率 + * @param y Y軸の拡大率 + */ + public scale(x: number, y: number): void + { + this._tr[0] = x; + this._tr[5] = y; + } + + /** + * 現在の行列に行列を乗算 + * + * @param m 行列 + */ + public multiplyByMatrix(m: CubismMatrix44): void + { + CubismMatrix44.multiply(m.getArray(), this._tr, this._tr); + } + + protected _tr: Float32Array; // 4x4行列データ + } +} \ No newline at end of file diff --git a/Framework/math/cubismmodelmatrix.ts b/Framework/math/cubismmodelmatrix.ts new file mode 100644 index 0000000..aa694be --- /dev/null +++ b/Framework/math/cubismmodelmatrix.ts @@ -0,0 +1,263 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as csmmap} from "../type/csmmap"; +import {Live2DCubismFramework as cubismmatrix44} from "./cubismmatrix44"; +import csmMap = csmmap.csmMap; +import CubismMatrix44 = cubismmatrix44.CubismMatrix44; + + +export namespace Live2DCubismFramework +{ + /** + * モデル座標設定用の4x4行列 + * + * モデル座標設定用の4x4行列クラス + */ + export class CubismModelMatrix extends CubismMatrix44 + { + /** + * コンストラクタ + * + * @param w 横幅 + * @param h 縦幅 + */ + constructor(w?: number, h?: number) + { + super(); + + this._width = (w !== undefined) + ? w + : 0.0; + this._height = (h !== undefined) + ? h + : 0.0; + + // 原点(0, 0)を中心にして、画面に納まるような大きさで初期化 + if (this._width > this._height) + { + this.setWidth(this._height / this._width); + } + else + { + this.setHeight(1.0); + } + } + + /** + * 横幅を設定 + * + * @param w 横幅 + */ + public setWidth(w: number): void + { + const scaleX: number = w / this._width; + const scaleY: number = scaleX; + this.scale(scaleX, scaleY); + } + + /** + * 縦幅を設定 + * @param h 縦幅 + */ + public setHeight(h: number): void + { + const scaleX: number = h / this._height; + const scaleY: number = scaleX; + this.scale(scaleX, scaleY); + } + + /** + * 位置を設定 + * + * @param x X軸の位置 + * @param y Y軸の位置 + */ + public setPosition(x: number, y: number): void + { + this.translate(x, y); + } + + /** + * 中心位置を設定 + * + * @param x X軸の中心位置 + * @param y Y軸の中心位置 + * + * @note widthかheightを設定したあとでないと、拡大率が正しく取得できないためずれる。 + */ + public setCenterPosition(x: number, y: number) + { + this.centerX(x); + this.centerY(y); + } + + /** + * 上辺の位置を設定する + * + * @param y 上辺のY軸位置 + */ + public top(y: number): void + { + this.setY(y); + } + + /** + * 下辺の位置を設定する + * + * @param y 下辺のY軸位置 + */ + public bottom(y: number) + { + const h: number = this._height * this.getScaleY(); + + this.translateY(y - h); + } + + /** + * 左辺の位置を設定 + * + * @param x 左辺のX軸位置 + */ + public left(x: number): void + { + this.setX(x); + } + + /** + * 右辺の位置を設定 + * + * @param x 右辺のX軸位置 + */ + public right(x: number): void + { + const w = this._width * this.getScaleX(); + + this.translateX(x - w); + } + + /** + * X軸の中心位置を設定 + * + * @param x X軸の中心位置 + */ + public centerX(x: number): void + { + const w = this._width * this.getScaleX(); + + this.translateX(x - (w / 2.0)); + } + + /** + * X軸の位置を設定 + * + * @param x X軸の位置 + */ + public setX(x: number): void + { + this.translateX(x); + } + + /** + * Y軸の中心位置を設定 + * + * @param y Y軸の中心位置 + */ + public centerY(y: number): void + { + const h: number = this._height * this.getScaleY(); + + this.translateY(y - (h / 2.0)); + } + + /** + * Y軸の位置を設定する + * + * @param y Y軸の位置 + */ + public setY(y: number): void + { + this.translateY(y); + } + + /** + * レイアウト情報から位置を設定 + * + * @param layout レイアウト情報 + */ + public setupFromLayout(layout: csmMap): void + { + const keyWidth = "width"; + const keyHeight = "height"; + const keyX = "x"; + const keyY = "y"; + const keyCenterX = "center_x"; + const keyCenterY = "center_y"; + const keyTop = "top"; + const keyBottom = "bottom"; + const keyLeft = "left"; + const keyRight = "right"; + + for(const ite: csmMap.iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) + { + const key: string = ite.ptr().first; + const value: number = ite.ptr().second; + + if(key == keyWidth) + { + this.setWidth(value); + } + else if(key == keyHeight) + { + this.setHeight(value); + } + } + + for(const ite: csmMap.iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) + { + const key: string = ite.ptr().first; + const value: number = ite.ptr().second; + + if(key == keyX) + { + this.setX(value); + } + else if(key == keyY) + { + this.setY(value); + } + else if(key == keyCenterX) + { + this.centerX(value); + } + else if(key == keyCenterY) + { + this.centerY(value); + } + else if(key == keyTop) + { + this.top(value); + } + else if(key == keyBottom) + { + this.bottom(value); + } + else if(key == keyLeft) + { + this.left(value); + } + else if(key == keyRight) + { + this.right(value); + } + } + } + + private _width: number; // 横幅 + private _height: number; // 縦幅 + } +} \ No newline at end of file diff --git a/Framework/math/cubismtargetpoint.ts b/Framework/math/cubismtargetpoint.ts new file mode 100644 index 0000000..f27f3f6 --- /dev/null +++ b/Framework/math/cubismtargetpoint.ts @@ -0,0 +1,172 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismmath} from "./cubismmath"; +import CubismMath = cubismmath.CubismMath; + + +export namespace Live2DCubismFramework +{ + const FrameRate: number = 30; + const Epsilon: number = 0.01; + + /** + * 顔の向きの制御機能 + * + * 顔の向きの制御機能を提供するクラス。 + */ + export class CubismTargetPoint + { + /** + * コンストラクタ + */ + public constructor() + { + this._faceTargetX = 0.0; + this._faceTargetY = 0.0; + this._faceX = 0.0; + this._faceY = 0.0; + this._faceVX = 0.0; + this._faceVY = 0.0; + this._lastTimeSeconds = 0.0; + this._userTimeSeconds = 0.0; + } + + /** + * 更新処理 + */ + public update(deltaTimeSeconds: number): void + { + // デルタ時間を加算する + this._userTimeSeconds += deltaTimeSeconds; + + // 首を中央から左右に振るときの平均的な速さは 秒速度。加速・減速を考慮して、その2倍を最高速度とする + // 顔の振り具合を、中央(0.0)から、左右は(+-1.0)とする + const faceParamMaxV: number = 40.0 / 10.0; // 7.5秒間に40分移動(5.3/sc) + const maxV: number = faceParamMaxV * 1.0 / FrameRate; // 1frameあたりに変化できる速度の上限 + + if(this._lastTimeSeconds == 0.0) + { + this._lastTimeSeconds = this._userTimeSeconds; + return; + } + + const deltaTimeWeight: number = (this._userTimeSeconds - this._lastTimeSeconds) * FrameRate; + this._lastTimeSeconds = this._userTimeSeconds; + + // 最高速度になるまでの時間を + const timeToMaxSpeed: number = 0.15; + const frameToMaxSpeed: number = timeToMaxSpeed * FrameRate; // sec * frame/sec + const maxA: number = deltaTimeWeight * maxV / frameToMaxSpeed; // 1frameあたりの加速度 + + // 目指す向きは、(dx, dy)方向のベクトルとなる + const dx: number = this._faceTargetX - this._faceX; + const dy: number = this._faceTargetY - this._faceY; + + if(CubismMath.abs(dx) <= Epsilon && CubismMath.abs(dy) <= Epsilon) + { + return; // 変化なし + } + + // 速度の最大よりも大きい場合は、速度を落とす + const d: number = CubismMath.sqrt((dx * dx) + (dy * dy)); + + // 進行方向の最大速度ベクトル + const vx: number = maxV * dx / d; + const vy: number = maxV * dy / d; + + // 現在の速度から、新規速度への変化(加速度)を求める + let ax: number = vx - this._faceVX; + let ay: number = vy - this._faceVY; + + const a: number = CubismMath.sqrt((ax * ax) + (ay * ay)); + + // 加速のとき + if(a < -maxA || a > maxA) + { + ax *= maxA / a; + ay *= maxA / a; + } + + // 加速度を元の速度に足して、新速度とする + this._faceVX += ax; + this._faceVY += ay; + + // 目的の方向に近づいたとき、滑らかに減速するための処理 + // 設定された加速度で止まる事の出来る距離と速度の関係から + // 現在とりうる最高速度を計算し、それ以上の時は速度を落とす + // ※本来、人間は筋力で力(加速度)を調整できるため、より自由度が高いが、簡単な処理で済ませている + { + // 加速度、速度、距離の関係式。 + // 2 6 2 3 + // sqrt(a t + 16 a h t - 8 a h) - a t + // v = -------------------------------------- + // 2 + // 4 t - 2 + // (t=1) + // 時刻tは、あらかじめ加速度、速度を1/60(フレームレート、単位なし)で + // 考えているので、t=1として消してよい(※未検証) + + const maxV: number = 0.5 * (CubismMath.sqrt((maxA * maxA) + 16.0 * maxA * d - 8.0 * maxA * d) - maxA); + const curV: number = CubismMath.sqrt((this._faceVX * this._faceVX) + (this._faceVY * this._faceVY)); + + if(curV > maxV) + { + // 現在の速度 > 最高速度のとき、最高速度まで減速 + this._faceVX *= maxV / curV; + this._faceVY *= maxV / curV; + } + } + + this._faceX += this._faceVX; + this._faceY += this._faceVY; + } + + /** + * X軸の顔の向きの値を取得 + * + * @return X軸の顔の向きの値(-1.0 ~ 1.0) + */ + public getX(): number + { + return this._faceX; + } + + /** + * Y軸の顔の向きの値を取得 + * + * @return Y軸の顔の向きの値(-1.0 ~ 1.0) + */ + public getY(): number + { + return this._faceY; + } + + /** + * 顔の向きの目標値を設定 + * + * @param x X軸の顔の向きの値(-1.0 ~ 1.0) + * @param y Y軸の顔の向きの値(-1.0 ~ 1.0) + */ + public set(x: number, y: number): void + { + this._faceTargetX = x; + this._faceTargetY = y; + } + + + private _faceTargetX: number; // 顔の向きのX目標値(この値に近づいていく) + private _faceTargetY: number; // 顔の向きのY目標値(この値に近づいていく) + private _faceX: number; // 顔の向きX(-1.0 ~ 1.0) + private _faceY: number; // 顔の向きY(-1.0 ~ 1.0) + private _faceVX: number; // 顔の向きの変化速度X + private _faceVY: number; // 顔の向きの変化速度Y + private _lastTimeSeconds: number; // 最後の実行時間[秒] + private _userTimeSeconds: number; // デルタ時間の積算値[秒] + + } +} \ No newline at end of file diff --git a/Framework/math/cubismvector2.ts b/Framework/math/cubismvector2.ts new file mode 100644 index 0000000..2f61e90 --- /dev/null +++ b/Framework/math/cubismvector2.ts @@ -0,0 +1,180 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +export namespace Live2DCubismFramework +{ + /** + * 2次元ベクトル型 + * + * 2次元ベクトル型の機能を提供する。 + */ + export class CubismVector2 + { + /** + * コンストラクタ + */ + public constructor(public x?: number, public y?: number) + { + this.x = (x == undefined) + ? 0.0 + : x; + + this.y = (y == undefined) + ? 0.0 + : y; + } + + /** + * ベクトルの加算 + * + * @param vector2 加算するベクトル値 + * @return 加算結果 ベクトル値 + */ + public add(vector2: CubismVector2): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(0.0, 0.0); + ret.x = this.x + vector2.x; + ret.y = this.y + vector2.y; + return ret; + } + + /** + * ベクトルの減算 + * + * @param vector2 減算するベクトル値 + * @return 減算結果 ベクトル値 + */ + public substract(vector2: CubismVector2): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(0.0, 0.0); + ret.x = this.x - vector2.x; + ret.y = this.y - vector2.y; + return ret; + } + + /** + * ベクトルの乗算 + * + * @param vector2 乗算するベクトル値 + * @return 乗算結果 ベクトル値 + */ + public multiply(vector2: CubismVector2): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(0.0, 0.0); + ret.x = this.x * vector2.x; + ret.y = this.y * vector2.y; + return ret; + } + + /** + * ベクトルの乗算(スカラー) + * + * @param scalar 乗算するスカラー値 + * @return 乗算結果 ベクトル値 + */ + public multiplyByScaler(scalar: number): CubismVector2 + { + return this.multiply(new CubismVector2(scalar, scalar)); + } + + /** + * ベクトルの除算 + * + * @param vector2 除算するベクトル値 + * @return 除算結果 ベクトル値 + */ + public division(vector2: CubismVector2): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(0.0, 0.0); + ret.x = this.x / vector2.x; + ret.y = this.y / vector2.y; + return ret; + } + + /** + * ベクトルの除算(スカラー) + * + * @param scalar 除算するスカラー値 + * @return 除算結果 ベクトル値 + */ + public divisionByScalar(scalar: number): CubismVector2 + { + return this.division(new CubismVector2(scalar, scalar)); + } + + /** + * ベクトルの長さを取得する + * + * @return ベクトルの長さ + */ + public getLength(): number + { + return Math.sqrt(this.x * this.x + this.y * this.y); + } + + /** + * ベクトルの距離の取得 + * + * @param a 点 + * @return ベクトルの距離 + */ + public getDistanceWith(a: CubismVector2): number + { + return Math.sqrt(((this.x - a.x) * (this.x - a.x)) + ((this.y - a.y) * (this.y - a.y))); + } + + /** + * ドット積の計算 + * + * @param a 値 + * @return 結果 + */ + public dot(a: CubismVector2): number + { + return (this.x * a.x) + (this.y * a.y); + } + + /** + * 正規化の適用 + */ + public normalize(): void + { + const length: number = Math.pow((this.x * this.x) + (this.y * this.y), 0.5); + + this.x = this.x / length; + this.y = this.y / length; + } + + /** + * 等しさの確認(等しいか?) + * + * 値が等しいか? + * + * @param rhs 確認する値 + * @return true 値は等しい + * @return false 値は等しくない + */ + public isEqual(rhs: CubismVector2): boolean + { + return (this.x == rhs.x) && (this.y == rhs.y); + } + + /** + * 等しさの確認(等しくないか?) + * + * 値が等しくないか? + * + * @param rhs 確認する値 + * @return true 値は等しくない + * @return false 値は等しい + */ + public isNotEqual(rhs: CubismVector2): boolean + { + return !(this.isEqual(rhs)); + } + } +} \ No newline at end of file diff --git a/Framework/math/cubismviewmatrix.ts b/Framework/math/cubismviewmatrix.ts new file mode 100644 index 0000000..17b0acd --- /dev/null +++ b/Framework/math/cubismviewmatrix.ts @@ -0,0 +1,312 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismmatrix44} from "./cubismmatrix44"; +import CubismMatrix44 = cubismmatrix44.CubismMatrix44; + +export namespace Live2DCubismFramework +{ + /** + * カメラの位置変更に使うと便利な4x4行列 + * + * カメラの位置変更に使うと便利な4x4行列のクラス。 + */ + export class CubismViewMatrix extends CubismMatrix44 + { + + /** + * コンストラクタ + */ + public constructor() + { + super(); + this._screenLeft = 0.0; + this._screenRight = 0.0; + this._screenTop = 0.0; + this._screenBottom = 0.0; + this._maxLeft = 0.0; + this._maxRight = 0.0; + this._maxTop = 0.0; + this._maxBottom = 0.0; + this._maxScale = 0.0; + this._minScale = 0.0; + } + + /** + * 移動を調整 + * + * @param x X軸の移動量 + * @param y Y軸の移動量 + */ + public adjustTranslate(x: number, y: number): void + { + if(this._tr[0] * this._maxLeft + (this._tr[12] + x) > this._screenLeft) + { + x = this._screenLeft - this._tr[0] * this._maxLeft - this._tr[12]; + } + + if(this._tr[0] * this._maxRight + (this._tr[12] + x) < this._screenRight) + { + x = this._screenRight - this._tr[0] * this._maxRight - this._tr[12]; + } + + if(this._tr[5] * this._maxTop + (this._tr[13] + y) < this._screenTop) + { + y = this._screenTop - this._tr[5] * this._maxTop - this._tr[13]; + } + + if(this._tr[5] * this._maxBottom + (this._tr[13] + y) > this._screenBottom) + { + y = this._screenBottom - this._tr[5] * this._maxBottom - this._tr[13]; + } + + let tr1: Float32Array = new Float32Array( + [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + x, y, 0.0, 1.0 + ] + ); + + CubismMatrix44.multiply(tr1, this._tr, this._tr); + } + + /** + * 拡大率を調整 + * + * @param cx 拡大を行うX軸の中心位置 + * @param cy 拡大を行うY軸の中心位置 + * @param scale 拡大率 + */ + public adjustScale(cx: number, cy: number, scale: number): void + { + let maxScale: number = this.getMaxScale(); + let minScale: number = this.getMinScale(); + + let targetScale = scale * this._tr[0]; + + if(targetScale < minScale) + { + if(this._tr[0] > 0.0) + { + scale = minScale / this._tr[0]; + } + } + else if(targetScale > maxScale) + { + if(this._tr[0] > 0.0) + { + scale = maxScale / this._tr[0]; + } + } + + let tr1: Float32Array = new Float32Array( + [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + cx, cy, 0.0, 1.0 + ] + ); + + let tr2: Float32Array = new Float32Array( + [ + scale, 0.0, 0.0, 0.0, + 0.0, scale, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ] + ); + + let tr3: Float32Array = new Float32Array( + [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + -cx, -cy, 0.0, 1.0, + ] + ); + + CubismMatrix44.multiply(tr3, this._tr, this._tr); + CubismMatrix44.multiply(tr2, this._tr, this._tr); + CubismMatrix44.multiply(tr1, this._tr, this._tr); + } + + /** + * デバイスに対応する論理座養生の範囲の設定 + * + * @param left 左辺のX軸の位置 + * @param right 右辺のX軸の位置 + * @param bottom 下辺のY軸の位置 + * @param top 上辺のY軸の位置 + */ + public setScreenRect(left: number, right: number, bottom: number, top: number): void + { + this._screenLeft = left; + this._screenRight = right; + this._screenBottom = bottom; + this._screenTop = top; + } + + /** + * デバイスに対応する論理座標上の移動可能範囲の設定 + * @param left 左辺のX軸の位置 + * @param right 右辺のX軸の位置 + * @param bottom 下辺のY軸の位置 + * @param top 上辺のY軸の位置 + */ + public setMaxScreenRect(left: number, right: number, bottom: number, top: number): void + { + this._maxLeft = left; + this._maxRight = right; + this._maxTop = top; + this._maxBottom = bottom; + } + + /** + * 最大拡大率の設定 + * @param maxScale 最大拡大率 + */ + public setMaxScale(maxScale: number): void + { + this._maxScale = maxScale; + } + + /** + * 最小拡大率の設定 + * @param minScale 最小拡大率 + */ + public setMinScale(minScale: number): void + { + this._minScale = minScale; + } + + /** + * 最大拡大率の取得 + * @return 最大拡大率 + */ + public getMaxScale(): number + { + return this._maxScale; + } + + /** + * 最小拡大率の取得 + * @return 最小拡大率 + */ + public getMinScale(): number + { + return this._minScale; + } + + /** + * 拡大率が最大になっているかを確認する + * + * @return true 拡大率は最大 + * @return false 拡大率は最大ではない + */ + public isMaxScale(): boolean + { + return this.getScaleX() >= this._maxScale; + } + + /** + * 拡大率が最小になっているかを確認する + * + * @return true 拡大率は最小 + * @return false 拡大率は最小ではない + */ + public isMinScale(): boolean + { + return this.getScaleX() <= this._minScale; + } + + /** + * デバイスに対応する論理座標の左辺のX軸位置を取得する + * @return デバイスに対応する論理座標の左辺のX軸位置 + */ + public getScreenLeft(): number + { + return this._screenLeft; + } + + /** + * デバイスに対応する論理座標の右辺のX軸位置を取得する + * @return デバイスに対応する論理座標の右辺のX軸位置 + */ + public getScreenRight(): number + { + return this._screenRight; + } + + /** + * デバイスに対応する論理座標の下辺のY軸位置を取得する + * @return デバイスに対応する論理座標の下辺のY軸位置 + */ + public getScreenBottom(): number + { + return this._screenBottom; + } + + /** + * デバイスに対応する論理座標の上辺のY軸位置を取得する + * @return デバイスに対応する論理座標の上辺のY軸位置 + */ + public getScreenTop(): number + { + return this._screenTop; + } + + /** + * 左辺のX軸位置の最大値の取得 + * @return 左辺のX軸位置の最大値 + */ + public getMaxLeft(): number + { + return this._maxLeft; + } + + /** + * 右辺のX軸位置の最大値の取得 + * @return 右辺のX軸位置の最大値 + */ + public getMaxRight(): number + { + return this._maxRight; + } + + /** + * 下辺のY軸位置の最大値の取得 + * @return 下辺のY軸位置の最大値 + */ + public getMaxBottom(): number + { + return this._maxBottom; + } + + /** + * 上辺のY軸位置の最大値の取得 + * @return 上辺のY軸位置の最大値 + */ + public getMaxTop(): number + { + return this._maxTop; + } + + private _screenLeft: number; // デバイスに対応する論理座標上の範囲(左辺X軸位置) + private _screenRight: number; // デバイスに対応する論理座標上の範囲(右辺X軸位置) + private _screenTop: number; // デバイスに対応する論理座標上の範囲(上辺Y軸位置) + private _screenBottom: number; // デバイスに対応する論理座標上の範囲(下辺Y軸位置) + private _maxLeft: number; // 論理座標上の移動可能範囲(左辺X軸位置) + private _maxRight: number; // 論理座標上の移動可能範囲(右辺X軸位置) + private _maxTop: number; // 論理座標上の移動可能範囲(上辺Y軸位置) + private _maxBottom: number; // 論理座標上の移動可能範囲(下辺Y軸位置) + private _maxScale: number; // 拡大率の最大値 + private _minScale: number; // 拡大率の最小値 + } +} \ No newline at end of file diff --git a/Framework/model/cubismmoc.ts b/Framework/model/cubismmoc.ts new file mode 100644 index 0000000..2f09698 --- /dev/null +++ b/Framework/model/cubismmoc.ts @@ -0,0 +1,106 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismmodel} from "./cubismmodel"; +import CubismModel = cubismmodel.CubismModel; +import { CSM_ASSERT } from "../utils/cubismdebug"; + +export namespace Live2DCubismFramework +{ + /** + * Mocデータの管理 + * + * Mocデータの管理を行うクラス。 + */ + export class CubismMoc + { + /** + * Mocデータの作成 + */ + public static create(mocBytes: ArrayBuffer): CubismMoc + { + let cubismMoc: CubismMoc = null; + let moc: Live2DCubismCore.Moc = Live2DCubismCore.Moc.fromArrayBuffer(mocBytes); + + if (moc) + { + cubismMoc = new CubismMoc(moc); + } + + return cubismMoc; + } + + /** + * Mocデータを削除 + * + * Mocデータを削除する + */ + public static delete(moc: CubismMoc): void + { + moc._moc._release(); + moc._moc = null; + moc = null; + } + + /** + * モデルを作成する + * + * @return Mocデータから作成されたモデル + */ + createModel(): CubismModel + { + let cubismModel: CubismModel = null; + + let model: Live2DCubismCore.Model = Live2DCubismCore.Model.fromMoc(this._moc); + + if (model) + { + cubismModel = new CubismModel(model); + cubismModel.initialize(); + + ++this._modelCount; + } + + return cubismModel; + } + + /** + * モデルを削除する + */ + deleteModel(model: CubismModel): void + { + model.release(); + model = void 0; + + --this._modelCount; + } + + + /** + * コンストラクタ + */ + private constructor(moc: Live2DCubismCore.Moc) + { + this._moc = moc; + this._modelCount = 0; + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + CSM_ASSERT(this._modelCount == 0); + + this._moc._release(); + this._moc = null; + } + + _moc: Live2DCubismCore.Moc; ///< Mocデータ + _modelCount: number; ///< Mocデータから作られたモデルの個数 + } +} \ No newline at end of file diff --git a/Framework/model/cubismmodel.ts b/Framework/model/cubismmodel.ts new file mode 100644 index 0000000..833520e --- /dev/null +++ b/Framework/model/cubismmodel.ts @@ -0,0 +1,803 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +/// +import {Live2DCubismFramework as cubismrenderer} from "../rendering/cubismrenderer"; +import {Live2DCubismFramework as cubismid} from "../id/cubismid"; +import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; +import {Live2DCubismFramework as csmmap} from "../type/csmmap"; +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {CSM_ASSERT} from "../utils/cubismdebug"; +import CubismFramework = cubismframework.CubismFramework; +import CubismRenderer = cubismrenderer.CubismRenderer; +import csmVector = csmvector.csmVector; +import csmMap = csmmap.csmMap; +import CubismIdHandle = cubismid.CubismIdHandle; + +export namespace Live2DCubismFramework +{ + /** + * モデル + * + * Mocデータから生成されるモデルのクラス。 + */ + export class CubismModel + { + /** + * モデルのパラメータの更新 + */ + public update(): void + { + // Update model + this._model.update(); + + this._model.drawables.resetDynamicFlags(); + } + + /** + * キャンバスの幅を取得する + */ + public getCanvasWidth(): number + { + if (this._model == null) + { + return 0.0; + } + + return this._model.canvasinfo.CanvasWidth / this._model.canvasinfo.PixelsPerUnit; + } + + /** + * キャンバスの高さを取得する + */ + public getCanvasHeight(): number + { + if (this._model == null) + { + return 0.0; + } + + return this._model.canvasinfo.CanvasHeight / this._model.canvasinfo.PixelsPerUnit; + } + + /** + * パラメータを保存する + */ + public saveParameters(): void + { + const parameterCount: number = this._model.parameters.count; + const savedParameterCount: number = this._savedParameters.getSize(); + + for (let i: number = 0; i < parameterCount; ++i) + { + if (i < savedParameterCount) + { + this._savedParameters.set(i, this._parameterValues[i]); + } + else + { + this._savedParameters.pushBack(this._parameterValues[i]); + } + } + } + + /** + * モデルを取得 + */ + public getModel(): Live2DCubismCore.Model + { + return this._model; + } + + /** + * パーツのインデックスを取得 + * @param partId パーツのID + * @return パーツのインデックス + */ + public getPartIndex(partId: CubismIdHandle): number + { + let partIndex: number; + const partCount: number = this._model.parts.count; + + for(partIndex = 0; partIndex < partCount; ++partIndex) + { + if(partId == this._partIds.at(partIndex)) + { + return partIndex; + } + } + + // モデルに存在していない場合、非存在パーツIDリスト内にあるかを検索し、そのインデックスを返す + if(this._notExistPartId.isExist(partId)) + { + return this._notExistPartId.getValue(partId); + } + + // 非存在パーツIDリストにない場合、新しく要素を追加する + partIndex = partCount + this._notExistPartId.getSize(); + this._notExistPartId.setValue(partId, partIndex); + this._notExistPartOpacities.appendKey(partIndex); + + return partIndex; + } + + /** + * パーツの個数の取得 + * @return パーツの個数 + */ + public getPartCount(): number + { + const partCount: number = this._model.parts.count; + return partCount; + } + + /** + * パーツの不透明度の設定(Index) + * @param partIndex パーツのインデックス + * @param opacity 不透明度 + */ + public setPartOpacityByIndex(partIndex: number, opacity: number): void + { + if(this._notExistPartOpacities.isExist(partIndex)) + { + this._notExistPartOpacities.setValue(partIndex,opacity); + return; + } + + // インデックスの範囲内検知 + CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount()); + + this._partOpacities[partIndex] = opacity; + } + + /** + * パーツの不透明度の設定(Id) + * @param partId パーツのID + * @param opacity パーツの不透明度 + */ + public setPartOpacityById(partId: CubismIdHandle, opacity: number): void + { + // 高速化のためにPartIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要 + const index: number = this.getPartIndex(partId); + + if(index < 0) + { + return; // パーツがないのでスキップ + } + + this.setPartOpacityByIndex(index, opacity); + } + + /** + * パーツの不透明度の取得(index) + * @param partIndex パーツのインデックス + * @return パーツの不透明度 + */ + public getPartOpacityByIndex(partIndex: number): number + { + if(this._notExistPartOpacities.isExist(partIndex)) + { + // モデルに存在しないパーツIDの場合、非存在パーツリストから不透明度を返す。 + return this._notExistPartOpacities.getValue(partIndex); + } + + // インデックスの範囲内検知 + CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount()); + + return this._partOpacities[partIndex]; + } + + /** + * パーツの不透明度の取得(id) + * @param partId パーツのId + * @return パーツの不透明度 + */ + public getPartOpacityById(partId: CubismIdHandle): number + { + // 高速化のためにPartIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要 + const index: number = this.getPartIndex(partId); + + if(index < 0) + { + return 0; // パーツが無いのでスキップ + } + + return this.getPartOpacityByIndex(index); + } + + /** + * パラメータのインデックスの取得 + * @param パラメータID + * @return パラメータのインデックス + */ + public getParameterIndex(parameterId: CubismIdHandle): number + { + let parameterIndex: number; + const idCount: number = this._model.parameters.count; + + for(parameterIndex = 0; parameterIndex < idCount; ++parameterIndex) + { + if(parameterId != this._parameterIds.at(parameterIndex)) + { + continue; + } + + return parameterIndex; + } + + // モデルに存在していない場合、非存在パラメータIDリスト内を検索し、そのインデックスを返す + if(this._notExistParameterId.isExist(parameterId)) + { + return this._notExistParameterId.getValue(parameterId); + } + + // 非存在パラメータIDリストにない場合新しく要素を追加する + parameterIndex = this._model.parameters.count + this._notExistParameterId.getSize(); + + this._notExistParameterId.setValue(parameterId, parameterIndex); + this._notExistParameterValues.appendKey(parameterIndex); + + return parameterIndex; + } + + /** + * パラメータの個数の取得 + * @return パラメータの個数 + */ + public getParameterCount(): number + { + return this._model.parameters.count; + } + + /** + * パラメータの最大値の取得 + * @param parameterIndex パラメータのインデックス + * @return パラメータの最大値 + */ + public getParameterMaximumValue(parameterIndex: number): number + { + return this._model.parameters.maximumValues[parameterIndex]; + } + + /** + * パラメータの最小値の取得 + * @param parameterIndex パラメータのインデックス + * @return パラメータの最小値 + */ + public getParameterMinimumValue(parameterIndex: number): number + { + return this._model.parameters.minimumValues[parameterIndex]; + } + + /** + * パラメータのデフォルト値の取得 + * @param parameterIndex パラメータのインデックス + * @return パラメータのデフォルト値 + */ + public getParameterDefaultValue(parameterIndex: number): number + { + return this._model.parameters.defaultValues[parameterIndex]; + } + + /** + * パラメータの値の取得 + * @param parameterIndex パラメータのインデックス + * @return パラメータの値 + */ + public getParameterValueByIndex(parameterIndex: number): number + { + if(this._notExistParameterValues.isExist(parameterIndex)) + { + return this._notExistParameterValues.getValue(parameterIndex); + } + + // インデックスの範囲内検知 + CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount()); + + return this._parameterValues[parameterIndex]; + } + + /** + * パラメータの値の取得 + * @param parameterId パラメータのID + * @return パラメータの値 + */ + public getParameterValueById(parameterId: CubismIdHandle): number + { + // 高速化のためにparameterIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要 + const parameterIndex: number = this.getParameterIndex(parameterId); + return this.getParameterValueByIndex(parameterIndex); + } + + /** + * パラメータの値の設定 + * @param parameterIndex パラメータのインデックス + * @param value パラメータの値 + * @param weight 重み + */ + public setParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void + { + if(this._notExistParameterValues.isExist(parameterIndex)) + { + this._notExistParameterValues.setValue( + parameterIndex, + (weight == 1) + ? value + : (this._notExistParameterValues.getValue(parameterIndex) * (1 - weight)) + (value * weight) + ); + + return; + } + + // インデックスの範囲内検知 + CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount()); + + if(this._model.parameters.maximumValues[parameterIndex] < value) + { + value = this._model.parameters.maximumValues[parameterIndex]; + } + if(this._model.parameters.minimumValues[parameterIndex] > value) + { + value = this._model.parameters.minimumValues[parameterIndex]; + } + + this._parameterValues[parameterIndex] = (weight == 1) + ? value + : this._parameterValues[parameterIndex] = (this._parameterValues[parameterIndex] * (1 - weight)) + (value * weight); + } + + /** + * パラメータの値の設定 + * @param parameterId パラメータのID + * @param value パラメータの値 + * @param weight 重み + */ + public setParameterValueById(parameterId: CubismIdHandle, value: number, weight: number = 1.0): void + { + const index: number = this.getParameterIndex(parameterId); + this.setParameterValueByIndex(index, value, weight); + } + + /** + * パラメータの値の加算(index) + * @param parameterIndex パラメータインデックス + * @param value 加算する値 + * @param weight 重み + */ + public addParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void + { + this.setParameterValueByIndex(parameterIndex, (this.getParameterValueByIndex(parameterIndex) + (value * weight))); + } + + /** + * パラメータの値の加算(id) + * @param parameterId パラメータID + * @param value 加算する値 + * @param weight 重み + */ + public addParameterValueById(parameterId: any, value: number, weight: number = 1.0): void + { + const index: number = this.getParameterIndex(parameterId); + this.addParameterValueByIndex(index, value, weight); + } + + /** + * パラメータの値の乗算 + * @param parameterId パラメータのID + * @param value 乗算する値 + * @param weight 重み + */ + public multiplyParameterValueById(parameterId: CubismIdHandle, value: number, weight: number = 1.0): void + { + const index: number = this.getParameterIndex(parameterId); + this.multiplyParameterValueByIndex(index, value, weight); + } + + /** + * パラメータの値の乗算 + * @param parameterIndex パラメータのインデックス + * @param value 乗算する値 + * @param weight 重み + */ + public multiplyParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void + { + this.setParameterValueByIndex(parameterIndex, (this.getParameterValueByIndex(parameterIndex) * (1.0 + (value - 1.0) * weight))); + } + + + /** + * Drawableのインデックスの取得 + * @param drawableId DrawableのID + * @return Drawableのインデックス + */ + public getDrawableIndex(drawableId: CubismIdHandle): number + { + const drawableCount = this._model.drawables.count; + + for(let drawableIndex: number = 0; drawableIndex < drawableCount; ++drawableIndex) + { + if(this._drawableIds.at(drawableIndex) == drawableId) + { + return drawableIndex; + } + } + + return -1; + } + + /** + * Drawableの個数の取得 + * @return drawableの個数 + */ + public getDrawableCount(): number + { + const drawableCount = this._model.drawables.count; + return drawableCount; + } + + /** + * DrawableのIDを取得する + * @param drawableIndex Drawableのインデックス + * @return drawableのID + */ + public getDrawableId(drawableIndex: number): CubismIdHandle + { + const parameterIds: string[] = this._model.drawables.ids; + return CubismFramework.getIdManager().getId(parameterIds[drawableIndex]); + } + + /** + * Drawableの描画順リストの取得 + * @return Drawableの描画順リスト + */ + public getDrawableRenderOrders(): Int32Array + { + const renderOrders: Int32Array = this._model.drawables.renderOrders; + return renderOrders; + } + + /** + * Drawableのテクスチャインデックスリストの取得 + * @param drawableIndex Drawableのインデックス + * @return drawableのテクスチャインデックスリスト + */ + public getDrawableTextureIndices(drawableIndex: number): number + { + const textureIndices: Int32Array = this._model.drawables.textureIndices; + return textureIndices[drawableIndex]; + } + + /** + * DrawableのVertexPositionsの変化情報の取得 + * + * 直近のCubismModel.update関数でDrawableの頂点情報が変化したかを取得する。 + * + * @param drawableIndex Drawableのインデックス + * @retval true Drawableの頂点情報が直近のCubismModel.update関数で変化した + * @retval false Drawableの頂点情報が直近のCubismModel.update関数で変化していない + */ + public getDrawableDynamicFlagVertexPositionsDidChange(drawableIndex: number): boolean + { + const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; + return Live2DCubismCore.Utils.hasVertexPositionsDidChangeBit(dynamicFlags[drawableIndex]); + } + + /** + * Drawableの頂点インデックスの個数の取得 + * @param drawableIndex Drawableのインデックス + * @return drawableの頂点インデックスの個数 + */ + public getDrawableVertexIndexCount(drawableIndex: number): number + { + const indexCounts: Int32Array = this._model.drawables.indexCounts; + return indexCounts[drawableIndex]; + } + + /** + * Drawableの頂点の個数の取得 + * @param drawableIndex Drawableのインデックス + * @return drawableの頂点の個数 + */ + public getDrawableVertexCount(drawableIndex: number): number + { + const vertexCounts = this._model.drawables.vertexCounts; + return vertexCounts[drawableIndex]; + } + + /** + * Drawableの頂点リストの取得 + * @param drawableIndex drawableのインデックス + * @return drawableの頂点リスト + */ + public getDrawableVertices(drawableIndex: number): Float32Array + { + return this.getDrawableVertexPositions(drawableIndex); + } + + /** + * Drawableの頂点インデックスリストの取得 + * @param drarableIndex Drawableのインデックス + * @return drawableの頂点インデックスリスト + */ + public getDrawableVertexIndices(drawableIndex: number): Uint16Array + { + const indicesArray: Uint16Array[] = this._model.drawables.indices; + return indicesArray[drawableIndex]; + } + + /** + * Drawableの頂点リストの取得 + * @param drawableIndex Drawableのインデックス + * @return drawableの頂点リスト + */ + public getDrawableVertexPositions(drawableIndex: number): Float32Array + { + const verticesArray: Float32Array[] = this._model.drawables.vertexPositions; + return verticesArray[drawableIndex]; + } + + /** + * Drawableの頂点のUVリストの取得 + * @param drawableIndex Drawableのインデックス + * @return drawableの頂点UVリスト + */ + public getDrawableVertexUvs(drawableIndex: number): Float32Array + { + const uvsArray: Float32Array[] = this._model.drawables.vertexUvs; + return uvsArray[drawableIndex]; + } + + /** + * Drawableの不透明度の取得 + * @param drawableIndex Drawableのインデックス + * @return drawableの不透明度 + */ + public getDrawableOpacity(drawableIndex: number): number + { + const opacities: Float32Array = this._model.drawables.opacities; + return opacities[drawableIndex]; + } + + /** + * Drawableのカリング情報の取得 + * @param drawableIndex Drawableのインデックス + * @return drawableのカリング情報 + */ + public getDrawableCulling(drawableIndex: number): boolean + { + const constantFlags = this._model.drawables.constantFlags; + + return !Live2DCubismCore.Utils.hasIsDoubleSidedBit(constantFlags[drawableIndex]); + } + + /** + * Drawableのブレンドモードを取得 + * @param drawableIndex Drawableのインデックス + * @return drawableのブレンドモード + */ + public getDrawableBlendMode(drawableIndex: number): CubismRenderer.CubismBlendMode + { + const constantFlags = this._model.drawables.constantFlags; + + return (Live2DCubismCore.Utils.hasBlendAdditiveBit(constantFlags[drawableIndex])) + ? CubismRenderer.CubismBlendMode.CubismBlendMode_Additive + : (Live2DCubismCore.Utils.hasBlendMultiplicativeBit(constantFlags[drawableIndex])) + ? CubismRenderer.CubismBlendMode.CubismBlendMode_Multiplicative + : CubismRenderer.CubismBlendMode.CubismBlendMode_Normal; + } + + /** + * Drawableのクリッピングマスクリストの取得 + * @return Drawableのクリッピングマスクリスト + */ + public getDrawableMasks(): Int32Array[] + { + const masks: Int32Array[] = this._model.drawables.masks; + return masks; + } + + /** + * Drawableのクリッピングマスクの個数リストの取得 + * @return Drawableのクリッピングマスクの個数リスト + */ + public getDrawableMaskCounts(): Int32Array + { + const maskCounts: Int32Array = this._model.drawables.maskCounts; + return maskCounts; + } + + /** + * クリッピングマスクの使用状態 + * + * @return true クリッピングマスクを使用している + * @return false クリッピングマスクを使用していない + */ + public isUsingMasking(): boolean + { + for(let d: number = 0; d < this._model.drawables.count; ++d) + { + if(this._model.drawables.maskCounts[d] <= 0) + { + continue; + } + return true; + } + return false; + } + + /** + * Drawableの表示情報を取得する + * + * @param drawableIndex Drawableのインデックス + * @return true Drawableが表示 + * @return false Drawableが非表示 + */ + public getDrawableDynamicFlagIsVisible(drawableIndex: number): boolean + { + const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; + return Live2DCubismCore.Utils.hasIsVisibleBit(dynamicFlags[drawableIndex]); + } + + /** + * DrawableのDrawOrderの変化情報の取得 + * + * 直近のCubismModel.update関数でdrawableのdrawOrderが変化したかを取得する。 + * drawOrderはartMesh上で指定する0から1000の情報 + * @param drawableIndex drawableのインデックス + * @return true drawableの不透明度が直近のCubismModel.update関数で変化した + * @return false drawableの不透明度が直近のCubismModel.update関数で変化している + */ + public getDrawableDynamicFlagVisibilityDidChange(drawableIndex: number): boolean + { + const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; + return Live2DCubismCore.Utils.hasVisibilityDidChangeBit(dynamicFlags[drawableIndex]); + } + + /** + * Drawableの不透明度の変化情報の取得 + * + * 直近のCubismModel.update関数でdrawableの不透明度が変化したかを取得する。 + * + * @param drawableIndex drawableのインデックス + * @return true Drawableの不透明度が直近のCubismModel.update関数で変化した + * @return false Drawableの不透明度が直近のCubismModel.update関数で変化してない + */ + public getDrawableDynamicFlagOpacityDidChange(drawableIndex: number): boolean + { + const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; + return Live2DCubismCore.Utils.hasOpacityDidChangeBit(dynamicFlags[drawableIndex]); + } + + /** + * Drawableの描画順序の変化情報の取得 + * + * 直近のCubismModel.update関数でDrawableの描画の順序が変化したかを取得する。 + * + * @param drawableIndex Drawableのインデックス + * @return true Drawableの描画の順序が直近のCubismModel.update関数で変化した + * @return false Drawableの描画の順序が直近のCubismModel.update関数で変化してない + */ + public getDrawableDynamicFlagRenderOrderDidChange(drawableIndex: number): boolean + { + const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags; + return Live2DCubismCore.Utils.hasRenderOrderDidChangeBit(dynamicFlags[drawableIndex]); + } + + /** + * 保存されたパラメータの読み込み + */ + public loadParameters(): void + { + let parameterCount: number = this._model.parameters.count; + const savedParameterCount: number = this._savedParameters.getSize(); + + if(parameterCount > savedParameterCount) + { + parameterCount = savedParameterCount; + } + + for(let i: number = 0; i < parameterCount; ++i) + { + this._parameterValues[i] = this._savedParameters.at(i); + } + } + + /** + * 初期化する + */ + public initialize(): void + { + CSM_ASSERT(this._model); + + this._parameterValues = this._model.parameters.values; + this._partOpacities = this._model.parts.opacities; + this._parameterMaximumValues = this._model.parameters.maximumValues; + this._parameterMinimumValues = this._model.parameters.minimumValues; + + { + const parameterIds: string[] = this._model.parameters.ids; + const parameterCount: number = this._model.parameters.count; + + for(let i: number = 0; i < parameterCount; ++i) + { + this._parameterIds.pushBack(CubismFramework.getIdManager().getId(parameterIds[i])); + } + } + + { + const partIds: string[] = this._model.parts.ids; + const partCount: number = this._model.parts.count; + + for(let i: number = 0; i < partCount; ++i) + { + this._partIds.pushBack(CubismFramework.getIdManager().getId(partIds[i])); + } + } + + { + const drawableIds: string[] = this._model.drawables.ids; + const drawableCount: number = this._model.drawables.count; + + for(let i: number = 0; i < drawableCount; ++i) + { + this._drawableIds.pushBack(CubismFramework.getIdManager().getId(drawableIds[i])); + } + } + } + + /** + * コンストラクタ + * @param model モデル + */ + public constructor(model: Live2DCubismCore.Model) + { + this._model = model; + this._parameterValues = null; + this._parameterMaximumValues = null; + this._parameterMinimumValues = null; + this._partOpacities = null; + this._savedParameters = new csmVector(); + this._parameterIds = new csmVector(); + this._drawableIds = new csmVector(); + this._partIds = new csmVector(); + + this._notExistPartId = new csmMap(); + this._notExistParameterId = new csmMap(); + this._notExistParameterValues = new csmMap(); + this._notExistPartOpacities = new csmMap(); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + this._model.release(); + this._model = null; + } + + private _notExistPartOpacities: csmMap; // 存在していないパーツの不透明度のリスト + private _notExistPartId: csmMap; // 存在していないパーツIDのリスト + + private _notExistParameterValues: csmMap; // 存在していないパラメータの値のリスト + private _notExistParameterId: csmMap; // 存在していないパラメータIDのリスト + + private _savedParameters: csmVector; // 保存されたパラメータ + + private _model: Live2DCubismCore.Model; // モデル + + private _parameterValues: Float32Array; // パラメータの値のリスト + private _parameterMaximumValues: Float32Array; // パラメータの最大値のリスト + private _parameterMinimumValues: Float32Array; // パラメータの最小値のリスト + + private _partOpacities: Float32Array; // パーツの不透明度のリスト + + private _parameterIds: csmVector; + private _partIds: csmVector; + private _drawableIds: csmVector; + } +} \ No newline at end of file diff --git a/Framework/model/cubismmodeluserdata.ts b/Framework/model/cubismmodeluserdata.ts new file mode 100644 index 0000000..e84724e --- /dev/null +++ b/Framework/model/cubismmodeluserdata.ts @@ -0,0 +1,139 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as cubismmodeluserdatajson} from "./cubismmodeluserdatajson"; +import {Live2DCubismFramework as cubismid} from "../id/cubismid"; +import {Live2DCubismFramework as csmstring} from "../type/csmstring"; +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; +import CubismFramework = cubismframework.CubismFramework; +import csmVector = csmvector.csmVector; +import csmString = csmstring.csmString; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismModelUserDataJson = cubismmodeluserdatajson.CubismModelUserDataJson; + +export namespace Live2DCubismFramework +{ + const ArtMesh: string = "ArtMesh"; + + /** + * ユーザーデータインターフェース + * + * Jsonから読み込んだユーザーデータを記録しておくための構造体 + */ + export class CubismModelUserDataNode + { + targetType: CubismIdHandle; // ユーザーデータターゲットタイプ + targetId: CubismIdHandle; // ユーザーデータターゲットのID + value: csmString; // ユーザーデータ + } + + /** + * ユーザデータの管理クラス + * + * ユーザデータをロード、管理、検索インターフェイス、解放までを行う。 + */ + export class CubismModelUserData + { + /** + * インスタンスの作成 + * + * @param buffer userdata3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + * @return 作成されたインスタンス + */ + public static create(buffer: ArrayBuffer, size: number): CubismModelUserData + { + let ret: CubismModelUserData = new CubismModelUserData(); + + ret.parseUserData(buffer, size); + + return ret; + } + + /** + * インスタンスを破棄する + * + * @param modelUserData 破棄するインスタンス + */ + public static delete(modelUserData: CubismModelUserData): void + { + modelUserData.release(); + modelUserData = void 0; + modelUserData = null; + } + + /** + * ArtMeshのユーザーデータのリストの取得 + * + * @return ユーザーデータリスト + */ + public getArtMeshUserDatas(): csmVector + { + return this._artMeshUserDataNode; + } + + /** + * userdata3.jsonのパース + * + * @param buffer userdata3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public parseUserData(buffer: ArrayBuffer, size: number): void + { + let json: CubismModelUserDataJson = new CubismModelUserDataJson(buffer, size); + + const typeOfArtMesh = CubismFramework.getIdManager().getId(ArtMesh); + const nodeCount: number = json.getUserDataCount(); + + for(let i: number = 0; i < nodeCount; i++) + { + let addNode: CubismModelUserDataNode = new CubismModelUserDataNode(); + + addNode.targetId = json.getUserDataId(i); + addNode.targetType = CubismFramework.getIdManager().getId(json.getUserDataTargetType(i)); + addNode.value = new csmString(json.getUserDataValue(i)); + this._userDataNodes.pushBack(addNode); + + if(addNode.targetType == typeOfArtMesh) + { + this._artMeshUserDataNode.pushBack(addNode); + } + } + + json.release(); + json = void 0; + } + + /** + * コンストラクタ + */ + public constructor() + { + this._userDataNodes = new csmVector(); + this._artMeshUserDataNode = new csmVector(); + } + + /** + * デストラクタ相当の処理 + * + * ユーザーデータ構造体配列を解放する + */ + public release(): void + { + for(let i: number = 0; i < this._userDataNodes.getSize(); ++i) + { + this._userDataNodes.set(i, void 0); + } + + this._userDataNodes = null; + } + + private _userDataNodes: csmVector; // ユーザーデータ構造体配列 + private _artMeshUserDataNode: csmVector; // 閲覧リストの保持 + } +} \ No newline at end of file diff --git a/Framework/model/cubismmodeluserdatajson.ts b/Framework/model/cubismmodeluserdatajson.ts new file mode 100644 index 0000000..c81ab6c --- /dev/null +++ b/Framework/model/cubismmodeluserdatajson.ts @@ -0,0 +1,99 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismjson} from "../utils/cubismjson"; +import {Live2DCubismFramework as cubismid} from "../id/cubismid"; +import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; +import CubismFramework = cubismframework.CubismFramework; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismJson = cubismjson.CubismJson; + + +export namespace Live2DCubismFramework +{ + const Meta: string = "Meta"; + const UserDataCount: string = "UserDataCount"; + const TotalUserDataSize: string = "TotalUserDataSize"; + const UserData: string = "UserData"; + const Target: string = "Target"; + const Id: string = "Id"; + const Value: string = "Value"; + + export class CubismModelUserDataJson + { + /** + * コンストラクタ + * @param buffer userdata3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public constructor(buffer: ArrayBuffer, size: number) + { + this._json = CubismJson.create(buffer, size); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + CubismJson.delete(this._json); + } + + /** + * ユーザーデータ個数の取得 + * @return ユーザーデータの個数 + */ + public getUserDataCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(UserDataCount).toInt(); + } + + /** + * ユーザーデータ総文字列数の取得 + * + * @return ユーザーデータ総文字列数 + */ + public getTotalUserDataSize(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalUserDataSize).toInt(); + } + + /** + * ユーザーデータのタイプの取得 + * + * @return ユーザーデータのタイプ + */ + public getUserDataTargetType(i: number): string + { + return this._json.getRoot().getMap().getValue(UserData).getVector().at(i).getMap().getValue(Target).getRawString(); + } + + /** + * ユーザーデータのターゲットIDの取得 + * + * @param i インデックス + * @return ユーザーデータターゲットID + */ + public getUserDataId(i: number): CubismIdHandle + { + return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(UserData).getVector().at(i).getMap().getValue(Id).getRawString()); + } + + /** + * ユーザーデータの文字列の取得 + * + * @param i インデックス + * @return ユーザーデータ + */ + public getUserDataValue(i: number): string + { + return this._json.getRoot().getMap().getValue(UserData).getVector().at(i).getMap().getValue(Value).getRawString(); + } + + private _json: CubismJson; + } +} \ No newline at end of file diff --git a/Framework/model/cubismusermodel.ts b/Framework/model/cubismusermodel.ts new file mode 100644 index 0000000..667cb2f --- /dev/null +++ b/Framework/model/cubismusermodel.ts @@ -0,0 +1,466 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; +import {Live2DCubismFramework as cubismmotionmanager} from "../motion/cubismmotionmanager"; +import {Live2DCubismFramework as cubismtargetpoint} from "../math/cubismtargetpoint"; +import {Live2DCubismFramework as cubismmodelmatrix} from "../math/cubismmodelmatrix"; +import {Live2DCubismFramework as cubismmoc} from "./cubismmoc"; +import {Live2DCubismFramework as cubismmodel} from "./cubismmodel"; +import {Live2DCubismFramework as acubismmotion} from "../motion/acubismmotion"; +import {Live2DCubismFramework as cubismmotion} from "../motion/cubismmotion"; +import {Live2DCubismFramework as cubismexpressionmotion} from "../motion/cubismexpressionmotion"; +import {Live2DCubismFramework as cubismpose} from "../effect/cubismpose"; +import {Live2DCubismFramework as cubismmodeluserdata} from "./cubismmodeluserdata"; +import {Live2DCubismFramework as cubismphysics} from "../physics/cubismphysics"; +import {Live2DCubismFramework as cubismid} from "../id/cubismid"; +import {Live2DCubismFramework as csmstring} from "../type/csmstring"; +import {Live2DCubismFramework as cubismmotionqueuemanager} from "../motion/cubismmotionqueuemanager"; +import {Live2DCubismFramework as cubismbreath} from "../effect/cubismbreath"; +import {Live2DCubismFramework as cubismeyeblink} from "../effect/cubismeyeblink"; +import {Live2DCubismFramework as cubismrenderer_webgl} from "../rendering/cubismrenderer_WebGL"; +import {CubismLogError, CubismLogInfo} from "../utils/cubismdebug"; +import CubismRenderer_WebGL = cubismrenderer_webgl.CubismRenderer_WebGL; +import CubismEyeBlink = cubismeyeblink.CubismEyeBlink; +import CubismBreath = cubismbreath.CubismBreath; +import CubismMotionQueueManager = cubismmotionqueuemanager.CubismMotionQueueManager; +import csmString = csmstring.csmString; +import Constant = cubismframework.Constant; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismPhysics = cubismphysics.CubismPhysics; +import CubismModelUserData = cubismmodeluserdata.CubismModelUserData; +import CubismPose = cubismpose.CubismPose; +import CubismExpressionMotion = cubismexpressionmotion.CubismExpressionMotion; +import CubismMotion = cubismmotion.CubismMotion; +import ACubismMotion = acubismmotion.ACubismMotion; +import CubismModel = cubismmodel.CubismModel; +import CubismMoc = cubismmoc.CubismMoc; +import CubismModelMatrix = cubismmodelmatrix.CubismModelMatrix; +import CubismTargetPoint = cubismtargetpoint.CubismTargetPoint; +import CubismMotionManager = cubismmotionmanager.CubismMotionManager; + +export namespace Live2DCubismFramework +{ + /** + * ユーザーが実際に使用するモデル + * + * ユーザーが実際に使用するモデルの基底クラス。これを継承してユーザーが実装する。 + */ + export class CubismUserModel + { + /** + * 初期化状態の取得 + * + * 初期化されている状態か? + * + * @return true 初期化されている + * @return false 初期化されていない + */ + public isInitialized(): boolean + { + return this._initialized; + } + + /** + * 初期化状態の設定 + * + * 初期化状態を設定する。 + * + * @param v 初期化状態 + */ + public setInitialized(v: boolean): void + { + this._initialized = v; + } + + /** + * 更新状態の取得 + * + * 更新されている状態か? + * + * @return true 更新されている + * @return false 更新されていない + */ + public isUpdating(): boolean + { + return this._updating; + } + + /** + * 更新状態の設定 + * + * 更新状態を設定する + * + * @param v 更新状態 + */ + public setUpdating(v: boolean): void + { + this._updating = v; + } + + /** + * マウスドラッグ情報の設定 + * @param ドラッグしているカーソルのX位置 + * @param ドラッグしているカーソルのY位置 + */ + public setDragging(x: number, y: number): void + { + this._dragManager.set(x, y); + } + + /** + * 加速度の情報を設定する + * @param x X軸方向の加速度 + * @param y Y軸方向の加速度 + * @param z Z軸方向の加速度 + */ + public setAcceleration(x: number, y: number, z: number): void + { + this._accelerationX = x; + this._accelerationY = y; + this._accelerationZ = z; + } + + /** + * モデル行列を取得する + * @return モデル行列 + */ + public getModelMatrix(): CubismModelMatrix + { + return this._modelMatrix; + } + + /** + * 不透明度の設定 + * @param a 不透明度 + */ + public setOpacity(a: number): void + { + this._opacity = a; + } + + /** + * 不透明度の取得 + * @return 不透明度 + */ + public getOpacity(): number + { + return this._opacity; + } + + /** + * モデルデータを読み込む + * + * @param buffer moc3ファイルが読み込まれているバッファ + */ + public loadModel(buffer: ArrayBuffer) + { + this._moc = CubismMoc.create(buffer); + this._model = this._moc.createModel(); + this._model.saveParameters(); + + if ((this._moc == null) || (this._model == null)) + { + CubismLogError("Failed to CreateModel()."); + return; + } + + this._modelMatrix = new CubismModelMatrix(this._model.getCanvasWidth(), this._model.getCanvasHeight()); + } + + /** + * モーションデータを読み込む + * @param buffer motion3.jsonファイルが読み込まれているバッファ + * @param size バッファのサイズ + * @param name モーションの名前 + * @return モーションクラス + */ + public loadMotion(buffer: ArrayBuffer, size: number, name: string): ACubismMotion + { + return CubismMotion.create(buffer, size); + } + + /** + * 表情データの読み込み + * @param buffer expファイルが読み込まれているバッファ + * @param size バッファのサイズ + * @param name 表情の名前 + */ + public loadExpression(buffer: ArrayBuffer, size: number, name: string): ACubismMotion + { + return CubismExpressionMotion.create(buffer, size); + } + + /** + * ポーズデータの読み込み + * @param buffer pose3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public loadPose(buffer: ArrayBuffer, size: number): void + { + this._pose = CubismPose.create(buffer, size); + } + + /** + * モデルに付属するユーザーデータを読み込む + * @param buffer userdata3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public loadUserData(buffer: ArrayBuffer, size: number): void + { + this._modelUserData = CubismModelUserData.create(buffer, size); + } + + /** + * 物理演算データの読み込み + * @param buffer physics3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public loadPhysics(buffer: ArrayBuffer, size: number): void + { + this._physics = CubismPhysics.create(buffer, size); + } + + /** + * 当たり判定の取得 + * @param drawableId 検証したいDrawableのID + * @param pointX X位置 + * @param pointY Y位置 + * @return true ヒットしている + * @return false ヒットしていない + */ + public isHit(drawableId: CubismIdHandle, pointX: number, pointY: number): boolean + { + const drawIndex: number = this._model.getDrawableIndex(drawableId); + + if(drawIndex < 0) + { + return false; // 存在しない場合はfalse + } + + const count: number = this._model.getDrawableVertexCount(drawIndex); + const vertices: Float32Array = this._model.getDrawableVertices(drawIndex); + + let left: number = vertices[0]; + let right: number = vertices[0]; + let top: number = vertices[1]; + let bottom: number = vertices[1]; + + for(let j: number = 1; j < count; ++j) + { + let x = vertices[Constant.vertexOffset + j * Constant.vertexStep]; + let y = vertices[Constant.vertexOffset + j * Constant.vertexStep + 1]; + + if(x < left) + { + left = x; // Min x + } + + if(x > right) + { + right = x; // Max x + } + + if(y < top) + { + top = y; // Min y + } + + if(y > bottom) + { + bottom = y; // Max y + } + } + + const tx: number = this._modelMatrix.invertTransformX(pointX); + const ty: number = this._modelMatrix.invertTransformY(pointY); + + return ((left <= tx) && (tx <= right) && (top <= ty) && (ty <= bottom)); + } + + /** + * モデルの取得 + * @return モデル + */ + public getModel(): CubismModel + { + return this._model; + } + + /** + * レンダラの取得 + * @return レンダラ + */ + public getRenderer(): CubismRenderer_WebGL + { + return this._renderer; + } + + /** + * レンダラを作成して初期化を実行する + */ + public createRenderer(): void + { + if(this._renderer) + { + this.deleteRenderer(); + } + + this._renderer = new CubismRenderer_WebGL(); + this._renderer.initialize(this._model); + } + + /** + * レンダラの解放 + */ + public deleteRenderer(): void + { + if(this._renderer) + { + this._renderer = void 0; + this._renderer = null; + } + } + + /** + * イベント発火時の標準処理 + * + * Eventが再生処理時にあった場合の処理をする。 + * 継承で上書きすることを想定している。 + * 上書きしない場合はログ出力をする。 + * + * @param eventValue 発火したイベントの文字列データ + */ + public motionEventFired(eventValue: csmString): void + { + CubismLogInfo("{0}", eventValue.s); + } + + /** + * イベント用のコールバック + * + * CubismMotionQueueManagerにイベント用に登録するためのCallback。 + * CubismUserModelの継承先のEventFiredを呼ぶ。 + * + * @param caller 発火したイベントを管理していたモーションマネージャー、比較用 + * @param eventValue 発火したイベントの文字列データ + * @param customData CubismUserModelを継承したインスタンスを想定 + */ + public static cubismDefaultMotionEventCallback(caller: CubismMotionQueueManager, eventValue: csmString, customData: CubismUserModel): void + { + let model: CubismUserModel = customData; + + if(model != null) + { + model.motionEventFired(eventValue); + } + } + + /** + * コンストラクタ + */ + public constructor() + { + // 各変数初期化 + this._moc = null; + this._model = null; + this._motionManager = null; + this._expressionManager = null; + this._eyeBlink = null; + this._breath = null; + this._modelMatrix = null; + this._pose = null; + this._dragManager = null; + this._physics = null; + this._modelUserData = null; + this._initialized = false; + this._updating = false; + this._opacity = 1.0; + this._lipsync = true; + this._lastLipSyncValue = 0.0; + this._dragX = 0.0; + this._dragY = 0.0; + this._accelerationX = 0.0; + this._accelerationY = 0.0; + this._accelerationZ = 0.0; + this._debugMode = false; + this._renderer = null; + + // モーションマネージャーを作成 + this._motionManager = new CubismMotionManager(); + this._motionManager.setEventCallback(CubismUserModel.cubismDefaultMotionEventCallback, this); + + // 表情マネージャーを作成 + this._expressionManager = new CubismMotionManager(); + + // ドラッグによるアニメーション + this._dragManager = new CubismTargetPoint(); + } + + /** + * デストラクタに相当する処理 + */ + public release() + { + this._motionManager.release(); + this._motionManager = void 0; + this._motionManager = null; + + this._expressionManager.release(); + this._expressionManager = void 0; + this._expressionManager = null; + + this._moc.deleteModel(this._model); + this._moc.release(); + this._moc = void 0; + this._moc = null; + + this._modelMatrix = void 0; + this._modelMatrix = null; + + CubismPose.delete(this._pose); + CubismEyeBlink.delete(this._eyeBlink); + CubismBreath.delete(this._breath); + + this._dragManager = void 0; + this._dragManager = null; + + CubismPhysics.delete(this._physics); + CubismModelUserData.delete(this._modelUserData); + this.deleteRenderer(); + + } + + protected _moc: CubismMoc; // Mocデータ + protected _model: CubismModel; // Modelインスタンス + + protected _motionManager: CubismMotionManager; // モーション管理 + protected _expressionManager: CubismMotionManager; // 表情管理 + protected _eyeBlink: CubismEyeBlink; // 自動まばたき + protected _breath: CubismBreath; // 呼吸 + protected _modelMatrix: CubismModelMatrix; // モデル行列 + protected _pose: CubismPose; // ポーズ管理 + protected _dragManager: CubismTargetPoint; // マウスドラッグ + protected _physics: CubismPhysics; // 物理演算 + protected _modelUserData: CubismModelUserData; // ユーザーデータ + + protected _initialized: boolean; // 初期化されたかどうか + protected _updating: boolean; // 更新されたかどうか + protected _opacity: number; // 不透明度 + protected _lipsync: boolean; // リップシンクするかどうか + protected _lastLipSyncValue: number; // 最後のリップシンクの制御地 + protected _dragX: number; // マウスドラッグのX位置 + protected _dragY: number; // マウスドラッグのY位置 + protected _accelerationX: number; // X軸方向の加速度 + protected _accelerationY: number; // Y軸方向の加速度 + protected _accelerationZ: number; // Z軸方向の加速度 + protected _debugMode: boolean; // デバッグモードかどうか + + private _renderer: CubismRenderer_WebGL; // レンダラ + } + +} \ No newline at end of file diff --git a/Framework/motion/acubismmotion.ts b/Framework/motion/acubismmotion.ts new file mode 100644 index 0000000..e0bad58 --- /dev/null +++ b/Framework/motion/acubismmotion.ts @@ -0,0 +1,239 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismmath} from '../math/cubismmath'; +import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; +import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; +import {Live2DCubismFramework as csmstring} from '../type/csmstring'; +import {Live2DCubismFramework as csmvector} from '../type/csmvector'; +import { CSM_ASSERT } from '../utils/cubismdebug'; +import csmVector = csmvector.csmVector; +import csmString = csmstring.csmString; +import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; +import CubismModel = cubismmodel.CubismModel; +import CubismMath = cubismmath.CubismMath; + +export namespace Live2DCubismFramework +{ + /** + * モーションの抽象基底クラス + * + * モーションの抽象基底クラス。MotionQueueManagerによってモーションの再生を管理する。 + */ + export abstract class ACubismMotion + { + /** + * インスタンスの破棄 + */ + public static delete(motion: ACubismMotion): void + { + motion.release(); + motion = void 0; + motion = null; + } + + /** + * コンストラクタ + */ + public constructor() + { + this._fadeInSeconds = -1.0; + this._fadeOutSeconds = -1.0; + this._weight = 1.0; + this._offsetSeconds = 0.0; // 再生の開始時刻 + this._firedEventValues = new csmVector(); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + this._weight = 0.0; + } + + /** + * モデルのパラメータ + * @param model 対象のモデル + * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション + * @param userTimeSeconds デルタ時間の積算値[秒] + */ + public updateParameters(model: CubismModel, motionQueueEntry: CubismMotionQueueEntry, userTimeSeconds: number): void + { + if(!motionQueueEntry.isAvailable() || motionQueueEntry.isFinished()) + { + return; + } + + if(!motionQueueEntry.isStarted()) + { + motionQueueEntry.setIsStarted(true); + motionQueueEntry.setStartTime(userTimeSeconds - this._offsetSeconds); // モーションの開始時刻を記録 + motionQueueEntry.setFadeInStartTime(userTimeSeconds); // フェードインの開始時刻 + + const duration: number = this.getDuration(); + + if(motionQueueEntry.getEndTime() < 0) + { + // 開始していないうちに終了設定している場合がある。 + motionQueueEntry.setEndTime((duration <= 0) ? -1 : motionQueueEntry.getStartTime() + duration); + // duration == -1 の場合はループする + } + } + + let fadeWeight: number = this._weight; // 現在の値と掛け合わせる割合 + + //---- フェードイン・アウトの処理 ---- + // 単純なサイン関数でイージングする + const fadeIn: number = this._fadeInSeconds == 0.0 + ? 1.0 + : CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / this._fadeInSeconds); + + const fadeOut: number = (this._fadeOutSeconds == 0.0 || motionQueueEntry.getEndTime() < 0.0) + ? 1.0 + : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / this._fadeOutSeconds); + + fadeWeight = fadeWeight * fadeIn * fadeOut; + + motionQueueEntry.setState(userTimeSeconds, fadeWeight); + + CSM_ASSERT(0.0 <= fadeWeight && fadeWeight <= 1.0); + + //---- 全てのパラメータIDをループする ---- + this.doUpdateParameters(model, userTimeSeconds, fadeWeight, motionQueueEntry); + + // 後処理 + // 終了時刻を過ぎたら終了フラグを立てる(CubismMotionQueueManager) + if((motionQueueEntry.getEndTime() > 0) && (motionQueueEntry.getEndTime() < userTimeSeconds)) + { + motionQueueEntry.setIsFinished(true); // 終了 + } + } + + /** + * フェードインの時間を設定する + * @param fadeInSeconds フェードインにかかる時間[秒] + */ + public setFadeInTime(fadeInSeconds: number): void + { + this._fadeInSeconds = fadeInSeconds; + } + + /** + * フェードアウトの時間を設定する + * @param fadeOutSeconds フェードアウトにかかる時間[秒] + */ + public setFadeOutTime(fadeOutSeconds: number): void + { + this._fadeOutSeconds = fadeOutSeconds; + } + + /** + * フェードアウトにかかる時間の取得 + * @return フェードアウトにかかる時間[秒] + */ + public getFadeOutTime(): number + { + return this._fadeOutSeconds; + } + + /** + * フェードインにかかる時間の取得 + * @return フェードインにかかる時間[秒] + */ + public getFadeInTime(): number + { + return this._fadeInSeconds; + } + + /** + * モーション適用の重みの設定 + * @param weight 重み(0.0 - 1.0) + */ + public setWeight(weight: number): void + { + this._weight = weight; + } + + /** + * モーション適用の重みの取得 + * @return 重み(0.0 - 1.0) + */ + public getWeight(): number + { + return this._weight; + } + + /** + * モーションの長さの取得 + * @return モーションの長さ[秒] + * + * @note ループの時は「-1」。 + * ループでない場合は、オーバーライドする。 + * 正の値の時は取得される時間で終了する。 + * 「-1」の時は外部から停止命令がない限り終わらない処理となる。 + */ + public getDuration(): number + { + return -1.0; + } + + /** + * モーションのループ1回分の長さの取得 + * @return モーションのループ一回分の長さ[秒] + * + * @note ループしない場合は、getDuration()と同じ値を返す + * ループ一回分の長さが定義できない場合(プログラム的に動き続けるサブクラスなど)の場合は「-1」を返す + */ + public getLoopDuration(): number + { + return -1.0; + } + + /** + * モーション再生の開始時刻の設定 + * @param offsetSeconds モーション再生の開始時刻[秒] + */ + public setOffsetTime(offsetSeconds: number): void + { + this._offsetSeconds = offsetSeconds; + } + + /** + * モデルのパラメータ更新 + * + * イベント発火のチェック。 + * 入力する時間は呼ばれるモーションタイミングを0とした秒数で行う。 + * + * @param beforeCheckTimeSeconds 前回のイベントチェック時間[秒] + * @param motionTimeSeconds 今回の再生時間[秒] + */ + public getFiredEvent(beforeCheckTimeSeconds: number, motionTimeSeconds: number): csmVector + { + return this._firedEventValues; + } + + /** + * モーションを更新して、モデルにパラメータ値を反映する + * @param model 対象のモデル + * @param userTimeSeconds デルタ時間の積算値[秒] + * @param weight モーションの重み + * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション + * @return true モデルへパラメータ値の反映あり + * @return false モデルへのパラメータ値の反映なし(モーションの変化なし) + */ + public abstract doUpdateParameters(model: CubismModel, userTimeSeconds: number, weight: number, motionQueueEntry: CubismMotionQueueEntry): void; + + + public _fadeInSeconds: number; // フェードインにかかる時間[秒] + public _fadeOutSeconds: number; // フェードアウトにかかる時間[秒] + public _weight: number; // モーションの重み + public _offsetSeconds: number; // モーション再生の開始時間[秒] + + public _firedEventValues: csmVector; + } +} \ No newline at end of file diff --git a/Framework/motion/cubismexpressionmotion.ts b/Framework/motion/cubismexpressionmotion.ts new file mode 100644 index 0000000..1635150 --- /dev/null +++ b/Framework/motion/cubismexpressionmotion.ts @@ -0,0 +1,189 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; +import {Live2DCubismFramework as cubismjson} from '../utils/cubismjson'; +import {Live2DCubismFramework as cubismid} from '../id/cubismid'; +import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; +import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; +import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; +import {Live2DCubismFramework as csmvector} from '../type/csmvector'; +import JsonFloat = cubismjson.JsonFloat; +import csmVector = csmvector.csmVector; +import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; +import CubismModel = cubismmodel.CubismModel; +import CubismFramework = cubismframework.CubismFramework; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismJson = cubismjson.CubismJson; +import Value = cubismjson.Value; +import ACubismMotion = acubismmotion.ACubismMotion; + +export namespace Live2DCubismFramework +{ + // exp3.jsonのキーとデフォルト + const ExpressionKeyFadeIn: string = "FadeInTime"; + const ExpressionKeyFadeOut: string = "FadeOutTime"; + const ExpressionKeyParameters: string = "Parameters"; + const ExpressionKeyId: string = "Id"; + const ExpressionKeyValue: string = "Value"; + const ExpressionKeyBlend: string = "Blend"; + const BlendValueAdd: string = "Add"; + const BlendValueMultiply: string = "Multiply"; + const BlendValueOverwrite: string = "Overwrite"; + const DefaultFadeTime: number = 1.0; + + /** + * 表情のモーション + * + * 表情のモーションクラス。 + */ + export class CubismExpressionMotion extends ACubismMotion + { + /** + * インスタンスを作成する。 + * @param buffer expファイルが読み込まれているバッファ + * @param size バッファのサイズ + * @return 作成されたインスタンス + */ + public static create(buffer: ArrayBuffer, size: number): CubismExpressionMotion + { + let expression: CubismExpressionMotion = new CubismExpressionMotion(); + + let json: CubismJson = CubismJson.create(buffer, size); + let root: Value = json.getRoot(); + + // typescriptではnullを許容していないため仮の値を入れる + if(root.getMap().getValue(ExpressionKeyFadeIn) == null) + { + root.getMap().setValue(ExpressionKeyFadeIn, new JsonFloat(DefaultFadeTime)); + } + if(root.getMap().getValue(ExpressionKeyFadeOut) == null) + { + root.getMap().setValue(ExpressionKeyFadeOut, new JsonFloat(DefaultFadeTime)); + } + + expression.setFadeInTime(root.getMap().getValue(ExpressionKeyFadeIn).toFloat(DefaultFadeTime)); // フェードイン + expression.setFadeOutTime(root.getMap().getValue(ExpressionKeyFadeOut).toFloat(DefaultFadeTime)); // フェードアウト + + // 各パラメータについて + const parameterCount = root.getMap().getValue(ExpressionKeyParameters).getSize(); + + for(let i: number = 0; i < parameterCount; ++i) + { + let param: Value = root.getMap().getValue(ExpressionKeyParameters).getVector().at(i); + const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(param.getMap().getValue(ExpressionKeyId).getRawString()); // パラメータID + + const value: number = param.getMap().getValue(ExpressionKeyValue).toFloat(); // 値 + + // 計算方法の設定 + let blendType: CubismExpressionMotion.ExpressionBlendType; + + if(param.getMap().getValue(ExpressionKeyBlend).isNull() || param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueAdd) + { + blendType = this.ExpressionBlendType.ExpressionBlendType_Add; + } + else if(param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueMultiply) + { + blendType = this.ExpressionBlendType.ExpressionBlendType_Multiply; + } + else if(param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueOverwrite) + { + blendType = this.ExpressionBlendType.ExpressionBlendType_Overwrite; + } + else + { + // その他 仕様にない値を設定した時は加算モードにすることで復旧 + blendType = this.ExpressionBlendType.ExpressionBlendType_Add; + } + + // 設定オブジェクトを作成してリストに追加する + let item: CubismExpressionMotion.ExpressionParameter = new CubismExpressionMotion.ExpressionParameter(); + + item.parameterId = parameterId; + item.blendType = blendType; + item.value = value; + + expression._parameters.pushBack(item); + } + + CubismJson.delete(json); // JSONデータは不要になったら削除する + return expression; + } + + /** + * モデルのパラメータの更新の実行 + * @param model 対象のモデル + * @param userTimeSeconds デルタ時間の積算値[秒] + * @param weight モーションの重み + * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション + */ + public doUpdateParameters(model: CubismModel, userTimeSeconds: number, weight: number, motionQueueEntry: CubismMotionQueueEntry): void + { + for(let i: number = 0; i < this._parameters.getSize(); ++i) + { + let parameter: CubismExpressionMotion.ExpressionParameter = this._parameters.at(i); + + switch(parameter.blendType) + { + case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Add: + { + model.addParameterValueById(parameter.parameterId, parameter.value, weight); + break; + } + case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Multiply: + { + model.multiplyParameterValueById(parameter.parameterId, parameter.value, weight); + break; + } + case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Overwrite: + { + model.setParameterValueById(parameter.parameterId, parameter.value, weight) + break; + } + default: + // 仕様にない値を設定した時はすでに加算モードになっている + break; + } + } + } + + /** + * コンストラクタ + */ + constructor() + { + super(); + + this._parameters = new csmVector(); + } + + _parameters: csmVector; // 表情のパラメータ情報リスト + } + + export namespace CubismExpressionMotion + { + /** + * 表情パラメータ値の計算方式 + */ + export enum ExpressionBlendType + { + ExpressionBlendType_Add = 0, // 加算 + ExpressionBlendType_Multiply = 1, // 乗算 + ExpressionBlendType_Overwrite = 2 // 上書き + } + + /** + * 表情のパラメータ情報 + */ + export class ExpressionParameter + { + parameterId: CubismIdHandle; // パラメータID + blendType: ExpressionBlendType; // パラメータの演算種類 + value: number; // 値 + } + } +} \ No newline at end of file diff --git a/Framework/motion/cubismmotion.ts b/Framework/motion/cubismmotion.ts new file mode 100644 index 0000000..f113db5 --- /dev/null +++ b/Framework/motion/cubismmotion.ts @@ -0,0 +1,805 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismmotionjson} from './cubismmotionjson'; +import {Live2DCubismFramework as cubismmotioninternal} from './cubismmotioninternal'; +import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; +import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; +import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; +import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; +import {Live2DCubismFramework as cubismmath} from '../math/cubismmath'; +import {Live2DCubismFramework as csmvector} from '../type/csmvector'; +import {Live2DCubismFramework as cubismid} from '../id/cubismid'; +import {Live2DCubismFramework as csmstring} from '../type/csmstring'; +import {CubismLogDebug, CSM_ASSERT} from '../utils/cubismdebug'; +import csmString = csmstring.csmString; +import CubismMotionData = cubismmotioninternal.CubismMotionData; +import CubismMotionSegment = cubismmotioninternal.CubismMotionSegment; +import CubismMotionPoint = cubismmotioninternal.CubismMotionPoint; +import CubismMotionEvent = cubismmotioninternal.CubismMotionEvent; +import CubismMotionSegmentType = cubismmotioninternal.CubismMotionSegmentType; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismMotionCurve = cubismmotioninternal.CubismMotionCurve; +import CubismMotionCurveTarget = cubismmotioninternal.CubismMotionCurveTarget; +import csmVector = csmvector.csmVector; +import CubismMath = cubismmath.CubismMath; +import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; +import CubismFramework = cubismframework.CubismFramework; +import CubismModel = cubismmodel.CubismModel; +import ACubismMotion = acubismmotion.ACubismMotion; +import CubismMotionJson = cubismmotionjson.CubismMotionJson; + +export namespace Live2DCubismFramework +{ + const EffectNameEyeBlink: string = "EyeBlink"; + const EffectNameLipSync: string = "LipSync"; + const TargetNameModel: string = "Model"; + const TargetNameParameter: string = "Parameter"; + const TargetNamePartOpacity: string = "PartOpacity"; + + function lerpPoints(a: CubismMotionPoint, b: CubismMotionPoint, t: number): CubismMotionPoint + { + let result: CubismMotionPoint = new CubismMotionPoint(); + + result.time = a.time + ((b.time - a.time) * t); + result.value = a.value + ((b.value - a.value) * t); + + return result; + } + + function linearEvaluate(points: CubismMotionPoint[], time: number): number + { + let t: number = (time - points[0].time) / (points[1].time - points[0].time); + + if (t < 0.0) + { + t = 0.0; + } + + return points[0].value + ((points[1].value - points[0].value) * t); + } + + function bezierEvaluate(points: CubismMotionPoint[], time: number): number + { + let t: number = (time - points[0].time) / (points[3].time - points[0].time); + + if (t < 0.0) + { + t = 0.0; + } + + const p01: CubismMotionPoint = lerpPoints(points[0], points[1], t); + const p12: CubismMotionPoint = lerpPoints(points[1], points[2], t); + const p23: CubismMotionPoint = lerpPoints(points[2], points[3], t); + + const p012: CubismMotionPoint = lerpPoints(p01, p12, t); + const p123: CubismMotionPoint = lerpPoints(p12, p23, t); + + return lerpPoints(p012, p123, t).value; + } + + function steppedEvaluate(points: CubismMotionPoint[], time: number): number + { + return points[0].value; + } + + function inverseSteppedEvaluate(points: CubismMotionPoint[], time: number): number + { + return points[1].value; + } + + function evaluateCurve(motionData: CubismMotionData, index: number, time: number): number + { + // Find segment to evaluate. + const curve: CubismMotionCurve = motionData.curves.at(index); + + let target: number = -1; + const totalSegmentCount: number = curve.baseSegmentIndex + curve.segmentCount; + let pointPosition: number = 0; + for (let i: number = curve.baseSegmentIndex; i < totalSegmentCount; ++i) + { + // Get first point of next segment. + pointPosition = motionData.segments.at(i).basePointIndex + + (motionData.segments.at(i).segmentType == CubismMotionSegmentType.CubismMotionSegmentType_Bezier + ? 3 + : 1); + + + // Break if time lies within current segment. + if (motionData.points.at(pointPosition).time > time) + { + target = i; + break; + } + } + + + if (target == -1) + { + return motionData.points.at(pointPosition).value; + } + + + const segment: CubismMotionSegment = motionData.segments.at(target); + + return segment.evaluate(motionData.points.get(segment.basePointIndex), time); + } + + /** + * モーションクラス + * + * モーションのクラス。 + */ + export class CubismMotion extends ACubismMotion + { + /** + * インスタンスを作成する + * + * @param buffer motion3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + * @return 作成されたインスタンス + */ + public static create(buffer: ArrayBuffer, size: number): CubismMotion + { + let ret: CubismMotion = new CubismMotion(); + + ret.parse(buffer, size); + ret._sourceFrameRate = ret._motionData.fps; + ret._loopDurationSeconds = ret._motionData.duration; + + // NOTE: Editorではループありのモーション書き出しは非対応 + // ret->_loop = (ret->_motionData->Loop > 0); + return ret; + } + + /** + * モデルのパラメータの更新の実行 + * @param model 対象のモデル + * @param userTimeSeconds 現在の時刻[秒] + * @param fadeWeight モーションの重み + * @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション + */ + public doUpdateParameters(model: CubismModel, userTimeSeconds: number, fadeWeight: number, motionQueueEntry: CubismMotionQueueEntry): void + { + if (this._modelCurveIdEyeBlink == null) + { + this._modelCurveIdEyeBlink = CubismFramework.getIdManager().getId(EffectNameEyeBlink); + } + + if (this._modelCurveIdLipSync == null) + { + this._modelCurveIdLipSync = CubismFramework.getIdManager().getId(EffectNameLipSync); + } + + let timeOffsetSeconds: number = userTimeSeconds - motionQueueEntry.getStartTime(); + + if (timeOffsetSeconds < 0.0) + { + timeOffsetSeconds = 0.0; // エラー回避 + } + + let lipSyncValue: number = Number.MAX_VALUE; + let eyeBlinkValue: number = Number.MAX_VALUE; + + //まばたき、リップシンクのうちモーションの適用を検出するためのビット(maxFlagCount個まで + const MaxTargetSize = 64; + let lipSyncFlags = 0; + let eyeBlinkFlags = 0; + + //瞬き、リップシンクのターゲット数が上限を超えている場合 + if (this._eyeBlinkParameterIds.getSize() > MaxTargetSize) + { + CubismLogDebug("too many eye blink targets : {0}", this._eyeBlinkParameterIds.getSize()); + } + if (this._lipSyncParameterIds.getSize() > MaxTargetSize) + { + CubismLogDebug("too many lip sync targets : {0}", this._lipSyncParameterIds.getSize()); + } + + const tmpFadeIn: number = (this._fadeInSeconds <= 0.0) + ? 1.0 + : CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / this._fadeInSeconds); + + const tmpFadeOut: number = (this._fadeOutSeconds <= 0.0 || motionQueueEntry.getEndTime() < 0.0) + ? 1.0 + : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / this._fadeOutSeconds); + let value: number; + let c: number, parameterIndex: number; + + // 'Repeat' time as necessary. + let time: number = timeOffsetSeconds; + + if (this._isLoop) + { + while (time > this._motionData.duration) + { + time -= this._motionData.duration; + } + } + + let curves: csmVector = this._motionData.curves; + + // Evaluate model curves. + for (c = 0; c < this._motionData.curveCount && curves.at(c).type == CubismMotionCurveTarget.CubismMotionCurveTarget_Model; ++c) + { + // Evaluate curve and call handler. + value = evaluateCurve(this._motionData, c, time); + + if (curves.at(c).id == this._modelCurveIdEyeBlink) + { + eyeBlinkValue = value; + } + else if (curves.at(c).id == this._modelCurveIdLipSync) + { + lipSyncValue = value; + } + } + + let parameterMotionCurveCount: number = 0; + + for (; c < this._motionData.curveCount && curves.at(c).type == CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter; ++c) + { + parameterMotionCurveCount++; + + // Find parameter index. + parameterIndex = model.getParameterIndex(curves.at(c).id); + + // Skip curve evaluation if no value in sink. + if (parameterIndex == -1) + { + continue; + } + + const sourceValue: number = model.getParameterValueByIndex(parameterIndex); + + // Evaluate curve and apply value. + value = evaluateCurve(this._motionData, c, time); + + if (eyeBlinkValue != Number.MAX_VALUE) + { + for (let i: number = 0; i < this._eyeBlinkParameterIds.getSize() && i < MaxTargetSize; ++i) + { + if (this._eyeBlinkParameterIds.at(i) == curves.at(c).id) + { + value *= eyeBlinkValue; + eyeBlinkFlags |= 1 << i; + break; + } + } + } + + if(lipSyncValue != Number.MAX_VALUE) + { + for(let i: number = 0; i < this._lipSyncParameterIds.getSize() && i < MaxTargetSize; ++i) + { + if(this._lipSyncParameterIds.at(i) == curves.at(c).id) + { + value += lipSyncValue; + lipSyncFlags |= 1 << i; + break; + } + } + } + + let v: number; + + // パラメータごとのフェード + if(curves.at(c).fadeInTime < 0.0 && curves.at(c).fadeOutTime < 0.0) + { + // モーションのフェードを適用 + v = sourceValue + (value - sourceValue) * fadeWeight; + } + else + { + // パラメータに対してフェードインかフェードアウトが設定してある場合はそちらを適用 + let fin: number; + let fout: number; + + if(curves.at(c).fadeInTime < 0.0) + { + fin = tmpFadeIn; + } + else + { + fin = curves.at(c).fadeInTime == 0.0 + ? 1.0 + :CubismMath.getEasingSine((userTimeSeconds - motionQueueEntry.getFadeInStartTime()) / curves.at(c).fadeInTime); + } + + if(curves.at(c).fadeOutTime < 0.0) + { + fout = tmpFadeOut; + } + else + { + fout = (curves.at(c).fadeOutTime == 0.0 || motionQueueEntry.getEndTime() < 0.0) + ? 1.0 + : CubismMath.getEasingSine((motionQueueEntry.getEndTime() - userTimeSeconds) / curves.at(c).fadeOutTime); + } + + const paramWeight: number = this._weight * fin * fout; + + // パラメータごとのフェードを適用 + v = sourceValue + (value - sourceValue) * paramWeight; + } + + model.setParameterValueByIndex(parameterIndex, v, 1.0); + } + + { + if(eyeBlinkValue != Number.MAX_VALUE) + { + for(let i: number = 0; i < this._eyeBlinkParameterIds.getSize() && i < MaxTargetSize; ++i) + { + const sourceValue: number = model.getParameterValueById(this._eyeBlinkParameterIds.at(i)); + + // モーションでの上書きがあった時にはまばたきは適用しない + if((eyeBlinkFlags >> i) & 0x01) + { + continue; + } + + const v: number = sourceValue + (eyeBlinkValue - sourceValue) * fadeWeight; + + model.setParameterValueById(this._eyeBlinkParameterIds.at(i), v); + } + } + + if(lipSyncValue != Number.MAX_VALUE) + { + for(let i: number = 0; i < this._lipSyncParameterIds.getSize() && i < MaxTargetSize; ++i) + { + const sourceValue: number = model.getParameterValueById(this._lipSyncParameterIds.at(i)); + + // モーションでの上書きがあった時にはリップシンクは適用しない + if((lipSyncFlags >> i) & 0x01) + { + continue; + } + + const v: number = sourceValue + (lipSyncValue - sourceValue) * fadeWeight; + + model.setParameterValueById(this._lipSyncParameterIds.at(i), v); + } + } + } + + for(; c < this._motionData.curveCount && curves.at(c).type == CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity; ++c) + { + // Find parameter index. + parameterIndex = model.getParameterIndex(curves.at(c).id); + + // Skip curve evaluation if no value in sink. + if(parameterIndex == -1) + { + continue; + } + + // Evaluate curve and apply value. + value = evaluateCurve(this._motionData, c, time); + + model.setParameterValueByIndex(parameterIndex, value); + } + + if(timeOffsetSeconds >= this._motionData.duration) + { + if(this._isLoop) + { + motionQueueEntry.setStartTime(userTimeSeconds); // 最初の状態へ + if(this._isLoopFadeIn) + { + // ループ内でループ用フェードインが有効の時は、フェードイン設定し直し + motionQueueEntry.setFadeInStartTime(userTimeSeconds); + } + } + else + { + motionQueueEntry.setIsFinished(true); + } + } + this._lastWeight = fadeWeight; + } + + /** + * ループ情報の設定 + * @param loop ループ情報 + */ + public setIsLoop(loop: boolean): void + { + this._isLoop = loop; + } + + /** + * ループ情報の取得 + * @return true ループする + * @return false ループしない + */ + public isLoop(): boolean + { + return this._isLoop; + } + + /** + * ループ時のフェードイン情報の設定 + * @param loopFadeIn ループ時のフェードイン情報 + */ + public setIsLoopFadeIn(loopFadeIn: boolean): void + { + this._isLoopFadeIn = loopFadeIn; + } + + /** + * ループ時のフェードイン情報の取得 + * + * @return true する + * @return false しない + */ + public isLoopFadeIn(): boolean + { + return this._isLoopFadeIn; + } + + /** + * モーションの長さを取得する。 + * + * @return モーションの長さ[秒] + */ + public getDuration(): number + { + return this._isLoop ? -1.0 : this._loopDurationSeconds; + } + + /** + * モーションのループ時の長さを取得する。 + * + * @return モーションのループ時の長さ[秒] + */ + public getLoopDuration(): number + { + return this._loopDurationSeconds; + } + + /** + * パラメータに対するフェードインの時間を設定する。 + * + * @param parameterId パラメータID + * @param value フェードインにかかる時間[秒] + */ + public setParameterFadeInTime(parameterId: CubismIdHandle, value: number): void + { + let curves: csmVector = this._motionData.curves; + + for (let i: number = 0; i < this._motionData.curveCount; ++i) + { + if (parameterId == curves.at(i).id) + { + curves.at(i).fadeInTime = value; + return; + } + } + } + + /** + * パラメータに対するフェードアウトの時間の設定 + * @param parameterId パラメータID + * @param value フェードアウトにかかる時間[秒] + */ + public setParameterFadeOutTime(parameterId: CubismIdHandle, value: number): void + { + let curves: csmVector = this._motionData.curves; + + for (let i: number = 0; i < this._motionData.curveCount; ++i) + { + if (parameterId == curves.at(i).id) + { + curves.at(i).fadeOutTime = value; + return; + } + } + } + + /** + * パラメータに対するフェードインの時間の取得 + * @param parameterId パラメータID + * @return フェードインにかかる時間[秒] + */ + public getParameterFadeInTime(parameterId: CubismIdHandle): number + { + let curves: csmVector = this._motionData.curves; + + for (let i: number = 0; i < this._motionData.curveCount; ++i) + { + if (parameterId == curves.at(i).id) + { + return curves.at(i).fadeInTime; + } + } + + return -1; + } + + /** + * パラメータに対するフェードアウトの時間を取得 + * + * @param parameterId パラメータID + * @return フェードアウトにかかる時間[秒] + */ + public getParameterFadeOutTime(parameterId: CubismIdHandle): number + { + let curves: csmVector = this._motionData.curves; + + for (let i: number = 0; i < this._motionData.curveCount; ++i) + { + if (parameterId == curves.at(i).id) + { + return curves.at(i).fadeOutTime; + } + } + + return -1; + } + + /** + * 自動エフェクトがかかっているパラメータIDリストの設定 + * @param eyeBlinkParameterIds 自動まばたきがかかっているパラメータIDのリスト + * @param lipSyncParameterIds リップシンクがかかっているパラメータIDのリスト + */ + public setEffectIds(eyeBlinkParameterIds: csmVector, lipSyncParameterIds: csmVector): void + { + this._eyeBlinkParameterIds = eyeBlinkParameterIds; + this._lipSyncParameterIds = lipSyncParameterIds; + } + + /** + * コンストラクタ + */ + public constructor() + { + super(); + this._sourceFrameRate = 30.0; + this._loopDurationSeconds = -1.0; + this._isLoop = false; // trueから false へデフォルトを変更 + this._isLoopFadeIn = true; // ループ時にフェードインが有効かどうかのフラグ + this._lastWeight = 0.0; + this._motionData = null; + this._modelCurveIdEyeBlink = null; + this._modelCurveIdLipSync = null; + this._eyeBlinkParameterIds = null; + this._lipSyncParameterIds = null; + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + this._motionData = void 0; + this._motionData = null; + } + + /** + * motion3.jsonをパースする。 + * + * @param motionJson motion3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public parse(motionJson: ArrayBuffer, size: number): void + { + this._motionData = new CubismMotionData(); + + let json: CubismMotionJson = new CubismMotionJson(motionJson, size); + + this._motionData.duration = json.getMotionDuration(); + this._motionData.loop = json.isMotionLoop(); + this._motionData.curveCount = json.getMotionCurveCount(); + this._motionData.fps = json.getMotionFps(); + this._motionData.eventCount = json.getEventCount(); + + if (json.isExistMotionFadeInTime()) + { + this._fadeInSeconds = (json.getMotionFadeInTime() < 0.0) + ? 1.0 + : json.getMotionFadeInTime(); + } + else + { + this._fadeInSeconds = 1.0; + } + + if (json.isExistMotionFadeOutTime()) + { + this._fadeOutSeconds = (json.getMotionFadeOutTime() < 0.0) + ? 1.0 + : json.getMotionFadeOutTime(); + } + else + { + this._fadeOutSeconds = 1.0; + } + + this._motionData.curves.updateSize(this._motionData.curveCount, CubismMotionCurve, true); + this._motionData.segments.updateSize(json.getMotionTotalSegmentCount(), CubismMotionSegment, true); + this._motionData.points.updateSize(json.getMotionTotalPointCount(), CubismMotionPoint, true); + this._motionData.events.updateSize(this._motionData.eventCount, CubismMotionEvent, true); + + let totalPointCount: number = 0; + let totalSegmentCount: number = 0; + + // Curves + for (let curveCount: number = 0; curveCount < this._motionData.curveCount; ++curveCount) + { + if (json.getMotionCurveTarget(curveCount) == TargetNameModel) + { + this._motionData.curves.at(curveCount).type = CubismMotionCurveTarget.CubismMotionCurveTarget_Model; + } + else if (json.getMotionCurveTarget(curveCount) == TargetNameParameter) + { + this._motionData.curves.at(curveCount).type = CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter; + } + else if (json.getMotionCurveTarget(curveCount) == TargetNamePartOpacity) + { + this._motionData.curves.at(curveCount).type = CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity; + } + + this._motionData.curves.at(curveCount).id = json.getMotionCurveId(curveCount); + + this._motionData.curves.at(curveCount).baseSegmentIndex = totalSegmentCount; + + this._motionData.curves.at(curveCount).fadeInTime = + (json.isExistMotionCurveFadeInTime(curveCount)) + ? json.getMotionCurveFadeInTime(curveCount) + : -1.0 ; + this._motionData.curves.at(curveCount).fadeOutTime = + (json.isExistMotionCurveFadeOutTime(curveCount)) + ? json.getMotionCurveFadeOutTime(curveCount) + : -1.0; + + // Segments + for (let segmentPosition: number = 0; segmentPosition < json.getMotionCurveSegmentCount(curveCount);) + { + if (segmentPosition == 0) + { + this._motionData.segments.at(totalSegmentCount).basePointIndex = totalPointCount; + + this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, segmentPosition); + this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, segmentPosition + 1); + + totalPointCount += 1; + segmentPosition += 2; + } + else + { + this._motionData.segments.at(totalSegmentCount).basePointIndex = totalPointCount - 1; + } + + const segment: number = json.getMotionCurveSegment(curveCount, segmentPosition); + switch (segment) + { + case CubismMotionSegmentType.CubismMotionSegmentType_Linear: + { + this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Linear; + this._motionData.segments.at(totalSegmentCount).evaluate = linearEvaluate; + + this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); + this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); + + totalPointCount += 1; + segmentPosition += 3; + + break; + } + case CubismMotionSegmentType.CubismMotionSegmentType_Bezier: + { + this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Bezier; + this._motionData.segments.at(totalSegmentCount).evaluate = bezierEvaluate; + + this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); + this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); + + this._motionData.points.at(totalPointCount + 1).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 3)); + this._motionData.points.at(totalPointCount + 1).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 4)); + + this._motionData.points.at(totalPointCount + 2).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 5)); + this._motionData.points.at(totalPointCount + 2).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 6)); + + totalPointCount += 3; + segmentPosition += 7; + + break; + } + + case CubismMotionSegmentType.CubismMotionSegmentType_Stepped: + { + this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_Stepped; + this._motionData.segments.at(totalSegmentCount).evaluate = steppedEvaluate; + + this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); + this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); + + totalPointCount += 1; + segmentPosition += 3; + + break; + } + + case CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped: + { + this._motionData.segments.at(totalSegmentCount).segmentType = CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped; + this._motionData.segments.at(totalSegmentCount).evaluate = inverseSteppedEvaluate; + + this._motionData.points.at(totalPointCount).time = json.getMotionCurveSegment(curveCount, (segmentPosition + 1)); + this._motionData.points.at(totalPointCount).value = json.getMotionCurveSegment(curveCount, (segmentPosition + 2)); + + totalPointCount += 1; + segmentPosition += 3; + + break; + } + default: + { + CSM_ASSERT(0); + break; + } + } + + ++this._motionData.curves.at(curveCount).segmentCount; + ++totalSegmentCount; + } + } + + for (let userdatacount: number = 0; userdatacount < json.getEventCount(); ++userdatacount) + { + this._motionData.events.at(userdatacount).fireTime = json.getEventTime(userdatacount); + this._motionData.events.at(userdatacount).value = json.getEventValue(userdatacount); + } + + json.release(); + json = void 0; + json = null; + } + + /** + * モデルのパラメータ更新 + * + * イベント発火のチェック。 + * 入力する時間は呼ばれるモーションタイミングを0とした秒数で行う。 + * + * @param beforeCheckTimeSeconds 前回のイベントチェック時間[秒] + * @param motionTimeSeconds 今回の再生時間[秒] + */ + public getFiredEvent(beforeCheckTimeSeconds: number, motionTimeSeconds: number): csmVector + { + this._firedEventValues.updateSize(0); + + // イベントの発火チェック + for (let u: number = 0; u < this._motionData.eventCount; ++u) + { + if ((this._motionData.events.at(u).fireTime > beforeCheckTimeSeconds) && + (this._motionData.events.at(u).fireTime <= motionTimeSeconds)) + { + this._firedEventValues.pushBack(new csmString(this._motionData.events.at(u).value.s)); + } + } + + return this._firedEventValues; + } + + public _sourceFrameRate: number; // ロードしたファイルのFPS。記述が無ければデフォルト値15fpsとなる + public _loopDurationSeconds: number; // mtnファイルで定義される一連のモーションの長さ + public _isLoop: boolean; // ループするか? + public _isLoopFadeIn: boolean; // ループ時にフェードインが有効かどうかのフラグ。初期値では有効。 + public _lastWeight: number; // 最後に設定された重み + + public _motionData: CubismMotionData; // 実際のモーションデータ本体 + + public _eyeBlinkParameterIds: csmVector; // 自動まばたきを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。 + public _lipSyncParameterIds: csmVector; // リップシンクを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。 + + public _modelCurveIdEyeBlink: CubismIdHandle; // モデルが持つ自動まばたき用パラメータIDのハンドル。 モデルとモーションを対応付ける。 + public _modelCurveIdLipSync: CubismIdHandle; // モデルが持つリップシンク用パラメータIDのハンドル。 モデルとモーションを対応付ける。 + } +} \ No newline at end of file diff --git a/Framework/motion/cubismmotioninternal.ts b/Framework/motion/cubismmotioninternal.ts new file mode 100644 index 0000000..8794aa0 --- /dev/null +++ b/Framework/motion/cubismmotioninternal.ts @@ -0,0 +1,157 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismid} from '../id/cubismid'; +import {Live2DCubismFramework as csmstring} from '../type/csmstring'; +import {Live2DCubismFramework as csmvector} from '../type/csmvector'; +import csmVector = csmvector.csmVector; +import csmString = csmstring.csmString; +import CubismIdHandle = cubismid.CubismIdHandle; + +export namespace Live2DCubismFramework +{ + /** + * @brief モーションカーブの種類 + * + * モーションカーブの種類。 + */ + export enum CubismMotionCurveTarget + { + CubismMotionCurveTarget_Model, // モデルに対して + CubismMotionCurveTarget_Parameter, // パラメータに対して + CubismMotionCurveTarget_PartOpacity // パーツの不透明度に対して + }; + + + /** + * @brief モーションカーブのセグメントの種類 + * + * モーションカーブのセグメントの種類。 + */ + export enum CubismMotionSegmentType + { + CubismMotionSegmentType_Linear = 0, // リニア + CubismMotionSegmentType_Bezier = 1, // ベジェ曲線 + CubismMotionSegmentType_Stepped = 2, // ステップ + CubismMotionSegmentType_InverseStepped = 3 // インバースステップ + }; + + /** + * @brief モーションカーブの制御点 + * + * モーションカーブの制御点。 + */ + export class CubismMotionPoint + { + time: number = 0.0; // 時間[秒] + value: number = 0.0; // 値 + }; + + + /** + * モーションカーブのセグメントの評価関数 + * + * @param points モーションカーブの制御点リスト + * @param time 評価する時間[秒] + */ + export interface csmMotionSegmentEvaluationFunction + { + ( + points: CubismMotionPoint[], + time: number + ): number; + } + + /** + * @brief モーションカーブのセグメント + * + * モーションカーブのセグメント。 + */ + export class CubismMotionSegment + { + /** + * @brief コンストラクタ + * + * コンストラクタ。 + */ + public constructor() + { + this.evaluate = null; + this.basePointIndex = 0; + this.segmentType = 0; + } + + evaluate: csmMotionSegmentEvaluationFunction; // 使用する評価関数 + basePointIndex: number; // 最初のセグメントへのインデックス + segmentType: number; // セグメントの種類 + }; + + /** + * @brief モーションカーブ + * + * モーションカーブ。 + */ + export class CubismMotionCurve + { + public constructor() + { + this.type = CubismMotionCurveTarget.CubismMotionCurveTarget_Model; + this.segmentCount = 0; + this.baseSegmentIndex = 0; + this.fadeInTime = 0.0; + this.fadeOutTime = 0.0; + } + + type: CubismMotionCurveTarget; // カーブの種類 + id: CubismIdHandle; // カーブのID + segmentCount: number; // セグメントの個数 + baseSegmentIndex: number; // 最初のセグメントのインデックス + fadeInTime: number; // フェードインにかかる時間[秒] + fadeOutTime: number; // フェードアウトにかかる時間[秒] + }; + + /** + * イベント。 + */ + export class CubismMotionEvent + { + fireTime: number = 0.0; + value: csmString; + }; + + /** + * @brief モーションデータ + * + * モーションデータ。 + */ + export class CubismMotionData + { + public constructor() + { + this.duration = 0.0; + this.loop = false; + this.curveCount = 0; + this.eventCount = 0; + this.fps = 0.0; + + this.curves = new csmVector(); + this.segments = new csmVector(); + this.points = new csmVector(); + this.events = new csmVector(); + } + + duration: number; // モーションの長さ[秒] + loop: boolean; // ループするかどうか + curveCount: number; // カーブの個数 + eventCount: number; // UserDataの個数 + fps: number; // フレームレート + curves: csmVector; // カーブのリスト + segments: csmVector; // セグメントのリスト + points: csmVector; // ポイントのリスト + events: csmVector; // イベントのリスト + }; +} \ No newline at end of file diff --git a/Framework/motion/cubismmotionjson.ts b/Framework/motion/cubismmotionjson.ts new file mode 100644 index 0000000..8cc14cc --- /dev/null +++ b/Framework/motion/cubismmotionjson.ts @@ -0,0 +1,282 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismjson} from '../utils/cubismjson'; +import {Live2DCubismFramework as cubismid} from '../id/cubismid'; +import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; +import {Live2DCubismFramework as csmstring} from '../type/csmstring'; +import csmString = csmstring.csmString; +import CubismFramework = cubismframework.CubismFramework; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismJson = cubismjson.CubismJson; + +export namespace Live2DCubismFramework +{ + // JSON keys + const Meta: string = "Meta"; + const Duration: string = "Duration"; + const Loop: string = "Loop"; + const CurveCount: string = "CurveCount"; + const Fps: string = "Fps"; + const TotalSegmentCount: string = "TotalSegmentCount"; + const TotalPointCount: string = "TotalPointCount"; + const Curves: string = "Curves"; + const Target: string = "Target"; + const Id: string = "Id"; + const FadeInTime: string = "FadeInTime"; + const FadeOutTime: string = "FadeOutTime"; + const Segments: string = "Segments"; + const UserData: string = "UserData"; + const UserDataCount: string = "UserDataCount"; + const TotalUserDataSize: string = "TotalUserDataSize"; + const Time: string = "Time"; + const Value: string = "Value"; + + /** + * motion3.jsonのコンテナ。 + */ + export class CubismMotionJson + { + /** + * コンストラクタ + * @param buffer motion3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public constructor(buffer: ArrayBuffer, size: number) + { + this._json = CubismJson.create(buffer, size); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + CubismJson.delete(this._json); + } + + /** + * モーションの長さを取得する + * @return モーションの長さ[秒] + */ + public getMotionDuration(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(Duration).toFloat(); + } + + /** + * モーションのループ情報の取得 + * @return true ループする + * @return false ループしない + */ + public isMotionLoop(): boolean + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(Loop).toBoolean(); + } + + /** + * モーションカーブの個数の取得 + * @return モーションカーブの個数 + */ + public getMotionCurveCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(CurveCount).toInt(); + } + + /** + * モーションのフレームレートの取得 + * @return フレームレート[FPS] + */ + public getMotionFps(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(Fps).toFloat(); + } + + /** + * モーションのセグメントの総合計の取得 + * @return モーションのセグメントの取得 + */ + public getMotionTotalSegmentCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalSegmentCount).toInt(); + } + + /** + * モーションのカーブの制御店の総合計の取得 + * @return モーションのカーブの制御点の総合計 + */ + public getMotionTotalPointCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalPointCount).toInt(); + } + + /** + * モーションのフェードイン時間の存在 + * @return true 存在する + * @return false 存在しない + */ + public isExistMotionFadeInTime(): boolean + { + return this._json.getRoot().getMap().getValue(Meta).getMap().isExist(FadeInTime); + } + + /** + * モーションのフェードアウト時間の存在 + * @return true 存在する + * @return false 存在しない + */ + public isExistMotionFadeOutTime(): boolean + { + return this._json.getRoot().getMap().getValue(Meta).getMap().isExist(FadeOutTime); + } + + /** + * モーションのフェードイン時間の取得 + * @return フェードイン時間[秒] + */ + public getMotionFadeInTime(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(FadeInTime).toFloat(); + } + + /** + * モーションのフェードアウト時間の取得 + * @return フェードアウト時間[秒] + */ + public getMotionFadeOutTime(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(FadeOutTime).toFloat(); + } + + /** + * モーションのカーブの種類の取得 + * @param curveIndex カーブのインデックス + * @return カーブの種類 + */ + public getMotionCurveTarget(curveIndex: number): string + { + return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Target).getRawString(); + } + + /** + * モーションのカーブのIDの取得 + * @param curveIndex カーブのインデックス + * @return カーブのID + */ + public getMotionCurveId(curveIndex: number): CubismIdHandle + { + return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Id).getRawString()); + } + + /** + * モーションのカーブのフェードイン時間の存在 + * @param curveIndex カーブのインデックス + * @return true 存在する + * @return false 存在しない + */ + public isExistMotionCurveFadeInTime(curveIndex: number): boolean + { + return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().isExist(FadeInTime); + } + + /** + * モーションのカーブのフェードアウト時間の存在 + * @param curveIndex カーブのインデックス + * @return true 存在する + * @return false 存在しない + */ + public isExistMotionCurveFadeOutTime(curveIndex: number): boolean + { + return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().isExist(FadeOutTime); + } + + /** + * モーションのカーブのフェードイン時間の取得 + * @param curveIndex カーブのインデックス + * @return フェードイン時間[秒] + */ + public getMotionCurveFadeInTime(curveIndex: number): number + { + return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(FadeInTime).toFloat(); + } + + /** + * モーションのカーブのフェードアウト時間の取得 + * @param curveIndex カーブのインデックス + * @return フェードアウト時間[秒] + */ + public getMotionCurveFadeOutTime(curveIndex: number): number + { + return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(FadeOutTime).toFloat(); + } + + /** + * モーションのカーブのセグメントの個数を取得する + * @param curveIndex カーブのインデックス + * @return モーションのカーブのセグメントの個数 + */ + public getMotionCurveSegmentCount(curveIndex: number): number + { + return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Segments).getVector().getSize(); + } + + /** + * モーションのカーブのセグメントの値の取得 + * @param curveIndex カーブのインデックス + * @param segmentIndex セグメントのインデックス + * @return セグメントの値 + */ + public getMotionCurveSegment(curveIndex: number, segmentIndex: number): number + { + return this._json.getRoot().getMap().getValue(Curves).getVector().at(curveIndex).getMap().getValue(Segments).getVector().at(segmentIndex).toFloat(); + } + + /** + * イベントの個数の取得 + * @return イベントの個数 + */ + public getEventCount(): number + { + if(!this._json.getRoot().getMap().getValue(Meta).getMap().isExist(UserDataCount)) + { + return 0; + } + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(UserDataCount).toInt(); + } + + /** + * イベントの総文字数の取得 + * @return イベントの総文字数 + */ + public getTotalEventValueSize(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalUserDataSize).toInt(); + } + + /** + * イベントの時間の取得 + * @param userDataIndex イベントのインデックス + * @return イベントの時間[秒] + */ + public getEventTime(userDataIndex: number): number + { + return this._json.getRoot().getMap().getValue(UserData).getVector().at(userDataIndex).getMap().getValue(Time).toInt(); + } + + /** + * イベントの取得 + * @param userDataIndex イベントのインデックス + * @return イベントの文字列 + */ + public getEventValue(userDataIndex: number): csmString + { + return new csmString(this._json.getRoot().getMap().getValue(UserData).getVector().at(userDataIndex).getMap().getValue(Value).getRawString()); + } + + _json: CubismJson; // motion3.jsonのデータ + } +} \ No newline at end of file diff --git a/Framework/motion/cubismmotionmanager.ts b/Framework/motion/cubismmotionmanager.ts new file mode 100644 index 0000000..9299351 --- /dev/null +++ b/Framework/motion/cubismmotionmanager.ts @@ -0,0 +1,127 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismmotionqueuemanager} from "./cubismmotionqueuemanager"; +import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; +import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; +import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle; +import CubismModel = cubismmodel.CubismModel; +import ACubismMotion = acubismmotion.ACubismMotion; +import CubismMotionQueueManager = cubismmotionqueuemanager.CubismMotionQueueManager; + +export namespace Live2DCubismFramework +{ + /** + * モーションの管理 + * + * モーションの管理を行うクラス + */ + export class CubismMotionManager extends CubismMotionQueueManager + { + /** + * コンストラクタ + */ + public constructor() + { + super(); + this._currentPriority = 0; + this._reservePriority = 0; + } + + /** + * 再生中のモーションの優先度の取得 + * @return モーションの優先度 + */ + public getCurrentPriority(): number + { + return this._currentPriority; + } + + /** + * 予約中のモーションの優先度を取得する。 + * @return モーションの優先度 + */ + public getReservePriority(): number + { + return this._reservePriority; + } + + /** + * 予約中のモーションの優先度を設定する。 + * @param val 優先度 + */ + public setReservePriority(val: number): void + { + this._reservePriority = val; + } + + /** + * 優先度を設定してモーションを開始する。 + * + * @param motion モーション + * @param autoDelete 再生が狩猟したモーションのインスタンスを削除するならtrue + * @param priority 優先度 + * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 + */ + public startMotionPriority(motion: ACubismMotion, autoDelete: boolean, priority: number): CubismMotionQueueEntryHandle + { + if(priority == this._reservePriority) + { + this._reservePriority = 0; // 予約を解除 + } + + this._currentPriority = priority; // 再生中モーションの優先度を設定 + + return super.startMotion(motion, autoDelete, this._userTimeSeconds); + } + + /** + * モーションを更新して、モデルにパラメータ値を反映する。 + * + * @param model 対象のモデル + * @param deltaTimeSeconds デルタ時間[秒] + * @return true 更新されている + * @return false 更新されていない + */ + public updateMotion(model: CubismModel, deltaTimeSeconds: number): boolean + { + this._userTimeSeconds += deltaTimeSeconds; + + const updated: boolean = super.doUpdateMotion(model, this._userTimeSeconds); + + if(this.isFinished()) + { + this._currentPriority = 0; // 再生中のモーションの優先度を解除 + } + + return updated; + } + + /** + * モーションを予約する。 + * + * @param priority 優先度 + * @return true 予約できた + * @return false 予約できなかった + */ + public reserveMotion(priority: number): boolean + { + if((priority <= this._reservePriority) || (priority <= this._currentPriority)) + { + return false; + } + + this._reservePriority = priority; + + return true; + } + + _currentPriority: number; // 現在再生中のモーションの優先度 + _reservePriority: number; // 再生予定のモーションの優先度。再生中は0になる。モーションファイルを別スレッドで読み込むときの機能。 + } + +} \ No newline at end of file diff --git a/Framework/motion/cubismmotionqueueentry.ts b/Framework/motion/cubismmotionqueueentry.ts new file mode 100644 index 0000000..a34b779 --- /dev/null +++ b/Framework/motion/cubismmotionqueueentry.ts @@ -0,0 +1,240 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; +import {Live2DCubismFramework as cubismmotionqueuemanager} from './cubismmotionqueuemanager'; +import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle; +import ACubismMotion = acubismmotion.ACubismMotion; + +export namespace Live2DCubismFramework +{ + /** + * CubismMotionQueueManagerで再生している各モーションの管理クラス。 + */ + export class CubismMotionQueueEntry + { + /** + * コンストラクタ + */ + public constructor() + { + this._autoDelete = false; + this._motion = null; + this._available = true; + this._finished = false; + this._started = false; + this._startTimeSeconds = -1.0; + this._fadeInStartTimeSeconds = 0.0; + this._endTimeSeconds = -1.0; + this._stateTimeSeconds = 0.0; + this._stateWeight = 0.0; + this._lastEventCheckSeconds = 0.0; + this._motionQueueEntryHandle = this; + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + if(this._autoDelete && this._motion) + { + ACubismMotion.delete(this._motion); // + } + } + + /** + * フェードアウトの開始 + * @param fadeOutSeconds フェードアウトにかかる時間[秒] + * @param userTimeSeconds デルタ時間の積算値[秒] + */ + public startFadeout(fadeoutSeconds: number, userTimeSeconds: number): void + { + const newEndTimeSeconds: number = userTimeSeconds + fadeoutSeconds; + + if(this._endTimeSeconds < 0.0 || newEndTimeSeconds < this._endTimeSeconds) + { + this._endTimeSeconds = newEndTimeSeconds; + } + } + + /** + * モーションの終了の確認 + * + * @return true モーションが終了した + * @return false 終了していない + */ + public isFinished(): boolean + { + return this._finished; + } + + /** + * モーションの開始の確認 + * @return true モーションが開始した + * @return false 開始していない + */ + public isStarted(): boolean + { + return this._started; + } + + /** + * モーションの開始時刻の取得 + * @return モーションの開始時刻[秒] + */ + public getStartTime(): number + { + return this._startTimeSeconds; + } + + /** + * フェードインの開始時刻の取得 + * @return フェードインの開始時刻[秒] + */ + public getFadeInStartTime(): number + { + return this._fadeInStartTimeSeconds; + } + + /** + * フェードインの終了時刻の取得 + * @return フェードインの終了時刻の取得 + */ + public getEndTime(): number + { + return this._endTimeSeconds; + } + + /** + * モーションの開始時刻の設定 + * @param startTime モーションの開始時刻 + */ + public setStartTime(startTime: number): void + { + this._startTimeSeconds = startTime; + } + + /** + * フェードインの開始時刻の設定 + * @param startTime フェードインの開始時刻[秒] + */ + public setFadeInStartTime(startTime: number): void + { + this._fadeInStartTimeSeconds = startTime; + } + + /** + * フェードインの終了時刻の設定 + * @param endTime フェードインの終了時刻[秒] + */ + public setEndTime(endTime: number): void + { + this._endTimeSeconds = endTime; + } + + /** + * モーションの終了の設定 + * @param f trueならモーションの終了 + */ + public setIsFinished(f: boolean): void + { + this._finished = f; + } + + /** + * モーション開始の設定 + * @param f trueならモーションの開始 + */ + public setIsStarted(f: boolean): void + { + this._started = f; + } + + /** + * モーションの有効性の確認 + * @return true モーションは有効 + * @return false モーションは無効 + */ + public isAvailable(): boolean + { + return this._available; + } + + /** + * モーションの有効性の設定 + * @param v trueならモーションは有効 + */ + public setIsAvailable(v: boolean): void + { + this._available = v; + } + + /** + * モーションの状態の設定 + * @param timeSeconds 現在時刻[秒] + * @param weight モーション尾重み + */ + public setState(timeSeconds: number, weight: number): void + { + this._stateTimeSeconds = timeSeconds; + this._stateWeight = weight; + } + + /** + * モーションの現在時刻の取得 + * @return モーションの現在時刻[秒] + */ + public getStateTime(): number + { + return this._stateTimeSeconds; + } + + /** + * モーションの重みの取得 + * @return モーションの重み + */ + public getStateWeight(): number + { + return this._stateWeight; + } + + /** + * 最後にイベントの発火をチェックした時間を取得 + * + * @return 最後にイベントの発火をチェックした時間[秒] + */ + public getLastCheckEventTime(): number + { + return this._lastEventCheckSeconds; + } + + /** + * 最後にイベントをチェックした時間を設定 + * @param checkTime 最後にイベントをチェックした時間[秒] + */ + public setLastCheckEventTime(checkTime: number): void + { + this._lastEventCheckSeconds = checkTime; + } + + _autoDelete: boolean; // 自動削除 + _motion: ACubismMotion; // モーション + + _available: boolean; // 有効化フラグ + _finished: boolean; // 終了フラグ + _started: boolean; // 開始フラグ + _startTimeSeconds: number; // モーション再生開始時刻[秒] + _fadeInStartTimeSeconds: number; // フェードイン開始時刻(ループの時は初回のみ)[秒] + _endTimeSeconds: number; // 終了予定時刻[秒] + _stateTimeSeconds: number; // 時刻の状態[秒] + _stateWeight: number;  // 重みの状態 + _lastEventCheckSeconds: number; // 最終のMotion側のチェックした時間 + + _motionQueueEntryHandle: CubismMotionQueueEntryHandle; // インスタンスごとに一意の値を持つ識別番号 + } +} \ No newline at end of file diff --git a/Framework/motion/cubismmotionqueuemanager.ts b/Framework/motion/cubismmotionqueuemanager.ts new file mode 100644 index 0000000..0166dd7 --- /dev/null +++ b/Framework/motion/cubismmotionqueuemanager.ts @@ -0,0 +1,342 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as acubismmotion} from './acubismmotion'; +import {Live2DCubismFramework as cubismmotionqueueentry} from './cubismmotionqueueentry'; +import {Live2DCubismFramework as csmvector} from '../type/csmvector'; +import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; +import {Live2DCubismFramework as csmstring} from '../type/csmstring'; +import csmString = csmstring.csmString; +import CubismModel = cubismmodel.CubismModel; +import csmVector = csmvector.csmVector; +import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; +import ACubismMotion = acubismmotion.ACubismMotion; + +export namespace Live2DCubismFramework +{ + /** + * モーション再生の管理 + * + * モーション再生の管理用クラス。CubismMotionモーションなどACubismMotionのサブクラスを再生するために使用する。 + * + * @note 再生中に別のモーションが StartMotion()された場合は、新しいモーションに滑らかに変化し旧モーションは中断する。 + * 表情用モーション、体用モーションなどを分けてモーション化した場合など、 + * 複数のモーションを同時に再生させる場合は、複数のCubismMotionQueueManagerインスタンスを使用する。 + */ + export class CubismMotionQueueManager + { + /** + * コンストラクタ + */ + public constructor() + { + this._userTimeSeconds = 0.0; + this._eventCallBack = null; + this._eventCustomData = null; + this._motions = new csmVector(); + } + + /** + * デストラクタ + */ + public release(): void + { + for(let i: number = 0; i < this._motions.getSize(); ++i) + { + if(this._motions.at(i)) + { + this._motions.at(i).release(); + this._motions.set(i, void 0); + this._motions.set(i, null); + } + } + + this._motions = null; + } + + /** + * 指定したモーションの開始 + * + * 指定したモーションを開始する。同じタイプのモーションが既にある場合は、既存のモーションに終了フラグを立て、フェードアウトを開始させる。 + * + * @param motion 開始するモーション + * @param autoDelete 再生が終了したモーションのインスタンスを削除するなら true + * @param userTimeSeconds デルタ時間の積算値[秒] + * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 + */ + public startMotion(motion: ACubismMotion, autoDelete: boolean, userTimeSeconds: number): CubismMotionQueueEntryHandle + { + if(motion == null) + { + return InvalidMotionQueueEntryHandleValue; + } + + let motionQueueEntry: CubismMotionQueueEntry = null; + + // 既にモーションがあれば終了フラグを立てる + for(let i: number = 0; i < this._motions.getSize(); ++i) + { + motionQueueEntry = this._motions.at(i); + if(motionQueueEntry == null) + { + continue; + } + + motionQueueEntry.startFadeout(motionQueueEntry._motion.getFadeOutTime(), userTimeSeconds); // フェードアウトを開始し終了する + } + + motionQueueEntry = new CubismMotionQueueEntry(); // 終了時に破棄する + motionQueueEntry._autoDelete = autoDelete; + motionQueueEntry._motion = motion; + + this._motions.pushBack(motionQueueEntry); + + return motionQueueEntry._motionQueueEntryHandle; + } + + /** + * 全てのモーションの終了の確認 + * @return true 全て終了している + * @return false 終了していない + */ + public isFinished(): boolean + { + // ------- 処理を行う ------- + // 既にモーションがあれば終了フラグを立てる + + for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) + { + let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); + + if(motionQueueEntry == null) + { + ite = this._motions.erase(ite); // 削除 + continue; + } + + let motion: ACubismMotion = motionQueueEntry._motion; + + if(motion == null) + { + motionQueueEntry.release(); + motionQueueEntry = void 0; + motionQueueEntry = null; + ite = this._motions.erase(ite); // 削除 + continue; + } + + // ----- 終了済みの処理があれば削除する ------ + if(!motionQueueEntry.isFinished()) + { + return false; + } + else + { + ite.preIncrement(); + } + } + + return true; + } + + /** + * 指定したモーションの終了の確認 + * @param motionQueueEntryNumber モーションの識別番号 + * @return true 全て終了している + * @return false 終了していない + */ + public isFinishedByHandle(motionQueueEntryNumber: CubismMotionQueueEntryHandle): boolean + { + // 既にモーションがあれば終了フラグを立てる + for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());ite.increment()) + { + let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); + + if(motionQueueEntry == null) + { + continue; + } + + if(motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber && !motionQueueEntry.isFinished()) + { + return false; + } + } + return true; + } + + /** + * 全てのモーションを停止する + */ + public stopAllMotions(): void + { + // ------- 処理を行う ------- + // 既にモーションがあれば終了フラグを立てる + + for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) + { + let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); + + if(motionQueueEntry == null) + { + ite = this._motions.erase(ite); + + continue; + } + + // ----- 終了済みの処理があれば削除する ------ + motionQueueEntry.release(); + motionQueueEntry = void 0; + motionQueueEntry = null; + ite = this._motions.erase(ite); // 削除 + } + } + + /** + * 指定したCubismMotionQueueEntryの取得 + + * @param motionQueueEntryNumber モーションの識別番号 + * @return 指定したCubismMotionQueueEntry + * @return null 見つからなかった + */ + public getCubismMotionQueueEntry(motionQueueEntryNumber: any): CubismMotionQueueEntry + { + //------- 処理を行う ------- + // 既にモーションがあれば終了フラグを立てる + for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end()); ite.preIncrement()) + { + let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); + + if(motionQueueEntry == null) + { + continue; + } + + if(motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber) + { + return motionQueueEntry; + } + } + + return null; + } + + /** + * イベントを受け取るCallbackの登録 + * + * @param callback コールバック関数 + * @param customData コールバックに返されるデータ + */ + public setEventCallback(callback: CubismMotionEventFunction, customData: any = null): void + { + this._eventCallBack = callback; + this._eventCustomData = customData; + } + + /** + * モーションを更新して、モデルにパラメータ値を反映する。 + * + * @param model 対象のモデル + * @param userTimeSeconds デルタ時間の積算値[秒] + * @return true モデルへパラメータ値の反映あり + * @return false モデルへパラメータ値の反映なし(モーションの変化なし) + */ + public doUpdateMotion(model: CubismModel, userTimeSeconds: number): boolean + { + let updated: boolean = false; + + // ------- 処理を行う -------- + // 既にモーションがあれば終了フラグを立てる + + for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) + { + let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); + + if(motionQueueEntry == null) + { + ite = this._motions.erase(ite); // 削除 + continue; + } + + let motion: ACubismMotion = motionQueueEntry._motion; + + if(motion == null) + { + motionQueueEntry.release(); + motionQueueEntry = void 0; + motionQueueEntry = null; + ite = this._motions.erase(ite); // 削除 + + continue; + } + + // ------ 値を反映する ------ + motion.updateParameters(model, motionQueueEntry, userTimeSeconds); + updated = true; + + // ------ ユーザトリガーイベントを検査する ---- + const firedList: csmVector = motion.getFiredEvent( + motionQueueEntry.getLastCheckEventTime() - motionQueueEntry.getStartTime(), + userTimeSeconds - motionQueueEntry.getStartTime() + ); + + for(let i: number = 0; i < firedList.getSize(); ++i) + { + this._eventCallBack(this, firedList.at(i), this._eventCustomData); + } + + motionQueueEntry.setLastCheckEventTime(userTimeSeconds); + + // ------ 終了済みの処理があれば削除する ------ + if(motionQueueEntry.isFinished()) + { + motionQueueEntry.release(); + motionQueueEntry = void 0; + motionQueueEntry = null; + ite = this._motions.erase(ite); // 削除 + } + else + { + ite.preIncrement(); + } + } + + return updated; + } + _userTimeSeconds: number; // デルタ時間の積算値[秒] + + _motions: csmVector; // モーション + _eventCallBack: CubismMotionEventFunction; // コールバック関数 + _eventCustomData: any; // コールバックに戻されるデータ + } + + + /** + * イベントのコールバック関数を定義 + * + * イベントのコールバックに登録できる関数の型情報 + * @param caller 発火したイベントを再生させたCubismMotionQueueManager + * @param eventValue 発火したイベントの文字列データ + * @param customData コールバックに返される登録時に指定されたデータ + */ + export interface CubismMotionEventFunction + { + ( + caller: CubismMotionQueueManager, + eventValue: csmString, + customData: any + ): void; + } + + /** + * モーションの識別番号 + * + * モーションの識別番号の定義 + */ + export declare type CubismMotionQueueEntryHandle = any; + export const InvalidMotionQueueEntryHandleValue: CubismMotionQueueEntryHandle = -1; +} \ No newline at end of file diff --git a/Framework/physics/cubismphysics.ts b/Framework/physics/cubismphysics.ts new file mode 100644 index 0000000..4a7f6ad --- /dev/null +++ b/Framework/physics/cubismphysics.ts @@ -0,0 +1,826 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismphysicsinternal} from './cubismphysicsinternal'; +import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; +import {Live2DCubismFramework as cubismvector2} from '../math/cubismvector2'; +import {Live2DCubismFramework as cubismmath} from '../math/cubismmath'; +import {Live2DCubismFramework as cubismphysicsjson} from './cubismphysicsjson'; +import CubismPhysicsJson = cubismphysicsjson.CubismPhysicsJson; +import CubismMath = cubismmath.CubismMath; +import CubismPhysicsRig = cubismphysicsinternal.CubismPhysicsRig; +import CubismPhysicsSubRig = cubismphysicsinternal.CubismPhysicsSubRig; +import CubismPhysicsInput = cubismphysicsinternal.CubismPhysicsInput; +import CubismPhysicsOutput = cubismphysicsinternal.CubismPhysicsOutput; +import CubismPhysicsParticle = cubismphysicsinternal.CubismPhysicsParticle; +import CubismPhysicsSource = cubismphysicsinternal.CubismPhysicsSource; +import CubismPhysicsTargetType = cubismphysicsinternal.CubismPhysicsTargetType; +import CubismPhysicsNormalization = cubismphysicsinternal.CubismPhysicsNormalization; +import CubismVector2 = cubismvector2.CubismVector2; +import CubismModel = cubismmodel.CubismModel; + +export namespace Live2DCubismFramework +{ + + /// physics types tags. + const PhysicsTypeTagX: string = "X"; + const PhysicsTypeTagY: string = "Y"; + const PhysicsTypeTagAngle: string = "Angle"; + + /// Constant of air resistance. + const AirResistance: number = 5.0; + + /// Constant of maximum weight of input and output ratio. + const MaximumWeight: number = 100.0; + + /// Constant of threshold of movement. + const MovementThreshold: number = 0.001; + + /** + * 物理演算クラス + */ + export class CubismPhysics + { + /** + * インスタンスの作成 + * @param buffer physics3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + * @return 作成されたインスタンス + */ + public static create(buffer: ArrayBuffer, size: number): CubismPhysics + { + let ret: CubismPhysics = new CubismPhysics(); + + ret.parse(buffer, size); + ret._physicsRig.gravity.y = 0; + + return ret; + } + + /** + * インスタンスを破棄する + * @param physics 破棄するインスタンス + */ + public static delete(physics: CubismPhysics): void + { + physics.release(); + physics = void 0; + physics = null; + } + + /** + * 物理演算の評価 + * @param model 物理演算の結果を適用するモデル + * @param deltaTimeSeconds デルタ時間[秒] + */ + public evaluate(model: CubismModel, deltaTimeSeconds: number): void + { + let totalAngle: {angle: number}; + let weight: number; + let radAngle: number; + let outputValue: number; + let totalTranslation: CubismVector2 = new CubismVector2(); + let currentSetting: CubismPhysicsSubRig; + let currentInput: CubismPhysicsInput[]; + let currentOutput: CubismPhysicsOutput[]; + let currentParticles: CubismPhysicsParticle[]; + + let parameterValue: Float32Array; + let parameterMaximumValue: Float32Array; + let parameterMinimumValue: Float32Array; + let parameterDefaultValue: Float32Array; + + parameterValue = model.getModel().parameters.values; + parameterMaximumValue = model.getModel().parameters.maximumValues; + parameterMinimumValue = model.getModel().parameters.minimumValues; + parameterDefaultValue = model.getModel().parameters.defaultValues; + + for(let settingIndex: number = 0; settingIndex < this._physicsRig.subRigCount; ++settingIndex) + { + totalAngle = {angle: 0.0}; + totalTranslation.x = 0.0; + totalTranslation.y = 0.0; + currentSetting = this._physicsRig.settings.at(settingIndex); + currentInput = this._physicsRig.inputs.get(currentSetting.baseInputIndex); + currentOutput = this._physicsRig.outputs.get(currentSetting.baseOutputIndex); + currentParticles = this._physicsRig.particles.get(currentSetting.baseParticleIndex); + + // Load input parameters + for(let i: number = 0; i < currentSetting.inputCount; ++i) + { + weight = currentInput[i].weight / MaximumWeight; + + if(currentInput[i].sourceParameterIndex == -1) + { + currentInput[i].sourceParameterIndex = model.getParameterIndex(currentInput[i].source.id); + } + + currentInput[i].getNormalizedParameterValue( + totalTranslation, + totalAngle, + parameterValue[currentInput[i].sourceParameterIndex], + parameterMinimumValue[currentInput[i].sourceParameterIndex], + parameterMaximumValue[currentInput[i].sourceParameterIndex], + parameterDefaultValue[currentInput[i].sourceParameterIndex], + currentSetting.normalizationPosition, + currentSetting.normalizationAngle, + currentInput[0].reflect, + weight + ); + } + + radAngle = CubismMath.degreesToRadian(-totalAngle.angle); + + totalTranslation.x = (totalTranslation.x * CubismMath.cos(radAngle) - totalTranslation.y * CubismMath.sin(radAngle)); + totalTranslation.y = (totalTranslation.x * CubismMath.sin(radAngle) + totalTranslation.y * CubismMath.cos(radAngle)); + + // Calculate particles position. + updateParticles( + currentParticles, + currentSetting.particleCount, + totalTranslation, + totalAngle.angle, + this._options.wind, + MovementThreshold * currentSetting.normalizationPosition.maximum, + deltaTimeSeconds, + AirResistance + ); + + // Update output parameters. + for (let i: number = 0; i < currentSetting.outputCount; ++i) + { + let particleIndex = currentOutput[i].vertexIndex; + + if(particleIndex < 1 || particleIndex >= currentSetting.particleCount) + { + break; + } + + if(currentOutput[i].destinationParameterIndex == -1) + { + currentOutput[i].destinationParameterIndex = model.getParameterIndex(currentOutput[i].destination.id); + } + + let translation: CubismVector2 = new CubismVector2(); + translation.x = currentParticles[particleIndex].position.x - currentParticles[particleIndex - 1].position.x; + translation.y = currentParticles[particleIndex].position.y - currentParticles[particleIndex - 1].position.y; + + outputValue = currentOutput[i].getValue( + translation, + currentParticles, + particleIndex, + currentOutput[i].reflect, + this._options.gravity + ); + + let destinationParameterIndex = currentOutput[i].destinationParameterIndex; + let outParameterValue = parameterValue.slice(destinationParameterIndex); + + updateOutputParameterValue( + outParameterValue, + parameterMinimumValue[destinationParameterIndex], + parameterMaximumValue[destinationParameterIndex], + outputValue, + currentOutput[i] + ); + + // 値を反映 + for(let offset: number = destinationParameterIndex, outParamIndex: number = 0; offset < parameterValue.length; offset++, outParamIndex++) + { + parameterValue[offset] = outParameterValue[outParamIndex]; + } + } + } + } + + /** + * オプションの設定 + * @param options オプション + */ + public setOptions(options: CubismPhysics.Options): void + { + this._options = options; + } + + /** + * オプションの取得 + * @return オプション + */ + public getOption(): CubismPhysics.Options + { + return this._options; + } + + /** + * コンストラクタ + */ + public constructor() + { + this._physicsRig = null; + + // set default options + this._options = new CubismPhysics.Options(); + this._options.gravity.y = -1.0; + this._options.gravity.x = 0; + this._options.wind.x = 0; + this._options.wind.y = 0; + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + this._physicsRig = void 0; + this._physicsRig = null; + } + + /** + * physics3.jsonをパースする。 + * @param physicsJson physics3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public parse(physicsJson: ArrayBuffer, size: number): void + { + this._physicsRig = new CubismPhysicsRig(); + + let json: CubismPhysicsJson = new CubismPhysicsJson(physicsJson, size); + + this._physicsRig.gravity = json.getGravity(); + this._physicsRig.wind = json.getWind(); + this._physicsRig.subRigCount = json.getSubRigCount(); + + this._physicsRig.settings.updateSize(this._physicsRig.subRigCount, CubismPhysicsSubRig, true); + this._physicsRig.inputs.updateSize(json.getTotalInputCount(), CubismPhysicsInput, true); + this._physicsRig.outputs.updateSize(json.getTotalOutputCount(), CubismPhysicsOutput, true); + this._physicsRig.particles.updateSize(json.getVertexCount(), CubismPhysicsParticle, true); + + let inputIndex: number = 0, outputIndex: number = 0, particleIndex: number = 0; + + for(let i: number = 0; i < this._physicsRig.settings.getSize(); ++i) + { + this._physicsRig.settings.at(i).normalizationPosition.minimum = json.getNormalizationPositionMinimumValue(i); + this._physicsRig.settings.at(i).normalizationPosition.maximum = json.getNormalizationPositionMaximumValue(i); + this._physicsRig.settings.at(i).normalizationPosition.defalut = json.getNormalizationPositionDefaultValue(i); + + this._physicsRig.settings.at(i).normalizationAngle.minimum = json.getNormalizationAngleMinimumValue(i); + this._physicsRig.settings.at(i).normalizationAngle.maximum = json.getNormalizationAngleMaximumValue(i); + this._physicsRig.settings.at(i).normalizationAngle.defalut = json.getNormalizationAngleDefaultValue(i); + + // Input + this._physicsRig.settings.at(i).inputCount = json.getInputCount(i); + this._physicsRig.settings.at(i).baseInputIndex = inputIndex; + + for(let j: number = 0; j < this._physicsRig.settings.at(i).inputCount; ++j) + { + this._physicsRig.inputs.at(inputIndex + j).sourceParameterIndex = -1; + this._physicsRig.inputs.at(inputIndex + j).weight = json.getInputWeight(i, j); + this._physicsRig.inputs.at(inputIndex + j).reflect = json.getInputReflect(i, j); + + if(json.getInputType(i, j) == PhysicsTypeTagX) + { + this._physicsRig.inputs.at(inputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_X; + this._physicsRig.inputs.at(inputIndex + j).getNormalizedParameterValue = getInputTranslationXFromNormalizedParameterValue; + } + else if(json.getInputType(i, j) == PhysicsTypeTagY) + { + this._physicsRig.inputs.at(inputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Y; + this._physicsRig.inputs.at(inputIndex + j).getNormalizedParameterValue = getInputTranslationYFromNormalizedParamterValue; + } + else if(json.getInputType(i, j) == PhysicsTypeTagAngle) + { + this._physicsRig.inputs.at(inputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Angle; + this._physicsRig.inputs.at(inputIndex + j).getNormalizedParameterValue = getInputAngleFromNormalizedParameterValue; + } + + this._physicsRig.inputs.at(inputIndex + j).source.targetType = CubismPhysicsTargetType.CubismPhysicsTargetType_Parameter; + this._physicsRig.inputs.at(inputIndex + j).source.id = json.getInputSourceId(i, j); + } + inputIndex += this._physicsRig.settings.at(i).inputCount; + + // Output + this._physicsRig.settings.at(i).outputCount = json.getOutputCount(i); + this._physicsRig.settings.at(i).baseOutputIndex = outputIndex; + + for(let j: number = 0; j < this._physicsRig.settings.at(i).outputCount; ++j) + { + this._physicsRig.outputs.at(outputIndex + j).destinationParameterIndex = -1; + this._physicsRig.outputs.at(outputIndex + j).vertexIndex = json.getOutputVertexIndex(i, j); + this._physicsRig.outputs.at(outputIndex + j).angleScale = json.getOutputAngleScale(i, j); + this._physicsRig.outputs.at(outputIndex + j).weight = json.getOutputWeight(i, j); + this._physicsRig.outputs.at(outputIndex + j).destination.targetType = CubismPhysicsTargetType.CubismPhysicsTargetType_Parameter; + + this._physicsRig.outputs.at(outputIndex + j).destination.id = json.getOutputDestinationId(i, j); + + if(json.getOutputType(i, j) == PhysicsTypeTagX) + { + this._physicsRig.outputs.at(outputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_X; + this._physicsRig.outputs.at(outputIndex + j).getValue = getOutputTranslationX; + this._physicsRig.outputs.at(outputIndex + j).getScale = getOutputScaleTranslationX; + } + else if(json.getOutputType(i, j) == PhysicsTypeTagY) + { + this._physicsRig.outputs.at(outputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Y; + this._physicsRig.outputs.at(outputIndex + j).getValue = getOutputTranslationY; + this._physicsRig.outputs.at(outputIndex + j).getScale = getOutputScaleTranslationY; + } + else if(json.getOutputType(i, j) == PhysicsTypeTagAngle) + { + this._physicsRig.outputs.at(outputIndex + j).type = CubismPhysicsSource.CubismPhysicsSource_Angle; + this._physicsRig.outputs.at(outputIndex + j).getValue = getOutputAngle; + this._physicsRig.outputs.at(outputIndex + j).getScale = getOutputScaleAngle; + } + + this._physicsRig.outputs.at(outputIndex + j).reflect = json.getOutputReflect(i, j); + } + outputIndex += this._physicsRig.settings.at(i).outputCount; + + // Particle + this._physicsRig.settings.at(i).particleCount = json.getParticleCount(i); + this._physicsRig.settings.at(i).baseParticleIndex = particleIndex; + + for(let j: number = 0; j < this._physicsRig.settings.at(i).particleCount; ++j) + { + this._physicsRig.particles.at(particleIndex + j).mobility = json.getParticleMobility(i, j); + this._physicsRig.particles.at(particleIndex + j).delay = json.getParticleDelay(i, j); + this._physicsRig.particles.at(particleIndex + j).acceleration = json.getParticleAcceleration(i, j); + this._physicsRig.particles.at(particleIndex + j).radius = json.getParticleRadius(i, j); + this._physicsRig.particles.at(particleIndex + j).position = json.getParticlePosition(i, j); + } + + particleIndex += this._physicsRig.settings.at(i).particleCount; + } + + this.initialize(); + + json.release(); + json = void 0; + json = null; + } + + /** + * 初期化する + */ + public initialize(): void + { + let strand: CubismPhysicsParticle[]; + let currentSetting: CubismPhysicsSubRig; + let radius: CubismVector2; + + for (let settingIndex: number = 0; settingIndex < this._physicsRig.subRigCount; ++settingIndex) + { + currentSetting = this._physicsRig.settings.at(settingIndex); + strand = this._physicsRig.particles.get(currentSetting.baseParticleIndex); + + // Initialize the top of particle. + strand[0].initialPosition = new CubismVector2(0.0, 0.0); + strand[0].lastPosition = new CubismVector2(strand[0].initialPosition.x, strand[0].initialPosition.y); + strand[0].lastGravity = new CubismVector2(0.0, -1.0); + strand[0].lastGravity.y *= -1.0; + strand[0].velocity = new CubismVector2(0.0, 0.0); + strand[0].force = new CubismVector2(0.0, 0.0); + + // Initialize paritcles. + for (let i: number = 1; i < currentSetting.particleCount; ++i) + { + radius = new CubismVector2(0.0, 0.0); + radius.y = strand[i].radius; + strand[i].initialPosition = new CubismVector2(strand[i - 1].initialPosition.x + radius.x, strand[i - 1].initialPosition.y + radius.y); + strand[i].position = new CubismVector2(strand[i].initialPosition.x, strand[i].initialPosition.y); + strand[i].lastPosition = new CubismVector2(strand[i].initialPosition.x, strand[i].initialPosition.y); + strand[i].lastGravity = new CubismVector2(0.0, -1.0); + strand[i].lastGravity.y *= -1.0; + strand[i].velocity = new CubismVector2(0.0, 0.0); + strand[i].force = new CubismVector2(0.0, 0.0); + } + } + } + + _physicsRig: CubismPhysicsRig; // 物理演算のデータ + _options: CubismPhysics.Options; // オプション + } + + export namespace CubismPhysics + { + /** + * 物理演算のオプション + */ + export class Options + { + constructor() + { + this.gravity = new CubismVector2(0, 0); + this.wind = new CubismVector2(0, 0); + } + + gravity: CubismVector2; // 重力方向 + wind: CubismVector2; // 風の方向 + } + + } + + /** + * Gets sign. + * + * @param value Evaluation target value. + * + * @return Sign of value. + */ + function sign(value: number): number + { + let ret: number = 0; + + if(value > 0.0) + { + ret = 1; + } + else if(value < 0.0) + { + ret = -1; + } + + return ret; + } + + function getInputTranslationXFromNormalizedParameterValue( + targetTranslation: CubismVector2, + targetAngle: {angle: number}, + value: number, + parameterMinimumValue: number, + parameterMaximumValue: number, + parameterDefaultValue: number, + normalizationPosition: CubismPhysicsNormalization, + normalizationAngle: CubismPhysicsNormalization, + isInverted: boolean, + weight: number): void + { + targetTranslation.x += normalizeParameterValue( + value, + parameterMinimumValue, + parameterMaximumValue, + parameterDefaultValue, + normalizationPosition.minimum, + normalizationPosition.maximum, + normalizationPosition.defalut, + isInverted + ) * weight; + } + + function getInputTranslationYFromNormalizedParamterValue( + targetTranslation: CubismVector2, + targetAngle: {angle: number}, + value: number, + parameterMinimumValue: number, + parameterMaximumValue: number, + parameterDefaultValue: number, + normalizationPosition: CubismPhysicsNormalization, + normalizationAngle: CubismPhysicsNormalization, + isInverted: boolean, + weight: number): void + { + targetTranslation.y += normalizeParameterValue( + value, + parameterMinimumValue, + parameterMaximumValue, + parameterDefaultValue, + normalizationPosition.minimum, + normalizationPosition.maximum, + normalizationPosition.defalut, + isInverted + ) * weight; + } + + function getInputAngleFromNormalizedParameterValue( + targetTranslation: CubismVector2, + targetAngle: {angle: number}, + value: number, + parameterMinimumValue: number, + parameterMaximumValue: number, + parameterDefaultValue: number, + normalizaitionPosition: CubismPhysicsNormalization, + normalizationAngle: CubismPhysicsNormalization, + isInverted: boolean, + weight: number): void + { + targetAngle.angle += normalizeParameterValue( + value, + parameterMinimumValue, + parameterMaximumValue, + parameterDefaultValue, + normalizationAngle.minimum, + normalizationAngle.maximum, + normalizationAngle.defalut, + isInverted, + ) * weight; + } + + function getOutputTranslationX( + translation: CubismVector2, + particles: CubismPhysicsParticle[], + particleIndex: number, + isInverted: boolean, + parentGravity: CubismVector2): number + { + let outputValue: number = translation.x; + + if(isInverted) + { + outputValue *= -1.0; + } + + return outputValue; + } + + function getOutputTranslationY( + translation: CubismVector2, + particles: CubismPhysicsParticle[], + particleIndex: number, + isInverted: boolean, + parentGravity: CubismVector2): number + { + let outputValue: number = translation.y; + + if(isInverted) + { + outputValue *= -1.0; + } + return outputValue; + } + + function getOutputAngle( + translation: CubismVector2, + particles: CubismPhysicsParticle[], + particleIndex: number, + isInverted: boolean, + parentGravity: CubismVector2): number + { + let outputValue: number; + + if(particleIndex >= 2) + { + parentGravity = particles[particleIndex - 1].position.substract(particles[particleIndex - 2].position); + } + else + { + parentGravity = parentGravity.multiplyByScaler(-1.0); + } + + outputValue = CubismMath.directionToRadian(parentGravity, translation); + + if(isInverted) + { + outputValue *= -1.0; + } + + return outputValue; + } + + function getRangeValue(min: number, max: number): number + { + let maxValue: number = CubismMath.max(min, max); + let minValue: number = CubismMath.min(min, max); + + return CubismMath.abs(maxValue - minValue); + } + + function getDefaultValue(min: number, max: number): number + { + const minValue: number = CubismMath.min(min, max); + return minValue + (getRangeValue(min, max) / 2.0); + } + + function getOutputScaleTranslationX(translationScale: CubismVector2, angleScale: number): number + { + return JSON.parse(JSON.stringify(translationScale.x)); + } + + function getOutputScaleTranslationY(translationScale: CubismVector2, angleScale: number): number + { + return JSON.parse(JSON.stringify(translationScale.y)); + } + + function getOutputScaleAngle(translationScale: CubismVector2, angleScale: number): number + { + return JSON.parse(JSON.stringify(angleScale)); + } + + + /** + * Updates particles. + * + * @param strand Target array of particle. + * @param strandCount Count of particle. + * @param totalTranslation Total translation value. + * @param totalAngle Total angle. + * @param windDirection Direction of Wind. + * @param thresholdValue Threshold of movement. + * @param deltaTimeSeconds Delta time. + * @param airResistance Air resistance. + */ + function updateParticles( + strand: CubismPhysicsParticle[], + strandCount: number, + totalTranslation: CubismVector2, + totalAngle: number, + windDirection: CubismVector2, + thresholdValue: number, + deltaTimeSeconds: number, + airResistance: number) + { + let totalRadian: number; + let delay: number; + let radian: number; + let currentGravity: CubismVector2; + let direction: CubismVector2 = new CubismVector2(0.0, 0.0); + let velocity: CubismVector2 = new CubismVector2(0.0, 0.0); + let force: CubismVector2 = new CubismVector2(0.0, 0.0); + let newDirection: CubismVector2 = new CubismVector2(0.0, 0.0); + + strand[0].position = new CubismVector2(totalTranslation.x, totalTranslation.y); + + totalRadian = CubismMath.degreesToRadian(totalAngle); + currentGravity = CubismMath.radianToDirection(totalRadian); + currentGravity.normalize(); + + for(let i: number = 1; i < strandCount; ++i) + { + strand[i].force = currentGravity.multiplyByScaler(strand[i].acceleration).add(windDirection); + + strand[i].lastPosition = new CubismVector2(strand[i].position.x, strand[i].position.y); + + delay = strand[i].delay * deltaTimeSeconds * 30.0; + + direction = strand[i].position.substract(strand[i - 1].position); + + radian = CubismMath.directionToRadian(strand[i].lastGravity, currentGravity) / airResistance; + + direction.x = ((CubismMath.cos(radian) * direction.x) - (direction.y * CubismMath.sin(radian))); + direction.y = ((CubismMath.sin(radian) * direction.x) + (direction.y * CubismMath.cos(radian))); + + strand[i].position = strand[i - 1].position.add(direction); + + velocity = strand[i].velocity.multiplyByScaler(delay); + force = strand[i].force.multiplyByScaler(delay).multiplyByScaler(delay); + + strand[i].position = strand[i].position.add(velocity).add(force); + + newDirection = strand[i].position.substract(strand[i - 1].position); + newDirection.normalize(); + + strand[i].position = strand[i - 1].position.add(newDirection.multiplyByScaler(strand[i].radius)); + + if (CubismMath.abs(strand[i].position.x) < thresholdValue) + { + strand[i].position.x = 0.0; + } + + if (delay != 0.0) + { + strand[i].velocity = strand[i].position.substract(strand[i].lastPosition); + strand[i].velocity = strand[i].velocity.divisionByScalar(delay); + strand[i].velocity = strand[i].velocity.multiplyByScaler(strand[i].mobility); + } + + strand[i].force = new CubismVector2(0.0, 0.0); + strand[i].lastGravity = new CubismVector2(currentGravity.x, currentGravity.y); + } + + } + + /** + * Updates output parameter value. + * @param parameterValue Target parameter value. + * @param parameterValueMinimum Minimum of parameter value. + * @param parameterValueMaximum Maximum of parameter value. + * @param translation Translation value. + */ + function updateOutputParameterValue( + parameterValue: Float32Array, + parameterValueMinimum: number, + parameterValueMaximum: number, + translation: number, + output: CubismPhysicsOutput): void + { + let outputScale: number; + let value: number; + let weight: number; + + outputScale = output.getScale(output.translationScale, output.angleScale); + + value = translation * outputScale; + + if (value < parameterValueMinimum) + { + if (value < output.valueBelowMinimum) + { + output.valueBelowMinimum = value; + } + + value = parameterValueMinimum; + } + else if (value > parameterValueMaximum) + { + if (value > output.valueExceededMaximum) + { + output.valueExceededMaximum = value; + } + + value = parameterValueMaximum; + } + + weight = (output.weight / MaximumWeight); + + if (weight >= 1.0) + { + parameterValue[0] = value; + } + else + { + value = (parameterValue[0] * (1.0 - weight)) + (value * weight); + parameterValue[0] = value; + } + } + + + function normalizeParameterValue( + value: number, + parameterMinimum: number, + parameterMaximum: number, + parameterDefault: number, + normalizedMinimum: number, + normalizedMaximum: number, + normalizedDefault: number, + isInverted: boolean) + { + let result: number = 0.0; + + const maxValue: number = CubismMath.max(parameterMaximum, parameterMinimum); + + if(maxValue < value) + { + return result; + } + + const minValue: number = CubismMath.min(parameterMaximum, parameterMinimum); + + if(minValue > value) + { + return result; + } + + const minNormValue: number = CubismMath.min(normalizedMinimum, normalizedMaximum); + const maxNormValue: number = CubismMath.max(normalizedMinimum, normalizedMaximum); + const middleNormValue: number = normalizedDefault; + + const middleValue: number = getDefaultValue(minValue, maxValue); + const paramValue: number = value - middleValue; + + switch(sign(paramValue)) + { + case 1: + { + const nLength: number = maxNormValue - middleNormValue; + const pLength: number = maxValue - middleValue; + + if(pLength != 0.0) + { + result = paramValue * (nLength / pLength); + result += middleNormValue; + } + + break; + } + case -1: + { + const nLength: number = minNormValue - middleNormValue; + const pLength: number = minValue - middleValue; + + if(pLength != 0.0) + { + result = paramValue * (nLength / pLength); + result += middleNormValue; + } + + break; + } + case 0: + { + result = middleNormValue; + + break; + } + default: + { + break; + } + } + + return (isInverted) + ? result + : (result * -1.0); + } +} \ No newline at end of file diff --git a/Framework/physics/cubismphysicsinternal.ts b/Framework/physics/cubismphysicsinternal.ts new file mode 100644 index 0000000..de54c9c --- /dev/null +++ b/Framework/physics/cubismphysicsinternal.ts @@ -0,0 +1,248 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismvector2} from '../math/cubismvector2'; +import {Live2DCubismFramework as cubismid} from '../id/cubismid'; +import {Live2DCubismFramework as csmvector} from '../type/csmvector'; +import csmVector = csmvector.csmVector; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismVector2 = cubismvector2.CubismVector2; + +export namespace Live2DCubismFramework +{ + /** + * 物理演算の適用先の種類 + */ + export enum CubismPhysicsTargetType + { + CubismPhysicsTargetType_Parameter, // パラメータに対して適用 + } + + /** + * 物理演算の入力の種類 + */ + export enum CubismPhysicsSource + { + CubismPhysicsSource_X, // X軸の位置から + CubismPhysicsSource_Y, // Y軸の位置から + CubismPhysicsSource_Angle, // 角度から + } + + /** + * @brief 物理演算で使用する外部の力 + * + * 物理演算で使用する外部の力。 + */ + export class PhysicsJsonEffectiveForces + { + constructor() + { + this.gravity = new CubismVector2(0, 0); + this.wind = new CubismVector2(0, 0); + } + gravity: CubismVector2; ///< 重力 + wind: CubismVector2; ///< 風 + } + + /** + * 物理演算のパラメータ情報 + */ + export class CubismPhysicsParameter + { + id: CubismIdHandle; // パラメータ + targetType: CubismPhysicsTargetType; // 適用先の種類 + } + + /** + * 物理演算の正規化情報 + */ + export class CubismPhysicsNormalization + { + minimum: number; // 最大値 + maximum: number; // 最小値 + defalut: number; // デフォルト値 + } + + /** + * 物理演算の演算委使用する物理点の情報 + */ + export class CubismPhysicsParticle + { + constructor() + { + this.initialPosition = new CubismVector2(0, 0); + this.position = new CubismVector2(0, 0); + this.lastPosition = new CubismVector2(0, 0); + this.lastGravity = new CubismVector2(0, 0); + this.force = new CubismVector2(0, 0); + this.velocity = new CubismVector2(0, 0); + } + + initialPosition: CubismVector2; // 初期位置 + mobility: number; // 動きやすさ + delay: number; // 遅れ + acceleration: number; // 加速度 + radius: number; // 距離 + position: CubismVector2; // 現在の位置 + lastPosition: CubismVector2; // 最後の位置 + lastGravity: CubismVector2; // 最後の重力 + force: CubismVector2; // 現在かかっている力 + velocity: CubismVector2; // 現在の速度 + } + + /** + * 物理演算の物理点の管理 + */ + export class CubismPhysicsSubRig + { + constructor() + { + this.normalizationPosition = new CubismPhysicsNormalization(); + this.normalizationAngle = new CubismPhysicsNormalization(); + } + inputCount: number; // 入力の個数 + outputCount: number; // 出力の個数 + particleCount: number; // 物理点の個数 + baseInputIndex: number; // 入力の最初のインデックス + baseOutputIndex: number; // 出力の最初のインデックス + baseParticleIndex: number; // 物理点の最初のインデックス + normalizationPosition: CubismPhysicsNormalization; // 正規化された位置 + normalizationAngle: CubismPhysicsNormalization; // 正規化された角度 + } + + /** + * 正規化されたパラメータの取得関数の宣言 + * @param targetTranslation // 演算結果の移動値 + * @param targetAngle // 演算結果の角度 + * @param value // パラメータの値 + * @param parameterMinimunValue // パラメータの最小値 + * @param parameterMaximumValue // パラメータの最大値 + * @param parameterDefaultValue // パラメータのデフォルト値 + * @param normalizationPosition // 正規化された位置 + * @param normalizationAngle // 正規化された角度 + * @param isInverted // 値が反転されているか? + * @param weight // 重み + */ + export interface normalizedPhysicsParameterValueGetter + { + ( + targetTranslation: CubismVector2, + targetAngle: {angle: number}, + value: number, + parameterMinimunValue: number, + parameterMaximumValue: number, + parameterDefaultValue: number, + normalizationPosition: CubismPhysicsNormalization, + normalizationAngle: CubismPhysicsNormalization, + isInverted: boolean, + weight: number + ): void + } + + /** + * 物理演算の値の取得関数の宣言 + * @param translation 移動値 + * @param particles 物理点のリスト + * @param isInverted 値が反映されているか + * @param parentGravity 重力 + * @return 値 + */ + export interface physicsValueGetter + { + ( + translation: CubismVector2, + particles: CubismPhysicsParticle[], + particleIndex: number, + isInverted: boolean, + parentGravity: CubismVector2 + ): number + } + + /** + * 物理演算のスケールの取得関数の宣言 + * @param translationScale 移動値のスケール + * @param angleScale 角度のスケール + * @return スケール値 + */ + export interface physicsScaleGetter + { + ( + translationScale: CubismVector2, + angleScale: number + ): number; + } + + /** + * 物理演算の入力情報 + */ + export class CubismPhysicsInput + { + constructor() + { + this.source = new CubismPhysicsParameter(); + } + source: CubismPhysicsParameter; // 入力元のパラメータ + sourceParameterIndex: number; // 入力元のパラメータのインデックス + weight: number; // 重み + type: number; // 入力の種類 + reflect: boolean; // 値が反転されているかどうか + getNormalizedParameterValue: normalizedPhysicsParameterValueGetter; // 正規化されたパラメータ値の取得関数 + } + + /** + * @brief 物理演算の出力情報 + * + * 物理演算の出力情報。 + */ + export class CubismPhysicsOutput + { + constructor() + { + this.destination = new CubismPhysicsParameter(); + this.translationScale = new CubismVector2(0, 0); + } + + destination: CubismPhysicsParameter; ///< 出力先のパラメータ + destinationParameterIndex: number; ///< 出力先のパラメータのインデックス + vertexIndex: number; ///< 振り子のインデックス + translationScale: CubismVector2; ///< 移動値のスケール + angleScale: number; ///< 角度のスケール + weight: number; /// 重み + type: CubismPhysicsSource; ///< 出力の種類 + reflect: boolean; ///< 値が反転されているかどうか + valueBelowMinimum: number; ///< 最小値を下回った時の値 + valueExceededMaximum: number; ///< 最大値をこえた時の値 + getValue: physicsValueGetter; ///< 物理演算の値の取得関数 + getScale: physicsScaleGetter; ///< 物理演算のスケール値の取得関数 + } + + /** + * @brief 物理演算のデータ + * + * 物理演算のデータ。 + */ + export class CubismPhysicsRig + { + constructor() + { + this.settings = new csmVector(); + this.inputs = new csmVector(); + this.outputs = new csmVector(); + this.particles = new csmVector(); + this.gravity = new CubismVector2(0, 0); + this.wind = new CubismVector2(0, 0); + } + + subRigCount: number; ///< 物理演算の物理点の個数 + settings: csmVector; ///< 物理演算の物理点の管理のリスト + inputs: csmVector; ///< 物理演算の入力のリスト + outputs: csmVector; ///< 物理演算の出力のリスト + particles: csmVector; ///< 物理演算の物理点のリスト + gravity: CubismVector2; ///< 重力 + wind: CubismVector2; ///< 風 + }; +} \ No newline at end of file diff --git a/Framework/physics/cubismphysicsjson.ts b/Framework/physics/cubismphysicsjson.ts new file mode 100644 index 0000000..bcb784f --- /dev/null +++ b/Framework/physics/cubismphysicsjson.ts @@ -0,0 +1,407 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismjson} from '../utils/cubismjson'; +import {Live2DCubismFramework as cubismvector2} from '../math/cubismvector2'; +import {Live2DCubismFramework as cubismid} from '../id/cubismid'; +import {Live2DCubismFramework as cubismframework} from '../live2dcubismframework'; +import CubismFramework = cubismframework.CubismFramework; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismVector2 = cubismvector2.CubismVector2; +import CubismJson = cubismjson.CubismJson; + +export namespace Live2DCubismFramework +{ + // JSON keys + const Position: string = "Position"; + const X: string = "X"; + const Y: string = "Y"; + const Angle: string = "Angle"; + const Type: string = "Type"; + const Id: string = "Id"; + + // Meta + const Meta: string = "Meta"; + const EffectiveForces: string = "EffectiveForces"; + const TotalInputCount: string = "TotalInputCount"; + const TotalOutputCount: string = "TotalOutputCount"; + const PhysicsSettingCount: string = "PhysicsSettingCount"; + const Gravity: string = "Gravity"; + const Wind: string = "Wind"; + const VertexCount: string = "VertexCount"; + + // PhysicsSettings + const PhysicsSettings: string = "PhysicsSettings"; + const Normalization: string = "Normalization"; + const Minimum: string = "Minimum"; + const Maximum: string = "Maximum"; + const Default: string = "Default"; + const Reflect: string = "Reflect"; + const Weight: string = "Weight"; + + // Input + const Input: string = "Input"; + const Source: string = "Source"; + + // Output + const Output: string = "Output"; + const Scale: string = "Scale"; + const VertexIndex: string = "VertexIndex"; + const Destination: string = "Destination"; + + // Particle + const Vertices: string = "Vertices"; + const Mobility: string = "Mobility"; + const Delay: string = "Delay"; + const Radius: string = "Radius"; + const Acceleration: string = "Acceleration"; + + /** + * physics3.jsonのコンテナ。 + */ + export class CubismPhysicsJson + { + /** + * コンストラクタ + * @param buffer physics3.jsonが読み込まれているバッファ + * @param size バッファのサイズ + */ + public constructor(buffer: ArrayBuffer, size: number) + { + this._json = CubismJson.create(buffer, size); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + CubismJson.delete(this._json); + } + + /** + * 重力の取得 + * @return 重力 + */ + public getGravity(): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(0, 0); + ret.x = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Gravity).getMap().getValue(X).toFloat(); + ret.y = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Gravity).getMap().getValue(Y).toFloat(); + return ret; + } + + /** + * 風の取得 + * @return 風 + */ + public getWind(): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(0, 0); + ret.x = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Wind).getMap().getValue(X).toFloat(); + ret.y = this._json.getRoot().getMap().getValue(Meta).getMap().getValue(EffectiveForces).getMap().getValue(Wind).getMap().getValue(Y).toFloat(); + return ret; + } + + /** + * 物理店の管理の個数の取得 + * @return 物理店の管理の個数 + */ + public getSubRigCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(PhysicsSettingCount).toInt(); + } + + /** + * 入力の総合計の取得 + * @return 入力の総合計 + */ + public getTotalInputCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalInputCount).toInt(); + } + + /** + * 出力の総合計の取得 + * @return 出力の総合計 + */ + public getTotalOutputCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(TotalOutputCount).toInt(); + } + + /** + * 物理点の個数の取得 + * @return 物理点の個数 + */ + public getVertexCount(): number + { + return this._json.getRoot().getMap().getValue(Meta).getMap().getValue(VertexCount).toInt(); + } + + /** + * 正規化された位置の最小値の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @return 正規化された位置の最小値 + */ + public getNormalizationPositionMinimumValue(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Position).getMap().getValue(Minimum).toFloat(); + } + + /** + * 正規化された位置の最大値の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @return 正規化された位置の最大値 + */ + public getNormalizationPositionMaximumValue(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Position).getMap().getValue(Maximum).toFloat(); + } + + /** + * 正規化された位置のデフォルト値の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @return 正規化された位置のデフォルト値 + */ + public getNormalizationPositionDefaultValue(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Position).getMap().getValue(Default).toFloat(); + } + + /** + * 正規化された角度の最小値の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @return 正規化された角度の最小値 + */ + public getNormalizationAngleMinimumValue(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Angle).getMap().getValue(Minimum).toFloat(); + } + + /** + * 正規化された角度の最大値の取得 + * @param physicsSettingIndex + * @return 正規化された角度の最大値 + */ + public getNormalizationAngleMaximumValue(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Angle).getMap().getValue(Maximum).toFloat(); + } + + /** + * 正規化された角度のデフォルト値の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @return 正規化された角度のデフォルト値 + */ + public getNormalizationAngleDefaultValue(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Normalization).getMap().getValue(Angle).getMap().getValue(Default).toFloat(); + } + + /** + * 入力の個数の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @return 入力の個数 + */ + public getInputCount(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().getSize(); + } + + /** + * 入力の重みの取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param inputIndex 入力のインデックス + * @return 入力の重み + */ + public getInputWeight(physicsSettingIndex: number, inputIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Weight).toFloat(); + } + + /** + * 入力の反転の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param inputIndex 入力のインデックス + * @return 入力の反転 + */ + public getInputReflect(physicsSettingIndex: number, inputIndex: number): boolean + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Reflect).toBoolean(); + } + + /** + * 入力の種類の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param inputIndex 入力のインデックス + * @return 入力の種類 + */ + public getInputType(physicsSettingIndex: number, inputIndex: number): string + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Type).getRawString(); + } + + /** + * 入力元のIDの取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param inputIndex 入力のインデックス + * @return 入力元のID + */ + public getInputSourceId(physicsSettingIndex: number, inputIndex: number): CubismIdHandle + { + return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Input).getVector().at(inputIndex).getMap().getValue(Source).getMap().getValue(Id).getRawString()); + } + + /** + * 出力の個数の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @return 出力の個数 + */ + public getOutputCount(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().getSize(); + } + + /** + * 出力の物理点のインデックスの取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param outputIndex 出力のインデックス + * @return 出力の物理点のインデックス + */ + public getOutputVertexIndex(physicsSettingIndex: number, outputIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(VertexIndex).toInt(); + } + + /** + * 出力の角度のスケールを取得する + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param outputIndex 出力のインデックス + * @return 出力の角度のスケール + */ + public getOutputAngleScale(physicsSettingIndex: number, outputIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Scale).toFloat(); + } + + /** + * 出力の重みの取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param outputIndex 出力のインデックス + * @return 出力の重み + */ + public getOutputWeight(physicsSettingIndex: number, outputIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Weight).toFloat(); + } + + /** + * 出力先のIDの取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param outputIndex 出力のインデックス + * @return 出力先のID + */ + public getOutputDestinationId(physicsSettingIndex: number, outputIndex: number): CubismIdHandle + { + return CubismFramework.getIdManager().getId(this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Destination).getMap().getValue(Id).getRawString()); + } + + /** + * 出力の種類の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param outputIndex 出力のインデックス + * @return 出力の種類 + */ + public getOutputType(physicsSettingIndex: number, outputIndex: number): string + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Type).getRawString(); + } + + /** + * 出力の反転の取得 + * @param physicsSettingIndex 物理演算のインデックス + * @param outputIndex 出力のインデックス + * @return 出力の反転 + */ + public getOutputReflect(physicsSettingIndex: number, outputIndex: number): boolean + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Output).getVector().at(outputIndex).getMap().getValue(Reflect).toBoolean(); + } + + /** + * 物理点の個数の取得 + * @param physicsSettingIndex 物理演算男設定のインデックス + * @return 物理点の個数 + */ + public getParticleCount(physicsSettingIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().getSize(); + } + + /** + * 物理点の動きやすさの取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param vertexIndex 物理点のインデックス + * @return 物理点の動きやすさ + */ + public getParticleMobility(physicsSettingIndex: number, vertexIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Mobility).toFloat(); + } + + /** + * 物理点の遅れの取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param vertexIndex 物理点のインデックス + * @return 物理点の遅れ + */ + public getParticleDelay(physicsSettingIndex: number, vertexIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Delay).toFloat(); + } + + /** + * 物理点の加速度の取得 + * @param physicsSettingIndex 物理演算の設定 + * @param vertexIndex 物理点のインデックス + * @return 物理点の加速度 + */ + public getParticleAcceleration(physicsSettingIndex: number, vertexIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Acceleration).toFloat(); + } + + /** + * 物理点の距離の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param vertexIndex 物理点のインデックス + * @return 物理点の距離 + */ + public getParticleRadius(physicsSettingIndex: number, vertexIndex: number): number + { + return this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Radius).toInt(); + } + + /** + * 物理点の位置の取得 + * @param physicsSettingIndex 物理演算の設定のインデックス + * @param vertexInde 物理点のインデックス + * @return 物理点の位置 + */ + public getParticlePosition(physicsSettingIndex: number, vertexIndex: number): CubismVector2 + { + let ret: CubismVector2 = new CubismVector2(0, 0); + ret.x = this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Position).getMap().getValue(X).toFloat(); + ret.y = this._json.getRoot().getMap().getValue(PhysicsSettings).getVector().at(physicsSettingIndex).getMap().getValue(Vertices).getVector().at(vertexIndex).getMap().getValue(Position).getMap().getValue(Y).toFloat(); + return ret; + } + + _json: CubismJson; // physics3.jsonデータ + } + +} \ No newline at end of file diff --git a/Framework/rendering/cubismrenderer.ts b/Framework/rendering/cubismrenderer.ts new file mode 100644 index 0000000..5e8cf64 --- /dev/null +++ b/Framework/rendering/cubismrenderer.ts @@ -0,0 +1,312 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismmatrix44} from '../math/cubismmatrix44'; +import {Live2DCubismFramework as cubismmodel} from '../model/cubismmodel'; +import CubismModel = cubismmodel.CubismModel; +import CubismMatrix44 = cubismmatrix44.CubismMatrix44; + +export namespace Live2DCubismFramework +{ + /** + * モデル描画を処理するレンダラ + * + * サブクラスに環境依存の描画命令を記述する。 + */ + export abstract class CubismRenderer + { + /** + * レンダラのインスタンスを生成して取得する + * + * @return レンダラのインスタンス + */ + public static create(): CubismRenderer + { + return null; + } + + /** + * レンダラのインスタンスを解放する + */ + public static delete(renderer: CubismRenderer): void + { + renderer = void 0; + renderer = null; + } + + /** + * レンダラが保持する静的なリソースを開放する + */ + public static StaticRelease(): void + { + //CubismRenderer_WebGL.doStaticRelease(); + } + + /** + * レンダラの初期化処理を実行する + * 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる + * @param model モデルのインスタンス + */ + public initialize(model: CubismModel): void + { + this._model = model; + } + + /** + * モデルを描画する + */ + public drawModel(): void + { + if(this.getModel() == null) return; + /** + * doDrawModelの描画前と描画後に以下の関数を呼んでください + * ・saveProfile(); + * ・restoreProfile(); + * これはレンダラの描画設定を保存復帰させることで、 + * モデル描画直前の状態に戻すための処理です。 + */ + + this.saveProfile(); + this.doDrawModel(); + this.restoreProfile(); + } + + /** + * Model-View-Projection 行列をセットする + * 配列は複製されるので、元の配列は外で破棄して良い + * @param matrix44 Model-View-Projection 行列 + */ + public setMvpMatrix(matrix44: CubismMatrix44): void + { + this._mvpMatrix4x4.setMatrix(matrix44.getArray()); + } + + /** + * Model-View-Projection 行列を取得する + * @return Model-View-Projection 行列 + */ + public getMvpMatrix(): CubismMatrix44 + { + return this._mvpMatrix4x4; + } + + /** + * モデルの色をセットする + * 各色0.0~1.0の間で指定する(1.0が標準の状態) + * @param red 赤チャンネルの値 + * @param green 緑チャンネルの値 + * @param blue 青チャンネルの値 + * @param alpha αチャンネルの値 + */ + public setModelColor(red: number, green: number, blue: number, alpha: number): void + { + if(red < 0.0) + { + red = 0.0; + } + else if(red > 1.0) + { + red = 1.0; + } + + if(green < 0.0) + { + green = 0.0; + } + else if(green > 1.0) + { + green = 1.0; + } + + if(blue < 0.0) + { + blue = 0.0; + } + else if(blue > 1.0) + { + blue = 1.0; + } + + if(alpha < 0.0) + { + alpha = 0.0; + } + else if(alpha > 1.0) + { + alpha = 1.0; + } + + this._modelColor.R = red; + this._modelColor.G = green; + this._modelColor.B = blue; + this._modelColor.A = alpha; + } + + /** + * モデルの色を取得する + * 各色0.0~1.0の間で指定する(1.0が標準の状態) + * + * @return RGBAのカラー情報 + */ + public getModelColor(): CubismRenderer.CubismTextureColor + { + return JSON.parse(JSON.stringify(this._modelColor)); + } + + /** + * 乗算済みαの有効・無効をセットする + * 有効にするならtrue、無効にするならfalseをセットする + */ + public setIsPremultipliedAlpha(enable: boolean): void + { + this._isPremultipliedAlpha = enable; + } + + /** + * 乗算済みαの有効・無効を取得する + * @return true 乗算済みのα有効 + * @return false 乗算済みのα無効 + */ + public isPremultipliedAlpha(): boolean + { + return this._isPremultipliedAlpha; + } + + /** + * カリング(片面描画)の有効・無効をセットする。 + * 有効にするならtrue、無効にするならfalseをセットする + */ + public setIsCulling(culling: boolean): void + { + this._isCulling = culling; + } + + /** + * カリング(片面描画)の有効・無効を取得する。 + * @return true カリング有効 + * @return false カリング無効 + */ + public isCulling(): boolean + { + return this._isCulling; + } + + /** + * テクスチャの異方性フィルタリングのパラメータをセットする + * パラメータ値の影響度はレンダラの実装に依存する + * @param n パラメータの値 + */ + public setAnisotropy(n: number): void + { + this._anisortopy = n; + } + + /** + * テクスチャの異方性フィルタリングのパラメータをセットする + * @return 異方性フィルタリングのパラメータ + */ + public getAnisotropy(): number + { + return this._anisortopy; + } + + /** + * レンダリングするモデルを取得する + * @return レンダリングするモデル + */ + public getModel(): CubismModel + { + return this._model; + } + + /** + * コンストラクタ + */ + protected constructor() + { + this._isCulling = false; + this._isPremultipliedAlpha = false; + this._anisortopy = 0.0; + this._model = null; + this._modelColor = new CubismRenderer.CubismTextureColor(); + + // 単位行列に初期化 + this._mvpMatrix4x4 = new CubismMatrix44(); + this._mvpMatrix4x4.loadIdentity(); + } + + /** + * モデル描画の実装 + */ + public abstract doDrawModel(): void; + + /** + * 描画オブジェクト(アートメッシュ)を描画する + * ポリゴンメッシュとテクスチャ番号をセットで渡す。 + * @param textureNo 描画するテクスチャ番号 + * @param indexCount 描画オブジェクトのインデックス値 + * @param vertexCount ポリゴンメッシュの頂点数 + * @param indexArray ポリゴンメッシュ頂点のインデックス配列 + * @param vertexArray ポリゴンメッシュの頂点配列 + * @param uvArray uv配列 + * @param opacity 不透明度 + * @param colorBlendMode カラーブレンディングのタイプ + */ + public abstract drawMesh(textureNo: number, indexCount: number, vertexCount: number, + indexArray: Uint16Array, vertexArray: Float32Array, uvArray: Float32Array, + opacity: number, colorBlendMode: CubismRenderer.CubismBlendMode): void; + + /** + * モデル描画直前のレンダラのステートを保持する + */ + public abstract saveProfile(): void; + + /** + * モデル描画直前のレンダラのステートを復帰させる + */ + public abstract restoreProfile(): void; + + protected _mvpMatrix4x4: CubismMatrix44; // Model-View-Projection 行列 + protected _modelColor: CubismRenderer.CubismTextureColor; // モデル自体のカラー(RGBA) + protected _isCulling: boolean; // カリングが有効ならtrue + protected _isPremultipliedAlpha: boolean; // 乗算済みαならtrue + protected _anisortopy: any; // テクスチャの異方性フィルタリングのパラメータ + protected _model: CubismModel; // レンダリング対象のモデル + } + + export namespace CubismRenderer + { + export enum CubismBlendMode + { + CubismBlendMode_Normal = 0, // 通常 + CubismBlendMode_Additive = 1, // 加算 + CubismBlendMode_Multiplicative = 2, // 乗算 + }; + + /** + * テクスチャの色をRGBAで扱うためのクラス + */ + export class CubismTextureColor + { + /** + * コンストラクタ + */ + constructor() + { + this.R = 1.0; + this.G = 1.0; + this.B = 1.0; + this.A = 1.0; + } + + R: number; // 赤チャンネル + G: number; // 緑チャンネル + B: number; // 青チャンネル + A: number; // αチャンネル + } + } +} \ No newline at end of file diff --git a/Framework/rendering/cubismrenderer_WebGL.ts b/Framework/rendering/cubismrenderer_WebGL.ts new file mode 100644 index 0000000..b6e7395 --- /dev/null +++ b/Framework/rendering/cubismrenderer_WebGL.ts @@ -0,0 +1,1986 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework"; +import {Live2DCubismFramework as csmrect} from "../type/csmrectf"; +import {Live2DCubismFramework as cubismrenderer} from "./cubismrenderer"; +import {Live2DCubismFramework as cubismmodel} from "../model/cubismmodel"; +import {Live2DCubismFramework as cubsimmatrix44} from "../math/cubismmatrix44"; +import {Live2DCubismFramework as csmmap} from "../type/csmmap"; +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {CubismLogError} from "../utils/cubismdebug"; +import Constant = cubismframework.Constant; +import CubismMatrix44 = cubsimmatrix44.CubismMatrix44; +import csmRect = csmrect.csmRect; +import csmMap = csmmap.csmMap; +import csmVector = csmvector.csmVector; +import CubismModel = cubismmodel.CubismModel; +import CubismRenderer = cubismrenderer.CubismRenderer; + +export namespace Live2DCubismFramework +{ + const ColorChannelCount: number = 4; // 実験時に1チャンネルの場合は1、RGBだけの場合は3、アルファも含める場合は4 + + const shaderCount: number = 13; // シェーダーの数 = マスク生成用 + (通常用 + 加算 + 乗算) * (マスク無 + マスク有 + マスク無の乗算済アルファ対応版 + マスク有の乗算済アルファ対応版) + let s_instance: CubismShader_WebGL; + + /** + * クリッピングマスクの処理を実行するクラス + */ + export class CubismClippingManager_WebGL + { + /** + * カラーチャンネル(RGBA)のフラグを取得する + * @param channelNo カラーチャンネル(RGBA)の番号(0:R, 1:G, 2:B, 3:A) + */ + public getChannelFlagAsColor(channelNo: number): CubismRenderer.CubismTextureColor + { + return this._channelColors.at(channelNo); + } + + /** + * テンポラリのレンダーテクスチャのアドレスを取得する + * FrameBufferObjectが存在しない場合、新しく生成する + * + * @return レンダーテクスチャのアドレス + */ + public getMaskRenderTexture(): WebGLFramebuffer + { + let ret: WebGLFramebuffer = 0; + + // テンポラリのRenderTextureを取得する + if(this._maskTexture && this._maskTexture.texture != 0) // 前回使ったものを返す + { + this._maskTexture.frameNo = this._currentFrameNo; + ret = this._maskTexture.texture; + } + + if(ret == 0) + { + // FrameBufferObjectが存在しない場合、新しく生成する + + // クリッピングバッファサイズを取得 + const size: number = this._clippingMaskBufferSize; + + this._colorBuffer = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, this._colorBuffer); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0 ,this.gl.RGBA, size, size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); + this.gl.bindTexture(this.gl.TEXTURE_2D, null); + + let tmpFrameBufferObject: GLint; + tmpFrameBufferObject = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING); + + ret = this.gl.createFramebuffer(); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, ret); + this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._colorBuffer, 0); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, tmpFrameBufferObject); + + this._maskTexture = new CubismRenderTextureResource(this._currentFrameNo, ret); + } + + return ret; + } + + /** + * WebGLレンダリングコンテキストを設定する + * @param gl WebGLレンダリングコンテキスト + */ + public setGL(gl: WebGLRenderingContext): void + { + this.gl = gl; + } + + /** + * マスクされる描画オブジェクト群全体を囲む矩形(モデル座標系)を計算する + * @param model モデルのインスタンス + * @param clippingContext クリッピングマスクのコンテキスト + */ + public calcClippedDrawTotalBounds(model: CubismModel, clippingContext: CubismClippingContext): void + { + // 被クリッピングマスク(マスクされる描画オブジェクト)の全体の矩形 + let clippedDrawTotalMinX: number = Number.MAX_VALUE; + let clippedDrawTotalMinY: number = Number.MAX_VALUE; + let clippedDrawTotalMaxX: number = Number.MIN_VALUE; + let clippedDrawTotalMaxY: number = Number.MIN_VALUE; + + // このマスクが実際に必要か判定する + // このクリッピングを利用する「描画オブジェクト」がひとつでも使用可能であればマスクを生成する必要がある + const clippedDrawCount: number = clippingContext._clippedDrawableIndexList.length; + + for(let clippedDrawableIndex: number = 0; clippedDrawableIndex < clippedDrawCount; clippedDrawableIndex++) + { + // マスクを使用する描画オブジェクトの描画される矩形を求める + const drawableIndex: number = clippingContext._clippedDrawableIndexList[clippedDrawableIndex]; + + const drawableVertexCount: number = model.getDrawableVertexCount(drawableIndex); + let drawableVertexes: Float32Array = model.getDrawableVertices(drawableIndex); + + let minX: number = Number.MAX_VALUE; + let minY: number = Number.MAX_VALUE; + let maxX: number = Number.MIN_VALUE; + let maxY: number = Number.MIN_VALUE; + + let loop: number = drawableVertexCount * Constant.vertexStep; + for(let pi: number = Constant.vertexOffset; pi < loop; pi += Constant.vertexStep) + { + let x: number = drawableVertexes[pi]; + let y: number = drawableVertexes[pi + 1]; + + if(x < minX) + { + minX = x; + } + if(x > maxX) + { + maxX = x; + } + if(y < minY) + { + minY = y; + } + if(y > maxY) + { + maxY = y; + } + } + + // 有効な点が一つも取れなかったのでスキップ + if(minX == Number.MAX_VALUE) + { + continue; + } + + // 全体の矩形に反映 + if(minX < clippedDrawTotalMinX) + { + clippedDrawTotalMinX = minX; + } + if(minY < clippedDrawTotalMinY) + { + clippedDrawTotalMinY = minY; + } + if(maxX > clippedDrawTotalMaxX) + { + clippedDrawTotalMaxX = maxX; + } + if(maxY > clippedDrawTotalMaxY) + { + clippedDrawTotalMaxY = maxY; + } + + if(clippedDrawTotalMinX == Number.MAX_VALUE) + { + clippingContext._allClippedDrawRect.x = 0.0; + clippingContext._allClippedDrawRect.y = 0.0; + clippingContext._allClippedDrawRect.width = 0.0; + clippingContext._allClippedDrawRect.height = 0.0; + clippingContext._isUsing = false; + } + else + { + clippingContext._isUsing = true; + let w: number = clippedDrawTotalMaxX - clippedDrawTotalMinX; + let h: number = clippedDrawTotalMaxY - clippedDrawTotalMinY; + clippingContext._allClippedDrawRect.x = clippedDrawTotalMinX; + clippingContext._allClippedDrawRect.y = clippedDrawTotalMinY; + clippingContext._allClippedDrawRect.width = w; + clippingContext._allClippedDrawRect.height = h; + } + + } + } + + /** + * コンストラクタ + */ + public constructor() + { + this._maskRenderTexture = null; + this._colorBuffer = null; + this._currentFrameNo = 0; + this._clippingMaskBufferSize = 256; + this._clippingContextListForMask = new csmVector(); + this._clippingContextListForDraw = new csmVector(); + this._channelColors = new csmVector(); + this._tmpBoundsOnModel = new csmRect(); + this._tmpMatrix = new CubismMatrix44(); + this._tmpMatrixForMask = new CubismMatrix44(); + this._tmpMatrixForDraw = new CubismMatrix44(); + this._maskTexture = null; + ; + let tmp: CubismRenderer.CubismTextureColor = new CubismRenderer.CubismTextureColor(); + tmp.R = 1.0; + tmp.G = 0.0; + tmp.B = 0.0; + tmp.A = 0.0; + this._channelColors.pushBack(tmp); + + tmp = new CubismRenderer.CubismTextureColor(); + tmp.R = 0.0; + tmp.G = 1.0; + tmp.B = 0.0; + tmp.A = 0.0; + this._channelColors.pushBack(tmp); + + tmp = new CubismRenderer.CubismTextureColor(); + tmp.R = 0.0; + tmp.G = 0.0; + tmp.B = 1.0; + tmp.A = 0.0; + this._channelColors.pushBack(tmp); + + tmp = new CubismRenderer.CubismTextureColor(); + tmp.R = 0.0; + tmp.G = 0.0; + tmp.B = 0.0; + tmp.A = 1.0; + this._channelColors.pushBack(tmp); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + for(let i: number = 0; i < this._clippingContextListForMask.getSize(); i++) + { + if(this._clippingContextListForMask.at(i)) + { + this._clippingContextListForMask.at(i).release(); + this._clippingContextListForMask.set(i, void 0); + } + this._clippingContextListForMask.set(i, null); + } + this._clippingContextListForMask = null; + + // _clippingContextListForDrawは_clippingContextListForMaskにあるインスタンスを指している。上記の処理により要素ごとのDELETEha不要。 + for(let i: number = 0; i < this._clippingContextListForDraw.getSize(); i++) + { + this._clippingContextListForDraw.at(i).release(); + this._clippingContextListForDraw.set(i, null); + } + this._clippingContextListForDraw = null; + + if(this._maskTexture) + { + this.gl.deleteFramebuffer(this._maskTexture.texture); + + this._maskTexture = void 0; + this._maskTexture = null; + } + + for(let i: number = 0; i < this._channelColors.getSize(); i++) + { + if(this._channelColors.at(i)) + { + this._channelColors.set(i, void 0); + } + this._channelColors.set(i, null); + } + + this._channelColors = null; + } + + /** + * マネージャの初期化処理 + * クリッピングマスクを使う描画オブジェクトの登録を行う + * @param model モデルのインスタンス + * @param drawableCount 描画オブジェクトの数 + * @param drawableMasks 描画オブジェクトをマスクする描画オブジェクトのインデックスのリスト + * @param drawableCounts 描画オブジェクトをマスクする描画オブジェクトの数 + */ + public initialize(model: CubismModel, drawableCount: number, drawableMasks: Int32Array[], drawableMaskCounts: Int32Array): void + { + // クリッピングマスクを使う描画オブジェクトをすべて登録する + // クリッピングマスクは、通常数個程度に限定して使うものとする + for(let i: number = 0; i < drawableCount; i++) + { + if(drawableMaskCounts[i] <= 0) + { + // クリッピングマスクが使用されていないアートメッシュ(多くの場合使用しない) + this._clippingContextListForDraw.pushBack(null); + continue; + } + + // 既にあるClipContextと同じかチェックする + let clippingContext: CubismClippingContext = this.findSameClip(drawableMasks[i], drawableMaskCounts[i]); + if(clippingContext == null) + { + // 同一のマスクが存在していない場合は生成する + clippingContext = new CubismClippingContext(this, drawableMasks[i], drawableMaskCounts[i]); + this._clippingContextListForMask.pushBack(clippingContext); + } + + clippingContext.addClippedDrawable(i); + + this._clippingContextListForDraw.pushBack(clippingContext); + } + } + + /** + * クリッピングコンテキストを作成する。モデル描画時に実行する。 + * @param model モデルのインスタンス + * @param renderer レンダラのインスタンス + */ + public setupClippingContext(model: CubismModel, renderer: CubismRenderer_WebGL): void + { + this._currentFrameNo++; + + // 全てのクリッピングを用意する + // 同じクリップ(複数の場合はまとめて一つのクリップ)を使う場合は1度だけ設定する + let usingClipCount: number = 0; + for(let clipIndex = 0; clipIndex < this._clippingContextListForMask.getSize(); clipIndex++) + { + // 1つのクリッピングマスクに関して + let cc: CubismClippingContext = this._clippingContextListForMask.at(clipIndex); + + // このクリップを利用する描画オブジェクト群全体を囲む矩形を計算 + this.calcClippedDrawTotalBounds(model, cc); + + if(cc._isUsing) + { + usingClipCount++; // 使用中としてカウント + } + } + + // マスク作成処理 + if(usingClipCount > 0) + { + // 現在のビューポートの値を退避 + let viewport: number[] = new Array(4); + + // 現在のビューポートの値を退避 + viewport = this.gl.getParameter(this.gl.VIEWPORT); + + // 生成したFrameBufferと同じサイズでビューポートを設定 + this.gl.viewport(0, 0, this._clippingMaskBufferSize, this._clippingMaskBufferSize); + + // マスクactive切り替え前のFBOを退避 + let oldFBO: number; + oldFBO = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING); + + // マスクをactiveにする + this._maskRenderTexture = this.getMaskRenderTexture(); + + // モデル描画時にDrawMeshNowに渡される変換(モデルtoワールド座標変換) + let modelToWorldF: CubismMatrix44 = renderer.getMvpMatrix(); + + renderer.preDraw(); // バッファをクリアする + + // 各マスクのレイアウトを決定していく + this.setupLayoutBounds(usingClipCount); + + // ---------- マスク描画処理 ---------- + // マスク用RenderTextureをactiveにセット + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this._maskRenderTexture); + + // マスクをクリアする + // (仮仕様) 1が無効(描かれない)領域、0が有効(描かれる)領域。(シェーダーCd*Csで0に近い値をかけてマスクを作る。1をかけると何も起こらない) + this.gl.clearColor(1.0, 1.0, 1.0, 1.0); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); + + // 実際にマスクを生成する + // 全てのマスクをどのようにレイアウトして描くかを決定し、ClipContext, ClippedDrawContextに記憶する + for(let clipIndex: number = 0; clipIndex < this._clippingContextListForMask.getSize(); clipIndex++) + { + // --- 実際に1つのマスクを描く --- + let clipContext: CubismClippingContext = this._clippingContextListForMask.at(clipIndex); + let allClipedDrawRect: csmRect = clipContext._allClippedDrawRect; // このマスクを使う、すべての描画オブジェクトの論理座標上の囲み矩形 + let layoutBoundsOnTex01: csmRect = clipContext._layoutBounds; // この中にマスクを収める + + // モデル座標上の矩形を、適宜マージンを付けて使う + const MARGIN: number = 0.05; + this._tmpBoundsOnModel.setRect(allClipedDrawRect); + this._tmpBoundsOnModel.expand(allClipedDrawRect.width * MARGIN, allClipedDrawRect.height * MARGIN); + //########## 本来は割り当てられた領域の全体を使わず必要最低限のサイズがよい + + // シェーダ用の計算式を求める。回転を考慮しない場合は以下のとおり + // movePeriod' = movePeriod * scaleX + offX [[ movePeriod' = (movePeriod - tmpBoundsOnModel.movePeriod)*scale + layoutBoundsOnTex01.movePeriod ]] + const scaleX: number = layoutBoundsOnTex01.width / this._tmpBoundsOnModel.width; + const scaleY: number = layoutBoundsOnTex01.height / this._tmpBoundsOnModel.height; + + // マスク生成時に使う行列を求める + { + // シェーダに渡す行列を求める <<<<<<<<<<<<<<<<<<<<<<<< 要最適化(逆順に計算すればシンプルにできる) + this._tmpMatrix.loadIdentity(); + { + // layout0..1 を -1..1に変換 + this._tmpMatrix.translateRelative(-1.0, -1.0); + this._tmpMatrix.scaleRelative(2.0, 2.0); + } + { + // view to layout0..1 + this._tmpMatrix.translateRelative(layoutBoundsOnTex01.x, layoutBoundsOnTex01.y); + this._tmpMatrix.scaleRelative(scaleX, scaleY); // new = [translate][scale] + this._tmpMatrix.translateRelative(-this._tmpBoundsOnModel.x, -this._tmpBoundsOnModel.y); + // new = [translate][scale][translate] + } + // tmpMatrixForMaskが計算結果 + this._tmpMatrixForMask.setMatrix(this._tmpMatrix.getArray()); + } + + //--------- draw時の mask 参照用行列を計算 + { + // シェーダに渡す行列を求める <<<<<<<<<<<<<<<<<<<<<<<< 要最適化(逆順に計算すればシンプルにできる) + this._tmpMatrix.loadIdentity(); + { + this._tmpMatrix.translateRelative(layoutBoundsOnTex01.x, layoutBoundsOnTex01.y); + this._tmpMatrix.scaleRelative(scaleX, scaleY); // new = [translate][scale] + this._tmpMatrix.translateRelative(-this._tmpBoundsOnModel.x, -this._tmpBoundsOnModel.y); + // new = [translate][scale][translate] + } + this._tmpMatrixForDraw.setMatrix(this._tmpMatrix.getArray()); + } + clipContext._matrixForMask.setMatrix(this._tmpMatrixForMask.getArray()); + clipContext._matrixForDraw.setMatrix(this._tmpMatrixForDraw.getArray()); + + const clipDrawCount: number = clipContext._clippingIdCount; + for(let i: number = 0; i < clipDrawCount; i++) + { + const clipDrawIndex: number = clipContext._clippingIdList[i]; + + // 頂点情報が更新されておらず、信頼性がない場合は描画をパスする + if(!model.getDrawableDynamicFlagVertexPositionsDidChange(clipDrawIndex)) + { + continue; + } + + renderer.setIsCulling(model.getDrawableCulling(clipDrawIndex) != false); + + // 今回専用の変換を適用して描く + // チャンネルも切り替える必要がある(A,R,G,B) + renderer.setClippingContextBufferForMask(clipContext); + renderer.drawMesh( + model.getDrawableTextureIndices(clipDrawIndex), + model.getDrawableVertexIndexCount(clipDrawIndex), + model.getDrawableVertexCount(clipDrawIndex), + model.getDrawableVertexIndices(clipDrawIndex), + model.getDrawableVertices(clipDrawIndex), + model.getDrawableVertexUvs(clipDrawIndex), + model.getDrawableOpacity(clipDrawIndex), + CubismRenderer.CubismBlendMode.CubismBlendMode_Normal // クリッピングは通常描画を強制 + ); + } + } + + // --- 後処理 --- + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, oldFBO); // 描画対象を戻す + renderer.setClippingContextBufferForMask(null); + + this.gl.viewport(viewport[0], viewport[1], viewport[2], viewport[3]); + } + } + + /** + * 既にマスクを作っているかを確認 + * 作っている様であれば該当するクリッピングマスクのインスタンスを返す + * 作っていなければNULLを返す + * @param drawableMasks 描画オブジェクトをマスクする描画オブジェクトのリスト + * @param drawableMaskCounts 描画オブジェクトをマスクする描画オブジェクトの数 + * @return 該当するクリッピングマスクが存在すればインスタンスを返し、なければNULLを返す + */ + public findSameClip(drawableMasks: Int32Array, drawableMaskCounts: number): CubismClippingContext + { + // 作成済みClippingContextと一致するか確認 + for(let i: number = 0; i < this._clippingContextListForMask.getSize(); i++) + { + let clippingContext: CubismClippingContext = this._clippingContextListForMask.at(i); + const count: number = clippingContext._clippingIdCount; + + // 個数が違う場合は別物 + if(count != drawableMaskCounts) + { + continue; + } + + let sameCount = 0; + + // 同じIDを持つか確認。配列の数が同じなので、一致した個数が同じなら同じ物を持つとする + for(let j: number = 0; j < count; j++) + { + const clipId: number = clippingContext._clippingIdList[j]; + + for(let k: number = 0; k < count; k++) + { + if(drawableMasks[k] == clipId) + { + sameCount++; + break; + } + } + } + + if(sameCount == count) + { + return clippingContext; + } + } + + return null; // 見つからなかった + } + + /** + * クリッピングコンテキストを配置するレイアウト + * 一つのレンダーテクスチャを極力いっぱいに使ってマスクをレイアウトする + * マスクグループの数が4以下ならRGBA各チャンネルに一つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する。 + * + * @param usingClipCount 配置するクリッピングコンテキストの数 + */ + public setupLayoutBounds(usingClipCount: number): void + { + // ひとつのRenderTextureを極力いっぱいに使ってマスクをレイアウトする + // マスクグループの数が4以下ならRGBA各チャンネルに1つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する + + // RGBAを順番に使っていく + let div: number = usingClipCount / ColorChannelCount; // 1チャンネルに配置する基本のマスク + let mod: number = usingClipCount % ColorChannelCount; // 余り、この番号のチャンネルまでに一つずつ配分する + + // 小数点は切り捨てる + div = ~~div; + mod = ~~mod; + + // RGBAそれぞれのチャンネルを用意していく(0:R, 1:G, 2:B, 3:A) + let curClipIndex: number = 0; // 順番に設定していく + + for(let channelNo: number = 0; channelNo < ColorChannelCount; channelNo++) + { + // このチャンネルにレイアウトする数 + let layoutCount: number = div + (channelNo < mod ? 1 : 0); + + // 分割方法を決定する + if(layoutCount == 0) + { + // 何もしない + } + else if(layoutCount == 1) + { + // 全てをそのまま使う + let clipContext: CubismClippingContext = this._clippingContextListForMask.at(curClipIndex++); + clipContext._layoutChannelNo = channelNo; + clipContext._layoutBounds.x = 0.0; + clipContext._layoutBounds.y = 0.0; + clipContext._layoutBounds.width = 1.0; + clipContext._layoutBounds.height = 1.0; + } + else if(layoutCount == 2) + { + for(let i: number = 0; i < layoutCount; i++) + { + let xpos: number = i % 2; + + // 小数点は切り捨てる + xpos = ~~xpos; + + let cc: CubismClippingContext = this._clippingContextListForMask.at(curClipIndex++); + cc._layoutChannelNo = channelNo; + + cc._layoutBounds.x = xpos * 0.5; + cc._layoutBounds.y = 0.0; + cc._layoutBounds.width = 0.5; + cc._layoutBounds.height = 1.0; + // UVを2つに分解して使う + } + } + else if(layoutCount <= 4) + { + // 4分割して使う + for(let i: number = 0; i < layoutCount; i++) + { + let xpos: number = i % 2; + let ypos: number = i / 2; + + // 小数点は切り捨てる + xpos = ~~xpos; + ypos = ~~ypos; + + let cc = this._clippingContextListForMask.at(curClipIndex++); + cc._layoutChannelNo = channelNo; + + cc._layoutBounds.x = xpos * 0.5; + cc._layoutBounds.y = ypos * 0.5; + cc._layoutBounds.width = 0.5; + cc._layoutBounds.height = 0.5; + } + } + else if(layoutCount <= 9) + { + // 9分割して使う + for(let i: number = 0; i < layoutCount; i++) + { + let xpos = i % 3; + let ypos = i / 3; + + // 小数点は切り捨てる + xpos = ~~xpos; + ypos = ~~ypos; + + let cc: CubismClippingContext = this._clippingContextListForMask.at(curClipIndex++); + cc._layoutChannelNo = channelNo; + + cc._layoutBounds.x = xpos / 3.0; + cc._layoutBounds.y = ypos / 3.0; + cc._layoutBounds.width = 1.0 / 3.0; + cc._layoutBounds.height = 1.0 / 3.0; + } + } + else + { + CubismLogError("not supported mask count : {0}", layoutCount); + } + } + + } + + /** + * カラーバッファを取得する + * @return カラーバッファ + */ + public getColorBuffer(): WebGLTexture + { + return this._colorBuffer; + } + + /** + * 画面描画に使用するクリッピングマスクのリストを取得する + * @return 画面描画に使用するクリッピングマスクのリスト + */ + public getClippingContextListForDraw(): csmVector + { + return this._clippingContextListForDraw; + } + + /** + * クリッピングマスクバッファのサイズを設定する + * @param size クリッピングマスクバッファのサイズ + */ + public setClippingMaskBufferSize(size: number): void + { + this._clippingMaskBufferSize = size; + } + + /** + * クリッピングマスクバッファのサイズを取得する + * @return クリッピングマスクバッファのサイズ + */ + public getClippingMaskBufferSize(): number + { + return this._clippingMaskBufferSize; + } + + public _maskRenderTexture: WebGLFramebuffer; // マスク用レンダーテクスチャのアドレス + public _colorBuffer: WebGLTexture; // マスク用カラーバッファーのアドレス + public _currentFrameNo: number; // マスクテクスチャに与えるフレーム番号 + + public _channelColors: csmVector; + public _maskTexture: CubismRenderTextureResource; // マスク用のテクスチャリソースのリスト + public _clippingContextListForMask: csmVector; // マスク用クリッピングコンテキストのリスト + public _clippingContextListForDraw: csmVector; // 描画用クリッピングコンテキストのリスト + public _clippingMaskBufferSize: number; // クリッピングマスクのバッファサイズ(初期値:256) + + private _tmpMatrix: CubismMatrix44; // マスク計算用の行列 + private _tmpMatrixForMask: CubismMatrix44; // マスク計算用の行列 + private _tmpMatrixForDraw: CubismMatrix44; // マスク計算用の行列 + private _tmpBoundsOnModel: csmRect; // マスク配置計算用の矩形 + + gl: WebGLRenderingContext; // WebGLレンダリングコンテキスト + } + + /** + * レンダーテクスチャのリソースを定義する構造体 + * クリッピングマスクで使用する + */ + export class CubismRenderTextureResource + { + /** + * 引数付きコンストラクタ + * @param frameNo レンダラーのフレーム番号 + * @param texture テクスチャのアドレス + */ + public constructor(frameNo: number, texture: WebGLFramebuffer) + { + this.frameNo = frameNo; + this.texture = texture; + } + + public frameNo: number; // レンダラのフレーム番号 + public texture: WebGLFramebuffer; // テクスチャのアドレス + } + + /** + * クリッピングマスクのコンテキスト + */ + export class CubismClippingContext + { + /** + * 引数付きコンストラクタ + */ + public constructor(manager: CubismClippingManager_WebGL, clippingDrawableIndices: Int32Array, clipCount: number) + { + this._owner = manager; + + // クリップしている(=マスク用の)Drawableのインデックスリスト + this._clippingIdList = clippingDrawableIndices; + + // マスクの数 + this._clippingIdCount = clipCount; + + this._allClippedDrawRect = new csmRect(); + this._layoutBounds = new csmRect(); + + this._clippedDrawableIndexList = new Array(); + + this._matrixForMask = new CubismMatrix44(); + this._matrixForDraw = new CubismMatrix44(); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + if(this._layoutBounds != null) + { + this._layoutBounds = void 0; + this._layoutBounds = null; + } + + if(this._allClippedDrawRect != null) + { + this._allClippedDrawRect = void 0; + this._allClippedDrawRect = null; + } + + if(this._clippedDrawableIndexList != null) + { + this._clippedDrawableIndexList = void 0; + this._clippedDrawableIndexList = null; + } + } + + /** + * このマスクにクリップされる描画オブジェクトを追加する + * + * @param drawableIndex クリッピング対象に追加する描画オブジェクトのインデックス + */ + public addClippedDrawable(drawableIndex: number) + { + this._clippedDrawableIndexList.push(drawableIndex); + } + + /** + * このマスクを管理するマネージャのインスタンスを取得する + * @return クリッピングマネージャのインスタンス + */ + public getClippingManager(): CubismClippingManager_WebGL + { + return this._owner; + } + + public setGl(gl: WebGLRenderingContext): void + { + this._owner.setGL(gl); + } + + public _isUsing: boolean; // 現在の描画状態でマスクの準備が必要ならtrue + public readonly _clippingIdList: Int32Array; // クリッピングマスクのIDリスト + public _clippingIdCount: number; // クリッピングマスクの数 + public _layoutChannelNo: number; // RGBAのいずれのチャンネルにこのクリップを配置するか(0:R, 1:G, 2:B, 3:A) + public _layoutBounds: csmRect; // マスク用チャンネルのどの領域にマスクを入れるか(View座標-1~1, UVは0~1に直す) + public _allClippedDrawRect: csmRect; // このクリッピングで、クリッピングされるすべての描画オブジェクトの囲み矩形(毎回更新) + public _matrixForMask: CubismMatrix44; // マスクの位置計算結果を保持する行列 + public _matrixForDraw: CubismMatrix44; // 描画オブジェクトの位置計算結果を保持する行列 + public _clippedDrawableIndexList: number[]; // このマスクにクリップされる描画オブジェクトのリスト + + private _owner: CubismClippingManager_WebGL; // このマスクを管理しているマネージャのインスタンス + } + + /** + * WebGL用のシェーダープログラムを生成・破棄するクラス + * シングルトンなクラスであり、CubismShader_WebGL.getInstanceからアクセスする。 + */ + export class CubismShader_WebGL + { + /** + * インスタンスを取得する(シングルトン) + * @return インスタンス + */ + public static getInstance(): CubismShader_WebGL + { + if(s_instance == null) + { + s_instance = new CubismShader_WebGL(); + + return s_instance; + } + return s_instance; + } + + /** + * インスタンスを開放する(シングルトン) + */ + public static deleteInstance(): void + { + if(s_instance) + { + s_instance.release(); + s_instance = void 0; + s_instance = null; + } + } + + /** + * privateなコンストラクタ + */ + private constructor() + { + this._shaderSets = new csmVector(); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + this.releaseShaderProgram(); + } + + /** + * シェーダープログラムの一連のセットアップを実行する + * @param renderer レンダラのインスタンス + * @param textureId GPUのテクスチャID + * @param vertexCount ポリゴンメッシュの頂点数 + * @param vertexArray ポリゴンメッシュの頂点配列 + * @param indexArray インデックスバッファの頂点配列 + * @param uvArray uv配列 + * @param opacity 不透明度 + * @param colorBlendMode カラーブレンディングのタイプ + * @param baseColor ベースカラー + * @param isPremultipliedAlpha 乗算済みアルファかどうか + * @param matrix4x4 Model-View-Projection行列 + */ + public setupShaderProgram(renderer: CubismRenderer_WebGL, + textureId: WebGLTexture, + vertexCount: number, + vertexArray: Float32Array, + indexArray: Uint16Array, + uvArray: Float32Array, + opacity: number, + colorBlendMode: CubismRenderer.CubismBlendMode, + baseColor: CubismRenderer.CubismTextureColor, + isPremultipliedAlpha: boolean, + matrix4x4: CubismMatrix44): void + { + if(this._shaderSets.getSize() == 0) + { + this.generateShaders(); + } + + let vertexBuffer = null; + let uvBuffer = null; + let indexBuffer = null; + + // Blending + let SRC_COLOR: number; + let DST_COLOR: number; + let SRC_ALPHA: number; + let DST_ALPHA: number; + + if(renderer.getClippingContextBufferForMask() != null) // マスク生成時 + { + let shaderSet: CubismShader_WebGL.CubismShaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_SetupMask); + this.gl.useProgram(shaderSet.shaderProgram); + + // テクスチャ設定 + this.gl.activeTexture(this.gl.TEXTURE0); + this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); + this.gl.uniform1i(shaderSet.samplerTexture0Location, 0); + + // 頂点配列の設定(VBO) + if(vertexBuffer == null) + { + vertexBuffer = this.gl.createBuffer(); + } + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer); + this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); + this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); + this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); + + // テクスチャ頂点の設定 + if(uvBuffer == null) + { + uvBuffer = this.gl.createBuffer(); + } + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer); + this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); + this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); + this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); + + // チャンネル + const channelNo: number = renderer.getClippingContextBufferForMask()._layoutChannelNo; + let colorChannel: CubismRenderer.CubismTextureColor = renderer.getClippingContextBufferForMask().getClippingManager().getChannelFlagAsColor(channelNo); + this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); + + this.gl.uniformMatrix4fv(shaderSet.uniformClipMatrixLocation, false, renderer.getClippingContextBufferForMask()._matrixForMask.getArray()); + + let rect: csmRect = renderer.getClippingContextBufferForMask()._layoutBounds; + + this.gl.uniform4f( + shaderSet.uniformBaseColorLocation, + rect.x * 2.0 - 1.0, + rect.y * 2.0 - 1.0, + rect.getRight() * 2.0 - 1.0, + rect.getBottom() * 2.0 - 1.0 + ); + + SRC_COLOR = this.gl.ZERO; + DST_COLOR = this.gl.ONE_MINUS_SRC_COLOR; + SRC_ALPHA = this.gl.ZERO; + DST_ALPHA = this.gl.ONE_MINUS_SRC_ALPHA; + } + else // マスク生成以外の場合 + { + const masked: boolean = renderer.getClippingContextBufferForDraw() != null; // この描画オブジェクトはマスク対象か + const offset: number = (masked ? 1 : 0) + (isPremultipliedAlpha ? 2 : 0); + + let shaderSet: CubismShader_WebGL.CubismShaderSet = new CubismShader_WebGL.CubismShaderSet(); + + switch(colorBlendMode) + { + case CubismRenderer.CubismBlendMode.CubismBlendMode_Normal: + default: + shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Normal + offset); + SRC_COLOR = this.gl.ONE; + DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; + SRC_ALPHA = this.gl.ONE; + DST_ALPHA = this.gl.ONE_MINUS_SRC_ALPHA; + break; + + case CubismRenderer.CubismBlendMode.CubismBlendMode_Additive: + shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Add + offset); + SRC_COLOR = this.gl.ONE; + DST_COLOR = this.gl.ONE; + SRC_ALPHA = this.gl.ZERO; + DST_ALPHA = this.gl.ONE; + break; + + case CubismRenderer.CubismBlendMode.CubismBlendMode_Multiplicative: + shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Mult + offset); + SRC_COLOR = this.gl.DST_COLOR; + DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; + SRC_ALPHA = this.gl.ZERO; + DST_ALPHA = this.gl.ONE; + break; + } + + this.gl.useProgram(shaderSet.shaderProgram); + + // 頂点配列の設定 + if(vertexBuffer == null) + { + vertexBuffer = this.gl.createBuffer(); + } + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer); + this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); + this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); + this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); + + // テクスチャ頂点の設定 + if(uvBuffer == null) + { + uvBuffer = this.gl.createBuffer(); + } + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer); + this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); + this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); + this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); + + if(masked) + { + this.gl.activeTexture(this.gl.TEXTURE1); + let tex: WebGLTexture = renderer.getClippingContextBufferForDraw().getClippingManager().getColorBuffer(); + this.gl.bindTexture(this.gl.TEXTURE_2D, tex); + this.gl.uniform1i(shaderSet.samplerTexture1Location, 1); + + // view座標をClippingContextの座標に変換するための行列を設定 + this.gl.uniformMatrix4fv(shaderSet.uniformClipMatrixLocation, false,renderer.getClippingContextBufferForDraw()._matrixForDraw.getArray()); + + // 使用するカラーチャンネルを設定 + const channelNo: number = renderer.getClippingContextBufferForDraw()._layoutChannelNo; + let colorChannel: CubismRenderer.CubismTextureColor = renderer.getClippingContextBufferForDraw().getClippingManager().getChannelFlagAsColor(channelNo); + this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); + } + + // テクスチャ設定 + this.gl.activeTexture(this.gl.TEXTURE0); + this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); + this.gl.uniform1i(shaderSet.samplerTexture0Location, 0); + + // 座標変換 + this.gl.uniformMatrix4fv(shaderSet.uniformMatrixLocation, false, matrix4x4.getArray()); + + this.gl.uniform4f(shaderSet.uniformBaseColorLocation, baseColor.R, baseColor.G, baseColor.B, baseColor.A); + } + + // IBOを作成し、データを転送(OpenGLにはなかったが、これがないとdrawElenmentが使用できない) + if(indexBuffer == null) + { + indexBuffer = this.gl.createBuffer(); + } + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, indexArray, this.gl.DYNAMIC_DRAW); + this.gl.blendFuncSeparate(SRC_COLOR, DST_COLOR, SRC_ALPHA, DST_ALPHA); + } + + /** + * シェーダープログラムを解放する + */ + public releaseShaderProgram(): void + { + for(let i: number = 0; i < this._shaderSets.getSize(); i++) + { + this.gl.deleteProgram(this._shaderSets.at(i).shaderProgram); + this._shaderSets.at(i).shaderProgram = 0; + this._shaderSets.set(i, void 0); + this._shaderSets.set(i, null); + } + } + + /** + * シェーダープログラムを初期化する + * @param vertShaderSrc 頂点シェーダのソース + * @param fragShaderSrc フラグメントシェーダのソース + */ + public generateShaders(): void + { + for(let i: number = 0; i < shaderCount; i++) + { + this._shaderSets.pushBack(new CubismShader_WebGL.CubismShaderSet()); + } + + this._shaderSets.at(0).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcSetupMask, CubismShader_WebGL.fragmentShaderSrcsetupMask); + + this._shaderSets.at(1).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrc, CubismShader_WebGL.fragmentShaderSrc); + this._shaderSets.at(2).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcMasked, CubismShader_WebGL.fragmentShaderSrcMask); + this._shaderSets.at(3).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrc, CubismShader_WebGL.fragmentShaderSrcPremultipliedAlpha); + this._shaderSets.at(4).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcMasked, CubismShader_WebGL.fragmentShaderSrcMaskPremultipliedAlpha); + + // 加算も通常と同じシェーダーを利用する + this._shaderSets.at(5).shaderProgram = this._shaderSets.at(1).shaderProgram; + this._shaderSets.at(6).shaderProgram = this._shaderSets.at(2).shaderProgram; + this._shaderSets.at(7).shaderProgram = this._shaderSets.at(3).shaderProgram; + this._shaderSets.at(8).shaderProgram = this._shaderSets.at(4).shaderProgram; + + // 乗算も通常と同じシェーダーを利用する + this._shaderSets.at(9).shaderProgram = this._shaderSets.at(1).shaderProgram; + this._shaderSets.at(10).shaderProgram = this._shaderSets.at(2).shaderProgram; + this._shaderSets.at(11).shaderProgram = this._shaderSets.at(3).shaderProgram; + this._shaderSets.at(12).shaderProgram = this._shaderSets.at(4).shaderProgram; + + // SetupMask + this._shaderSets.at(0).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(0).shaderProgram, "a_position"); + this._shaderSets.at(0).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(0).shaderProgram, "a_texCoord"); + this._shaderSets.at(0).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "s_texture0"); + this._shaderSets.at(0).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_clipMatrix"); + this._shaderSets.at(0).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_channelFlag"); + this._shaderSets.at(0).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_baseColor"); + + // 通常 + this._shaderSets.at(1).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(1).shaderProgram, "a_position"); + this._shaderSets.at(1).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(1).shaderProgram, "a_texCoord"); + this._shaderSets.at(1).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "s_texture0"); + this._shaderSets.at(1).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "u_matrix"); + this._shaderSets.at(1).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "u_baseColor"); + + // 通常(クリッピング) + this._shaderSets.at(2).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(2).shaderProgram, "a_position"); + this._shaderSets.at(2).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(2).shaderProgram, "a_texCoord"); + this._shaderSets.at(2).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "s_texture0"); + this._shaderSets.at(2).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "s_texture1"); + this._shaderSets.at(2).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_matrix"); + this._shaderSets.at(2).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_clipMatrix"); + this._shaderSets.at(2).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_channelFlag"); + this._shaderSets.at(2).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_baseColor"); + + // 通常(PremultipliedAlpha) + this._shaderSets.at(3).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(3).shaderProgram, "a_position"); + this._shaderSets.at(3).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(3).shaderProgram, "a_texCoord"); + this._shaderSets.at(3).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "s_texture0"); + this._shaderSets.at(3).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "u_matrix"); + this._shaderSets.at(3).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "u_baseColor"); + + // 通常(クリッピング、PremultipliedAlpha) + this._shaderSets.at(4).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(4).shaderProgram, "a_position"); + this._shaderSets.at(4).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(4).shaderProgram, "a_texCoord"); + this._shaderSets.at(4).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "s_texture0"); + this._shaderSets.at(4).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "s_texture1"); + this._shaderSets.at(4).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_matrix"); + this._shaderSets.at(4).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_clipMatrix"); + this._shaderSets.at(4).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_channelFlag"); + this._shaderSets.at(4).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_baseColor"); + + // 加算 + this._shaderSets.at(5).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(5).shaderProgram, "a_position"); + this._shaderSets.at(5).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(5).shaderProgram, "a_texCoord"); + this._shaderSets.at(5).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "s_texture0"); + this._shaderSets.at(5).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "u_matrix"); + this._shaderSets.at(5).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "u_baseColor"); + // 加算(クリッピング) + this._shaderSets.at(6).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(6).shaderProgram, "a_position"); + this._shaderSets.at(6).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(6).shaderProgram, "a_texCoord"); + this._shaderSets.at(6).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "s_texture0"); + this._shaderSets.at(6).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "s_texture1"); + this._shaderSets.at(6).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_matrix"); + this._shaderSets.at(6).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_clipMatrix"); + this._shaderSets.at(6).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_channelFlag"); + this._shaderSets.at(6).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_baseColor"); + + // 加算(PremultipliedAlpha) + this._shaderSets.at(7).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(7).shaderProgram, "a_position"); + this._shaderSets.at(7).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(7).shaderProgram, "a_texCoord"); + this._shaderSets.at(7).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "s_texture0"); + this._shaderSets.at(7).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "u_matrix"); + this._shaderSets.at(7).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "u_baseColor"); + + // 加算(クリッピング、PremultipliedAlpha) + this._shaderSets.at(8).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(8).shaderProgram, "a_position"); + this._shaderSets.at(8).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(8).shaderProgram, "a_texCoord"); + this._shaderSets.at(8).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "s_texture0"); + this._shaderSets.at(8).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "s_texture1"); + this._shaderSets.at(8).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_matrix"); + this._shaderSets.at(8).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_clipMatrix"); + this._shaderSets.at(8).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_channelFlag"); + this._shaderSets.at(8).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_baseColor"); + + // 乗算 + this._shaderSets.at(9).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(9).shaderProgram, "a_position"); + this._shaderSets.at(9).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(9).shaderProgram, "a_texCoord"); + this._shaderSets.at(9).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "s_texture0"); + this._shaderSets.at(9).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "u_matrix"); + this._shaderSets.at(9).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "u_baseColor"); + + // 乗算(クリッピング) + this._shaderSets.at(10).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(10).shaderProgram, "a_position"); + this._shaderSets.at(10).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(10).shaderProgram, "a_texCoord"); + this._shaderSets.at(10).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "s_texture0"); + this._shaderSets.at(10).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "s_texture1"); + this._shaderSets.at(10).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_matrix"); + this._shaderSets.at(10).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_clipMatrix"); + this._shaderSets.at(10).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_channelFlag"); + this._shaderSets.at(10).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_baseColor"); + + // 乗算(PremultipliedAlpha) + this._shaderSets.at(11).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(11).shaderProgram, "a_position"); + this._shaderSets.at(11).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(11).shaderProgram, "a_texCoord"); + this._shaderSets.at(11).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "s_texture0"); + this._shaderSets.at(11).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "u_matrix"); + this._shaderSets.at(11).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "u_baseColor"); + + // 乗算(クリッピング、PremultipliedAlpha) + this._shaderSets.at(12).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(12).shaderProgram, "a_position"); + this._shaderSets.at(12).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(12).shaderProgram, "a_texCoord"); + this._shaderSets.at(12).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "s_texture0"); + this._shaderSets.at(12).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "s_texture1"); + this._shaderSets.at(12).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_matrix"); + this._shaderSets.at(12).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_clipMatrix"); + this._shaderSets.at(12).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_channelFlag"); + this._shaderSets.at(12).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_baseColor"); + } + + /** + * シェーダプログラムをロードしてアドレスを返す + * @param vertexShaderSource 頂点シェーダのソース + * @param fragmentShaderSource フラグメントシェーダのソース + * @return シェーダプログラムのアドレス + */ + public loadShaderProgram(vertexShaderSource: string, fragmentShaderSource: string): WebGLProgram + { + // Create Shader Program + let shaderProgram: WebGLProgram = this.gl.createProgram(); + + let vertShader = this.compileShaderSource(this.gl.VERTEX_SHADER, vertexShaderSource); + + if(!vertShader) + { + CubismLogError("Vertex shader compile error!"); + return 0; + } + + let fragShader = this.compileShaderSource(this.gl.FRAGMENT_SHADER, fragmentShaderSource); + if(!fragShader) + { + CubismLogError("Vertex shader compile error!"); + return 0; + } + + // Attach vertex shader to program + this.gl.attachShader(shaderProgram, vertShader); + + // Attach fragment shader to program + this.gl.attachShader(shaderProgram, fragShader); + + // link program + this.gl.linkProgram(shaderProgram) + let linkStatus = this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS); + + // リンクに失敗したらシェーダーを削除 + if(!linkStatus) + { + CubismLogError("Failed to link program: {0}", shaderProgram); + + this.gl.deleteShader(vertShader); + vertShader = 0; + + this.gl.deleteShader(fragShader); + fragShader = 0; + + if(shaderProgram) + { + this.gl.deleteProgram(shaderProgram); + shaderProgram = 0; + } + + return 0; + } + + // Release vertex and fragment shaders. + this.gl.detachShader(shaderProgram, vertShader); + this.gl.deleteShader(vertShader); + + this.gl.detachShader(shaderProgram, fragShader); + this.gl.deleteShader(fragShader); + + return shaderProgram; + } + + /** + * シェーダープログラムをコンパイルする + * @param shaderType シェーダタイプ(Vertex/Fragment) + * @param shaderSource シェーダソースコード + * + * @return コンパイルされたシェーダープログラム + */ + public compileShaderSource(shaderType: GLenum, shaderSource: string): WebGLProgram + { + const source: string = shaderSource; + + let shader: WebGLProgram = this.gl.createShader(shaderType); + this.gl.shaderSource(shader, source); + this.gl.compileShader(shader); + + if(!shader) + { + let log: string = this.gl.getShaderInfoLog(shader); + CubismLogError("Shader compile log: {0} ", log); + } + + let status: any = this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS); + if(!status) + { + this.gl.deleteShader(shader); + return null; + } + + return shader; + } + + public setGl(gl: WebGLRenderingContext): void + { + this.gl = gl; + } + + _shaderSets: csmVector; // ロードしたシェーダープログラムを保持する変数 + gl: WebGLRenderingContext; // webglコンテキスト + } + + /** + * CubismShader_WebGLのインナークラス + */ + export namespace CubismShader_WebGL + { + export class CubismShaderSet + { + shaderProgram: WebGLProgram; // シェーダープログラムのアドレス + attributePositionLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(Position) + attributeTexCoordLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(TexCoord) + uniformMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Matrix) + uniformClipMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ClipMatrix) + samplerTexture0Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture0) + samplerTexture1Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture1) + uniformBaseColorLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(BaseColor) + uniformChannelFlagLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ChannelFlag) + } + + export enum ShaderNames + { + // SetupMask + ShaderNames_SetupMask, + + // Normal + ShaderNames_Normal, + ShaderNames_NormalMasked, + ShaderNames_NormalPremultipliedAlpha, + ShaderNames_NormalMaskedPremultipliedAlpha, + + // Add + ShaderNames_Add, + ShaderNames_AddMasked, + ShaderNames_AddPremultipliedAlpha, + ShaderNames_AddMaskedPremultipledAlpha, + + // Mult + ShaderNames_Mult, + ShaderNames_MultMasked, + ShaderNames_MultPremultipliedAlpha, + ShaderNames_MultMaskedPremultipliedAlpha, + }; + + export const vertexShaderSrcSetupMask = + "attribute vec4 a_position;" + + "attribute vec2 a_texCoord;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_myPos;" + + "uniform mat4 u_clipMatrix;" + + "void main()" + + "{" + + " gl_Position = u_clipMatrix * a_position;" + + " v_myPos = u_clipMatrix * a_position;" + + " v_texCoord = a_texCoord;" + + " v_texCoord.y = 1.0 - v_texCoord.y;" + + "}"; + export const fragmentShaderSrcsetupMask = + "precision mediump float;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_myPos;" + + "uniform sampler2D s_texture0;" + + "uniform vec4 u_channelFlag;" + + "uniform vec4 u_baseColor;" + + "void main()" + + "{" + + " float isInside = " + + " step(u_baseColor.x, v_myPos.x/v_myPos.w)" + + " * step(u_baseColor.y, v_myPos.y/v_myPos.w)" + + " * step(v_myPos.x/v_myPos.w, u_baseColor.z)" + + " * step(v_myPos.y/v_myPos.w, u_baseColor.w);" + + " gl_FragColor = u_channelFlag * texture2D(s_texture0, v_texCoord).a * isInside;" + + "}"; + + //----- バーテックスシェーダプログラム ----- + // Normal & Add & Mult 共通 + export const vertexShaderSrc = + "attribute vec4 a_position;" + //v.vertex + "attribute vec2 a_texCoord;" + //v.texcoord + "varying vec2 v_texCoord;" + //v2f.texcoord + "uniform mat4 u_matrix;" + + "void main()" + + "{" + + " gl_Position = u_matrix * a_position;" + + " v_texCoord = a_texCoord;" + + " v_texCoord.y = 1.0 - v_texCoord.y;" + + "}"; + + // Normal & Add & Mult 共通(クリッピングされたものの描画用) + export const vertexShaderSrcMasked = + "attribute vec4 a_position;" + + "attribute vec2 a_texCoord;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_clipPos;" + + "uniform mat4 u_matrix;" + + "uniform mat4 u_clipMatrix;" + + "void main()" + + "{" + + " gl_Position = u_matrix * a_position;" + + " v_clipPos = u_clipMatrix * a_position;" + + " v_texCoord = a_texCoord;" + + " v_texCoord.y = 1.0 - v_texCoord.y;" + + "}"; + + //----- フラグメントシェーダプログラム ----- + // Normal & Add & Mult 共通 + export const fragmentShaderSrc = + "precision mediump float;" + + "varying vec2 v_texCoord;" + //v2f.texcoord + "uniform sampler2D s_texture0;" + //_MainTex + "uniform vec4 u_baseColor;" + //v2f.color + "void main()" + + "{" + + " vec4 color = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + + " gl_FragColor = vec4(color.rgb * color.a, color.a);" + + "}"; + + // Normal & Add & Mult 共通 (PremultipliedAlpha) + export const fragmentShaderSrcPremultipliedAlpha = + "precision mediump float;" + + "varying vec2 v_texCoord;" + //v2f.texcoord + "uniform sampler2D s_texture0;" + //_MainTex + "uniform vec4 u_baseColor;" + //v2f.color + "void main()" + + "{" + + " gl_FragColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + + "}"; + + // Normal & Add & Mult 共通(クリッピングされたものの描画用) + export const fragmentShaderSrcMask = + "precision mediump float;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_clipPos;" + + "uniform sampler2D s_texture0;" + + "uniform sampler2D s_texture1;" + + "uniform vec4 u_channelFlag;" + + "uniform vec4 u_baseColor;" + + "void main()" + + "{" + + " vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + + " col_formask.rgb = col_formask.rgb * col_formask.a ;" + + " vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" + + " float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" + + " col_formask = col_formask * maskVal;" + + " gl_FragColor = col_formask;" + + "}"; + + // Normal (クリッピングされたものの描画用、PremultipliedAlpha兼用) + export const fragmentShaderSrcMaskPremultipliedAlpha = + "precision mediump float;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_clipPos;" + + "uniform sampler2D s_texture0;" + + "uniform sampler2D s_texture1;" + + "uniform vec4 u_channelFlag;" + + "uniform vec4 u_baseColor;" + + "void main()" + + "{" + + " vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + + " vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" + + " float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" + + " col_formask = col_formask * maskVal;" + + " gl_FragColor = col_formask;" + + "}"; + + //テクスチャを使わないデバッグ用の表示 + export const vertexShaderSrcDebug = + "varying lowp vec4 colorVarying;" + + "void main()" + + "{" + + " gl_Position = a_position;vec4 diffuseColor = vec4(0.0, 0.0 , 1.0, 0.5);" + + " colorVarying = diffuseColor ;" + + "}"; + + export const fragmentShaderSrcDebug = + "precision mediump float;" + + "varying lowp vec4 colorVarying;" + + "void main()" + + "{" + + " gl_FragColor = colorVarying;" + + "}"; + } + + /** + * Cubismモデルを描画する直前のWebGLのステートを保持・復帰させるクラス + */ + export class CubismRendererProfile_WebGL + { + + /** + * コンストラクタ + */ + public constructor() + { + this._lastVertexAttribArrayEnabled = new Array(4); + this._lastColorMask = new Array(4); + this._lastBlending = new Array(4); + } + + /** + * WebGLのステートを保持する + */ + public save(): void + { + //-- push state -- + this._lastArrayBufferBinding = this.gl.getParameter(this.gl.ARRAY_BUFFER_BINDING); + this._lastElementArrayBufferBinding = this.gl.getParameter(this.gl.ELEMENT_ARRAY_BUFFER_BINDING); + this._lastProgram = this.gl.getParameter(this.gl.CURRENT_PROGRAM); + + this._lastActiveTexture = this.gl.getParameter(this.gl.ACTIVE_TEXTURE); + this.gl.activeTexture(this.gl.TEXTURE1); // テクスチャユニット1をアクティブに(以降の設定対象とする) + this._lastTexture1Binding2D = this.gl.getParameter(this.gl.TEXTURE_BINDING_2D); + + this.gl.activeTexture(this.gl.TEXTURE0); // テクスチャユニット0をアクティブに(以降の設定対象とする) + this._lastTexture0Binding2D = this.gl.getParameter(this.gl.TEXTURE_BINDING_2D); + + this._lastVertexAttribArrayEnabled[0] = this.gl.getVertexAttrib(0, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); + this._lastVertexAttribArrayEnabled[1] = this.gl.getVertexAttrib(1, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); + this._lastVertexAttribArrayEnabled[2] = this.gl.getVertexAttrib(2, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); + this._lastVertexAttribArrayEnabled[3] = this.gl.getVertexAttrib(3, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); + + this._lastScissorTest = this.gl.isEnabled(this.gl.SCISSOR_TEST); + this._lastStencilTest = this.gl.isEnabled(this.gl.STENCIL_TEST); + this._lastDepthTest = this.gl.isEnabled(this.gl.DEPTH_TEST); + this._lastCullFace = this.gl.isEnabled(this.gl.CULL_FACE); + this._lastBlend = this.gl.isEnabled(this.gl.BLEND); + + this._lastFrontFace = this.gl.getParameter(this.gl.FRONT_FACE); + + this._lastColorMask = this.gl.getParameter(this.gl.COLOR_WRITEMASK); + + // backup blending + this._lastBlending[0] = this.gl.getParameter(this.gl.BLEND_SRC_RGB); + this._lastBlending[1] = this.gl.getParameter(this.gl.BLEND_DST_RGB); + this._lastBlending[2] = this.gl.getParameter(this.gl.BLEND_SRC_ALPHA); + this._lastBlending[3] = this.gl.getParameter(this.gl.BLEND_DST_ALPHA); + } + + /** + * 保持したWebGLのステートを復帰させる + */ + public restore(): void + { + this.gl.useProgram(this._lastProgram); + + this.setGLEnableVertexAttribArray(0, this._lastVertexAttribArrayEnabled[0]); + this.setGLEnableVertexAttribArray(1, this._lastVertexAttribArrayEnabled[1]); + this.setGLEnableVertexAttribArray(2, this._lastVertexAttribArrayEnabled[2]); + this.setGLEnableVertexAttribArray(3, this._lastVertexAttribArrayEnabled[3]); + + this.setGLEnable(this.gl.SCISSOR_TEST, this._lastScissorTest); + this.setGLEnable(this.gl.STENCIL_TEST, this._lastStencilTest); + this.setGLEnable(this.gl.DEPTH_TEST, this._lastDepthTest); + this.setGLEnable(this.gl.CULL_FACE, this._lastCullFace); + this.setGLEnable(this.gl.BLEND, this._lastBlend); + + this.gl.frontFace(this._lastFrontFace); + + this.gl.colorMask(this._lastColorMask[0], this._lastColorMask[1], this._lastColorMask[2], this._lastColorMask[3]); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._lastArrayBufferBinding); // 前にバッファがバインドされていたら破棄する必要がある + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._lastElementArrayBufferBinding); + + this.gl.activeTexture(this.gl.TEXTURE1); // テクスチャユニット1を復元 + this.gl.bindTexture(this.gl.TEXTURE_2D, this._lastTexture1Binding2D); + + this.gl.activeTexture(this.gl.TEXTURE0); // テクスチャユニット0を復元 + this.gl.bindTexture(this.gl.TEXTURE_2D, this._lastTexture0Binding2D); + + this.gl.activeTexture(this._lastActiveTexture); + + // restore blending + this.gl.blendFuncSeparate(this._lastBlending[0], this._lastBlending[1], this._lastBlending[2], this._lastBlending[3]); + } + + /** + * WebGLの機能の有効・無効をセットする + * @param index 有効・無効にする機能 + * @param enabled trueなら有効にする + */ + private setGLEnable(index: GLenum, enabled: GLboolean): void + { + if(enabled == true) + { + this.gl.enable(index); + } + else + { + this.gl.disable(index); + } + } + + /** + * WebGLのVertex Attribute Array機能の有効・無効をセットする + * + * @param index 有効・無効にする機能 + * @param enabled trueなら有効にする + */ + private setGLEnableVertexAttribArray(index: GLuint, enabled: GLint): void + { + if(enabled) + { + this.gl.enableVertexAttribArray(index); + } + else + { + this.gl.disableVertexAttribArray(index); + } + } + + /** + * glの設定 + */ + public setGl(gl: WebGLRenderingContext): void + { + this.gl = gl; + } + + _lastArrayBufferBinding: GLint; // モデル描画直前の頂点バッファ + _lastElementArrayBufferBinding: GLint; // モデル描画直前のElementバッファ + _lastProgram: GLint; // モデル描画直前のシェーダプログラムバッファ + _lastActiveTexture: GLint; // モデル描画直前のアクティブなテクスチャ + _lastTexture0Binding2D: GLint; // モデル描画直前のテクスチャユニット0 + _lastTexture1Binding2D: GLint; // モデル描画直前のテクスチャユニット1 + _lastVertexAttribArrayEnabled: GLint[]; // モデル描画直前のGL_VERTEX_ATTRIB_ARRAY_ENABLEDパラメータ + _lastScissorTest: GLboolean; // モデル描画直前のGL_SCISSOR_TESTパラメータ + _lastBlend: GLboolean; // モデル描画直前のGL_BLENDパラメータ + _lastStencilTest: GLboolean; // モデル描画直前のGL_STENCIL_TESTパラメータ + _lastDepthTest: GLboolean; // モデル描画直前のGL_DEPTH_TESTパラメータ + _lastCullFace: GLboolean; // モデル描画直前のGL_CULL_FACEパラメータ + _lastFrontFace: GLint; // モデル描画直前のGL_FRONT_FACEパラメータ + _lastColorMask: GLboolean[]; // モデル描画直前のCOLOR_WRITEMASKパラメータ + _lastBlending: GLint[]; // モデル描画直前のカラーブレンディングパラメータ + + gl: WebGLRenderingContext; + } + + /** + * WebGL用の描画命令を実装したクラス + */ + export class CubismRenderer_WebGL extends CubismRenderer + { + /** + * レンダラの初期化処理を実行する + * 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる + * + * @param model モデルのインスタンス + */ + public initialize(model: CubismModel): void + { + if(model.isUsingMasking()) + { + this._clippingManager = new CubismClippingManager_WebGL(); // クリッピングマスク・バッファ前処理方式を初期化 + this._clippingManager.initialize( + model, + model.getDrawableCount(), + model.getDrawableMasks(), + model.getDrawableMaskCounts() + ); + } + + this._sortedDrawableIndexList.resize(model.getDrawableCount(), 0); + + super.initialize(model); // 親クラスの処理を呼ぶ + } + + /** + * WebGLテクスチャのバインド処理 + * CubismRendererにテクスチャを設定し、CubismRenderer内でその画像を参照するためのIndex値を戻り値とする + * @param modelTextureNo セットするモデルテクスチャの番号 + * @param glTextureNo WebGLテクスチャの番号 + */ + public bindTexture(modelTextureNo: number, glTexture: WebGLTexture): void + { + this._textures.setValue(modelTextureNo, glTexture); + } + + /** + * WebGLにバインドされたテクスチャのリストを取得する + * @return テクスチャのリスト + */ + public getBindedTextures(): csmMap + { + return this._textures; + } + + /** + * クリッピングマスクバッファのサイズを設定する + * マスク用のFrameBufferを破棄、再作成する為処理コストは高い + * @param size クリッピングマスクバッファのサイズ + */ + public setClippingMaskBufferSize(size: number) + { + // FrameBufferのサイズを変更するためにインスタンスを破棄・再作成する + this._clippingManager.release(); + this._clippingManager = void 0; + this._clippingManager = null; + + this._clippingManager = new CubismClippingManager_WebGL(); + + this._clippingManager.setClippingMaskBufferSize(size); + + this._clippingManager.initialize( + this.getModel(), + this.getModel().getDrawableCount(), + this.getModel().getDrawableMasks(), + this.getModel().getDrawableMaskCounts() + ); + } + + /** + * クリッピングマスクバッファのサイズを取得する + * @return クリッピングマスクバッファのサイズ + */ + public getClippingMaskBufferSize(): number + { + return this._clippingManager.getClippingMaskBufferSize(); + } + + /** + * コンストラクタ + */ + public constructor() + { + super(); + this._clippingContextBufferForMask = null; + this._clippingContextBufferForDraw = null; + this._clippingManager = new CubismClippingManager_WebGL(); + this.firstDraw = true; + this._rendererProfile = new CubismRendererProfile_WebGL(); + this._textures = new csmMap(); + this._sortedDrawableIndexList = new csmVector(); + + // テクスチャ対応マップの容量を確保しておく + this._textures.prepareCapacity(32, true); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + this._clippingManager.release(); + this._clippingManager = void 0; + this._clippingManager = null; + } + + /** + * モデルを描画する実際の処理 + */ + public doDrawModel(): void + { + //------------ クリッピングマスク・バッファ前処理方式の場合 ------------ + if(this._clippingManager != null) + { + this.preDraw(); + this._clippingManager.setupClippingContext(this.getModel(), this); + } + + // 上記クリッピング処理内でも一度PreDrawを呼ぶので注意!! + this.preDraw(); + + const drawableCount: number = this.getModel().getDrawableCount(); + const renderOrder: Int32Array = this.getModel().getDrawableRenderOrders(); + + // インデックスを描画順でソート + for(let i: number = 0; i < drawableCount; ++i) + { + const order: number = renderOrder[i]; + this._sortedDrawableIndexList.set(order, i); + } + + // 描画 + for(let i: number = 0; i < drawableCount; ++i) + { + const drawableIndex: number = this._sortedDrawableIndexList.at(i); + + // Drawableが表示状態でなければ処理をパスする + if(!this.getModel().getDrawableDynamicFlagIsVisible(drawableIndex)) + { + continue; + } + + // クリッピングマスクをセットする + this.setClippingContextBufferForDraw( + (this._clippingManager != null) + ? (this._clippingManager.getClippingContextListForDraw()).at(drawableIndex) + : null + ); + + this.setIsCulling(this.getModel().getDrawableCulling(drawableIndex)); + + this.drawMesh( + this.getModel().getDrawableTextureIndices(drawableIndex), + this.getModel().getDrawableVertexIndexCount(drawableIndex), + this.getModel().getDrawableVertexCount(drawableIndex), + this.getModel().getDrawableVertexIndices(drawableIndex), + this.getModel().getDrawableVertices(drawableIndex), + this.getModel().getDrawableVertexUvs(drawableIndex), + this.getModel().getDrawableOpacity(drawableIndex), + this.getModel().getDrawableBlendMode(drawableIndex) + ); + } + } + + /** + * [オーバーライド] + * 描画オブジェクト(アートメッシュ)を描画する。 + * ポリゴンメッシュとテクスチャ番号をセットで渡す。 + * @param textureNo 描画するテクスチャ番号 + * @param indexCount 描画オブジェクトのインデックス値 + * @param vertexCount ポリゴンメッシュの頂点数 + * @param indexArray ポリゴンメッシュのインデックス配列 + * @param vertexArray ポリゴンメッシュの頂点配列 + * @param uvArray uv配列 + * @param opacity 不透明度 + * @param colorBlendMode カラー合成タイプ + */ + public drawMesh(textureNo: number, indexCount: number, vertexCount: number, + indexArray: Uint16Array, vertexArray: Float32Array, uvArray: Float32Array, + opacity: number, colorBlendMode: CubismRenderer.CubismBlendMode): void + { + // 裏面描画の有効・無効 + if(this.isCulling()) + { + this.gl.enable(this.gl.CULL_FACE); + } + else + { + this.gl.disable(this.gl.CULL_FACE); + } + + this.gl.frontFace(this.gl.CCW); // Cubism3 OpenGLはマスク・アートメッシュ共にCCWが表面 + + let modelColorRGBA: CubismRenderer.CubismTextureColor = this.getModelColor(); + + if(this.getClippingContextBufferForMask() == null) // マスク生成時以外 + { + modelColorRGBA.A *= opacity; + if(this.isPremultipliedAlpha()) + { + modelColorRGBA.R *= modelColorRGBA.A; + modelColorRGBA.G *= modelColorRGBA.A; + modelColorRGBA.B *= modelColorRGBA.A; + } + } + + let drawtexture: WebGLTexture; // シェーダに渡すテクスチャ + + // テクスチャマップからバインド済みテクスチャIDを取得 + // バインドされていなければダミーのテクスチャIDをセットする + if(this._textures.getValue(textureNo) != null) + { + drawtexture = this._textures.getValue(textureNo); + } + else + { + drawtexture = null; + } + + CubismShader_WebGL.getInstance().setupShaderProgram( + this, drawtexture, vertexCount, vertexArray, indexArray, uvArray, + opacity, colorBlendMode, modelColorRGBA, this.isPremultipliedAlpha(), + this.getMvpMatrix() + ); + + // ポリゴンメッシュを描画する + this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_SHORT, 0); + + // 後処理 + this.gl.useProgram(null); + this.setClippingContextBufferForDraw(null); + this.setClippingContextBufferForMask(null); + } + + /** + * レンダラが保持する静的なリソースを解放する + * WebGLの静的なシェーダープログラムを解放する + */ + public static doStaticRelease(): void + { + CubismShader_WebGL.deleteInstance(); + } + + /** + * 描画開始時の追加処理 + * モデルを描画する前にクリッピングマスクに必要な処理を実装している + */ + public preDraw(): void + { + if(this.firstDraw) + { + this.firstDraw = false; + + // 拡張機能を有効にする + this._anisortopy = this.gl.getExtension("EXT_texture_filter_anisotropic") || + this.gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic") || + this.gl.getExtension("MOZ_EXT_texture_filter_anisotropic"); + } + + this.gl.disable(this.gl.SCISSOR_TEST); + this.gl.disable(this.gl.STENCIL_TEST); + this.gl.disable(this.gl.DEPTH_TEST); + + // カリング(1.0beta3) + this.gl.frontFace(this.gl.CW); + + this.gl.enable(this.gl.BLEND); + this.gl.colorMask(true, true, true, true); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null); // 前にバッファがバインドされていたら破棄する必要がある + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null); + } + + /** + * モデル描画直前のWebGLのステートを保持する + */ + public saveProfile(): void + { + this._rendererProfile.save(); + } + + /** + * モデル描画直前のWebGLのステートを保持する + */ + public restoreProfile(): void + { + this._rendererProfile.restore(); + } + + /** + * マスクテクスチャに描画するクリッピングコンテキストをセットする + */ + public setClippingContextBufferForMask(clip: CubismClippingContext) + { + this._clippingContextBufferForMask = clip; + } + + /** + * マスクテクスチャに描画するクリッピングコンテキストを取得する + * @return マスクテクスチャに描画するクリッピングコンテキスト + */ + public getClippingContextBufferForMask(): CubismClippingContext + { + return this._clippingContextBufferForMask; + } + + /** + * 画面上に描画するクリッピングコンテキストをセットする + */ + public setClippingContextBufferForDraw(clip: CubismClippingContext): void + { + this._clippingContextBufferForDraw = clip; + } + + /** + * 画面上に描画するクリッピングコンテキストを取得する + * @return 画面上に描画するクリッピングコンテキスト + */ + public getClippingContextBufferForDraw(): CubismClippingContext + { + return this._clippingContextBufferForDraw; + } + + /** + * glの設定 + */ + public startUp(gl: WebGLRenderingContext): void + { + this.gl = gl; + this._rendererProfile.setGl(gl); + this._clippingManager.setGL(gl); + CubismShader_WebGL.getInstance().setGl(gl); + } + + _textures: csmMap; // モデルが参照するテクスチャとレンダラでバインドしているテクスチャとのマップ + _sortedDrawableIndexList: csmVector; // 描画オブジェクトのインデックスを描画順に並べたリスト + _rendererProfile: CubismRendererProfile_WebGL; // WebGLのステートを保持するオブジェクト + _clippingManager: CubismClippingManager_WebGL; // クリッピングマスク管理オブジェクト + _clippingContextBufferForMask: CubismClippingContext; // マスクテクスチャに描画するためのクリッピングコンテキスト + _clippingContextBufferForDraw: CubismClippingContext; // 画面上描画するためのクリッピングコンテキスト + firstDraw: boolean; + gl: WebGLRenderingContext; // webglコンテキスト + } + +} \ No newline at end of file diff --git a/Framework/tsconfig.json b/Framework/tsconfig.json new file mode 100644 index 0000000..2bc7bcc --- /dev/null +++ b/Framework/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "sourceMap": true, + "target": "es5", + "module": "es2015", + "moduleResolution": "node", + "lib": [ + "dom", + "es2018" + ], + "noImplicitAny": true + } +} \ No newline at end of file diff --git a/Framework/type/csmmap.ts b/Framework/type/csmmap.ts new file mode 100644 index 0000000..6dad45f --- /dev/null +++ b/Framework/type/csmmap.ts @@ -0,0 +1,360 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import { CubismLogDebug } from "../utils/cubismdebug"; + +export namespace Live2DCubismFramework +{ + /** + * Key-Valueのペアを定義するクラス + * csmMapクラスの内部データで使用する。 + */ + export class csmPair<_KeyT, _ValT> + { + /** + * コンストラクタ + * @param key Keyとしてセットする値 + * @param value Valueとしてセットする値 + */ + public constructor(key?: _KeyT, value?: _ValT) + { + this.first = (key == undefined) + ? null + : key; + + this.second = (value == undefined) + ? null + : value; + } + + public first: _KeyT; // keyとして用いる変数 + public second: _ValT; // valueとして用いる変数 + } + + /** + * マップ型 + */ + export class csmMap<_KeyT, _ValT> + { + /** + * 引数付きコンストラクタ + * @param size 初期化時点で確保するサイズ + */ + public constructor(size?: number) + { + if(size != undefined) + { + if(size < 1) + { + this._keyValues = new Array(); + this._dummyValue = null; + this._size = 0; + } + else + { + this._keyValues = new Array(size); + this._size = size; + } + } + else + { + this._keyValues = new Array(); + this._dummyValue = null; + this._size = 0; + } + } + + /** + * デストラクタ + */ + public release() + { + this.clear(); + } + + /** + * キーを追加する + * @param key 新たに追加するキー + */ + public appendKey(key: _KeyT): void + { + // 新しくKey/Valueのペアを作る + this.prepareCapacity(this._size + 1, false); // 1つ以上入る隙間を作る + // 新しいkey/valueのインデックスは_size + + this._keyValues[this._size] = new csmPair<_KeyT, _ValT>(key); + this._size += 1; + } + + /** + * 添字演算子[key]のオーバーロード(get) + * @param key 添字から特定されるValue値 + */ + public getValue(key: _KeyT): _ValT + { + let found = -1; + + for(let i: number = 0; i < this._size; i++) + { + if(this._keyValues[i].first == key) + { + found = i; + break; + } + } + + if(found >= 0) + { + return this._keyValues[found].second; + } + else + { + this.appendKey(key); // 新規キーを追加 + return this._keyValues[this._size - 1].second; + } + } + + /** + * 添字演算子[key]のオーバーロード(set) + * @param key 添字から特定されるValue値 + * @param value 代入するValue値 + */ + public setValue(key: _KeyT, value: _ValT): void + { + let found = -1; + + for(let i: number = 0; i < this._size; i++) + { + if(this._keyValues[i].first == key) + { + found = i; + break; + } + } + + if(found >= 0) + { + this._keyValues[found].second = value; + } + else + { + this.appendKey(key); // 新規キーを追加 + this._keyValues[this._size - 1].second = value; + } + } + + /** + * 引数で渡したKeyを持つ要素が存在するか + * @param key 存在を確認するkey + * @return true 引数で渡したkeyを持つ要素が存在する + * @return false 引数で渡したkeyを持つ要素が存在しない + */ + public isExist(key: _KeyT): boolean + { + for(let i: number = 0; i < this._size; i++) + { + if(this._keyValues[i].first == key) + { + return true; + } + } + return false; + } + + /** + * keyValueのポインタを全て解放する + */ + public clear(): void + { + this._keyValues = void 0; + this._keyValues = null; + this._keyValues = new Array(); + + this._size = 0; + } + + /** + * コンテナのサイズを取得する + * + * @return コンテナのサイズ + */ + public getSize(): number + { + return this._size; + } + + /** + * コンテナのキャパシティを確保する + * @param newSize 新たなキャパシティ。引数の値が現在のサイズ未満の場合は何もしない。 + * @param fitToSize trueなら指定したサイズに合わせる。falseならサイズを2倍確保しておく。 + */ + public prepareCapacity(newSize: number, fitToSize: boolean): void + { + if(newSize > this._keyValues.length) + { + if(this._keyValues.length == 0) + { + if(!fitToSize && newSize < csmMap.DefaultSize) newSize = csmMap.DefaultSize; + this._keyValues.length = newSize; + } + else + { + if(!fitToSize && newSize < this._keyValues.length * 2) newSize = this._keyValues.length * 2; + this._keyValues.length = newSize; + } + } + } + + /** + * コンテナの先頭要素を返す + */ + public begin(): csmMap.iterator<_KeyT, _ValT> + { + let ite: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, 0); + return ite; + } + + /** + * コンテナの終端要素を返す + */ + public end(): csmMap.iterator<_KeyT, _ValT> + { + let ite: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, this._size); // 終了 + return ite; + } + + /** + * コンテナから要素を削除する + * + * @param ite 削除する要素 + */ + public erase(ite: csmMap.iterator<_KeyT, _ValT>): csmMap.iterator<_KeyT, _ValT> + { + let index: number = ite._index; + if(index < 0 || this._size <= index) + { + return ite; // 削除範囲外 + } + + // 削除 + this._keyValues.splice(index, 1); + --this._size; + + let ite2: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, index); // 終了 + return ite2; + } + + /** + * コンテナの値を32ビット符号付き整数型でダンプする + */ + public dumpAsInt() + { + for(let i = 0; i < this._size; i++) + { + CubismLogDebug("{0} ,", this._keyValues[i]); + CubismLogDebug("\n"); + } + } + + public static readonly DefaultSize = 10; // コンテナの初期化のデフォルトサイズ + public _keyValues: csmPair<_KeyT, _ValT>[];// key-valueペアの配列 + public _dummyValue: _ValT; // 空の値を返す為のダミー + public _size: number; // コンテナの要素数 + } + + export namespace csmMap + { + /** + * csmMapのイテレータ + */ + export class iterator<_KeyT, _ValT> + { + /** + * コンストラクタ + */ + constructor(v?: csmMap<_KeyT, _ValT>, idx?: number) + { + this._map = (v != undefined) + ? v + : new csmMap<_KeyT, _ValT>(); + + this._index = (idx != undefined) + ? idx + : 0; + } + + /** + * =演算子のオーバーロード + */ + public set(ite: iterator<_KeyT, _ValT>): iterator<_KeyT, _ValT> + { + this._index = ite._index; + this._map = ite._map; + return this; + } + + /** + * 前置き++演算子のオーバーロード + */ + public preIncrement(): iterator<_KeyT, _ValT> + { + ++this._index; + return this; + } + + /** + * 前置き--演算子のオーバーロード + */ + public preDecrement(): iterator<_KeyT, _ValT> + { + --this._index; + return this; + } + + /** + * 後置き++演算子のオーバーロード + */ + public increment(): iterator<_KeyT, _ValT> + { + let iteold = new iterator<_KeyT, _ValT>(this._map, this._index++); // 古い値を保存 + this._map = iteold._map; + this._index = iteold._index; + return this; + } + + /** + * 後置き--演算子のオーバーロード + */ + public decrement(): iterator<_KeyT, _ValT> + { + let iteold = new iterator<_KeyT, _ValT>(this._map, this._index); // 古い値を保存 + this._map = iteold._map; + this._index = iteold._index; + return this; + } + + /** + * *演算子のオーバーロード + */ + public ptr(): csmPair<_KeyT, _ValT> + { + return this._map._keyValues[this._index]; + } + + /** + * !=演算 + */ + public notEqual(ite: iterator<_KeyT, _ValT>): boolean + { + return (this._index != ite._index) || (this._map != ite._map); + } + + _index: number; // コンテナのインデックス値 + _map: csmMap<_KeyT, _ValT>; // コンテナ + } + } +} \ No newline at end of file diff --git a/Framework/type/csmrectf.ts b/Framework/type/csmrectf.ts new file mode 100644 index 0000000..0c8e30d --- /dev/null +++ b/Framework/type/csmrectf.ts @@ -0,0 +1,92 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +export namespace Live2DCubismFramework +{ + /** + * 矩形形状(座標・長さはfloat値)を定義するクラス + */ + export class csmRect + { + /** + * コンストラクタ + * @param x 左端X座標 + * @param y 上端Y座標 + * @param w 幅 + * @param h 高さ + */ + public constructor(x?: number, y?: number, w?: number, h?: number) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + } + + /** + * 矩形中央のX座標を取得する + */ + public getCenterX(): number + { + return this.x + 0.5 * this.width; + } + + /** + * 矩形中央のY座標を取得する + */ + public getCenterY(): number + { + return this.y + 0.5 * this.height; + } + + /** + * 右側のX座標を取得する + */ + public getRight(): number + { + return this.x + this.width; + } + + /** + * 下端のY座標を取得する + */ + public getBottom(): number + { + return this.y + this.height; + } + + /** + * 矩形に値をセットする + * @param r 矩形のインスタンス + */ + public setRect(r: csmRect): void + { + this.x = r.x; + this.y = r.y; + this.width = r.width; + this.height = r.height; + } + + /** + * 矩形中央を軸にして縦横を拡縮する + * @param w 幅方向に拡縮する量 + * @param h 高さ方向に拡縮する量 + */ + public expand(w: number, h: number) + { + this.x -= w; + this.y -= h; + this.width += w * 2.0; + this.height += h * 2.0; + } + + public x: number; // 左端X座標 + public y: number; // 上端Y座標 + public width: number; // 幅 + public height: number; // 高さ + } +} \ No newline at end of file diff --git a/Framework/type/csmstring.ts b/Framework/type/csmstring.ts new file mode 100644 index 0000000..23bc018 --- /dev/null +++ b/Framework/type/csmstring.ts @@ -0,0 +1,117 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +export namespace Live2DCubismFramework +{ + /** + * 文字列クラス。 + */ + export class csmString + { + /** + * 文字列を後方に追加する + * + * @param c 追加する文字列 + * @return 更新された文字列 + */ + public append(c: string, length?: number): csmString + { + this.s += (length !== undefined) + ? c.substr(0, length) + : c; + + return this; + } + + /** + * 文字サイズを拡張して文字を埋める + * @param length 拡張する文字数 + * @param v 埋める文字 + * @return 更新された文字列 + */ + public expansion(length: number, v: string): csmString + { + let ret: csmString = this; + + for(let i = 0; i < length; i++) + { + ret.append(v); + } + + return ret; + } + + /** + * 文字列の長さをバイト数で取得する + */ + public getBytes(): number + { + return encodeURIComponent(this.s) .replace(/%../g, "x").length; + } + + /** + * 文字列の長さを返す + */ + public getLength(): number + { + return this.s.length; + } + + /** + * 文字列比較 < + * @param s 比較する文字列 + * @return true: 比較する文字列より小さい + * @return false: 比較する文字列より大きい + */ + public isLess(s: csmString): boolean + { + return this.s < s.s; + } + + /** + * 文字列比較 > + * @param s 比較する文字列 + * @return true: 比較する文字列より大きい + * @return false: 比較する文字列より小さい + */ + public isGreat(s: csmString): boolean + { + return this.s > s.s; + } + + /** + * 文字列比較 == + * @param s 比較する文字列 + * @return true: 比較する文字列と等しい + * @return false: 比較する文字列と異なる + */ + public isEqual(s: string): boolean + { + return this.s == s; + } + + /** + * 文字列が空かどうか + * @return true: 空の文字列 + * @return false: 値が設定されている + */ + public isEmpty(): boolean + { + return this.s.length == 0; + } + + /** + * 引数付きコンストラクタ + */ + public constructor(s: string) + { + this.s = s; + } + + s: string; + } +} \ No newline at end of file diff --git a/Framework/type/csmvector.ts b/Framework/type/csmvector.ts new file mode 100644 index 0000000..746d0a8 --- /dev/null +++ b/Framework/type/csmvector.ts @@ -0,0 +1,396 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +export namespace Live2DCubismFramework +{ + /** + * ベクター型(可変配列型) + */ + export class csmVector + { + /** + * 引数付きコンストラクタ + * @param iniitalCapacity 初期化後のキャパシティ。データサイズは_capacity * sizeof(T) + * @param zeroClear trueなら初期化時に確保した領域を0で埋める + */ + constructor(initialCapacity: number = 0) + { + if(initialCapacity < 1) + { + this._ptr = new Array(); + this._capacity = 0; + this._size = 0; + } + else + { + this._ptr = new Array(initialCapacity); + this._capacity = initialCapacity; + this._size = 0; + } + } + + /** + * インデックスで指定した要素を返す + */ + public at(index: number): T + { + return this._ptr[index]; + } + + /** + * 要素をセット + * @param index 要素をセットするインデックス + * @param value セットする要素 + */ + public set(index: number, value: T): void + { + this._ptr[index] = value; + } + + /** + * コンテナを取得する + */ + public get(offset: number = 0): T[] + { + let ret: T[] = new Array(); + for(let i = offset; i < this._size; i++) + { + ret.push(this._ptr[i]); + } + return ret; + } + + /** + * pushBack処理、コンテナに新たな要素を追加する + * @param value PushBack処理で追加する値 + */ + public pushBack(value: T): void + { + if(this._size >= this._capacity) + { + this.prepareCapacity(this._capacity == 0 ? csmVector.s_defaultSize : this._capacity * 2); + } + + this._ptr[this._size++] = value; + } + + /** + * コンテナの全要素を解放する + */ + public clear(): void + { + this._ptr.length = 0; + this._size = 0; + } + + /** + * コンテナの要素数を返す + * @return コンテナの要素数 + */ + public getSize(): number + { + return this._size; + } + + /** + * コンテナの全要素に対して代入処理を行う + * @param newSize 代入処理後のサイズ + * @param value 要素に代入する値 + */ + public assign(newSize: number, value: T): void + { + let curSize = this._size; + + if(curSize < newSize) + { + this.prepareCapacity(newSize); // capacity更新 + } + + for(let i: number = 0; i < newSize; i++) + { + this._ptr[i] = value; + } + + this._size = newSize; + } + + /** + * サイズ変更 + */ + public resize(newSize: number, value: T = null): void + { + this.updateSize(newSize, value, true); + } + + /** + * サイズ変更 + */ + public updateSize(newSize: number, value: any = null, callPlacementNew: boolean = true): void + { + let curSize: number = this._size; + + if(curSize < newSize) + { + this.prepareCapacity(newSize); // capacity更新 + + if(callPlacementNew) + { + for(let i: number = this._size; i < newSize; i++) + { + if(typeof value == 'function') // new + { + this._ptr[i] = JSON.parse(JSON.stringify(new value())); + } + else // プリミティブ型なので値渡し + { + this._ptr[i] = value; + } + } + } + else + { + for(let i: number = this._size; i < newSize; i++) + { + this._ptr[i] = value; + } + } + } + else + { + // newSize <= this._size + //--- + let sub = this._size - newSize; + this._ptr.splice(this._size - sub, sub); // 不要なので破棄する + } + this._size = newSize; + } + + /** + * コンテナにコンテナ要素を挿入する + * @param position 挿入する位置 + * @param begin 挿入するコンテナの開始位置 + * @param end 挿入するコンテナの終端位置 + */ + public insert(position: csmVector.iterator, begin: csmVector.iterator, end: csmVector.iterator): void + { + let dstSi: number = position._index; + let srcSi: number = begin._index; + let srcEi: number = end._index; + + let addCount: number = srcEi - srcSi; + + this.prepareCapacity(this._size + addCount); + + // 挿入用の既存データをシフトして隙間を作る + let addSize = this._size - dstSi; + if(addSize > 0) + { + for(let i: number = 0; i < addSize; i++) + { + this._ptr.splice(dstSi + i, 0, null); + } + } + + for(let i: number = srcSi; i < srcEi; i++, dstSi++) + { + this._ptr[dstSi] = begin._vector._ptr[i]; + } + + this._size = this._size + addCount; + } + + /** + * コンテナからインデックスで指定した要素を削除する + * @param index インデックス値 + * @return true 削除実行 + * @return false 削除範囲外 + */ + public remove(index: number): boolean + { + if(index < 0 || this._size <= index) + { + return false; // 削除範囲外 + } + + this._ptr.splice(index, 1); + --this._size; + + return true; + } + + /** + * コンテナから要素を削除して他の要素をシフトする + * @param ite 削除する要素 + */ + public erase(ite: csmVector.iterator): csmVector.iterator + { + let index: number = ite._index; + if(index < 0 || this._size <= index) + { + return ite; // 削除範囲外 + } + + // 削除 + this._ptr.splice(index, 1); + --this._size; + + let ite2: csmVector.iterator = new csmVector.iterator(this, index); // 終了 + return ite2; + } + + /** + * コンテナのキャパシティを確保する + * @param newSize 新たなキャパシティ。引数の値が現在のサイズ未満の場合は何もしない. + */ + public prepareCapacity(newSize: number): void + { + if(newSize > this._capacity) + { + if(this._capacity == 0) + { + this._ptr = new Array(newSize); + this._capacity = newSize; + } + else + { + this._ptr.length = newSize; + this._capacity = newSize; + } + } + } + + /** + * コンテナの先頭要素を返す + */ + public begin(): csmVector.iterator + { + let ite: csmVector.iterator = (this._size == 0) + ? this.end() + : new csmVector.iterator(this, 0); + return ite; + } + + /** + * コンテナの終端要素を返す + */ + public end(): csmVector.iterator + { + let ite: csmVector.iterator = new csmVector.iterator(this, this._size); + return ite; + } + + public getOffset(offset: number): csmVector + { + let newVector = new csmVector(); + newVector._ptr = this.get(offset); + newVector._size = this.get(offset).length; + newVector._capacity = this.get(offset).length; + + return newVector; + } + + _ptr: T[]; // コンテナの先頭アドレス + _size: number; // コンテナの要素数 + _capacity: number; // コンテナのキャパシティ + + static readonly s_defaultSize = 10; // コンテナ初期化のデフォルトサイズ + } + + export namespace csmVector + { + export class iterator + { + /** + * コンストラクタ + */ + public constructor(v?: csmVector, index?: number) + { + this._vector = (v != undefined) ? v : null; + this._index = (index != undefined) ? index : 0; + } + + /** + * 代入 + */ + public set(ite: iterator): iterator + { + this._index = ite._index; + this._vector = ite._vector; + return this; + } + + /** + * 前置き++演算 + */ + public preIncrement(): iterator + { + ++this._index; + return this; + } + + /** + * 前置き--演算 + */ + public preDecrement(): iterator + { + --this._index; + return this; + } + + /** + * 後置き++演算子 + */ + public increment(): iterator + { + let iteold = new iterator(this._vector, this._index++); + this._vector = iteold._vector; + this._index = iteold._index; + return this; + } + + /** + * 後置き--演算子 + */ + public decrement(): iterator + { + let iteold = new iterator(this._vector, this._index--); // 古い値を保存 + this._vector = iteold._vector; + this._index = iteold._index; + return this; + } + + /** + * ptr + */ + public ptr(): T + { + return this._vector._ptr[this._index]; + } + + /** + * =演算子のオーバーロード + */ + public substitution(ite: iterator): iterator + { + this._index = ite._index; + this._vector = ite._vector; + return this; + } + + /** + * !=演算子のオーバーロード + */ + public notEqual(ite: iterator): boolean + { + return (this._index != ite._index) || (this._vector != ite._vector); + } + + _index: number; // コンテナのインデックス値 + _vector: csmVector; // コンテナ + } + } +} \ No newline at end of file diff --git a/Framework/utils/cubismdebug.ts b/Framework/utils/cubismdebug.ts new file mode 100644 index 0000000..e8e8f4a --- /dev/null +++ b/Framework/utils/cubismdebug.ts @@ -0,0 +1,194 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as live2dcubismframework, Option} from "../live2dcubismframework"; +import CubismFramework = live2dcubismframework.CubismFramework; +import { CSM_LOG_LEVEL, CSM_LOG_LEVEL_VERBOSE, CSM_LOG_LEVEL_DEBUG, CSM_LOG_LEVEL_INFO, CSM_LOG_LEVEL_WARNING, CSM_LOG_LEVEL_ERROR } from "../cubismframeworkconfig"; + +export const CubismLogPrint = (level: Option.LogLevel, fmt: string, ... args: any[]) => +{ + Live2DCubismFramework.CubismDebug.print(level, "[CSM]" + fmt, args); +} + +export const CubismLogPrintIn = (level: Option.LogLevel, fmt: string, ... args: any[]) => +{ + CubismLogPrint(level, fmt + "\n", args); +} + +export let CSM_ASSERT = (expr: any) => +{ + console.assert(expr); +}; + + +export let CubismLogVerbose = (fmt: string, ... args: any[]) => {}; +export let CubismLogDebug = (fmt: string, ... args: any[]) => {}; +export let CubismLogInfo = (fmt: string, ... args: any[]) => {}; +export let CubismLogWarning = (fmt: string, ... args: any[]) => {}; +export let CubismLogError = (fmt: string, ... args: any[]) => {}; + +if(CSM_LOG_LEVEL <= CSM_LOG_LEVEL_VERBOSE) +{ + CubismLogVerbose = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Verbose, "[V]" + fmt, args); + }; + + CubismLogDebug = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Debug, "[D]" + fmt, args); + }; + + CubismLogInfo = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); + }; + + CubismLogWarning = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + }; + + CubismLogError = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + }; +} +else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_DEBUG) +{ + CubismLogDebug = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Debug, "[D]" + fmt, args); + }; + + CubismLogInfo = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); + }; + + CubismLogWarning = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + }; + + CubismLogError = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + }; +} +else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_INFO) +{ + CubismLogInfo = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); + }; + + CubismLogWarning = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + }; + + CubismLogError = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + }; +} +else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_WARNING) +{ + CubismLogWarning = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + }; + + CubismLogError = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + }; +} +else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_ERROR) +{ + CubismLogError = (fmt: string, ... args: any[]) => + { + CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + }; +} + +//------------ LIVE2D NAMESPACE ------------ +export namespace Live2DCubismFramework +{ + + /** + * デバッグ用のユーティリティクラス。 + * ログの出力、バイトのダンプなど + */ + export class CubismDebug + { + /** + * ログを出力する。第一引数にログレベルを設定する。 + * CubismFramework.initialize()時にオプションで設定されたログ出力レベルを下回る場合はログに出さない。 + * + * @param logLevel ログレベルの設定 + * @param format 書式付き文字列 + * @param ... args 可変長引数 + */ + public static print(logLevel: Option.LogLevel, format: string, ... args: any[]): void + { + // オプションで設定されたログ出力レベルを下回る場合はログに出さない + // if(logLevel < CubismFramework.getLoggingLevel()) + // { + // return; + // } + + // TODO + // const Core::csmLogFunction logPrint = CubismFramework::CoreLogFunction; + + // if (!logPrint) + // return; + + let buffer: string = format; + buffer = buffer.replace( + /\{(\d+)\}/g, + (m, k) => // m="{0}", k="0" + { + return args[k]; + } + ); + + // logPrint(buffer); + } + + /** + * データから指定した長さだけダンプ出力する。 + * CubismFramework.initialize()時にオプションで設定されたログ出力レベルを下回る場合はログに出さない。 + * + * @param logLevel ログレベルの設定 + * @param data ダンプするデータ + * @param length ダンプする長さ + */ + public static dumpBytes(logLevel: Option.LogLevel, data: Uint8Array, length: number): void + { + for (let i: number = 0; i < length; i++) + { + if (i % 16 == 0 && i > 0) this.print(logLevel, "\n"); + else if (i % 8 == 0 && i > 0) this.print(logLevel, " "); + this.print(logLevel, "{0} ", (data[i] & 0xFF)); + } + + this.print(logLevel, "\n"); + } + + /** + * private コンストラクタ + */ + private constructor() + { + + } + } +} + +//------------ LIVE2D NAMESPACE ------------ \ No newline at end of file diff --git a/Framework/utils/cubismjson.ts b/Framework/utils/cubismjson.ts new file mode 100644 index 0000000..f28dfaf --- /dev/null +++ b/Framework/utils/cubismjson.ts @@ -0,0 +1,1249 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import {Live2DCubismFramework as csmstring} from "../type/csmstring"; +import {Live2DCubismFramework as csmmap} from "../type/csmmap"; +import {Live2DCubismFramework as csmvector} from "../type/csmvector"; +import {CubismLogInfo} from "./cubismdebug"; +import {strtod} from "../live2dcubismframework"; +import csmVector = csmvector.csmVector; +import csmMap = csmmap.csmMap; +import csmString = csmstring.csmString; + +export namespace Live2DCubismFramework +{ + // StaticInitializeNotForClientCall()で初期化する + const CSM_JSON_ERROR_TYPE_MISMATCH: string = "Error: type mismatch"; + const CSM_JSON_ERROR_INDEX_OF_BOUNDS: string = "Error: index out of bounds"; + + /** + * パースしたJSONエレメントの要素の基底クラス。 + */ + export abstract class Value + { + /** + * コンストラクタ + */ + public constructor() + { + + } + + /** + * 要素を文字列型で返す(csmString型) + */ + public abstract getString(defaultValue?: string, indent?: string): string; + + /** + * 要素を文字列型で返す(string) + */ + public getRawString(defaultValue?: string, indent?: string): string + { + return this.getString(defaultValue, indent); + } + + /** + * 要素を数値型で返す(number) + */ + public toInt(defaultValue: number = 0): number + { + return defaultValue; + } + + /** + * 要素を数値型で返す(number) + */ + public toFloat(defaultValue: number = 0): number + { + return defaultValue; + } + + /** + * 要素を真偽値で返す(boolean) + */ + public toBoolean(defaultValue: boolean = false): boolean + { + return defaultValue; + } + + /** + * サイズを返す + */ + public getSize(): number + { + return 0; + } + + /** + * 要素を配列で返す(Value[]) + */ + public getArray(defaultValue: Value[] = null): Value[] + { + return defaultValue; + } + + /** + * 要素をコンテナで返す(array) + */ + public getVector(defaultValue?: csmVector): csmVector + { + return defaultValue; + } + + /** + * 要素をマップで返す(csmMap) + */ + public getMap(defaultValue?: csmMap): csmMap + { + return defaultValue; + } + + /** + * マップのキー一覧をコンテナで返す + * + * @return マップのキーの一覧 + */ + public getKeys(): csmVector + { + return Value.s_dummyKeys; + } + + /** + * Valueの種類がエラー値ならtrue + */ + public isError(): boolean + { + return false; + } + + /** + * Valueの種類がnullならtrue + */ + public isNull(): boolean + { + return false; + } + + /** + * Valueの種類が真偽値ならtrue + */ + public isBool(): boolean + { + return false; + } + + /** + * Valueの種類が数値型ならtrue + */ + public isFloat(): boolean + { + return false; + } + + /** + * Valueの種類が文字列ならtrue + */ + public isString(): boolean + { + return false; + } + + /** + * Valueの種類が配列ならtrue + */ + public isArray(): boolean + { + return false; + } + + /** + * Valueの種類がマップ型ならtrue + */ + public isMap(): boolean + { + return false; + } + + /** + * 引数の値と等しければtrue + */ + public equals(value: csmString): boolean; + public equals(value: string): boolean; + public equals(value: number): boolean; + public equals(value: boolean): boolean; + public equals(value: any):boolean + { + return false; + } + + /** + * Valueの値が静的ならtrue、静的なら解放しない + */ + public isStatic(): boolean + { + return false; + } + + /** + * Valueにエラー値をセットする + */ + public setErrorNotForClientCall(errorStr: string): Value + { + return Value.errorValue; + } + + /** + * 初期化用メソッド + */ + public static staticInitializeNotForClientCall(): void + { + JsonBoolean.trueValue = new JsonBoolean(true); + JsonBoolean.falseValue = new JsonBoolean(false); + + JsonError.errorValue = new JsonError("ERROR", true); + this.nullValue = new JsonNullvalue(); + + Value.s_dummyKeys = new csmVector(); + } + + /** + * リリース用メソッド + */ + public static staticReleaseNotForClientCall(): void + { + JsonBoolean.trueValue = void 0; + JsonBoolean.falseValue = void 0; + JsonError.errorValue = void 0; + Value.nullValue = void 0; + Value.s_dummyKeys = void 0; + + JsonBoolean.trueValue = null; + JsonBoolean.falseValue = null; + JsonError.errorValue = null; + Value.nullValue = null; + Value.s_dummyKeys = null; + } + + protected _stringBuffer: string; // 文字列バッファ + + private static s_dummyKeys: csmVector; // ダミーキー + + public static errorValue: Value; // 一時的な返り値として返すエラー。 CubismFramework::Disposeするまではdeleteしない + public static nullValue: Value; // 一時的な返り値として返すNULL。 CubismFramework::Disposeするまではdeleteしない + } + + /** + * Ascii文字のみ対応した最小限の軽量JSONパーサ。 + * 仕様はJSONのサブセットとなる。 + * 設定ファイル(model3.json)などのロード用 + * + * [未対応項目] + * ・日本語などの非ASCII文字 + * ・eによる指数表現 + */ + export class CubismJson + { + /** + * コンストラクタ + */ + public constructor(buffer?: ArrayBuffer, length?: number) + { + this._error = null; + this._lineCount = 0; + this._root = null; + + if(buffer != undefined) + { + this.parseBytes(buffer, length); + } + } + + /** + * バイトデータから直接ロードしてパースする + * + * @param buffer バッファ + * @param size バッファサイズ + * @return CubismJsonクラスのインスタンス。失敗したらNULL + */ + public static create(buffer: ArrayBuffer, size: number) + { + let json = new CubismJson(); + const succeeded: boolean = json.parseBytes(buffer, size); + + if(!succeeded) + { + CubismJson.delete(json); + console.log("parseBytes is failed"); + return null; + } + else + { + return json; + } + } + + /** + * パースしたJSONオブジェクトの解放処理 + * + * @param instance CubismJsonクラスのインスタンス + */ + public static delete(instance: CubismJson) + { + instance = void 0; + instance = null; + } + + /** + * パースしたJSONのルート要素を返す + */ + public getRoot(): Value + { + return this._root; + } + + /** + * JSONのパースを実行する + * @param buffer パース対象のデータバイト + * @param size データバイトのサイズ + * return true : 成功 + * return false: 失敗 + */ + public parseBytes(buffer: ArrayBuffer, size: number): boolean + { + let endPos: number[] = new Array(1); // 参照渡しにするため配列 + let decodeBuffer: string = new TextDecoder('utf-8').decode(buffer); + this._root = this.parseValue(decodeBuffer, size, 0, endPos); + + if(this._error) + { + console.log(this._error); + let strbuf: string = '\0'; + strbuf = "Json parse error : @line " + (this._lineCount + 1) + "\n"; + this._root = new JsonString(strbuf); + + CubismLogInfo("{0}", this._root.getRawString()); + return false; + } + else if(this._root == null) + { + this._root = new JsonError(new csmString(this._error), false); // rootは解放されるのでエラーオブジェクトを別途作成する + return false; + } + return true; + } + + /** + * パース時のエラー値を返す + */ + public getParseError(): string + { + return this._error; + } + + /** + * ルート要素の次の要素がファイルの終端だったらtrueを返す + */ + public checkEndOfFile(): boolean + { + return this._root.getArray()[1].equals("EOF"); + } + + /** + * JSONエレメントからValue(float,String,Value*,Array,null,true,false)をパースする + * エレメントの書式に応じて内部でParseString(), ParseObject(), ParseArray()を呼ぶ + * + * @param buffer JSONエレメントのバッファ + * @param length パースする長さ + * @param begin パースを開始する位置 + * @param outEndPos パース終了時の位置 + * @return パースから取得したValueオブジェクト + */ + protected parseValue(buffer: string, length: number, begin: number, outEndPos: number[]) + { + if (this._error) return null; + + let o: Value = null; + let i: number = begin; + let f: number; + + for (; i < length; i++) + { + let c: string = buffer[i]; + switch(c) + { + case '-': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + let afterString: string[] = new Array(1); // 参照渡しにするため + f = strtod(buffer.slice(i), afterString); + outEndPos[0] = buffer.indexOf(afterString[0]); + return new JsonFloat(f); + } + case '\"': + return new JsonString(this.parseString(buffer, length, i + 1, outEndPos)); // \"の次の文字から + case '[': + o = this.parseArray(buffer, length, i + 1, outEndPos); + return o; + case '{': + o = this.parseObject(buffer, length, i + 1, outEndPos); + return o; + case 'n': // null以外にない + if(i + 3 < length) + { + o = new JsonNullvalue(); // 解放できるようにする + outEndPos[0] = i + 4; + } + else + { + this._error = "parse null"; + } + return o; + case 't': // true以外にない + if(i + 3 < length) + { + o = JsonBoolean.trueValue; + outEndPos[0] = i + 4; + } + else + { + this._error = "parse true"; + } + return o; + case 'f': // false以外にない + if(i + 4 < length) + { + o = JsonBoolean.falseValue; + outEndPos[0] = i + 5; + } + else + { + this._error = "illegal ',' position"; + } + return o; + case ',': // Array separator + this._error = "illegal ',' position"; + return null; + case ']': // 不正な}だがスキップする。配列の最後に不要な , があると思われる + outEndPos[0] = i; // 同じ文字を再処理 + return null; + case '\n': + this._lineCount++; + case ' ': + case '\t': + case '\r': + default: // スキップ + break; + } + } + + this._error = "illegal end of value"; + return null; + } + + /** + * 次の「"」までの文字列をパースする。 + * + * @param string -> パース対象の文字列 + * @param length -> パースする長さ + * @param begin -> パースを開始する位置 + * @param outEndPos -> パース終了時の位置 + * @return パースした文F字列要素 + */ + protected parseString(string: string, length: number, begin: number, outEndPos: number[]): string + { + if (this._error) return null; + + let i = begin; + let c: string, c2: string; + let ret: csmString = new csmString(""); + let bufStart: number = begin; // sbufに登録されていない文字の開始位置 + + for (; i < length; i++) + { + c = string[i]; + + switch(c) + { + case '\"': // 終端の”、エスケープ文字は別に処理されるのでここに来ない + { + outEndPos[0] = i + 1; // ”の次の文字 + ret.append(string.slice(bufStart), (i - bufStart)); // 前の文字までを登録する + return ret.s; + } + case '//': // エスケープの場合 + { + i++; // 2文字をセットで扱う + + if(i - 1 > bufStart) + { + ret.append(string.slice(bufStart), (i - bufStart)); // 前の文字までを登録する + } + bufStart = i + 1; // エスケープ(2文字)の次の文字から + + if (i < length) + { + c2 = string[i]; + + switch(c2) + { + case '\\': + ret.expansion(1, '\\'); + break; + case '\"': + ret.expansion(1, '\"'); + break; + case '/': + ret.expansion(1, '/'); + break; + case 'b': + ret.expansion(1, '\b'); + break; + case 'f': + ret.expansion(1, '\f'); + break; + case 'n': + ret.expansion(1, '\n'); + break; + case 'r': + ret.expansion(1, '\r'); + break; + case 't': + ret.expansion(1, '\t'); + break; + case 'u': + this._error = "parse string/unicord escape not supported"; + break; + default: + break; + } + } + else + { + this._error = "parse string/escape error"; + } + } + default: + { + break; + } + } + } + + this._error = "parse string/illegal end"; + return null; + } + + /** + * JSONのオブジェクトエレメントをパースしてValueオブジェクトを返す + * + * @param buffer JSONエレメントのバッファ + * @param length パースする長さ + * @param begin パースを開始する位置 + * @param outEndPos パース終了時の位置 + * @return パースから取得したValueオブジェクト + */ + protected parseObject(buffer: string, length: number, begin: number, outEndPos: number[]): Value + { + if(this._error) return null; + let ret: JsonMap = new JsonMap(); + + // Key: Value + let key: string = ""; + let i: number = begin; + let c: string = ""; + let localRetEndPos2: number[] = Array(1); + let ok: boolean = false; + + // , が続く限りループ + for(; i < length; i++) + { + FOR_LOOP: for(; i < length; i++) + { + c = buffer[i]; + + switch(c) + { + case '\"': + key = this.parseString(buffer, length, i + 1, localRetEndPos2); + if(this._error) + { + return null; + } + + i = localRetEndPos2[0]; + ok = true; + break FOR_LOOP; //-- loopから出る + case '}': // 閉じカッコ + outEndPos[0] = i + 1; + return ret; // 空 + case ':': + this._error = "illegal ':' position"; + break; + case '\n': + this._lineCount++; + default: + break; // スキップする文字 + } + } + if(!ok) + { + this._error = "key not found"; + return null; + } + + ok = false; + + // : をチェック + FOR_LOOP2: for(; i < length; i++) + { + c = buffer[i]; + + switch(c) + { + case ':': + ok = true; + i++; + break FOR_LOOP2; + case '}': + this._error = "illegal '}' position"; + break; + case '\n': this._lineCount++; + // case ' ': case '\t' : case '\r': + default: + break; // スキップする文字 + } + } + + if(!ok) + { + this._error = "':' not found"; + return null; + } + + // 値をチェック + let value: Value = this.parseValue(buffer, length, i, localRetEndPos2); + if(this._error) + { + return null; + } + + i = localRetEndPos2[0]; + + // ret.put(key, value); + ret.put(key, value); + + FOR_LOOP3: for(; i < length; i++) + { + c = buffer[i]; + + switch(c) + { + case ',': + break FOR_LOOP3; + case '}': + outEndPos[0] = i + 1; + return ret; // 正常終了 + case '\n': + this._lineCount++; + default: + break; // スキップ + } + } + } + + this._error = "illegal end of perseObject"; + return null; + } + + /** + * 次の「"」までの文字列をパースする。 + * @param buffer JSONエレメントのバッファ + * @param length パースする長さ + * @param begin パースを開始する位置 + * @param outEndPos パース終了時の位置 + * @return パースから取得したValueオブジェクト + */ + protected parseArray(buffer: string, length: number, begin: number, outEndPos: number[]): Value + { + if(this._error) return null; + let ret:JsonArray = new JsonArray(); + + // key : value + let i: number = begin; + let c: string; + let localRetEndpos2: number[] = new Array(1); + + // , が続く限りループ + for(; i < length; i++) + { + // : をチェック + let value: Value = this.parseValue(buffer, length, i, localRetEndpos2); + + if(this._error) + { + return null; + } + i = localRetEndpos2[0]; + + if(value) + { + ret.add(value); + } + + // FOR_LOOP3: + // boolean breakflag = false; + FOR_LOOP: for(; i < length; i++) + { + c = buffer[i]; + + switch(c) + { + case ',': + // breakflag = true; + // break; // 次のKEY, VAlUEへ + break FOR_LOOP; + case ']': + outEndPos[0] = i + 1; + return ret; // 終了 + case '\n': + ++this._lineCount; + //case ' ': case '\t': case '\r': + default: + break; // スキップ + } + } + } + + ret = void 0; + this._error = "illegal end of parseObject"; + return null; + } + + _error: string; // パース時のエラー + _lineCount: number; // エラー報告に用いる行数カウント + _root: Value; // パースされたルート要素 + } + + /** + * パースしたJSONの要素をfloat値として扱う + */ + export class JsonFloat extends Value + { + /** + * コンストラクタ + */ + constructor(v: number) + { + super(); + + this._value = v; + } + + /** + * Valueの種類が数値型ならtrue + */ + public isFloat(): boolean + { + return true; + } + + /** + * 要素を文字列で返す(csmString型) + */ + public getString(defaultValue: string, indent: string): string + { + let strbuf: string = '\0'; + this._value = parseFloat(strbuf); + this._stringBuffer = strbuf; + + return this._stringBuffer; + } + + /** + * 要素を数値型で返す(number) + */ + public toInt(defaultValue: number = 0): number + { + return parseInt(this._value.toString()); + } + + /** + * 要素を数値型で返す(number) + */ + public toFloat(defaultValue: number = 0.0): number + { + return this._value; + } + + /** + * 引数の値と等しければtrue + */ + public equals(value: csmString): boolean; + public equals(value: string): boolean; + public equals(value: number): boolean; + public equals(value: boolean): boolean; + public equals(value: any):boolean + { + if ('number' === typeof(value)) + { + // int + if (Math.round(value)) + { + return false; + } + // float + else + { + return value == this._value; + } + } + return false; + } + + private _value: number; // JSON要素の値 + } + + /** + * パースしたJSONの要素を真偽値として扱う + */ + export class JsonBoolean extends Value + { + + /** + * Valueの種類が真偽値ならtrue + */ + public isBool(): boolean + { + return true; + } + + /** + * 要素を真偽値で返す(boolean) + */ + public toBoolean(defaultValue: boolean = false): boolean + { + return this._boolValue; + } + + /** + * 要素を文字列で返す(csmString型) + */ + public getString(defaultValue: string, indent: string): string + { + this._stringBuffer = this._boolValue + ? "true" + : "false"; + + return this._stringBuffer; + } + + /** + * 引数の値と等しければtrue + */ + public equals(value: csmString): boolean; + public equals(value: string): boolean; + public equals(value: number): boolean; + public equals(value: boolean): boolean; + public equals(value: any):boolean + { + if ('boolean' === typeof(value)) + { + return value == this._boolValue; + } + return false; + } + + /** + * Valueの値が静的ならtrue, 静的なら解放しない + */ + public isStatic(): boolean + { + return true; + } + + /** + * 引数付きコンストラクタ + */ + public constructor(v: boolean) + { + super(); + + this._boolValue = v; + } + + static trueValue: JsonBoolean; // true + static falseValue: JsonBoolean; // false + + private _boolValue: boolean; // JSON要素の値 + } + + /** + * パースしたJSONの要素を文字列として扱う + */ + export class JsonString extends Value + { + /** + * 引数付きコンストラクタ + */ + public constructor(s: string); + public constructor(s: csmString) + public constructor(s: any) + { + super(); + + if('string' === typeof(s)) + { + this._stringBuffer = s; + } + + if(s instanceof csmString) + { + this._stringBuffer = s.s; + } + } + + /** + * Valueの種類が文字列ならtrue + */ + public isString(): boolean + { + return true; + } + + /** + * 要素を文字列で返す(csmString型) + */ + public getString(defaultValue: string, indent: string): string + { + return this._stringBuffer; + } + + /** + * 引数の値と等しければtrue + */ + public equals(value: csmString): boolean; + public equals(value: string): boolean; + public equals(value: number): boolean; + public equals(value: boolean): boolean; + public equals(value: any):boolean + { + if ('string' === typeof(value)) + { + return this._stringBuffer == value; + } + + if (value instanceof csmString) + { + return (this._stringBuffer == value.s); + } + + return false; + } + } + + /** + * JSONパース時のエラー結果。文字列型のようにふるまう + */ + export class JsonError extends JsonString + { + /** + * Valueの値が静的ならtrue、静的なら解放しない + */ + public isStatic(): boolean + { + return this._isStatic; + } + + /** + * エラー情報をセットする + */ + public setErrorNotForClientCall(s: string): Value + { + this._stringBuffer = s; + return this; + } + + /** + * 引数付きコンストラクタ + */ + public constructor(s: csmString|string, isStatic: boolean) + { + if("string" === typeof(s)) + { + super(s); + } + else + { + super(s); + } + this._isStatic = isStatic; + } + + /** + * Valueの種類がエラー値ならtrue + */ + public isError(): boolean + { + return true; + } + + + protected _isStatic: boolean; // 静的なValueかどうか + } + + /** + * パースしたJSONの要素をNULL値として持つ + */ + export class JsonNullvalue extends Value + { + /** + * Valueの種類がNULL値ならtrue + */ + public isNull(): boolean + { + return true; + } + + /** + * 要素を文字列で返す(csmString型) + */ + public getString(defaultValue: string, indent: string): string + { + return this._stringBuffer; + } + + /** + * Valueの値が静的ならtrue, 静的なら解放しない + */ + public isStatic(): boolean + { + return true; + } + + /** + * コンストラクタ + */ + public constructor() + { + super(); + + this._stringBuffer = "NullValue"; + } + + } + + /** + * パースしたJSONの要素を配列として持つ + */ + export class JsonArray extends Value + { + /** + * コンストラクタ + */ + public constructor() + { + super(); + this._array = new csmVector(); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + for(let ite: csmVector.iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.preIncrement()) + { + let v: Value = ite.ptr(); + + if(v && !v.isStatic()) + { + v = void 0; + v = null; + } + } + } + + /** + * Valueの種類が配列ならtrue + */ + public isArray(): boolean + { + return true; + } + + /** + * 要素を文字列で返す(csmString型) + */ + public getString(defaultValue: string, indent: string): string + { + let stringBuffer: string = indent + "[\n"; + + for(let ite: csmVector.iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.increment()) + { + let v: Value = ite.ptr(); + this._stringBuffer += indent + "" + v.getString(indent + " ") + "\n"; + } + + this._stringBuffer = stringBuffer + indent + "]\n"; + + return this._stringBuffer; + } + + /** + * 配列要素を追加する + * @param v 追加する要素 + */ + public add(v: Value): void + { + this._array.pushBack(v); + } + + /** + * 要素をコンテナで返す(csmVector) + */ + public getVector(defaultValue: csmVector = null): csmVector + { + return this._array; + } + + /** + * 要素の数を返す + */ + public getSize(): number + { + return this._array.getSize(); + } + + private _array: csmVector; // JSON要素の値 + } + + /** + * パースしたJSONの要素をマップとして持つ + */ + export class JsonMap extends Value + { + /** + * コンストラクタ + */ + public constructor() + { + super(); + //this._keys = new csmVector(); + this._map = new csmMap(); + } + + /** + * デストラクタ相当の処理 + */ + public release(): void + { + const ite: csmMap.iterator = this._map.begin(); + + while(ite.notEqual(this._map.end())) + { + let v: Value = ite.ptr().second; + + if(v && !v.isStatic()) + { + v = void 0; + v = null; + } + + ite.preIncrement(); + } + } + + /** + * Valueの値がMap型ならtrue + */ + public isMap(): boolean + { + return true; + } + + /** + * 要素を文字列で返す(csmString型) + */ + public getString(defaultValue: string, indent: string) + { + this._stringBuffer = indent + "{\n"; + + const ite: csmMap.iterator = this._map.begin(); + while(ite.notEqual(this._map.end())) + { + const key = ite.ptr().first; + let v: Value = ite.ptr().second; + + this._stringBuffer += indent + " " + key + " : " + v.getString(indent + " ") + " \n"; + ite.preIncrement(); + } + + this._stringBuffer += indent + "}\n"; + + return this._stringBuffer; + } + + /** + * 要素をMap型で返す + */ + public getMap(defaultValue?: csmMap): csmMap + { + return this._map; + } + + /** + * Mapに要素を追加する + */ + public put(key: string, v: Value): void + { + this._map.setValue(key, v); + } + + /** + * Mapからキーのリストを取得する + */ + public getKeys(): csmVector + { + if (!this._keys) + { + this._keys = new csmVector(); + + const ite: csmMap.iterator = this._map.begin(); + + while(ite.notEqual(this._map.end())) + { + const key: string = ite.ptr().first; + this._keys.pushBack(key); + ite.preIncrement(); + } + } + return this._keys; + } + + /** + * Mapの要素数を取得する + */ + public getSize(): number + { + return this._keys.getSize(); + } + + + private _map: csmMap; // JSON要素の値 + private _keys: csmVector; // JSON要素の値 + } +} \ No newline at end of file diff --git a/Framework/utils/cubismstring.ts b/Framework/utils/cubismstring.ts new file mode 100644 index 0000000..fefcb03 --- /dev/null +++ b/Framework/utils/cubismstring.ts @@ -0,0 +1,136 @@ +/* + * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +export namespace Live2DCubismFramework +{ + export class CubismString + { + /** + * 標準出力の書式を適用した文字列を取得する。 + * @param format 標準出力の書式指定文字列 + * @param ...args 書式指定文字列に渡す文字列 + * @return 書式を適用した文字列 + */ + public static getFormatedString(format: string, ... args: any[]): string + { + let ret: string = format; + return ret.replace( + /\{(\d+)\}/g, + (m, k) => // m="{0}", k="0" + { + return args[k]; + } + ); + } + + /** + * textがstartWordで始まっているかどうかを返す + * @param test 検査対象の文字列 + * @param startWord 比較対象の文字列 + * @return true textがstartWordで始まっている + * @return false textがstartWordで始まっていない + */ + public static isStartWith(text: string, startWord: string): boolean + { + let textIndex = 0; + let startWordIndex = 0; + while(startWord[startWordIndex] != '\0') + { + if(text[textIndex] == '\0' || text[textIndex++] != startWord[startWordIndex++]) + { + return false; + } + } + return false; + } + + /** + * position位置の文字から数字を解析する。 + * + * @param string 文字列 + * @param length 文字列の長さ + * @param position 解析したい文字の位置 + * @param outEndPos 一文字も読み込まなかった場合はエラー値(-1)が入る + * @return 解析結果の数値 + */ + public static stringToFloat(string: string, length: number, position: number, outEndPos: number[]): number + { + let i: number = position; + let minus: boolean = false; // マイナスフラグ + let period: boolean = false; + let v1: number = 0; + + //負号の確認 + let c: number = parseInt(string[i]); + if (c < 0) + { + minus = true; + i++; + } + + //整数部の確認 + for (; i < length; i++) + { + let c = string[i]; + if (0 <= parseInt(c) && parseInt(c) <= 9) + { + v1 = v1 * 10 + (parseInt(c) - 0); + } + else if (c == '.') + { + period = true; + i++; + break; + } + else + { + break; + } + } + + //小数部の確認 + if (period) + { + let mul: number = 0.1; + for (; i < length; i++) + { + c = parseFloat(string[i]) & 0xFF; + if (0 <= c && c <= 9) + { + v1 += mul * (c - 0); + } + else + { + break; + } + mul *= 0.1; //一桁下げる + if (!c) break; + } + } + + if (i == position) + { + //一文字も読み込まなかった場合 + outEndPos[0] = -1; //エラー値が入るので呼び出し元で適切な処理を行う + return 0; + } + + if (minus) v1 = -v1; + + outEndPos[0] = i; + return v1; + } + + /** + * コンストラクタ呼び出し不可な静的クラスにする。 + */ + private constructor() + { + + } + } +} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappdefine.ts b/Sample/TypeScript/Demo/src/lappdefine.ts new file mode 100644 index 0000000..df53e09 --- /dev/null +++ b/Sample/TypeScript/Demo/src/lappdefine.ts @@ -0,0 +1,70 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as live2dcubismframework, Option} from "../../../../Framework/live2dcubismframework"; +import Csm_CubismFramework_Option = Option; + +/** + * Sample Appで使用する定数 + */ +export namespace LAppDefine +{ + // 画面 + export const ViewMaxScale: number = 2.0; + export const ViewMinScale: number = 0.8; + + export const ViewLogicalLeft: number = -1.0; + export const ViewLogicalRight: number = 1.0; + + export const ViewLogicalMaxLeft: number = -2.0; + export const ViewLogicalMaxRight: number = 2.0; + export const ViewLogicalMaxBottom: number = -2.0; + export const ViewLogicalMaxTop: number = 2.0; + + // 相対パス + export const ResourcesPath: string = "./Resources/"; + + // モデルの後ろにある背景の画像ファイル + export const BackImageName: string = "back_class_normal.png"; + + // 歯車 + export const GearImageName: string = "icon_gear.png"; + + // 終了ボタン + export const PowerImageName: string = "CloseNormal.png"; + + // モデル定義--------------------------------------------- + // モデルを配置したディレクトリ名の配列 + // ディレクトリ名とmodel3.jsonの名前を一致させておくこと + export const ModelDir: string[] = [ + "Haru", + "Hiyori", + "Mark" + ] + export const ModelDirSize: number = ModelDir.length; + + // 外部定義ファイル(json)と合わせる + export const MotionGroupIdle: string = "Idle"; // アイドリング + export const MotionGroupTapBody: string = "TapBody"; // 体をタップしたとき + + // 外部定義ファイル(json)と合わせる + export const HitAreaNameHead: string = "Head"; + export const HitAreaNameBody: string = "Body"; + + // モーションの優先度定数 + export const PriorityNone: number = 0; + export const PriorityIdle: number = 1; + export const PriorityNormal: number = 2; + export const PriorityForce: number = 3; + + // デバッグ用ログの表示オプション + export const DebugLogEnable: boolean = true; + export const DebugTouchLogEnable: boolean = false; + + // Frameworkから出力するログのレベル設定 + export const CubismLoggingLevel: Csm_CubismFramework_Option.LogLevel = Csm_CubismFramework_Option.LogLevel.LogLevel_Verbose; +} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappdelegate.ts b/Sample/TypeScript/Demo/src/lappdelegate.ts new file mode 100644 index 0000000..69e2f58 --- /dev/null +++ b/Sample/TypeScript/Demo/src/lappdelegate.ts @@ -0,0 +1,340 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as live2dcubismframework, Option} from "../../../../Framework/live2dcubismframework"; +import {Live2DCubismFramework as cubismmatrix44} from "../../../../Framework/math/cubismmatrix44"; +import Csm_CubismMatrix44 = cubismmatrix44.CubismMatrix44; +import Csm_CubismFramework = live2dcubismframework.CubismFramework; +import Csm_Option = Option; +import { LAppView } from "./lappview"; +import { LAppPal } from "./lapppal"; +import { LAppTextureManager } from "./lapptexturemanager"; +import { LAppLive2DManager } from "./lapplive2dmanager"; + +export let canvas: HTMLCanvasElement = null; +export let s_instance: LAppDelegate = null; +export let gl: WebGLRenderingContext = null; + +/** + * アプリケーションクラス。 + * Cubism3の管理を行う。 + */ +export class LAppDelegate +{ + /** + * クラスのインスタンス(シングルトン)を返す。 + * インスタンスが生成されていない場合は内部でインスタンスを生成する。 + * + * @return クラスのインスタンス + */ + public static getInstance(): LAppDelegate + { + if(s_instance == null) + { + s_instance = new LAppDelegate(); + } + + return s_instance; + } + + /** + * クラスのインスタンス(シングルトン)を解放する。 + */ + public static releaseInstance(): void + { + if(s_instance != null) + { + s_instance = void 0; + } + + s_instance = null; + } + + /** + * APPに必要な物を初期化する。 + */ + public initialize(): boolean + { + // キャンバスの取得 + canvas = document.getElementById("SAMPLE"); + + // glコンテキストを初期化 + gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); + + if(!gl) + { + alert("WebGLを初期化できません。ブラウザはサポートしていないようです。"); + gl = null; + + // gl初期化失敗 + return false; + } + + // 透過設定 + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + + // マウス関連コールバック関数登録 + canvas.onmousedown = onClickBegan; + canvas.onmousemove = onMouseMoved; + canvas.onmouseup = onClickEnded; + + // AppViewの初期化 + this._view.initialize(); + + // Cubism3の初期化 + this.initializeCubism(); + + return true; + } + + /** + * 解放する。 + */ + public release(): void + { + this._textureManager = void 0; + this._view = void 0; + + // リソースを解放 + LAppLive2DManager.releaseInstance(); + + // Cubism3の解放 + Csm_CubismFramework.dispose(); + } + + /** + * 実行処理。 + */ + public run(): void + { + // メインループ + let loop = () => + { + // 時間更新 + LAppPal.updateTime(); + + // 画面の初期化 + gl.clearColor(0.0, 0.0, 0.0, 1.0); + + // 深度テストを有効化 + gl.enable(gl.DEPTH_TEST); + + // 近くにある物体は、遠くにある物体を覆い隠す + gl.depthFunc(gl.LEQUAL); + + // カラーバッファや深度バッファをクリアする + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + gl.clearDepth(1.0); + + this._view.initializeSprite(); + + // 描画更新 + this._view.render(); + + // ループのために再帰呼び出し + setTimeout(loop, 1000.0/60); + }; + loop(); + } + + /** + * シェーダーを登録する。 + */ + public createShader(): WebGLProgram + { + // バーテックスシェーダーのコンパイル + let vertexShaderId = gl.createShader(gl.VERTEX_SHADER); + + if(vertexShaderId == null) + { + console.log("failed to create vertexShader"); + return null; + } + + const vertexShader: string = + "precision mediump float;" + + "attribute vec3 position;" + + "attribute vec2 uv;" + + "varying vec2 vuv;" + + "void main(void)" + + "{" + + " gl_Position = vec4(position, 1.0);" + + " vuv = uv;" + + "}"; + + gl.shaderSource(vertexShaderId, vertexShader); + gl.compileShader(vertexShaderId); + + // フラグメントシェーダのコンパイル + let fragmentShaderId = gl.createShader(gl.FRAGMENT_SHADER); + + if(fragmentShaderId == null) + { + console.log("failed to create fragmentShader"); + return null; + } + + const fragmentShader: string = + "precision mediump float;" + + "varying vec2 vuv;" + + "uniform sampler2D texture;" + + "void main(void)" + + "{" + + " gl_FragColor = texture2D(texture, vuv);" + + "}"; + + gl.shaderSource(fragmentShaderId, fragmentShader); + gl.compileShader(fragmentShaderId); + + // プログラムオブジェクトの作成 + let programId = gl.createProgram(); + gl.attachShader(programId, vertexShaderId); + gl.attachShader(programId, fragmentShaderId); + + // リンク + gl.linkProgram(programId); + + gl.useProgram(programId); + + return programId; + } + + /** + * View情報を取得する。 + */ + public getView(): LAppView + { + return this._view; + } + + /** + * アプリケーションを終了するかどうか。 + */ + public getIsEnd(): boolean + { + return this._isEnd; + } + + /** + * アプリケーションを終了する。 + */ + public appEnd(): void + { + this._isEnd = true; + } + + public getTextureManager(): LAppTextureManager + { + return this._textureManager; + } + + /** + * コンストラクタ + */ + constructor() + { + this._captured = false; + this._mouseX = 0.0; + this._mouseY = 0.0; + this._isEnd = false; + + this._cubismOption = new Csm_Option(); + this._view = new LAppView(); + this._textureManager = new LAppTextureManager(); + } + + /** + * Cubism3の初期化 + */ + public initializeCubism(): void + { + // setup cubism + Csm_CubismFramework.startUp(); + + // initialize cubism + Csm_CubismFramework.initialize(); + + // load model + LAppLive2DManager.getInstance(); + + // default proj + let projection: Csm_CubismMatrix44 = new Csm_CubismMatrix44(); + + LAppPal.updateTime(); + } + + _cubismOption: Csm_Option; // Cubism3 Option + _view: LAppView; // View情報 + _captured: boolean; // クリックしているか + _mouseX: number; // マウスX座標 + _mouseY: number; // マウスY座標 + _isEnd: boolean; // APP終了しているか + _textureManager: LAppTextureManager;// テクスチャマネージャー +} + + + +/** + * クリックしたときに呼ばれる。 + */ +function onClickBegan(e: MouseEvent): void +{ + LAppDelegate.getInstance()._captured = true; + if(!LAppDelegate.getInstance()._view) + { + console.log("view notfound"); + return; + } + + let posX: number = e.pageX; + let posY: number = e.pageY; + + LAppDelegate.getInstance()._view.onTouchesBegan(posX, posY); +} + +/** + * マウスポインタが動いたら呼ばれる。 + */ +function onMouseMoved(e: MouseEvent): void +{ + let rect = e.toElement.getBoundingClientRect(); + let posX: number = e.clientX - rect.left; + let posY: number = e.clientY - rect.top; + + if(!LAppDelegate.getInstance()._captured) + { + return; + } + + if(!LAppDelegate.getInstance()._view) + { + console.log("view notfound"); + return; + } + + LAppDelegate.getInstance()._view.onTouchesMoved(posX, posY); +} + +/** + * クリックが終了したら呼ばれる。 + */ +function onClickEnded(e: MouseEvent): void +{ + LAppDelegate.getInstance()._captured = false; + let rect = e.toElement.getBoundingClientRect(); + let posX: number = e.clientX - rect.left; + let posY: number = e.clientY - rect.top; + + if(!LAppDelegate.getInstance()._view) + { + console.log("view notfound"); + return; + } + LAppDelegate.getInstance()._view.onTouchesEnded(posX, posY); +} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lapplive2dmanager.ts b/Sample/TypeScript/Demo/src/lapplive2dmanager.ts new file mode 100644 index 0000000..2a1e12c --- /dev/null +++ b/Sample/TypeScript/Demo/src/lapplive2dmanager.ts @@ -0,0 +1,218 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as cubismmatrix44} from "../../../../Framework/math/cubismmatrix44"; +import {Live2DCubismFramework as csmvector} from "../../../../Framework/type/csmvector"; +import Csm_csmVector = csmvector.csmVector; +import Csm_CubismMatrix44 = cubismmatrix44.CubismMatrix44; + +import { LAppModel } from "./lappmodel"; +import { LAppDefine } from "./lappdefine"; +import { LAppPal } from "./lapppal"; +import { canvas } from "./lappdelegate"; + + +export let s_instance: LAppLive2DManager = null; + +/** + * サンプルアプリケーションにおいてCubismModelを管理するクラス + * モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。 + */ +export class LAppLive2DManager +{ + /** + * クラスのインスタンス(シングルトン)を返す。 + * インスタンスが生成されていない場合は内部でインスタンスを生成する。 + * + * @return クラスのインスタンス + */ + public static getInstance(): LAppLive2DManager + { + if(s_instance == null) + { + s_instance = new LAppLive2DManager(); + } + + return s_instance; + } + + /** + * クラスのインスタンス(シングルトン)を解放する。 + */ + public static releaseInstance(): void + { + if(s_instance != null) + { + s_instance = void 0; + } + + s_instance = null; + } + + /** + * 現在のシーンで保持しているモデルを返す。 + * + * @param no モデルリストのインデックス値 + * @return モデルのインスタンスを返す。インデックス値が範囲外の場合はNULLを返す。 + */ + public getModel(no: number): LAppModel + { + if(no < this._models.getSize()) + { + return this._models.at(no); + } + + return null; + } + + /** + * 現在のシーンで保持しているすべてのモデルを解放する + */ + public releaseAllModel(): void + { + for(let i: number = 0; i < this._models.getSize(); i++) + { + this._models.set(i, void 0); + } + + this._models.clear(); + } + + /** + * 画面をドラッグした時の処理 + * + * @param x 画面のX座標 + * @param y 画面のY座標 + */ + public onDrag(x: number, y: number): void + { + for(let i: number = 0; i < this._models.getSize(); i++) + { + let model: LAppModel = this.getModel(i); + + if(model) + { + model.setDragging(x, y); + } + } + } + + /** + * 画面をタップした時の処理 + * + * @param x 画面のX座標 + * @param y 画面のY座標 + */ + public onTap(x: number, y: number): void + { + if(LAppDefine.DebugLogEnable) + { + LAppPal.printLog("[APP]tap point: {x: {0} y: {1}}", x.toFixed(2), y.toFixed(2)); + } + + for(let i: number = 0; i < this._models.getSize(); i++) + { + if(this._models.at(i).hitTest(LAppDefine.HitAreaNameHead, x, y)) + { + if(LAppDefine.DebugLogEnable) + { + LAppPal.printLog("[APP]hit area: [{0}]", LAppDefine.HitAreaNameHead); + } + this._models.at(i).setRandomExpression(); + } + else if(this._models.at(i).hitTest(LAppDefine.HitAreaNameBody, x, y)) + { + if(LAppDefine.DebugLogEnable) + { + LAppPal.printLog("[APP]hit area: [{0}]", LAppDefine.HitAreaNameBody); + } + this._models.at(i).startRandomMotion(LAppDefine.MotionGroupTapBody, LAppDefine.PriorityNormal); + } + } + } + + /** + * 画面を更新するときの処理 + * モデルの更新処理及び描画処理を行う + */ + public onUpdate(): void + { + let projection: Csm_CubismMatrix44 = new Csm_CubismMatrix44(); + + let width: number, height: number; + width = canvas.width; + height = canvas.height; + projection.scale(1.0, width / height); + + if(this._viewMatrix != null) + { + projection.multiplyByMatrix(this._viewMatrix); + } + + const saveProjection: Csm_CubismMatrix44 = projection; + let modelCount: number = this._models.getSize(); + + for(let i: number = 0; i < modelCount; ++i) + { + let model: LAppModel = this.getModel(i); + projection = saveProjection; + + model.update(); + model.draw(projection); // 参照渡しなのでprojectionは変質する。 + } + } + + /** + * 次のシーンに切りかえる + * サンプルアプリケーションではモデルセットの切り替えを行う。 + */ + public nextScene(): void + { + let no: number = (this._sceneIndex + 1) % LAppDefine.ModelDirSize; + this.changeScene(no); + } + + /** + * シーンを切り替える + * サンプルアプリケーションではモデルセットの切り替えを行う。 + */ + public changeScene(index: number): void + { + this._sceneIndex = index; + if(LAppDefine.DebugLogEnable) + { + LAppPal.printLog("[APP]model index: {0}", this._sceneIndex); + } + + // ModelDir[]に保持したディレクトリ名から + // model3.jsonのパスを決定する。 + // ディレクトリ名とmodel3.jsonの名前を一致させておくこと。 + let model: string = LAppDefine.ModelDir[index]; + let modelPath: string = LAppDefine.ResourcesPath + model + "/"; + let modelJsonName: string = LAppDefine.ModelDir[index]; + modelJsonName += ".model3.json"; + + this.releaseAllModel(); + this._models.pushBack(new LAppModel()); + this._models.at(0).loadAssets(modelPath, modelJsonName); + } + + /** + * コンストラクタ + */ + constructor() + { + this._viewMatrix = new Csm_CubismMatrix44(); + this._models = new Csm_csmVector(); + this._sceneIndex = 0; + this.changeScene(this._sceneIndex); + } + + _viewMatrix: Csm_CubismMatrix44; // モデル描画に用いるview行列 + _models: Csm_csmVector; // モデルインスタンスのコンテナ + _sceneIndex: number; // 表示するシーンのインデックス値 +} diff --git a/Sample/TypeScript/Demo/src/lappmodel.ts b/Sample/TypeScript/Demo/src/lappmodel.ts new file mode 100644 index 0000000..4fcfff7 --- /dev/null +++ b/Sample/TypeScript/Demo/src/lappmodel.ts @@ -0,0 +1,993 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as live2dcubismframework} from "../../../../Framework/live2dcubismframework"; +import {Live2DCubismFramework as cubismid} from "../../../../Framework/id/cubismid"; +import {Live2DCubismFramework as cubismusermodel} from "../../../../Framework/model/cubismusermodel"; +import {Live2DCubismFramework as icubismmodelsetting} from "../../../../Framework/icubismmodelsetting"; +import {Live2DCubismFramework as cubismmodelsettingjson} from "../../../../Framework/cubismmodelsettingjson"; +import {Live2DCubismFramework as cubismdefaultparameterid} from "../../../../Framework/cubismdefaultparameterid"; +import {Live2DCubismFramework as acubismmotion} from "../../../../Framework/motion/acubismmotion"; +import {Live2DCubismFramework as cubismeyeblink} from "../../../../Framework/effect/cubismeyeblink"; +import {Live2DCubismFramework as cubismbreath} from "../../../../Framework/effect/cubismbreath"; +import {Live2DCubismFramework as csmvector} from "../../../../Framework/type/csmvector"; +import {Live2DCubismFramework as csmmap} from "../../../../Framework/type/csmmap"; +import {Live2DCubismFramework as cubismmatrix44} from "../../../../Framework/math/cubismmatrix44"; +import {Live2DCubismFramework as cubismstring} from "../../../../Framework/utils/cubismstring"; +import {Live2DCubismFramework as cubismmotion} from "../../../../Framework/motion/cubismmotion"; +import {Live2DCubismFramework as cubismmotionqueuemanager} from "../../../../Framework/motion/cubismmotionqueuemanager"; +import {Live2DCubismFramework as csmstring} from "../../../../Framework/type/csmstring"; +import {Live2DCubismFramework as csmrect} from "../../../../Framework/type/csmrectf"; +import {CubismLogInfo} from "../../../../Framework/utils/cubismdebug"; +import csmRect = csmrect.csmRect; +import csmString = csmstring.csmString; +import InvalidMotionQueueEntryHandleValue = cubismmotionqueuemanager.InvalidMotionQueueEntryHandleValue; +import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle; +import CubismMotion = cubismmotion.CubismMotion; +import CubismString = cubismstring.CubismString; +import CubismMatrix44 = cubismmatrix44.CubismMatrix44; +import csmMap = csmmap.csmMap; +import csmVector = csmvector.csmVector; +import CubismBreath = cubismbreath.CubismBreath; +import CubismEyeBlink = cubismeyeblink.CubismEyeBlink; +import ACubismMotion = acubismmotion.ACubismMotion; +import CubismFramework = live2dcubismframework.CubismFramework; +import CubismIdHandle = cubismid.CubismIdHandle; +import CubismUserModel = cubismusermodel.CubismUserModel; +import ICubismModelSetting = icubismmodelsetting.ICubismModelSetting; +import CubismModelSettingJson = cubismmodelsettingjson.CubismModelSettingJson; +import CubismDefaultParameterId = cubismdefaultparameterid; + +import {LAppDefine} from "./lappdefine"; +import {LAppPal} from "./lapppal"; +import {gl} from "./lappdelegate"; + +function createBuffer(path: string, callBack: any): void +{ + LAppPal.loadFileAsBytes(path, callBack); +} + +function deleteBuffer(buffer: ArrayBuffer, path: string = "") +{ + LAppPal.releaseBytes(buffer); +} + +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 + { + this._modelHomeDir = dir; + + const path: string = dir + fileName; + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + let buffer: ArrayBuffer = arrayBuffer; + let size = buffer.byteLength; + let setting: ICubismModelSetting = new CubismModelSettingJson(buffer, size); + + // ステートを更新 + 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; + + let buffer: ArrayBuffer; + let size: number; + + // CubismModel + if (this._modelSetting.getModelFileName() != "") + { + let path: string = this._modelSetting.getModelFileName(); + path = this._modelHomeDir + path; + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + buffer = arrayBuffer; + this.loadModel(buffer); + deleteBuffer(buffer, path); + this._state = LoadStep.LoadExpression; + + // callback + loadCubismExpression(); + } + ); + + this._state = LoadStep.WaitLoadModel; + } + else + { + console.log("ModelData is not exist"); + } + + // Expression + let loadCubismExpression = () => + { + if(this._modelSetting.getExpressionCount() > 0) + { + const count: number = this._modelSetting.getExpressionCount(); + + for(let i: number = 0; i < count; i++) + { + let name: string = this._modelSetting.getExpressionName(i); + let path: string = this._modelSetting.getExpressionFileName(i); + path = this._modelHomeDir + path; + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + let buffer: ArrayBuffer = arrayBuffer; + let size: number = buffer.byteLength; + + let motion: ACubismMotion = this.loadExpression(buffer, size, name); + + if(this._expressions.getValue(name) != null) + { + ACubismMotion.delete(this._expressions.getValue(name)); + this._expressions.setValue(name, null); + } + + this._expressions.setValue(name, motion); + + deleteBuffer(buffer, path); + + this._expressionCount++; + + if(this._expressionCount >= count) + { + this._state = LoadStep.LoadPhysics; + + // callback + loadCubismPhysics(); + } + } + ); + } + this._state = LoadStep.WaitLoadExpression; + } + else + { + this._state = LoadStep.LoadPhysics; + + // callback + loadCubismPhysics(); + } + }; + + // Physics + let loadCubismPhysics = () => + { + if(this._modelSetting.getPhysicsFileName() != "") + { + let path: string = this._modelSetting.getPhysicsFileName(); + path = this._modelHomeDir + path; + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + let buffer: ArrayBuffer = arrayBuffer; + let size: number = buffer.byteLength; + + this.loadPhysics(buffer, size); + deleteBuffer(buffer, path); + + this._state = LoadStep.LoadPose; + + // callback + loadCubismPose(); + } + ); + this._state = LoadStep.WaitLoadPhysics; + } + else + { + this._state = LoadStep.LoadPose; + + // callback + loadCubismPose(); + } + }; + + // Pose + let loadCubismPose = () => + { + if(this._modelSetting.getPoseFileName() != "") + { + let path: string = this._modelSetting.getPoseFileName(); + path = this._modelHomeDir + path; + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + let buffer: ArrayBuffer = arrayBuffer; + let size: number = buffer.byteLength; + + this.loadPose(buffer, size); + deleteBuffer(buffer, path); + + this._state = LoadStep.SetupEyeBlink; + + // callback + setupEyeBlink(); + } + ); + this._state = LoadStep.WaitLoadPose; + } + else + { + this._state = LoadStep.SetupEyeBlink; + + // callback + setupEyeBlink(); + } + }; + + // EyeBlink + let setupEyeBlink = () => + { + if(this._modelSetting.getEyeBlinkParameterCount() > 0) + { + this._eyeBlink = CubismEyeBlink.create(this._modelSetting); + this._state = LoadStep.SetupBreath; + + } + + // callback + setupBreath(); + }; + + // Breath + let setupBreath = () => + { + this._breath = CubismBreath.create(); + + let breathParameters: csmVector = new csmVector(); + breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleX, 0.0, 15.0, 6.5345, 0.5)); + breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleY, 0.0, 8.0, 3.5345, 0.5)); + breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleZ, 0.0, 10.0, 5.5345, 0.5)); + breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamBodyAngleX, 0.0, 4.0, 15.5345, 0.5)); + breathParameters.pushBack(new CubismBreath.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 + let loadUserData = () => + { + if(this._modelSetting.getUserDataFile() != "") + { + let path: string = this._modelSetting.getUserDataFile(); + path = this._modelHomeDir + path; + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + let buffer: ArrayBuffer = arrayBuffer; + let size: number = buffer.byteLength; + + this.loadUserData(buffer, size); + deleteBuffer(buffer, path); + + this._state = LoadStep.SetupEyeBlinkIds; + + // callback + setupEyeBlinkIds(); + } + ); + + this._state = LoadStep.WaitLoadUserData; + } + else + { + this._state = LoadStep.SetupEyeBlinkIds; + + // callback + setupEyeBlinkIds(); + } + }; + + // EyeBlinkIds + let setupEyeBlinkIds = () => + { + let eyeBlinkIdCount: number = this._modelSetting.getEyeBlinkParameterCount(); + + for(let i: number = 0; i < eyeBlinkIdCount; ++i) + { + this._eyeBlinkIds.pushBack(this._modelSetting.getEyeBlinkParameterId(i)); + } + + this._state = LoadStep.SetupLipSyncIds; + + // callback + setupLipSyncIds(); + }; + + // LipSyncIds + let setupLipSyncIds = () => + { + let lipSyncIdCount = this._modelSetting.getLipSyncParameterCount(); + + for(let i: number = 0; i < lipSyncIdCount; ++i) + { + this._lipSyncIds.pushBack(this._modelSetting.getLipSyncParameterId(i)); + } + this._state = LoadStep.SetupLayout; + + // callback + setupLayout(); + }; + + // Layout + let setupLayout = () => + { + let layout: csmMap = new csmMap(); + this._modelSetting.getLayoutMap(layout); + this._modelMatrix.setupFromLayout(layout); + this._state = LoadStep.LoadMotion; + + // callback + loadCubismMotion(); + }; + + // Motion + let loadCubismMotion = () => + { + this._state = LoadStep.WaitLoadMotion; + this._model.saveParameters(); + this._allMotionCount = 0; + this._motionCount = 0; + let group: string[] = []; + + let motionGroupCount: number = this._modelSetting.getMotionGroupCount(); + + // モーションの総数を求める + for(let i: number = 0; i < motionGroupCount; i++) + { + group[i] = this._modelSetting.getMotionGroupName(i); + this._allMotionCount += this._modelSetting.getMotionCount(group[i]); + } + + // モーションの読み込み + for(let i: number = 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 + { + if(this._state == LoadStep.LoadTexture) + { + // テクスチャ読み込み用 + let textureCount: number = this._modelSetting.getTextureCount(); + let img: HTMLImageElement[] = new Array(textureCount); + + for(let modelTextureNumber = 0; modelTextureNumber < textureCount; modelTextureNumber++) + { + // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ + if(this._modelSetting.getTextureFileName(modelTextureNumber) == "") + { + console.log("getTextureFileName null"); + continue; + } + + // WebGLのテクスチャユニットにテクスチャをロードする + let texturePath = this._modelSetting.getTextureFileName(modelTextureNumber); + texturePath = this._modelHomeDir + texturePath; + + // データのオンロードをトリガーにする + img[modelTextureNumber] = new Image(); + img[modelTextureNumber].onload = () => + { + // テクスチャオブジェクトの作成 + let tex: WebGLTexture = gl.createTexture(); + + // テクスチャを選択 + gl.bindTexture(gl.TEXTURE_2D, tex); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + // テクスチャにピクセルを書き込む + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[modelTextureNumber]); + + // ミップマップを生成 + gl.generateMipmap(gl.TEXTURE_2D); + + this.getRenderer().bindTexture(modelTextureNumber, tex); + + this._textureCount++; + + if(this._textureCount >= textureCount) + { + // ロード完了 + this._state = LoadStep.CompleteSetup; + } + } + img[modelTextureNumber].src = texturePath; + + this.getRenderer().setIsPremultipliedAlpha(false); + } + + 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); + + } + 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) + { + let value: number = 0; // リアルタイムでリップシンクを行う場合、システムから音量を取得して、0~1の範囲で値を入力します。 + + for(let i: number = 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 優先度 + * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するisFinished()の引数で使用する。開始できない時は[-1] + */ + public startMotion(group: string, no: number, priority: number): CubismMotionQueueEntryHandle + { + if(priority == LAppDefine.PriorityForce) + { + this._motionManager.setReservePriority(priority); + } + else if(!this._motionManager.reserveMotion(priority)) + { + if(this._debugMode) + { + LAppPal.printLog("[APP]can't start motion."); + } + return InvalidMotionQueueEntryHandleValue; + } + + const fileName: string = this._modelSetting.getMotionFileName(group, no); + + // ex) idle_0 + let name: string = CubismString.getFormatedString("{0}_{1}", group, no); + let motion: CubismMotion = this._motions.getValue(name); + let autoDelete: boolean = false; + + if(motion == null) + { + let path: string = fileName; + path = this._modelHomeDir + path; + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + let buffer: ArrayBuffer = arrayBuffer; + let size = buffer.byteLength; + + motion = this.loadMotion(buffer, size, null); + 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; // 終了時にメモリから削除 + + deleteBuffer(buffer, path); + } + ); + } + + if(this._debugMode) + { + LAppPal.printLog("[APP]start motion: [{0}_{1}", group, no); + } + return this._motionManager.startMotionPriority(motion, autoDelete, priority); + } + + /** + * ランダムに選ばれたモーションの再生を開始する。 + * @param group モーショングループ名 + * @param priority 優先度 + * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するisFinished()の引数で使用する。開始できない時は[-1] + */ + public startRandomMotion(group: string, priority: number): CubismMotionQueueEntryHandle + { + if(this._modelSetting.getMotionCount(group) == 0) + { + return InvalidMotionQueueEntryHandleValue; + } + + let no: number = Math.floor(Math.random() * this._modelSetting.getMotionCount(group)); + + return this.startMotion(group, no, priority); + } + + /** + * 引数で指定した表情モーションをセットする + * + * @param expressionId 表情モーションのID + */ + public setExpression(expressionId: string): void + { + let motion: ACubismMotion = this._expressions.getValue(expressionId); + + if(this._debugMode) + { + LAppPal.printLog("[APP]expression: [{0}]", expressionId); + } + + if(motion != null) + { + this._expressionManager.startMotionPriority(motion, false, LAppDefine.PriorityForce); + } + else + { + if(this._debugMode) + { + LAppPal.printLog("[APP]expression[{0}] is null", expressionId); + } + } + } + + /** + * ランダムに選ばれた表情モーションをセットする + */ + public setRandomExpression(): void + { + if(this._expressions.getSize() == 0) + { + return; + } + + let no: number = Math.floor(Math.random() * this._expressions.getSize()); + + for(let i: number = 0; i < this._expressions.getSize(); i++) + { + if(i == no) + { + let 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の頂点リストから矩形を計算し、座標をが矩形範囲内か判定する。 + * + * @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: number = 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から取得する。 + * + * @param group モーションデータのグループ名 + */ + public preLoadMotionGroup(group: string): void + { + for(let i: number = 0; i < this._modelSetting.getMotionCount(group); i++) + { + // ex) idle_0 + let name: string = CubismString.getFormatedString("{0}_{1}", group, i); + let path = this._modelSetting.getMotionFileName(group, i); + path = this._modelHomeDir + path; + + if(this._debugMode) + { + LAppPal.printLog("[APP]load motion: {0} => [{1}_{2}]", path, group, i); + } + + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + let buffer: ArrayBuffer = arrayBuffer; + let size = buffer.byteLength; + + let tmpMotion: CubismMotion = this.loadMotion(buffer, size, 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); + + deleteBuffer(buffer, path); + + this._motionCount++; + if(this._motionCount >= this._allMotionCount) + { + this._state = LoadStep.LoadTexture; + + // 全てのモーションを停止する + this._motionManager.stopAllMotions(); + + this._updating = false; + this._initialized = true; + + this.createRenderer(); + this.setupTextures(); + this.getRenderer().startUp(gl); + } + } + ); + } + } + + /** + * すべてのモーションデータを解放する。 + */ + public releaseMotions(): void + { + this._motions.clear(); + } + + /** + * 全ての表情データを解放する。 + */ + public releaseExpressions(): void + { + this._expressions.clear(); + } + + /** + * モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。 + */ + public doDraw(): void + { + if(this._model == null) return; + + 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; // モーション総数 +} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lapppal.ts b/Sample/TypeScript/Demo/src/lapppal.ts new file mode 100644 index 0000000..fa5d819 --- /dev/null +++ b/Sample/TypeScript/Demo/src/lapppal.ts @@ -0,0 +1,102 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +/** + * プラットフォーム依存機能を抽象化する Cubism Platform Abstraction Layer. + * + * ファイル読み込みや時刻取得等のプラットフォームに依存する関数をまとめる。 + */ +export class LAppPal +{ + /** + * ファイルをバイトデータとして読みこむ + * + * @param filePath 読み込み対象ファイルのパス + * @return + * { + * buffer, 読み込んだバイトデータ + * size ファイルサイズ + * } + */ + public static loadFileAsBytes(filePath: string, callback: any): void + { + //filePath;// + const path: string = filePath; + + let size = 0; + fetch(path).then( + (response) => + { + return response.arrayBuffer(); + } + ).then( + (arrayBuffer) => + { + size = arrayBuffer.byteLength; + callback(arrayBuffer, size); + } + ); + } + + /** + * バイトデータを解放する + * @param byteData 解放したいバイトデータ + */ + public static releaseBytes(byteData: ArrayBuffer): void + { + byteData = void 0; + } + + /** + * デルタ時間(前回フレームとの差分)を取得する + * @return デルタ時間[ms] + */ + public static getDeltaTime(): number + { + return this.s_deltaTime; + } + + public static updateTime(): void + { + this.s_currentFrame = Date.now(); + this.s_deltaTime = (this.s_currentFrame - this.s_lastFrame) / 1000; + this.s_lastFrame = this.s_currentFrame; + } + + /** + * ログを出力する + * @param format 書式付き文字列 + * @param ... args(可変長引数)文字列 + */ + public static printLog(format: string, ... args: any[]): void + { + console.log( + format.replace( + /\{(\d+)\}/g, + (m, k) => + { + return args[k]; + } + ) + ); + } + + /** + * メッセージを出力する + * @param message 文字列 + */ + public static printMessage(message: string): void + { + this.printLog(message); + } + + static lastUpdate = Date.now(); + + static s_currentFrame = 0.0; + static s_lastFrame = 0.0; + static s_deltaTime = 0.0; +} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappsprite.ts b/Sample/TypeScript/Demo/src/lappsprite.ts new file mode 100644 index 0000000..7a7f37a --- /dev/null +++ b/Sample/TypeScript/Demo/src/lappsprite.ts @@ -0,0 +1,137 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import { gl, canvas } from "./lappdelegate"; + +/** + * スプライトを実装するクラス + * + * テクスチャID、Rectの管理 + */ + export class LAppSprite + { + /** + * コンストラクタ + * @param x x座標 + * @param y y座標 + * @param width 横幅 + * @param height 高さ + * @param textureId テクスチャ + */ + constructor(x: number, y: number, width: number, height: number, textureId: WebGLTexture) + { + this._rect = new Rect(); + this._rect.left = (x - width * 0.5); + this._rect.right = (x + width * 0.5); + this._rect.up = (y + height * 0.5); + this._rect.down = (y - height * 0.5); + this._texture = textureId; + } + + /** + * テクスチャを返す + */ + public getTexture(): WebGLTexture + { + return this._texture; + } + + /** + * 描画する。 + * @param programId シェーダープログラム + * @param canvas 描画するキャンパス情報 + */ + public render(programId: WebGLProgram): void + { + if(!this._texture) + { + return; + } + + // 何番目のattribute変数か + let positionLocation = gl.getAttribLocation(programId, "position"); + let uvLocation = gl.getAttribLocation(programId, "uv"); + + let textureLocation: WebGLUniformLocation = null; + textureLocation = gl.getUniformLocation(programId, "texture"); + + // attribute属性を有効にする + gl.enableVertexAttribArray(positionLocation); + gl.enableVertexAttribArray(uvLocation); + + // uniform属性の登録 + gl.uniform1i(textureLocation, 0); + + const uvVertex: Float32Array = new Float32Array([ + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0 + ]); + let vuv: WebGLBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vuv); + gl.bufferData(gl.ARRAY_BUFFER, uvVertex, gl.STATIC_DRAW); + + // attribute属性を登録 + gl.vertexAttribPointer(uvLocation, 2, gl.FLOAT, false, 0, 0); + + // 画面サイズを取得する。 + let maxWidth, maxHeight; + maxWidth = canvas.width; + maxHeight = canvas.height; + + // 頂点データ + let positionVertex: Float32Array = new Float32Array([ + (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), + (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), + (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5), + (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5) + ]); + + let vposition: WebGLBuffer = gl.createBuffer(); + gl.activeTexture(gl.TEXTURE0); + gl.bindBuffer(gl.ARRAY_BUFFER, vposition); + gl.bufferData(gl.ARRAY_BUFFER, positionVertex, gl.STATIC_DRAW); + + // attribute属性を登録 + gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); + + // モデルの描画 + gl.bindTexture(gl.TEXTURE_2D, this._texture); + gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); + } + + /** + * 当たり判定 + * @param pointX x座標 + * @param pointY y座標 + */ + public isHit(pointX: number, pointY: number): boolean + { + // 画面サイズを取得する。 + let maxWidth, maxHeight; + maxWidth = canvas.width; + maxHeight = canvas.height; + + // Y座標は変換する必要あり + let y = maxHeight - pointY; + + return (pointX >= this._rect.left && pointX <= this._rect.right && y <= this._rect.up && y >= this._rect.down); + } + + _texture: WebGLTexture; // テクスチャ + _rect: Rect; // 矩形 + } + + + export class Rect + { + public left: number; // 左辺 + public right: number; // 右辺 + public up: number; // 上辺 + public down: number; // 下辺 + } \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lapptexturemanager.ts b/Sample/TypeScript/Demo/src/lapptexturemanager.ts new file mode 100644 index 0000000..5731b60 --- /dev/null +++ b/Sample/TypeScript/Demo/src/lapptexturemanager.ts @@ -0,0 +1,168 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as csmvector} from "../../../../Framework/type/csmvector"; +import Csm_csmVector = csmvector.csmVector; +import { gl } from "./lappdelegate"; + +/** + * テクスチャ管理クラス + * 画像読み込み、管理を行うクラス。 + */ +export class LAppTextureManager +{ + /** + * コンストラクタ + */ + constructor() + { + this._textures = new Csm_csmVector(); + } + + /** + * プリマルチプライ処理 + * @param red 画像のRed値 + * @param green 画像のGreen値 + * @param blue 画像のBlue値 + * @param alpha 画像のAlpha値 + */ + public premultiply(red: number, green: number, blue: number, alpha: number): number + { + return ( + (red * (alpha + 1) >> 8) | + ((green * (alpha + 1) >> 8) << 8) | + ((blue * (alpha + 1) >> 8) << 16) | + (((alpha)) << 24) + ); + } + + /** + * 画像読み込み + * + * @param fileName 読み込む画像ファイルパス名 + * @return 画像情報、読み込み失敗時はnullを返す + */ + public createTextureFromPngFile(fileName: string, callback: any): TextureInfo + { + // search loaded texture already + for(let i: number = 0; i < this._textures.getSize(); i++) + { + if(this._textures.at(i).fileName == fileName) + { + return this._textures.at(i); + } + } + + // データのオンロードをトリガーにする + let img = new Image(); + img.onload = () => + { + // テクスチャオブジェクトの作成 + let tex: WebGLTexture = gl.createTexture(); + + // テクスチャを選択 + gl.bindTexture(gl.TEXTURE_2D, tex); + + // テクスチャにピクセルを書き込む + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + + // テクスチャにピクセルを書き込む + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); + + // ミップマップを生成 + gl.generateMipmap(gl.TEXTURE_2D); + + // テクスチャをバインド + gl.bindTexture(gl.TEXTURE_2D, tex); + + let textureInfo: TextureInfo = new TextureInfo(); + + if(textureInfo != null) + { + textureInfo.fileName = fileName; + textureInfo.width = img.width; + textureInfo.height = img.height; + textureInfo.id = tex; + this._textures.pushBack(textureInfo); + } + + callback(textureInfo); + } + img.src = fileName; + + return null; + } + + /** + * 画像の解放 + * + * 配列に存在する画像全てを解放する。 + */ + public releaseTextures(): void + { + for(let i: number = 0; i < this._textures.getSize(); i++) + { + this._textures.set(i, void 0); + } + + this._textures.clear(); + } + + /** + * 画像の解放 + * + * 指定したテクスチャの画像を解放する。 + * @param texture 解放するテクスチャ + */ + public releaseTextureByTexture(texture: WebGLTexture) + { + for(let i: number = 0; i < this._textures.getSize(); i++) + { + if(this._textures.at(i).id != texture) + { + continue; + } + + this._textures.set(i, void 0); + this._textures.remove(i); + break; + } + } + + /** + * 画像の解放 + * + * 指定した名前の画像を解放する。 + * @param fileName 解放する画像ファイルパス名 + */ + public releaseTextureByFilePath(fileName: string): void + { + for(let i: number = 0; i < this._textures.getSize(); i++) + { + if(this._textures.at(i).fileName == fileName) + { + this._textures.set(i, void 0); + this._textures.remove(i); + break; + } + } + } + + _textures: Csm_csmVector; +} + +/** + * 画像情報構造体 + */ +export class TextureInfo +{ + id: WebGLTexture = null; // テクスチャ + width: number = 0; // 横幅 + height: number = 0; // 高さ + fileName: string; // ファイル名 +} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappview.ts b/Sample/TypeScript/Demo/src/lappview.ts new file mode 100644 index 0000000..697f51f --- /dev/null +++ b/Sample/TypeScript/Demo/src/lappview.ts @@ -0,0 +1,290 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import {Live2DCubismFramework as cubismMatrix44} from "../../../../Framework/math/cubismmatrix44"; +import {Live2DCubismFramework as cubismviewmatrix} from "../../../../Framework/math/cubismviewmatrix"; +import Csm_CubismViewMatrix = cubismviewmatrix.CubismViewMatrix; +import Csm_CubismMatrix44 = cubismMatrix44.CubismMatrix44; +import { TouchManager } from "./touchmanager"; +import { LAppDefine } from "./lappdefine"; +import { LAppLive2DManager } from "./lapplive2dmanager"; +import { LAppDelegate, canvas} from "./lappdelegate"; +import { LAppSprite } from "./lappsprite"; +import { TextureInfo } from "./lapptexturemanager"; +import { LAppPal } from "./lapppal"; + +enum LoadStep +{ + BackImage, + GearImage, + PowerImage, + CompleteLoad +} + +/** + * 描画クラス。 + */ +export class LAppView +{ + /** + * コンストラクタ + */ + constructor() + { + this._loadStep = LoadStep.BackImage; + + this._programId = null; + this._back = null; + this._gear = null; + + // タッチ関係のイベント管理 + this._touchManager = new TouchManager(); + + // デバイス座標からスクリーン座標に変換するための + this._deviceToScreen = new Csm_CubismMatrix44(); + + // 画面の表示の拡大縮小や移動の変換を行う行列 + this._viewMatrix = new Csm_CubismViewMatrix(); + } + + /** + * 初期化する。 + */ + public initialize(): void + { + let width: number, height: number; + width = canvas.width; + height = canvas.height; + + let ratio: number = height / width; + let left: number = LAppDefine.ViewLogicalLeft; + let right: number = LAppDefine.ViewLogicalRight; + let bottom: number = -ratio; + let top: number = ratio; + + this._viewMatrix.setScreenRect(left, right, bottom, top); // デバイスに対応する画面の範囲。 Xの左端、Xの右端、Yの下端、Yの上端 + + let screenW: number = Math.abs(left - right); + this._deviceToScreen.scaleRelative(screenW / width, -screenW / width); + this._deviceToScreen.translateRelative(-width * 0.5, -height * 0.5); + + // 表示範囲の設定 + this._viewMatrix.setMaxScale(LAppDefine.ViewMaxScale); // 限界拡張率 + this._viewMatrix.setMinScale(LAppDefine.ViewMinScale); // 限界縮小率 + + // 表示できる最大範囲 + this._viewMatrix.setMaxScreenRect( + LAppDefine.ViewLogicalMaxLeft, + LAppDefine.ViewLogicalMaxRight, + LAppDefine.ViewLogicalMaxBottom, + LAppDefine.ViewLogicalMaxTop + ); + } + + /** + * 描画する。 + */ + public render(): void + { + if(this._loadStep != LoadStep.CompleteLoad) + { + return; + } + + if(this._back) + { + this._back.render(this._programId); + } + if(this._gear) + { + this._gear.render(this._programId); + } + + let live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance(); + + live2DManager.onUpdate(); + } + + /** + * 画像の初期化を行う。 + */ + public initializeSprite(): void + { + let width: number, height: number; + width = canvas.width; + height = canvas.height; + + let textureManager = LAppDelegate.getInstance().getTextureManager(); + const resourcesPath = LAppDefine.ResourcesPath; + + let imageName: string = ""; + + // 背景画像初期化 + if(this._loadStep == LoadStep.BackImage) + { + imageName = LAppDefine.BackImageName; + + // 非同期なのでコールバック関数を作成 + let initBackGroundTexture = (textureInfo: TextureInfo): void => + { + let x: number = width * 0.5; + let y: number = height * 0.5; + + let fwidth = textureInfo.width * 2.0; + let fheight = height * 0.95; + this._back = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); + this._loadStep = LoadStep.GearImage; + } + let backGroundTexture: TextureInfo = textureManager.createTextureFromPngFile(resourcesPath + imageName, initBackGroundTexture); + + // 既に画像があれば直接初期化 + if(backGroundTexture != null) + { + initBackGroundTexture(backGroundTexture); + } + } + + // 歯車画像初期化 + if(this._loadStep == LoadStep.GearImage) + { + imageName = LAppDefine.GearImageName; + let initGearTexture = (textureInfo: TextureInfo): void => + { + let x = width - textureInfo.width * 0.5; + let y = height - textureInfo.height * 0.5; + let fwidth = textureInfo.width; + let fheight = textureInfo.height; + this._gear = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); + + this._loadStep = LoadStep.CompleteLoad; + } + let gearTexture: TextureInfo = textureManager.createTextureFromPngFile(resourcesPath + imageName, initGearTexture); + + // 既に画像があれば直接初期化 + if(gearTexture != null) + { + initGearTexture(gearTexture); + } + } + + if(this._loadStep == LoadStep.CompleteLoad) + { + this._programId = LAppDelegate.getInstance().createShader(); + } + } + + /** + * タッチされた時に呼ばれる。 + * + * @param pointX スクリーンX座標 + * @param pointY スクリーンY座標 + */ + public onTouchesBegan(pointX: number, pointY: number): void + { + this._touchManager.touchesBegan(pointX, pointY); + } + + /** + * タッチしているときにポインタが動いたら呼ばれる。 + * + * @param pointX スクリーンX座標 + * @param pointY スクリーンY座標 + */ + public onTouchesMoved(pointX: number, pointY: number): void + { + let viewX: number = this.transformViewX(this._touchManager.getX()); + let viewY: number = this.transformViewY(this._touchManager.getY()); + + this._touchManager.touchesMoved(pointX, pointY); + + let live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance(); + live2DManager.onDrag(viewX, viewY); + } + + /** + * タッチが終了したら呼ばれる。 + * + * @param pointX スクリーンX座標 + * @param pointY スクリーンY座標 + */ + public onTouchesEnded(pointX: number, pointY: number): void + { + // タッチ終了 + let live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance(); + live2DManager.onDrag(0.0, 0.0); + + { + // シングルタップ + let x: number = this._deviceToScreen.transformX(this._touchManager.getX()); // 論理座標変換した座標を取得。 + let y: number = this._deviceToScreen.transformY(this._touchManager.getY()); // 論理座標変化した座標を取得。 + + if(LAppDefine.DebugTouchLogEnable) + { + LAppPal.printLog("[APP]touchesEnded x: {0} y: {1}", x, y); + } + live2DManager.onTap(x, y); + + // 歯車にタップしたか + if(this._gear.isHit(pointX, pointY)) + { + live2DManager.nextScene(); + } + } + } + + /** + * X座標をView座標に変換する。 + * + * @param deviceX デバイスX座標 + */ + public transformViewX(deviceX: number): number + { + let screenX: number = this._deviceToScreen.transformX(deviceX); // 論理座標変換した座標を取得。 + return this._viewMatrix.invertTransformX(screenX); // 拡大、縮小、移動後の値。 + } + + /** + * Y座標をView座標に変換する。 + * + * @param deviceY デバイスY座標 + */ + public transformViewY(deviceY: number): number + { + let screenY: number = this._deviceToScreen.transformY(deviceY); // 論理座標変換した座標を取得。 + return this._viewMatrix.invertTransformY(screenY); + } + + /** + * X座標をScreen座標に変換する。 + * @param deviceX デバイスX座標 + */ + public transformScreenX(deviceX: number): number + { + return this._deviceToScreen.transformX(deviceX); + } + + /** + * Y座標をScreen座標に変換する。 + * + * @param deviceY デバイスY座標 + */ + public transformScreenY(deviceY: number): number + { + return this._deviceToScreen.transformY(deviceY); + } + + _touchManager: TouchManager; // タッチマネージャー + _deviceToScreen: Csm_CubismMatrix44; // デバイスからスクリーンへの行列 + _viewMatrix: Csm_CubismViewMatrix; // viewMatrix + _programId: WebGLProgram; // シェーダID + _back: LAppSprite; // 背景画像 + _gear: LAppSprite; // ギア画像 + _changeModel: boolean; // モデル切り替えフラグ + _isClick: boolean; // クリック中 + + _loadStep: number; +} \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/main.ts b/Sample/TypeScript/Demo/src/main.ts new file mode 100644 index 0000000..b587f2d --- /dev/null +++ b/Sample/TypeScript/Demo/src/main.ts @@ -0,0 +1,32 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +import { LAppDelegate } from "./lappdelegate"; + +let main: any = () => +{ + // create the application instance + if(LAppDelegate.getInstance().initialize() == false) + { + console.log("application iniitalize"); + return; + } + + LAppDelegate.getInstance().run(); +} + + +main(); + +/** + * 終了時の処理 + */ +window.onbeforeunload = () => +{ + LAppDelegate.getInstance().release(); + LAppDelegate.releaseInstance(); +}; diff --git a/Sample/TypeScript/Demo/src/touchmanager.ts b/Sample/TypeScript/Demo/src/touchmanager.ts new file mode 100644 index 0000000..96006a1 --- /dev/null +++ b/Sample/TypeScript/Demo/src/touchmanager.ts @@ -0,0 +1,199 @@ +/* +* 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. +*/ + +export class TouchManager +{ + /** + * コンストラクタ + */ + constructor() + { + this._startX = 0.0; + this._startY = 0.0; + this._lastX = 0.0; + this._lastY = 0.0; + this._lastX1 = 0.0; + this._lastY1 = 0.0; + this._lastX2 = 0.0; + this._lastY2 = 0.0; + this._lastTouchDistance = 0.0; + this._deltaX = 0.0; + this._deltaY = 0.0; + this._scale = 1.0; + this._touchSingle = false; + this._flipAvailable = false; + } + + public getCenterX(): number + { + return this._lastX; + } + + public getCenterY(): number + { + return this._lastY; + } + + public getDeltaX(): number + { + return this._deltaX; + } + + public getDeltaY(): number + { + return this._deltaY; + } + + public getStartX(): number + { + return this._startX; + } + + public getStartY(): number + { + return this._startY; + } + + public getScale(): number + { + return this._scale; + } + + public getX(): number + { + return this._lastX; + } + + public getY(): number + { + return this._lastY; + } + + public getX1(): number + { + return this._lastX1; + } + + public getY1(): number + { + return this._lastY1; + } + + public getX2(): number + { + return this._lastX2; + } + + public getY2(): number + { + return this._lastY2; + } + + public isSingleTouch(): boolean + { + return this._touchSingle; + } + + public isFlickAvailable(): boolean + { + return this._flipAvailable; + } + + public disableFlick(): void + { + this._flipAvailable = false; + } + + /** + * タッチ開始時イベント + * @param deviceX タッチした画面のxの値 + * @param deviceY タッチした画面のyの値 + */ + public touchesBegan(deviceX: number, deviceY: number): void + { + this._lastX = deviceX; + this._lastY = deviceY; + this._startX = deviceX; + this._startY = deviceY; + this._lastTouchDistance = -1.0; + this._flipAvailable = true; + this._touchSingle = true; + } + + /** + * ドラッグ時のイベント + * @param deviceX タッチした画面のxの値 + * @param deviceY タッチした画面のyの値 + */ + public touchesMoved(deviceX: number, deviceY: number): void + { + this._lastX = deviceX; + this._lastY = deviceY; + this._lastTouchDistance = -1.0; + this._touchSingle = true; + } + + /** + * フリックの距離測定 + * @return フリック距離 + */ + public getFlickDistance(): number + { + return this.calculateDistance(this._startX, this._startY, this._lastX, this._lastY) + } + + /** + * 点1から点2への距離を求める + * + * @param x1 1つ目のタッチした画面のxの値 + * @param y1 1つ目のタッチした画面のyの値 + * @param x2 2つ目のタッチした画面のxの値 + * @param y2 2つ目のタッチした画面のyの値 + */ + public calculateDistance(x1: number, y1: number, x2: number, y2: number): number + { + return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + } + + /** + * 2つ目の値から、移動量を求める。 + * 違う方向の場合は移動量0。同じ方向の場合は、絶対値が小さい方の値を参照する。 + * + * @param v1 1つ目の移動量 + * @param v2 2つ目の移動量 + * + * @return 小さい方の移動量 + */ + public calculateMovingAmount(v1: number, v2: number): number + { + if ((v1 > 0.0) != (v2 > 0.0)) + { + return 0.0; + } + + let sign: number = v1 > 0.0 ? 1.0 : -1.0; + let absoluteValue1 = Math.abs(v1); + let absoluteValue2 = Math.abs(v2); + return sign * ((absoluteValue1 < absoluteValue2) ? absoluteValue1: absoluteValue2); + } + + + _startY: number; // タッチを開始した時のxの値 + _startX: number; // タッチを開始した時のyの値 + _lastX: number; // シングルタッチ時のxの値 + _lastY: number; // シングルタッチ時のyの値 + _lastX1: number; // ダブルタッチ時の一つ目のxの値 + _lastY1: number; // ダブルタッチ時の一つ目のyの値 + _lastX2: number; // ダブルタッチ時の二つ目のxの値 + _lastY2: number; // ダブルタッチ時の二つ目のyの値 + _lastTouchDistance: number; // 2本以上でタッチしたときの指の距離 + _deltaX: number; // 前回の値から今回の値へのxの移動距離。 + _deltaY: number; // 前回の値から今回の値へのyの移動距離。 + _scale: number; // このフレームで掛け合わせる拡大率。拡大操作中以外は1。 + _touchSingle: boolean; // シングルタッチ時はtrue + _flipAvailable: boolean; // フリップが有効かどうか +} \ No newline at end of file From c8506e984b22f50cd792a4b5d45cbe2292cb8bf4 Mon Sep 17 00:00:00 2001 From: cubism-dev Date: Thu, 25 Oct 2018 17:18:40 +0900 Subject: [PATCH 4/4] improve performance. --- .gitignore | 4 +- Framework/cubismdefaultparameterid.ts | 2 +- Framework/cubismframeworkconfig.ts | 2 +- Framework/cubismmodelsettingjson.ts | 5 +- Framework/effect/cubismbreath.ts | 84 +- Framework/effect/cubismeyeblink.ts | 63 +- Framework/effect/cubismpose.ts | 136 ++-- Framework/icubismallcator.ts | 2 +- Framework/icubismmodelsetting.ts | 2 +- Framework/id/cubismid.ts | 2 +- Framework/id/cubismidmanager.ts | 2 +- Framework/live2dcubismframework.ts | 23 +- Framework/math/cubismmath.ts | 2 +- Framework/math/cubismmatrix44.ts | 17 +- Framework/math/cubismmodelmatrix.ts | 7 +- Framework/math/cubismtargetpoint.ts | 2 +- Framework/math/cubismvector2.ts | 2 +- Framework/math/cubismviewmatrix.ts | 2 +- Framework/model/cubismmoc.ts | 12 +- Framework/model/cubismmodel.ts | 12 +- Framework/model/cubismmodeluserdata.ts | 12 +- Framework/model/cubismmodeluserdatajson.ts | 2 +- Framework/model/cubismusermodel.ts | 36 +- Framework/motion/acubismmotion.ts | 2 +- Framework/motion/cubismexpressionmotion.ts | 63 +- Framework/motion/cubismmotion.ts | 2 +- Framework/motion/cubismmotioninternal.ts | 2 +- Framework/motion/cubismmotionjson.ts | 2 +- Framework/motion/cubismmotionmanager.ts | 2 +- Framework/motion/cubismmotionqueueentry.ts | 2 +- Framework/motion/cubismmotionqueuemanager.ts | 13 +- Framework/physics/cubismphysics.ts | 40 +- Framework/physics/cubismphysicsinternal.ts | 2 +- Framework/physics/cubismphysicsjson.ts | 2 +- Framework/rendering/cubismrenderer.ts | 74 +- Framework/rendering/cubismrenderer_WebGL.ts | 728 ++++++------------ Framework/type/csmmap.ts | 166 ++-- Framework/type/csmrectf.ts | 2 +- Framework/type/csmstring.ts | 2 +- Framework/type/csmvector.ts | 179 +++-- Framework/utils/cubismdebug.ts | 42 +- Framework/utils/cubismjson.ts | 39 +- Framework/utils/cubismstring.ts | 2 +- README.md | 12 + Sample/TypeScript/Demo/src/lappdefine.ts | 7 +- Sample/TypeScript/Demo/src/lappdelegate.ts | 194 +++-- .../TypeScript/Demo/src/lapplive2dmanager.ts | 9 +- Sample/TypeScript/Demo/src/lappmodel.ts | 40 +- Sample/TypeScript/Demo/src/lapppal.ts | 2 +- Sample/TypeScript/Demo/src/lappsprite.ts | 180 +++-- .../TypeScript/Demo/src/lapptexturemanager.ts | 11 +- Sample/TypeScript/Demo/src/lappview.ts | 113 ++- Sample/TypeScript/Demo/src/main.ts | 4 +- Sample/TypeScript/Demo/src/touchmanager.ts | 2 +- package.json | 8 +- 55 files changed, 1168 insertions(+), 1213 deletions(-) diff --git a/.gitignore b/.gitignore index c5aaf13..ae146e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ .idea/ node_modules/ - -/Core/* -!Please copy cubism core for web \ No newline at end of file +Sample/TypeScript/Demo/dist/ diff --git a/Framework/cubismdefaultparameterid.ts b/Framework/cubismdefaultparameterid.ts index ad7514b..bf16da8 100644 --- a/Framework/cubismdefaultparameterid.ts +++ b/Framework/cubismdefaultparameterid.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/cubismframeworkconfig.ts b/Framework/cubismframeworkconfig.ts index b6edc37..535b519 100644 --- a/Framework/cubismframeworkconfig.ts +++ b/Framework/cubismframeworkconfig.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/cubismmodelsettingjson.ts b/Framework/cubismmodelsettingjson.ts index b0bed8e..d6935db 100644 --- a/Framework/cubismmodelsettingjson.ts +++ b/Framework/cubismmodelsettingjson.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -11,6 +11,7 @@ import {Live2DCubismFramework as cubismid} from "./id/cubismid"; import {Live2DCubismFramework as cubismjson} from "./utils/cubismjson"; import {Live2DCubismFramework as csmmap} from"./type/csmmap"; import csmMap = csmmap.csmMap; +import iterator = csmmap.iterator; import CubismFramework = cubismframework.CubismFramework; import CubismIdHandle = cubismid.CubismIdHandle; import CubismJson = cubismjson.CubismJson; @@ -396,7 +397,7 @@ export namespace Live2DCubismFramework let ret: boolean = false; - for(const ite: csmMap.iterator = map.begin(); ite.notEqual(map.end()); ite.preIncrement()) + for(const ite: iterator = map.begin(); ite.notEqual(map.end()); ite.preIncrement()) { outLayoutMap.setValue(ite.ptr().first, ite.ptr().second.toFloat()); ret = true; diff --git a/Framework/effect/cubismbreath.ts b/Framework/effect/cubismbreath.ts index 2a2a407..32dc4a2 100644 --- a/Framework/effect/cubismbreath.ts +++ b/Framework/effect/cubismbreath.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -37,15 +37,17 @@ export namespace Live2DCubismFramework */ public static delete(instance: CubismBreath): void { - instance = void 0; - instance = null; + if(instance != null) + { + instance = null; + } } /** * 呼吸のパラメータの紐づけ * @param breathParameters 呼吸を紐づけたいパラメータのリスト */ - public setParameters(breathParameters: csmVector): void + public setParameters(breathParameters: csmVector): void { this._breathParameters = breathParameters; } @@ -54,7 +56,7 @@ export namespace Live2DCubismFramework * 呼吸に紐づいているパラメータの取得 * @return 呼吸に紐づいているパラメータのリスト */ - public getParameters(): csmVector + public getParameters(): csmVector { return this._breathParameters; } @@ -72,7 +74,7 @@ export namespace Live2DCubismFramework for(let i: number = 0; i < this._breathParameters.getSize(); ++i) { - let data: CubismBreath.BreathParameterData = this._breathParameters.at(i); + let data: BreathParameterData = this._breathParameters.at(i); model.addParameterValueById( data.parameterId, @@ -91,50 +93,46 @@ export namespace Live2DCubismFramework this._currentTime = 0.0; } - _breathParameters: csmVector; // 呼吸にひもづいているパラメータのリスト + _breathParameters: csmVector; // 呼吸にひもづいているパラメータのリスト _currentTime: number; // 積算時間[秒] } - export namespace CubismBreath + /** + * 呼吸のパラメータ情報 + */ + export class BreathParameterData { /** - * 呼吸のパラメータ情報 + * コンストラクタ + * @param parameterId 呼吸をひもづけるパラメータID + * @param offset 呼吸を正弦波としたときの、波のオフセット + * @param peak 呼吸を正弦波としたときの、波の高さ + * @param cycle 呼吸を正弦波としたときの、波の周期 + * @param weight パラメータへの重み */ - export class BreathParameterData + constructor(parameterId?: CubismIdHandle, offset?: number, peak?: number, cycle?: number, weight?: number) { - /** - * コンストラクタ - * @param parameterId 呼吸をひもづけるパラメータID - * @param offset 呼吸を正弦波としたときの、波のオフセット - * @param peak 呼吸を正弦波としたときの、波の高さ - * @param cycle 呼吸を正弦波としたときの、波の周期 - * @param weight パラメータへの重み - */ - constructor(parameterId?: CubismIdHandle, offset?: number, peak?: number, cycle?: number, weight?: number) - { - this.parameterId = (parameterId == undefined) - ? null - : parameterId; - this.offset = (offset == undefined) - ? 0.0 - : offset; - this.peak = (peak == undefined) - ? 0.0 - : peak; - this.cycle = (cycle == undefined) - ? 0.0 - : cycle; - this.weight = (weight == undefined) - ? 0.0 - : weight; - } - - parameterId: CubismIdHandle; // 呼吸をひもづけるパラメータID\ - offset: number; // 呼吸を正弦波としたときの、波のオフセット - peak: number; // 呼吸を正弦波としたときの、波の高さ - cycle: number; // 呼吸を正弦波としたときの、波の周期 - weight: number; // パラメータへの重み + this.parameterId = (parameterId == undefined) + ? null + : parameterId; + this.offset = (offset == undefined) + ? 0.0 + : offset; + this.peak = (peak == undefined) + ? 0.0 + : peak; + this.cycle = (cycle == undefined) + ? 0.0 + : cycle; + this.weight = (weight == undefined) + ? 0.0 + : weight; } - + + parameterId: CubismIdHandle; // 呼吸をひもづけるパラメータID\ + offset: number; // 呼吸を正弦波としたときの、波のオフセット + peak: number; // 呼吸を正弦波としたときの、波の高さ + cycle: number; // 呼吸を正弦波としたときの、波の周期 + weight: number; // パラメータへの重み } } \ No newline at end of file diff --git a/Framework/effect/cubismeyeblink.ts b/Framework/effect/cubismeyeblink.ts index 15fb7ac..3a1a444 100644 --- a/Framework/effect/cubismeyeblink.ts +++ b/Framework/effect/cubismeyeblink.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -40,8 +40,10 @@ export namespace Live2DCubismFramework */ public static delete(eyeBlink: CubismEyeBlink): void { - eyeBlink = void 0; - eyeBlink = null; + if(eyeBlink != null) + { + eyeBlink = null; + } } /** @@ -97,57 +99,57 @@ export namespace Live2DCubismFramework switch(this._blinkingState) { - case CubismEyeBlink.EyeState.EyeState_Closing: + case EyeState.EyeState_Closing: t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._closingSeconds); if(t >= 1.0) { t = 1.0; - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Closed; + this._blinkingState = EyeState.EyeState_Closed; this._stateStartTimeSeconds = this._userTimeSeconds; } parameterValue = 1.0 - t; break; - case CubismEyeBlink.EyeState.EyeState_Closed: + case EyeState.EyeState_Closed: t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._closedSeconds); if(t >= 1.0) { - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Opening; + this._blinkingState = EyeState.EyeState_Opening; this._stateStartTimeSeconds = this._userTimeSeconds; } parameterValue = 0.0; break; - case CubismEyeBlink.EyeState.EyeState_Opening: + case EyeState.EyeState_Opening: t = ((this._userTimeSeconds - this._stateStartTimeSeconds) / this._openingSeconds); if(t >= 1.0) { t = 1.0; - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Interval; + this._blinkingState = EyeState.EyeState_Interval; this._nextBlinkingTime = this.determinNextBlinkingTiming(); } parameterValue = t; break; - case CubismEyeBlink.EyeState.EyeState_Interval: + case EyeState.EyeState_Interval: if(this._nextBlinkingTime < this._userTimeSeconds) { - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Closing; + this._blinkingState = EyeState.EyeState_Closing; this._stateStartTimeSeconds = this._userTimeSeconds; } parameterValue = 1.0; break; - case CubismEyeBlink.EyeState.EyeState_First: + case EyeState.EyeState_First: default: - this._blinkingState = CubismEyeBlink.EyeState.EyeState_Interval; + this._blinkingState = EyeState.EyeState_Interval; this._nextBlinkingTime = this.determinNextBlinkingTiming(); parameterValue = 1.0; @@ -171,7 +173,7 @@ export namespace Live2DCubismFramework */ public constructor(modelSetting: ICubismModelSetting) { - this._blinkingState = CubismEyeBlink.EyeState.EyeState_First; + this._blinkingState = EyeState.EyeState_First; this._nextBlinkingTime = 0.0; this._stateStartTimeSeconds = 0.0; this._blinkingIntervalSeconds = 4.0; @@ -212,27 +214,24 @@ export namespace Live2DCubismFramework _closedSeconds: number; // まぶたを閉じている動作の所要時間[秒] _openingSeconds: number; // まぶたを開く動作の所要時間[秒] _userTimeSeconds: number; // デルタ時間の積算値[秒] - } - - export namespace CubismEyeBlink - { - /** - * まばたきの状態 - * - * まばたきの状態を表す列挙型 - */ - export enum EyeState - { - EyeState_First = 0, // 初期状態 - EyeState_Interval, // まばたきしていない状態 - EyeState_Closing, // まぶたが閉じていく途中の状態 - EyeState_Closed, // まぶたが閉じている状態 - EyeState_Opening // まぶたが開いていく途中の状態 - } /** * IDで指定された目のパラメータが、0のときに閉じるなら true 、1の時に閉じるなら false 。 */ - export const CloseIfZero = true; + static readonly CloseIfZero: boolean = true; + } + + /** + * まばたきの状態 + * + * まばたきの状態を表す列挙型 + */ + export enum EyeState + { + EyeState_First = 0, // 初期状態 + EyeState_Interval, // まばたきしていない状態 + EyeState_Closing, // まぶたが閉じていく途中の状態 + EyeState_Closed, // まぶたが閉じている状態 + EyeState_Opening // まぶたが開いていく途中の状態 } } \ No newline at end of file diff --git a/Framework/effect/cubismpose.ts b/Framework/effect/cubismpose.ts index cd4aff6..02dfc68 100644 --- a/Framework/effect/cubismpose.ts +++ b/Framework/effect/cubismpose.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -12,6 +12,7 @@ import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework import {Live2DCubismFramework as cubismjson} from "../utils/cubismjson"; import CubismIdHandle = cubismid.CubismIdHandle; import csmVector = csmvector.csmVector; +import iterator = csmvector.iterator; import CubismModel = cubismmodel.CubismModel; import CubismFramework = cubismframework.CubismFramework; import CubismJson = cubismjson.CubismJson; @@ -73,7 +74,7 @@ export namespace Live2DCubismFramework for(let groupIndex: number = 0; groupIndex < idCount; ++groupIndex) { let partInfo: Value = idListInfo.getVector().at(groupIndex); - let partData: CubismPose.PartData = new CubismPose.PartData(); + let partData: PartData = new PartData(); const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(partInfo.getMap().getValue(Id).getRawString()); partData.partId = parameterId; @@ -86,7 +87,7 @@ export namespace Live2DCubismFramework for(let linkIndex: number = 0; linkIndex < linkCount; ++linkIndex) { - let linkPart: CubismPose.PartData = new CubismPose.PartData(); + let linkPart: PartData = new PartData(); const linkId: CubismIdHandle = CubismFramework.getIdManager().getId(linkListInfo.getVector().at(linkIndex).getString()); linkPart.partId = linkId; @@ -114,8 +115,10 @@ export namespace Live2DCubismFramework */ public static delete(pose: CubismPose): void { - pose = void 0; - pose = null; + if(pose != null) + { + pose = null; + } } /** @@ -201,7 +204,7 @@ export namespace Live2DCubismFramework { for(let groupIndex: number = 0; groupIndex < this._partGroups.getSize(); ++groupIndex) { - let partData: CubismPose.PartData = this._partGroups.at(groupIndex); + let partData: PartData = this._partGroups.at(groupIndex); if(partData.link.getSize() == 0) { @@ -213,7 +216,7 @@ export namespace Live2DCubismFramework for(let linkIndex: number = 0; linkIndex < partData.link.getSize(); ++linkIndex) { - let linkPart: CubismPose.PartData = partData.link.at(linkIndex); + let linkPart: PartData = partData.link.at(linkIndex); const linkPartIndex: number = linkPart.partIndex; if(linkPartIndex < 0) @@ -323,94 +326,91 @@ export namespace Live2DCubismFramework { this._fadeTimeSeconds = DefaultFadeInSeconds; this._lastModel = null; - this._partGroups = new csmVector(); + this._partGroups = new csmVector(); this._partGroupCounts = new csmVector(); } - _partGroups: csmVector; // パーツグループ + _partGroups: csmVector; // パーツグループ _partGroupCounts: csmVector; // それぞれのパーツグループの個数 _fadeTimeSeconds: number; // フェード時間[秒] _lastModel: CubismModel; // 前回操作したモデル } - export namespace CubismPose + /** + * パーツにまつわるデータを管理 + */ + export class PartData { /** - * パーツにまつわるデータを管理 + * コンストラクタ */ - export class PartData + constructor(v?: PartData) { - /** - * コンストラクタ - */ - constructor(v?: PartData) - { - this.parameterIndex = 0; - this.partIndex = 0; - this.link = new csmVector(); - - if(v != undefined) - { - this.partId = v.partId; - - for(const ite: csmVector.iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) - { - this.link.pushBack(ite.ptr().clone()); - } - } - } - - /** - * =演算子のオーバーロード - */ - public assignment(v: PartData): PartData + this.parameterIndex = 0; + this.partIndex = 0; + this.link = new csmVector(); + + if(v != undefined) { this.partId = v.partId; - for(const ite: csmVector.iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) + for(const ite: iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) { this.link.pushBack(ite.ptr().clone()); } - - return this; } + } - /** - * 初期化 - * @param model 初期化に使用するモデル - */ - public initialize(model: CubismModel): void - { - this.parameterIndex = model.getParameterIndex(this.partId); - this.partIndex = model.getPartIndex(this.partId); + /** + * =演算子のオーバーロード + */ + public assignment(v: PartData): PartData + { + this.partId = v.partId; - model.setParameterValueByIndex(this.parameterIndex, 1); + for(const ite: iterator = v.link.begin(); ite.notEqual(v.link.end()); ite.preIncrement()) + { + this.link.pushBack(ite.ptr().clone()); } - /** - * オブジェクトのコピーを生成する - */ - public clone(): PartData - { - let clonePartData: PartData = new PartData(); + return this; + } - clonePartData.partId = this.partId; - clonePartData.parameterIndex = this.parameterIndex; - clonePartData.partIndex = this.partIndex; - clonePartData.link = new csmVector(); + /** + * 初期化 + * @param model 初期化に使用するモデル + */ + public initialize(model: CubismModel): void + { + this.parameterIndex = model.getParameterIndex(this.partId); + this.partIndex = model.getPartIndex(this.partId); - for(let ite: csmVector.iterator = this.link.begin(); ite.notEqual(this.link.end()); ite.increment()) - { - clonePartData.link.pushBack(ite.ptr().clone()); - } + model.setParameterValueByIndex(this.parameterIndex, 1); + } + + /** + * オブジェクトのコピーを生成する + */ + public clone(): PartData + { + let clonePartData: PartData = new PartData(); - return clonePartData; + clonePartData.partId = this.partId; + clonePartData.parameterIndex = this.parameterIndex; + clonePartData.partIndex = this.partIndex; + clonePartData.link = new csmVector(); + + for(let ite: iterator = this.link.begin(); ite.notEqual(this.link.end()); ite.increment()) + { + clonePartData.link.pushBack(ite.ptr().clone()); } - - partId: CubismIdHandle; // パーツID - parameterIndex: number; // パラメータのインデックス - partIndex: number; // パーツのインデックス - link: csmVector; // 連動するパラメータ + + return clonePartData; } + + partId: CubismIdHandle; // パーツID + parameterIndex: number; // パラメータのインデックス + partIndex: number; // パーツのインデックス + link: csmVector; // 連動するパラメータ } } \ No newline at end of file diff --git a/Framework/icubismallcator.ts b/Framework/icubismallcator.ts index 93fd333..feafb80 100644 --- a/Framework/icubismallcator.ts +++ b/Framework/icubismallcator.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/icubismmodelsetting.ts b/Framework/icubismmodelsetting.ts index 943838b..3b85b4d 100644 --- a/Framework/icubismmodelsetting.ts +++ b/Framework/icubismmodelsetting.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/id/cubismid.ts b/Framework/id/cubismid.ts index 3ab56fb..8b850a5 100644 --- a/Framework/id/cubismid.ts +++ b/Framework/id/cubismid.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/id/cubismidmanager.ts b/Framework/id/cubismidmanager.ts index 012c70f..096ea52 100644 --- a/Framework/id/cubismidmanager.ts +++ b/Framework/id/cubismidmanager.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/live2dcubismframework.ts b/Framework/live2dcubismframework.ts index 692acbe..7c374da 100644 --- a/Framework/live2dcubismframework.ts +++ b/Framework/live2dcubismframework.ts @@ -214,13 +214,13 @@ export namespace Live2DCubismFramework * * @return 現在のログ出力レベル設定の値 */ - public static getLoggingLevel(): Option.LogLevel + public static getLoggingLevel(): LogLevel { if (s_option != null) { return s_option.loggingLevel; } - return Option.LogLevel.LogLevel_Off; + return LogLevel.LogLevel_Off; } /** @@ -263,21 +263,18 @@ export namespace Live2DCubismFramework export class Option { - loggingLevel: Option.LogLevel; // ログ出力レベルの設定 + loggingLevel: LogLevel; // ログ出力レベルの設定 } /** * ログ出力のレベル */ -export namespace Option +export enum LogLevel { - export enum LogLevel - { - LogLevel_Verbose = 0, // 詳細ログ - LogLevel_Debug, // デバッグログ - LogLevel_Info, // Infoログ - LogLevel_Warning, // 警告ログ - LogLevel_Error, // エラーログ - LogLevel_Off // ログ出力無効 - } + LogLevel_Verbose = 0, // 詳細ログ + LogLevel_Debug, // デバッグログ + LogLevel_Info, // Infoログ + LogLevel_Warning, // 警告ログ + LogLevel_Error, // エラーログ + LogLevel_Off // ログ出力無効 } diff --git a/Framework/math/cubismmath.ts b/Framework/math/cubismmath.ts index 6e62b58..0131ef4 100644 --- a/Framework/math/cubismmath.ts +++ b/Framework/math/cubismmath.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/math/cubismmatrix44.ts b/Framework/math/cubismmatrix44.ts index bef0756..0adf543 100644 --- a/Framework/math/cubismmatrix44.ts +++ b/Framework/math/cubismmatrix44.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -274,6 +274,21 @@ export namespace Live2DCubismFramework CubismMatrix44.multiply(m.getArray(), this._tr, this._tr); } + /** + * オブジェクトのコピーを生成する + */ + public clone(): CubismMatrix44 + { + let cloneMatrix: CubismMatrix44 = new CubismMatrix44(); + + for(let i: number = 0; i < this._tr.length; i++) + { + cloneMatrix._tr[i] = this._tr[i]; + } + + return cloneMatrix; + } + protected _tr: Float32Array; // 4x4行列データ } } \ No newline at end of file diff --git a/Framework/math/cubismmodelmatrix.ts b/Framework/math/cubismmodelmatrix.ts index aa694be..1bdcca1 100644 --- a/Framework/math/cubismmodelmatrix.ts +++ b/Framework/math/cubismmodelmatrix.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -8,6 +8,7 @@ import {Live2DCubismFramework as csmmap} from "../type/csmmap"; import {Live2DCubismFramework as cubismmatrix44} from "./cubismmatrix44"; import csmMap = csmmap.csmMap; +import iterator = csmmap.iterator; import CubismMatrix44 = cubismmatrix44.CubismMatrix44; @@ -202,7 +203,7 @@ export namespace Live2DCubismFramework const keyLeft = "left"; const keyRight = "right"; - for(const ite: csmMap.iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) + for(const ite: iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) { const key: string = ite.ptr().first; const value: number = ite.ptr().second; @@ -217,7 +218,7 @@ export namespace Live2DCubismFramework } } - for(const ite: csmMap.iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) + for(const ite: iterator = layout.begin(); ite.notEqual(layout.end()); ite.preIncrement()) { const key: string = ite.ptr().first; const value: number = ite.ptr().second; diff --git a/Framework/math/cubismtargetpoint.ts b/Framework/math/cubismtargetpoint.ts index f27f3f6..386831c 100644 --- a/Framework/math/cubismtargetpoint.ts +++ b/Framework/math/cubismtargetpoint.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/math/cubismvector2.ts b/Framework/math/cubismvector2.ts index 2f61e90..e3c50a3 100644 --- a/Framework/math/cubismvector2.ts +++ b/Framework/math/cubismvector2.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/math/cubismviewmatrix.ts b/Framework/math/cubismviewmatrix.ts index 17b0acd..8b882a6 100644 --- a/Framework/math/cubismviewmatrix.ts +++ b/Framework/math/cubismviewmatrix.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/model/cubismmoc.ts b/Framework/model/cubismmoc.ts index 2f09698..3d3cfbe 100644 --- a/Framework/model/cubismmoc.ts +++ b/Framework/model/cubismmoc.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -73,10 +73,12 @@ export namespace Live2DCubismFramework */ deleteModel(model: CubismModel): void { - model.release(); - model = void 0; - - --this._modelCount; + if(model != null) + { + model.release(); + model = null; + --this._modelCount; + } } diff --git a/Framework/model/cubismmodel.ts b/Framework/model/cubismmodel.ts index 833520e..2ec612c 100644 --- a/Framework/model/cubismmodel.ts +++ b/Framework/model/cubismmodel.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -13,7 +13,7 @@ import {Live2DCubismFramework as csmmap} from "../type/csmmap"; import {Live2DCubismFramework as csmvector} from "../type/csmvector"; import {CSM_ASSERT} from "../utils/cubismdebug"; import CubismFramework = cubismframework.CubismFramework; -import CubismRenderer = cubismrenderer.CubismRenderer; +import CubismBlendMode = cubismrenderer.CubismBlendMode; import csmVector = csmvector.csmVector; import csmMap = csmmap.csmMap; import CubismIdHandle = cubismid.CubismIdHandle; @@ -579,15 +579,15 @@ export namespace Live2DCubismFramework * @param drawableIndex Drawableのインデックス * @return drawableのブレンドモード */ - public getDrawableBlendMode(drawableIndex: number): CubismRenderer.CubismBlendMode + public getDrawableBlendMode(drawableIndex: number): CubismBlendMode { const constantFlags = this._model.drawables.constantFlags; return (Live2DCubismCore.Utils.hasBlendAdditiveBit(constantFlags[drawableIndex])) - ? CubismRenderer.CubismBlendMode.CubismBlendMode_Additive + ? CubismBlendMode.CubismBlendMode_Additive : (Live2DCubismCore.Utils.hasBlendMultiplicativeBit(constantFlags[drawableIndex])) - ? CubismRenderer.CubismBlendMode.CubismBlendMode_Multiplicative - : CubismRenderer.CubismBlendMode.CubismBlendMode_Normal; + ? CubismBlendMode.CubismBlendMode_Multiplicative + : CubismBlendMode.CubismBlendMode_Normal; } /** diff --git a/Framework/model/cubismmodeluserdata.ts b/Framework/model/cubismmodeluserdata.ts index e84724e..bd98846 100644 --- a/Framework/model/cubismmodeluserdata.ts +++ b/Framework/model/cubismmodeluserdata.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -62,9 +62,11 @@ export namespace Live2DCubismFramework */ public static delete(modelUserData: CubismModelUserData): void { - modelUserData.release(); - modelUserData = void 0; - modelUserData = null; + if(modelUserData != null) + { + modelUserData.release(); + modelUserData = null; + } } /** @@ -127,7 +129,7 @@ export namespace Live2DCubismFramework { for(let i: number = 0; i < this._userDataNodes.getSize(); ++i) { - this._userDataNodes.set(i, void 0); + this._userDataNodes.set(i, null); } this._userDataNodes = null; diff --git a/Framework/model/cubismmodeluserdatajson.ts b/Framework/model/cubismmodeluserdatajson.ts index c81ab6c..1a7da60 100644 --- a/Framework/model/cubismmodeluserdatajson.ts +++ b/Framework/model/cubismmodeluserdatajson.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/model/cubismusermodel.ts b/Framework/model/cubismusermodel.ts index 667cb2f..e3ba72a 100644 --- a/Framework/model/cubismusermodel.ts +++ b/Framework/model/cubismusermodel.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -319,9 +319,9 @@ export namespace Live2DCubismFramework */ public deleteRenderer(): void { - if(this._renderer) + if(this._renderer != null) { - this._renderer = void 0; + this._renderer.release(); this._renderer = null; } } @@ -406,33 +406,37 @@ export namespace Live2DCubismFramework */ public release() { - this._motionManager.release(); - this._motionManager = void 0; - this._motionManager = null; + if(this._motionManager != null) + { + this._motionManager.release(); + this._motionManager = null; + } - this._expressionManager.release(); - this._expressionManager = void 0; - this._expressionManager = null; + if(this._expressionManager != null) + { + this._expressionManager.release(); + this._expressionManager = null; + } - this._moc.deleteModel(this._model); - this._moc.release(); - this._moc = void 0; - this._moc = null; + if(this._moc != null) + { + this._moc.deleteModel(this._model); + this._moc.release(); + this._moc = null; + } - this._modelMatrix = void 0; this._modelMatrix = null; CubismPose.delete(this._pose); CubismEyeBlink.delete(this._eyeBlink); CubismBreath.delete(this._breath); - this._dragManager = void 0; this._dragManager = null; CubismPhysics.delete(this._physics); CubismModelUserData.delete(this._modelUserData); - this.deleteRenderer(); + this.deleteRenderer(); } protected _moc: CubismMoc; // Mocデータ diff --git a/Framework/motion/acubismmotion.ts b/Framework/motion/acubismmotion.ts index e0bad58..515d0d1 100644 --- a/Framework/motion/acubismmotion.ts +++ b/Framework/motion/acubismmotion.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/motion/cubismexpressionmotion.ts b/Framework/motion/cubismexpressionmotion.ts index 1635150..a2dd8d8 100644 --- a/Framework/motion/cubismexpressionmotion.ts +++ b/Framework/motion/cubismexpressionmotion.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -80,28 +80,28 @@ export namespace Live2DCubismFramework const value: number = param.getMap().getValue(ExpressionKeyValue).toFloat(); // 値 // 計算方法の設定 - let blendType: CubismExpressionMotion.ExpressionBlendType; + let blendType: ExpressionBlendType; if(param.getMap().getValue(ExpressionKeyBlend).isNull() || param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueAdd) { - blendType = this.ExpressionBlendType.ExpressionBlendType_Add; + blendType = ExpressionBlendType.ExpressionBlendType_Add; } else if(param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueMultiply) { - blendType = this.ExpressionBlendType.ExpressionBlendType_Multiply; + blendType = ExpressionBlendType.ExpressionBlendType_Multiply; } else if(param.getMap().getValue(ExpressionKeyBlend).getString() == BlendValueOverwrite) { - blendType = this.ExpressionBlendType.ExpressionBlendType_Overwrite; + blendType = ExpressionBlendType.ExpressionBlendType_Overwrite; } else { // その他 仕様にない値を設定した時は加算モードにすることで復旧 - blendType = this.ExpressionBlendType.ExpressionBlendType_Add; + blendType = ExpressionBlendType.ExpressionBlendType_Add; } // 設定オブジェクトを作成してリストに追加する - let item: CubismExpressionMotion.ExpressionParameter = new CubismExpressionMotion.ExpressionParameter(); + let item: ExpressionParameter = new ExpressionParameter(); item.parameterId = parameterId; item.blendType = blendType; @@ -125,21 +125,21 @@ export namespace Live2DCubismFramework { for(let i: number = 0; i < this._parameters.getSize(); ++i) { - let parameter: CubismExpressionMotion.ExpressionParameter = this._parameters.at(i); + let parameter: ExpressionParameter = this._parameters.at(i); switch(parameter.blendType) { - case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Add: + case ExpressionBlendType.ExpressionBlendType_Add: { model.addParameterValueById(parameter.parameterId, parameter.value, weight); break; } - case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Multiply: + case ExpressionBlendType.ExpressionBlendType_Multiply: { model.multiplyParameterValueById(parameter.parameterId, parameter.value, weight); break; } - case CubismExpressionMotion.ExpressionBlendType.ExpressionBlendType_Overwrite: + case ExpressionBlendType.ExpressionBlendType_Overwrite: { model.setParameterValueById(parameter.parameterId, parameter.value, weight) break; @@ -158,32 +158,29 @@ export namespace Live2DCubismFramework { super(); - this._parameters = new csmVector(); + this._parameters = new csmVector(); } - _parameters: csmVector; // 表情のパラメータ情報リスト + _parameters: csmVector; // 表情のパラメータ情報リスト } - export namespace CubismExpressionMotion + /** + * 表情パラメータ値の計算方式 + */ + export enum ExpressionBlendType { - /** - * 表情パラメータ値の計算方式 - */ - export enum ExpressionBlendType - { - ExpressionBlendType_Add = 0, // 加算 - ExpressionBlendType_Multiply = 1, // 乗算 - ExpressionBlendType_Overwrite = 2 // 上書き - } + ExpressionBlendType_Add = 0, // 加算 + ExpressionBlendType_Multiply = 1, // 乗算 + ExpressionBlendType_Overwrite = 2 // 上書き + } - /** - * 表情のパラメータ情報 - */ - export class ExpressionParameter - { - parameterId: CubismIdHandle; // パラメータID - blendType: ExpressionBlendType; // パラメータの演算種類 - value: number; // 値 - } - } + /** + * 表情のパラメータ情報 + */ + export class ExpressionParameter + { + parameterId: CubismIdHandle; // パラメータID + blendType: ExpressionBlendType; // パラメータの演算種類 + value: number; // 値 + } } \ No newline at end of file diff --git a/Framework/motion/cubismmotion.ts b/Framework/motion/cubismmotion.ts index f113db5..a5322c4 100644 --- a/Framework/motion/cubismmotion.ts +++ b/Framework/motion/cubismmotion.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/motion/cubismmotioninternal.ts b/Framework/motion/cubismmotioninternal.ts index 8794aa0..78cd828 100644 --- a/Framework/motion/cubismmotioninternal.ts +++ b/Framework/motion/cubismmotioninternal.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/motion/cubismmotionjson.ts b/Framework/motion/cubismmotionjson.ts index 8cc14cc..4f4049c 100644 --- a/Framework/motion/cubismmotionjson.ts +++ b/Framework/motion/cubismmotionjson.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/motion/cubismmotionmanager.ts b/Framework/motion/cubismmotionmanager.ts index 9299351..9870fe8 100644 --- a/Framework/motion/cubismmotionmanager.ts +++ b/Framework/motion/cubismmotionmanager.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/motion/cubismmotionqueueentry.ts b/Framework/motion/cubismmotionqueueentry.ts index a34b779..f80b75c 100644 --- a/Framework/motion/cubismmotionqueueentry.ts +++ b/Framework/motion/cubismmotionqueueentry.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/motion/cubismmotionqueuemanager.ts b/Framework/motion/cubismmotionqueuemanager.ts index 0166dd7..e4ce842 100644 --- a/Framework/motion/cubismmotionqueuemanager.ts +++ b/Framework/motion/cubismmotionqueuemanager.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -13,6 +13,7 @@ import {Live2DCubismFramework as csmstring} from '../type/csmstring'; import csmString = csmstring.csmString; import CubismModel = cubismmodel.CubismModel; import csmVector = csmvector.csmVector; +import iterator = csmvector.iterator; import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry; import ACubismMotion = acubismmotion.ACubismMotion; @@ -108,7 +109,7 @@ export namespace Live2DCubismFramework // ------- 処理を行う ------- // 既にモーションがあれば終了フラグを立てる - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) + for(let ite: iterator = this._motions.begin(); ite.notEqual(this._motions.end());) { let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); @@ -152,7 +153,7 @@ export namespace Live2DCubismFramework public isFinishedByHandle(motionQueueEntryNumber: CubismMotionQueueEntryHandle): boolean { // 既にモーションがあれば終了フラグを立てる - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());ite.increment()) + for(let ite: iterator = this._motions.begin(); ite.notEqual(this._motions.end());ite.increment()) { let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); @@ -177,7 +178,7 @@ export namespace Live2DCubismFramework // ------- 処理を行う ------- // 既にモーションがあれば終了フラグを立てる - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) + for(let ite: iterator = this._motions.begin(); ite.notEqual(this._motions.end());) { let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); @@ -207,7 +208,7 @@ export namespace Live2DCubismFramework { //------- 処理を行う ------- // 既にモーションがあれば終了フラグを立てる - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end()); ite.preIncrement()) + for(let ite: iterator = this._motions.begin(); ite.notEqual(this._motions.end()); ite.preIncrement()) { let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); @@ -252,7 +253,7 @@ export namespace Live2DCubismFramework // ------- 処理を行う -------- // 既にモーションがあれば終了フラグを立てる - for(let ite: csmVector.iterator = this._motions.begin(); ite.notEqual(this._motions.end());) + for(let ite: iterator = this._motions.begin(); ite.notEqual(this._motions.end());) { let motionQueueEntry: CubismMotionQueueEntry = ite.ptr(); diff --git a/Framework/physics/cubismphysics.ts b/Framework/physics/cubismphysics.ts index 4a7f6ad..79d15b7 100644 --- a/Framework/physics/cubismphysics.ts +++ b/Framework/physics/cubismphysics.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -67,9 +67,11 @@ export namespace Live2DCubismFramework */ public static delete(physics: CubismPhysics): void { - physics.release(); - physics = void 0; - physics = null; + if(physics != null) + { + physics.release(); + physics = null; + } } /** @@ -201,7 +203,7 @@ export namespace Live2DCubismFramework * オプションの設定 * @param options オプション */ - public setOptions(options: CubismPhysics.Options): void + public setOptions(options: Options): void { this._options = options; } @@ -210,7 +212,7 @@ export namespace Live2DCubismFramework * オプションの取得 * @return オプション */ - public getOption(): CubismPhysics.Options + public getOption(): Options { return this._options; } @@ -223,7 +225,7 @@ export namespace Live2DCubismFramework this._physicsRig = null; // set default options - this._options = new CubismPhysics.Options(); + this._options = new Options(); this._options.gravity.y = -1.0; this._options.gravity.x = 0; this._options.wind.x = 0; @@ -401,26 +403,22 @@ export namespace Live2DCubismFramework } _physicsRig: CubismPhysicsRig; // 物理演算のデータ - _options: CubismPhysics.Options; // オプション + _options: Options; // オプション } - export namespace CubismPhysics + /** + * 物理演算のオプション + */ + export class Options { - /** - * 物理演算のオプション - */ - export class Options + constructor() { - constructor() - { - this.gravity = new CubismVector2(0, 0); - this.wind = new CubismVector2(0, 0); - } - - gravity: CubismVector2; // 重力方向 - wind: CubismVector2; // 風の方向 + this.gravity = new CubismVector2(0, 0); + this.wind = new CubismVector2(0, 0); } + gravity: CubismVector2; // 重力方向 + wind: CubismVector2; // 風の方向 } /** diff --git a/Framework/physics/cubismphysicsinternal.ts b/Framework/physics/cubismphysicsinternal.ts index de54c9c..da51324 100644 --- a/Framework/physics/cubismphysicsinternal.ts +++ b/Framework/physics/cubismphysicsinternal.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/physics/cubismphysicsjson.ts b/Framework/physics/cubismphysicsjson.ts index bcb784f..00af2cc 100644 --- a/Framework/physics/cubismphysicsjson.ts +++ b/Framework/physics/cubismphysicsjson.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/rendering/cubismrenderer.ts b/Framework/rendering/cubismrenderer.ts index 5e8cf64..e70282a 100644 --- a/Framework/rendering/cubismrenderer.ts +++ b/Framework/rendering/cubismrenderer.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -62,17 +62,8 @@ export namespace Live2DCubismFramework public drawModel(): void { if(this.getModel() == null) return; - /** - * doDrawModelの描画前と描画後に以下の関数を呼んでください - * ・saveProfile(); - * ・restoreProfile(); - * これはレンダラの描画設定を保存復帰させることで、 - * モデル描画直前の状態に戻すための処理です。 - */ - this.saveProfile(); this.doDrawModel(); - this.restoreProfile(); } /** @@ -152,7 +143,7 @@ export namespace Live2DCubismFramework * * @return RGBAのカラー情報 */ - public getModelColor(): CubismRenderer.CubismTextureColor + public getModelColor(): CubismTextureColor { return JSON.parse(JSON.stringify(this._modelColor)); } @@ -232,7 +223,7 @@ export namespace Live2DCubismFramework this._isPremultipliedAlpha = false; this._anisortopy = 0.0; this._model = null; - this._modelColor = new CubismRenderer.CubismTextureColor(); + this._modelColor = new CubismTextureColor(); // 単位行列に初期化 this._mvpMatrix4x4 = new CubismMatrix44(); @@ -258,55 +249,42 @@ export namespace Live2DCubismFramework */ public abstract drawMesh(textureNo: number, indexCount: number, vertexCount: number, indexArray: Uint16Array, vertexArray: Float32Array, uvArray: Float32Array, - opacity: number, colorBlendMode: CubismRenderer.CubismBlendMode): void; - - /** - * モデル描画直前のレンダラのステートを保持する - */ - public abstract saveProfile(): void; - - /** - * モデル描画直前のレンダラのステートを復帰させる - */ - public abstract restoreProfile(): void; + opacity: number, colorBlendMode: CubismBlendMode): void; protected _mvpMatrix4x4: CubismMatrix44; // Model-View-Projection 行列 - protected _modelColor: CubismRenderer.CubismTextureColor; // モデル自体のカラー(RGBA) + protected _modelColor: CubismTextureColor; // モデル自体のカラー(RGBA) protected _isCulling: boolean; // カリングが有効ならtrue protected _isPremultipliedAlpha: boolean; // 乗算済みαならtrue protected _anisortopy: any; // テクスチャの異方性フィルタリングのパラメータ protected _model: CubismModel; // レンダリング対象のモデル } - export namespace CubismRenderer + export enum CubismBlendMode { - export enum CubismBlendMode - { - CubismBlendMode_Normal = 0, // 通常 - CubismBlendMode_Additive = 1, // 加算 - CubismBlendMode_Multiplicative = 2, // 乗算 - }; + CubismBlendMode_Normal = 0, // 通常 + CubismBlendMode_Additive = 1, // 加算 + CubismBlendMode_Multiplicative = 2, // 乗算 + }; + /** + * テクスチャの色をRGBAで扱うためのクラス + */ + export class CubismTextureColor + { /** - * テクスチャの色をRGBAで扱うためのクラス + * コンストラクタ */ - export class CubismTextureColor + constructor() { - /** - * コンストラクタ - */ - constructor() - { - this.R = 1.0; - this.G = 1.0; - this.B = 1.0; - this.A = 1.0; - } - - R: number; // 赤チャンネル - G: number; // 緑チャンネル - B: number; // 青チャンネル - A: number; // αチャンネル + this.R = 1.0; + this.G = 1.0; + this.B = 1.0; + this.A = 1.0; } + + R: number; // 赤チャンネル + G: number; // 緑チャンネル + B: number; // 青チャンネル + A: number; // αチャンネル } } \ No newline at end of file diff --git a/Framework/rendering/cubismrenderer_WebGL.ts b/Framework/rendering/cubismrenderer_WebGL.ts index b6e7395..fee248b 100644 --- a/Framework/rendering/cubismrenderer_WebGL.ts +++ b/Framework/rendering/cubismrenderer_WebGL.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -20,13 +20,17 @@ import csmMap = csmmap.csmMap; import csmVector = csmvector.csmVector; import CubismModel = cubismmodel.CubismModel; import CubismRenderer = cubismrenderer.CubismRenderer; +import CubismBlendMode = cubismrenderer.CubismBlendMode; +import CubismTextureColor = cubismrenderer.CubismTextureColor; export namespace Live2DCubismFramework { const ColorChannelCount: number = 4; // 実験時に1チャンネルの場合は1、RGBだけの場合は3、アルファも含める場合は4 - const shaderCount: number = 13; // シェーダーの数 = マスク生成用 + (通常用 + 加算 + 乗算) * (マスク無 + マスク有 + マスク無の乗算済アルファ対応版 + マスク有の乗算済アルファ対応版) + const shaderCount: number = 7; // シェーダーの数 = マスク生成用 + (通常用 + 加算 + 乗算) * (マスク無の乗算済アルファ対応版 + マスク有の乗算済アルファ対応版) let s_instance: CubismShader_WebGL; + let s_viewport: number[]; + let s_fbo: WebGLFramebuffer; /** * クリッピングマスクの処理を実行するクラス @@ -37,7 +41,7 @@ export namespace Live2DCubismFramework * カラーチャンネル(RGBA)のフラグを取得する * @param channelNo カラーチャンネル(RGBA)の番号(0:R, 1:G, 2:B, 3:A) */ - public getChannelFlagAsColor(channelNo: number): CubismRenderer.CubismTextureColor + public getChannelFlagAsColor(channelNo: number): CubismTextureColor { return this._channelColors.at(channelNo); } @@ -75,13 +79,10 @@ export namespace Live2DCubismFramework this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); this.gl.bindTexture(this.gl.TEXTURE_2D, null); - let tmpFrameBufferObject: GLint; - tmpFrameBufferObject = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING); - ret = this.gl.createFramebuffer(); this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, ret); this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._colorBuffer, 0); - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, tmpFrameBufferObject); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, s_fbo); this._maskTexture = new CubismRenderTextureResource(this._currentFrameNo, ret); } @@ -209,35 +210,35 @@ export namespace Live2DCubismFramework this._clippingMaskBufferSize = 256; this._clippingContextListForMask = new csmVector(); this._clippingContextListForDraw = new csmVector(); - this._channelColors = new csmVector(); + this._channelColors = new csmVector(); this._tmpBoundsOnModel = new csmRect(); this._tmpMatrix = new CubismMatrix44(); this._tmpMatrixForMask = new CubismMatrix44(); this._tmpMatrixForDraw = new CubismMatrix44(); this._maskTexture = null; - ; - let tmp: CubismRenderer.CubismTextureColor = new CubismRenderer.CubismTextureColor(); + + let tmp: CubismTextureColor = new CubismTextureColor(); tmp.R = 1.0; tmp.G = 0.0; tmp.B = 0.0; tmp.A = 0.0; this._channelColors.pushBack(tmp); - - tmp = new CubismRenderer.CubismTextureColor(); + + tmp = new CubismTextureColor(); tmp.R = 0.0; tmp.G = 1.0; tmp.B = 0.0; tmp.A = 0.0; this._channelColors.pushBack(tmp); - tmp = new CubismRenderer.CubismTextureColor(); + tmp = new CubismTextureColor(); tmp.R = 0.0; tmp.G = 0.0; tmp.B = 1.0; tmp.A = 0.0; this._channelColors.pushBack(tmp); - tmp = new CubismRenderer.CubismTextureColor(); + tmp = new CubismTextureColor(); tmp.R = 0.0; tmp.G = 0.0; tmp.B = 0.0; @@ -261,10 +262,9 @@ export namespace Live2DCubismFramework } this._clippingContextListForMask = null; - // _clippingContextListForDrawは_clippingContextListForMaskにあるインスタンスを指している。上記の処理により要素ごとのDELETEha不要。 + // _clippingContextListForDrawは_clippingContextListForMaskにあるインスタンスを指している。上記の処理により要素ごとのDELETEは不要。 for(let i: number = 0; i < this._clippingContextListForDraw.getSize(); i++) { - this._clippingContextListForDraw.at(i).release(); this._clippingContextListForDraw.set(i, null); } this._clippingContextListForDraw = null; @@ -272,21 +272,18 @@ export namespace Live2DCubismFramework if(this._maskTexture) { this.gl.deleteFramebuffer(this._maskTexture.texture); - - this._maskTexture = void 0; this._maskTexture = null; } for(let i: number = 0; i < this._channelColors.getSize(); i++) { - if(this._channelColors.at(i)) - { - this._channelColors.set(i, void 0); - } this._channelColors.set(i, null); } this._channelColors = null; + + // テクスチャ解放 + this.gl.deleteTexture(this._channelColors); } /** @@ -354,19 +351,9 @@ export namespace Live2DCubismFramework // マスク作成処理 if(usingClipCount > 0) { - // 現在のビューポートの値を退避 - let viewport: number[] = new Array(4); - - // 現在のビューポートの値を退避 - viewport = this.gl.getParameter(this.gl.VIEWPORT); - // 生成したFrameBufferと同じサイズでビューポートを設定 this.gl.viewport(0, 0, this._clippingMaskBufferSize, this._clippingMaskBufferSize); - // マスクactive切り替え前のFBOを退避 - let oldFBO: number; - oldFBO = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING); - // マスクをactiveにする this._maskRenderTexture = this.getMaskRenderTexture(); @@ -466,16 +453,16 @@ export namespace Live2DCubismFramework model.getDrawableVertices(clipDrawIndex), model.getDrawableVertexUvs(clipDrawIndex), model.getDrawableOpacity(clipDrawIndex), - CubismRenderer.CubismBlendMode.CubismBlendMode_Normal // クリッピングは通常描画を強制 + CubismBlendMode.CubismBlendMode_Normal // クリッピングは通常描画を強制 ); } } // --- 後処理 --- - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, oldFBO); // 描画対象を戻す + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, s_fbo); // 描画対象を戻す renderer.setClippingContextBufferForMask(null); - this.gl.viewport(viewport[0], viewport[1], viewport[2], viewport[3]); + this.gl.viewport(s_viewport[0], s_viewport[1], s_viewport[2], s_viewport[3]); } } @@ -679,7 +666,7 @@ export namespace Live2DCubismFramework public _colorBuffer: WebGLTexture; // マスク用カラーバッファーのアドレス public _currentFrameNo: number; // マスクテクスチャに与えるフレーム番号 - public _channelColors: csmVector; + public _channelColors: csmVector; public _maskTexture: CubismRenderTextureResource; // マスク用のテクスチャリソースのリスト public _clippingContextListForMask: csmVector; // マスク用クリッピングコンテキストのリスト public _clippingContextListForDraw: csmVector; // 描画用クリッピングコンテキストのリスト @@ -748,19 +735,16 @@ export namespace Live2DCubismFramework { if(this._layoutBounds != null) { - this._layoutBounds = void 0; this._layoutBounds = null; } if(this._allClippedDrawRect != null) { - this._allClippedDrawRect = void 0; this._allClippedDrawRect = null; } if(this._clippedDrawableIndexList != null) { - this._clippedDrawableIndexList = void 0; this._clippedDrawableIndexList = null; } } @@ -841,7 +825,7 @@ export namespace Live2DCubismFramework */ private constructor() { - this._shaderSets = new csmVector(); + this._shaderSets = new csmVector(); } /** @@ -872,21 +856,27 @@ export namespace Live2DCubismFramework vertexArray: Float32Array, indexArray: Uint16Array, uvArray: Float32Array, + bufferData: { + vertex: WebGLBuffer, + uv: WebGLBuffer, + index: WebGLBuffer, + }, opacity: number, - colorBlendMode: CubismRenderer.CubismBlendMode, - baseColor: CubismRenderer.CubismTextureColor, + colorBlendMode: CubismBlendMode, + baseColor: CubismTextureColor, isPremultipliedAlpha: boolean, matrix4x4: CubismMatrix44): void { + if(!isPremultipliedAlpha) + { + CubismLogError("NoPremultipliedAlpha is not allowed"); + } + if(this._shaderSets.getSize() == 0) { this.generateShaders(); } - let vertexBuffer = null; - let uvBuffer = null; - let indexBuffer = null; - // Blending let SRC_COLOR: number; let DST_COLOR: number; @@ -895,7 +885,7 @@ export namespace Live2DCubismFramework if(renderer.getClippingContextBufferForMask() != null) // マスク生成時 { - let shaderSet: CubismShader_WebGL.CubismShaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_SetupMask); + let shaderSet: CubismShaderSet = this._shaderSets.at(ShaderNames.ShaderNames_SetupMask); this.gl.useProgram(shaderSet.shaderProgram); // テクスチャ設定 @@ -904,28 +894,28 @@ export namespace Live2DCubismFramework this.gl.uniform1i(shaderSet.samplerTexture0Location, 0); // 頂点配列の設定(VBO) - if(vertexBuffer == null) + if(bufferData.vertex == null) { - vertexBuffer = this.gl.createBuffer(); + bufferData.vertex = this.gl.createBuffer(); } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.vertex); this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); // テクスチャ頂点の設定 - if(uvBuffer == null) + if(bufferData.uv == null) { - uvBuffer = this.gl.createBuffer(); + bufferData.uv = this.gl.createBuffer(); } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.uv); this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); // チャンネル const channelNo: number = renderer.getClippingContextBufferForMask()._layoutChannelNo; - let colorChannel: CubismRenderer.CubismTextureColor = renderer.getClippingContextBufferForMask().getClippingManager().getChannelFlagAsColor(channelNo); + let colorChannel: CubismTextureColor = renderer.getClippingContextBufferForMask().getClippingManager().getChannelFlagAsColor(channelNo); this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); this.gl.uniformMatrix4fv(shaderSet.uniformClipMatrixLocation, false, renderer.getClippingContextBufferForMask()._matrixForMask.getArray()); @@ -948,31 +938,31 @@ export namespace Live2DCubismFramework else // マスク生成以外の場合 { const masked: boolean = renderer.getClippingContextBufferForDraw() != null; // この描画オブジェクトはマスク対象か - const offset: number = (masked ? 1 : 0) + (isPremultipliedAlpha ? 2 : 0); + const offset: number = (masked ? 1 : 0); - let shaderSet: CubismShader_WebGL.CubismShaderSet = new CubismShader_WebGL.CubismShaderSet(); + let shaderSet: CubismShaderSet = new CubismShaderSet(); switch(colorBlendMode) { - case CubismRenderer.CubismBlendMode.CubismBlendMode_Normal: + case CubismBlendMode.CubismBlendMode_Normal: default: - shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Normal + offset); + shaderSet = this._shaderSets.at(ShaderNames.ShaderNames_NormalPremultipliedAlpha + offset); SRC_COLOR = this.gl.ONE; DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; SRC_ALPHA = this.gl.ONE; DST_ALPHA = this.gl.ONE_MINUS_SRC_ALPHA; break; - case CubismRenderer.CubismBlendMode.CubismBlendMode_Additive: - shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Add + offset); + case CubismBlendMode.CubismBlendMode_Additive: + shaderSet = this._shaderSets.at(ShaderNames.ShaderNames_AddPremultipliedAlpha + offset); SRC_COLOR = this.gl.ONE; DST_COLOR = this.gl.ONE; SRC_ALPHA = this.gl.ZERO; DST_ALPHA = this.gl.ONE; break; - case CubismRenderer.CubismBlendMode.CubismBlendMode_Multiplicative: - shaderSet = this._shaderSets.at(CubismShader_WebGL.ShaderNames.ShaderNames_Mult + offset); + case CubismBlendMode.CubismBlendMode_Multiplicative: + shaderSet = this._shaderSets.at(ShaderNames.ShaderNames_MultPremultipliedAlpha + offset); SRC_COLOR = this.gl.DST_COLOR; DST_COLOR = this.gl.ONE_MINUS_SRC_ALPHA; SRC_ALPHA = this.gl.ZERO; @@ -983,21 +973,21 @@ export namespace Live2DCubismFramework this.gl.useProgram(shaderSet.shaderProgram); // 頂点配列の設定 - if(vertexBuffer == null) + if(bufferData.vertex == null) { - vertexBuffer = this.gl.createBuffer(); + bufferData.vertex = this.gl.createBuffer(); } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.vertex); this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributePositionLocation); this.gl.vertexAttribPointer(shaderSet.attributePositionLocation, 2, this.gl.FLOAT, false, 0, 0); // テクスチャ頂点の設定 - if(uvBuffer == null) + if(bufferData.uv == null) { - uvBuffer = this.gl.createBuffer(); + bufferData.uv = this.gl.createBuffer(); } - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, bufferData.uv); this.gl.bufferData(this.gl.ARRAY_BUFFER, uvArray, this.gl.DYNAMIC_DRAW); this.gl.enableVertexAttribArray(shaderSet.attributeTexCoordLocation); this.gl.vertexAttribPointer(shaderSet.attributeTexCoordLocation, 2, this.gl.FLOAT, false, 0, 0); @@ -1014,7 +1004,7 @@ export namespace Live2DCubismFramework // 使用するカラーチャンネルを設定 const channelNo: number = renderer.getClippingContextBufferForDraw()._layoutChannelNo; - let colorChannel: CubismRenderer.CubismTextureColor = renderer.getClippingContextBufferForDraw().getClippingManager().getChannelFlagAsColor(channelNo); + let colorChannel: CubismTextureColor = renderer.getClippingContextBufferForDraw().getClippingManager().getChannelFlagAsColor(channelNo); this.gl.uniform4f(shaderSet.uniformChannelFlagLocation, colorChannel.R, colorChannel.G, colorChannel.B, colorChannel.A); } @@ -1029,12 +1019,12 @@ export namespace Live2DCubismFramework this.gl.uniform4f(shaderSet.uniformBaseColorLocation, baseColor.R, baseColor.G, baseColor.B, baseColor.A); } - // IBOを作成し、データを転送(OpenGLにはなかったが、これがないとdrawElenmentが使用できない) - if(indexBuffer == null) + // IBOを作成し、データを転送 + if(bufferData.index == null) { - indexBuffer = this.gl.createBuffer(); + bufferData.index = this.gl.createBuffer(); } - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, bufferData.index); this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, indexArray, this.gl.DYNAMIC_DRAW); this.gl.blendFuncSeparate(SRC_COLOR, DST_COLOR, SRC_ALPHA, DST_ALPHA); } @@ -1062,27 +1052,21 @@ export namespace Live2DCubismFramework { for(let i: number = 0; i < shaderCount; i++) { - this._shaderSets.pushBack(new CubismShader_WebGL.CubismShaderSet()); + this._shaderSets.pushBack(new CubismShaderSet()); } - this._shaderSets.at(0).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcSetupMask, CubismShader_WebGL.fragmentShaderSrcsetupMask); + this._shaderSets.at(0).shaderProgram = this.loadShaderProgram(vertexShaderSrcSetupMask, fragmentShaderSrcsetupMask); - this._shaderSets.at(1).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrc, CubismShader_WebGL.fragmentShaderSrc); - this._shaderSets.at(2).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcMasked, CubismShader_WebGL.fragmentShaderSrcMask); - this._shaderSets.at(3).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrc, CubismShader_WebGL.fragmentShaderSrcPremultipliedAlpha); - this._shaderSets.at(4).shaderProgram = this.loadShaderProgram(CubismShader_WebGL.vertexShaderSrcMasked, CubismShader_WebGL.fragmentShaderSrcMaskPremultipliedAlpha); + this._shaderSets.at(1).shaderProgram = this.loadShaderProgram(vertexShaderSrc, fragmentShaderSrcPremultipliedAlpha); + this._shaderSets.at(2).shaderProgram = this.loadShaderProgram(vertexShaderSrcMasked, fragmentShaderSrcMaskPremultipliedAlpha); // 加算も通常と同じシェーダーを利用する - this._shaderSets.at(5).shaderProgram = this._shaderSets.at(1).shaderProgram; - this._shaderSets.at(6).shaderProgram = this._shaderSets.at(2).shaderProgram; - this._shaderSets.at(7).shaderProgram = this._shaderSets.at(3).shaderProgram; - this._shaderSets.at(8).shaderProgram = this._shaderSets.at(4).shaderProgram; + this._shaderSets.at(3).shaderProgram = this._shaderSets.at(1).shaderProgram; + this._shaderSets.at(4).shaderProgram = this._shaderSets.at(2).shaderProgram; // 乗算も通常と同じシェーダーを利用する - this._shaderSets.at(9).shaderProgram = this._shaderSets.at(1).shaderProgram; - this._shaderSets.at(10).shaderProgram = this._shaderSets.at(2).shaderProgram; - this._shaderSets.at(11).shaderProgram = this._shaderSets.at(3).shaderProgram; - this._shaderSets.at(12).shaderProgram = this._shaderSets.at(4).shaderProgram; + this._shaderSets.at(5).shaderProgram = this._shaderSets.at(1).shaderProgram; + this._shaderSets.at(6).shaderProgram = this._shaderSets.at(2).shaderProgram; // SetupMask this._shaderSets.at(0).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(0).shaderProgram, "a_position"); @@ -1092,14 +1076,14 @@ export namespace Live2DCubismFramework this._shaderSets.at(0).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_channelFlag"); this._shaderSets.at(0).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(0).shaderProgram, "u_baseColor"); - // 通常 + // 通常(PremultipliedAlpha) this._shaderSets.at(1).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(1).shaderProgram, "a_position"); this._shaderSets.at(1).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(1).shaderProgram, "a_texCoord"); this._shaderSets.at(1).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "s_texture0"); this._shaderSets.at(1).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "u_matrix"); this._shaderSets.at(1).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(1).shaderProgram, "u_baseColor"); - // 通常(クリッピング) + // 通常(クリッピング、PremultipliedAlpha) this._shaderSets.at(2).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(2).shaderProgram, "a_position"); this._shaderSets.at(2).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(2).shaderProgram, "a_texCoord"); this._shaderSets.at(2).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "s_texture0"); @@ -1109,14 +1093,14 @@ export namespace Live2DCubismFramework this._shaderSets.at(2).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_channelFlag"); this._shaderSets.at(2).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(2).shaderProgram, "u_baseColor"); - // 通常(PremultipliedAlpha) + // 加算(PremultipliedAlpha) this._shaderSets.at(3).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(3).shaderProgram, "a_position"); this._shaderSets.at(3).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(3).shaderProgram, "a_texCoord"); this._shaderSets.at(3).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "s_texture0"); this._shaderSets.at(3).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "u_matrix"); this._shaderSets.at(3).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(3).shaderProgram, "u_baseColor"); - // 通常(クリッピング、PremultipliedAlpha) + // 加算(クリッピング、PremultipliedAlpha) this._shaderSets.at(4).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(4).shaderProgram, "a_position"); this._shaderSets.at(4).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(4).shaderProgram, "a_texCoord"); this._shaderSets.at(4).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "s_texture0"); @@ -1126,13 +1110,14 @@ export namespace Live2DCubismFramework this._shaderSets.at(4).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_channelFlag"); this._shaderSets.at(4).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(4).shaderProgram, "u_baseColor"); - // 加算 + // 乗算(PremultipliedAlpha) this._shaderSets.at(5).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(5).shaderProgram, "a_position"); this._shaderSets.at(5).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(5).shaderProgram, "a_texCoord"); this._shaderSets.at(5).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "s_texture0"); this._shaderSets.at(5).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "u_matrix"); this._shaderSets.at(5).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(5).shaderProgram, "u_baseColor"); - // 加算(クリッピング) + + // 乗算(クリッピング、PremultipliedAlpha) this._shaderSets.at(6).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(6).shaderProgram, "a_position"); this._shaderSets.at(6).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(6).shaderProgram, "a_texCoord"); this._shaderSets.at(6).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "s_texture0"); @@ -1141,57 +1126,6 @@ export namespace Live2DCubismFramework this._shaderSets.at(6).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_clipMatrix"); this._shaderSets.at(6).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_channelFlag"); this._shaderSets.at(6).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(6).shaderProgram, "u_baseColor"); - - // 加算(PremultipliedAlpha) - this._shaderSets.at(7).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(7).shaderProgram, "a_position"); - this._shaderSets.at(7).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(7).shaderProgram, "a_texCoord"); - this._shaderSets.at(7).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "s_texture0"); - this._shaderSets.at(7).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "u_matrix"); - this._shaderSets.at(7).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(7).shaderProgram, "u_baseColor"); - - // 加算(クリッピング、PremultipliedAlpha) - this._shaderSets.at(8).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(8).shaderProgram, "a_position"); - this._shaderSets.at(8).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(8).shaderProgram, "a_texCoord"); - this._shaderSets.at(8).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "s_texture0"); - this._shaderSets.at(8).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "s_texture1"); - this._shaderSets.at(8).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_matrix"); - this._shaderSets.at(8).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(8).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_channelFlag"); - this._shaderSets.at(8).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(8).shaderProgram, "u_baseColor"); - - // 乗算 - this._shaderSets.at(9).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(9).shaderProgram, "a_position"); - this._shaderSets.at(9).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(9).shaderProgram, "a_texCoord"); - this._shaderSets.at(9).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "s_texture0"); - this._shaderSets.at(9).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "u_matrix"); - this._shaderSets.at(9).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(9).shaderProgram, "u_baseColor"); - - // 乗算(クリッピング) - this._shaderSets.at(10).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(10).shaderProgram, "a_position"); - this._shaderSets.at(10).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(10).shaderProgram, "a_texCoord"); - this._shaderSets.at(10).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "s_texture0"); - this._shaderSets.at(10).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "s_texture1"); - this._shaderSets.at(10).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_matrix"); - this._shaderSets.at(10).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(10).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_channelFlag"); - this._shaderSets.at(10).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(10).shaderProgram, "u_baseColor"); - - // 乗算(PremultipliedAlpha) - this._shaderSets.at(11).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(11).shaderProgram, "a_position"); - this._shaderSets.at(11).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(11).shaderProgram, "a_texCoord"); - this._shaderSets.at(11).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "s_texture0"); - this._shaderSets.at(11).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "u_matrix"); - this._shaderSets.at(11).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(11).shaderProgram, "u_baseColor"); - - // 乗算(クリッピング、PremultipliedAlpha) - this._shaderSets.at(12).attributePositionLocation = this.gl.getAttribLocation(this._shaderSets.at(12).shaderProgram, "a_position"); - this._shaderSets.at(12).attributeTexCoordLocation = this.gl.getAttribLocation(this._shaderSets.at(12).shaderProgram, "a_texCoord"); - this._shaderSets.at(12).samplerTexture0Location = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "s_texture0"); - this._shaderSets.at(12).samplerTexture1Location = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "s_texture1"); - this._shaderSets.at(12).uniformMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_matrix"); - this._shaderSets.at(12).uniformClipMatrixLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_clipMatrix"); - this._shaderSets.at(12).uniformChannelFlagLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_channelFlag"); - this._shaderSets.at(12).uniformBaseColorLocation = this.gl.getUniformLocation(this._shaderSets.at(12).shaderProgram, "u_baseColor"); } /** @@ -1251,10 +1185,7 @@ export namespace Live2DCubismFramework } // Release vertex and fragment shaders. - this.gl.detachShader(shaderProgram, vertShader); this.gl.deleteShader(vertShader); - - this.gl.detachShader(shaderProgram, fragShader); this.gl.deleteShader(fragShader); return shaderProgram; @@ -1296,344 +1227,137 @@ export namespace Live2DCubismFramework this.gl = gl; } - _shaderSets: csmVector; // ロードしたシェーダープログラムを保持する変数 + _shaderSets: csmVector; // ロードしたシェーダープログラムを保持する変数 gl: WebGLRenderingContext; // webglコンテキスト } /** * CubismShader_WebGLのインナークラス */ - export namespace CubismShader_WebGL + export class CubismShaderSet { - export class CubismShaderSet - { - shaderProgram: WebGLProgram; // シェーダープログラムのアドレス - attributePositionLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(Position) - attributeTexCoordLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(TexCoord) - uniformMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Matrix) - uniformClipMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ClipMatrix) - samplerTexture0Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture0) - samplerTexture1Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture1) - uniformBaseColorLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(BaseColor) - uniformChannelFlagLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ChannelFlag) - } - - export enum ShaderNames - { - // SetupMask - ShaderNames_SetupMask, - - // Normal - ShaderNames_Normal, - ShaderNames_NormalMasked, - ShaderNames_NormalPremultipliedAlpha, - ShaderNames_NormalMaskedPremultipliedAlpha, - - // Add - ShaderNames_Add, - ShaderNames_AddMasked, - ShaderNames_AddPremultipliedAlpha, - ShaderNames_AddMaskedPremultipledAlpha, - - // Mult - ShaderNames_Mult, - ShaderNames_MultMasked, - ShaderNames_MultPremultipliedAlpha, - ShaderNames_MultMaskedPremultipliedAlpha, - }; - - export const vertexShaderSrcSetupMask = - "attribute vec4 a_position;" + - "attribute vec2 a_texCoord;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_myPos;" + - "uniform mat4 u_clipMatrix;" + - "void main()" + - "{" + - " gl_Position = u_clipMatrix * a_position;" + - " v_myPos = u_clipMatrix * a_position;" + - " v_texCoord = a_texCoord;" + - " v_texCoord.y = 1.0 - v_texCoord.y;" + - "}"; - export const fragmentShaderSrcsetupMask = - "precision mediump float;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_myPos;" + - "uniform sampler2D s_texture0;" + - "uniform vec4 u_channelFlag;" + - "uniform vec4 u_baseColor;" + - "void main()" + - "{" + - " float isInside = " + - " step(u_baseColor.x, v_myPos.x/v_myPos.w)" + - " * step(u_baseColor.y, v_myPos.y/v_myPos.w)" + - " * step(v_myPos.x/v_myPos.w, u_baseColor.z)" + - " * step(v_myPos.y/v_myPos.w, u_baseColor.w);" + - " gl_FragColor = u_channelFlag * texture2D(s_texture0, v_texCoord).a * isInside;" + - "}"; - - //----- バーテックスシェーダプログラム ----- - // Normal & Add & Mult 共通 - export const vertexShaderSrc = - "attribute vec4 a_position;" + //v.vertex - "attribute vec2 a_texCoord;" + //v.texcoord - "varying vec2 v_texCoord;" + //v2f.texcoord - "uniform mat4 u_matrix;" + - "void main()" + - "{" + - " gl_Position = u_matrix * a_position;" + - " v_texCoord = a_texCoord;" + - " v_texCoord.y = 1.0 - v_texCoord.y;" + - "}"; - - // Normal & Add & Mult 共通(クリッピングされたものの描画用) - export const vertexShaderSrcMasked = - "attribute vec4 a_position;" + - "attribute vec2 a_texCoord;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_clipPos;" + - "uniform mat4 u_matrix;" + - "uniform mat4 u_clipMatrix;" + - "void main()" + - "{" + - " gl_Position = u_matrix * a_position;" + - " v_clipPos = u_clipMatrix * a_position;" + - " v_texCoord = a_texCoord;" + - " v_texCoord.y = 1.0 - v_texCoord.y;" + - "}"; - - //----- フラグメントシェーダプログラム ----- - // Normal & Add & Mult 共通 - export const fragmentShaderSrc = - "precision mediump float;" + - "varying vec2 v_texCoord;" + //v2f.texcoord - "uniform sampler2D s_texture0;" + //_MainTex - "uniform vec4 u_baseColor;" + //v2f.color - "void main()" + - "{" + - " vec4 color = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - " gl_FragColor = vec4(color.rgb * color.a, color.a);" + - "}"; - - // Normal & Add & Mult 共通 (PremultipliedAlpha) - export const fragmentShaderSrcPremultipliedAlpha = - "precision mediump float;" + - "varying vec2 v_texCoord;" + //v2f.texcoord - "uniform sampler2D s_texture0;" + //_MainTex - "uniform vec4 u_baseColor;" + //v2f.color - "void main()" + - "{" + - " gl_FragColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - "}"; - - // Normal & Add & Mult 共通(クリッピングされたものの描画用) - export const fragmentShaderSrcMask = - "precision mediump float;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_clipPos;" + - "uniform sampler2D s_texture0;" + - "uniform sampler2D s_texture1;" + - "uniform vec4 u_channelFlag;" + - "uniform vec4 u_baseColor;" + - "void main()" + - "{" + - " vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - " col_formask.rgb = col_formask.rgb * col_formask.a ;" + - " vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" + - " float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" + - " col_formask = col_formask * maskVal;" + - " gl_FragColor = col_formask;" + - "}"; - - // Normal (クリッピングされたものの描画用、PremultipliedAlpha兼用) - export const fragmentShaderSrcMaskPremultipliedAlpha = - "precision mediump float;" + - "varying vec2 v_texCoord;" + - "varying vec4 v_clipPos;" + - "uniform sampler2D s_texture0;" + - "uniform sampler2D s_texture1;" + - "uniform vec4 u_channelFlag;" + - "uniform vec4 u_baseColor;" + - "void main()" + - "{" + - " vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + - " vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" + - " float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" + - " col_formask = col_formask * maskVal;" + - " gl_FragColor = col_formask;" + - "}"; - - //テクスチャを使わないデバッグ用の表示 - export const vertexShaderSrcDebug = - "varying lowp vec4 colorVarying;" + - "void main()" + - "{" + - " gl_Position = a_position;vec4 diffuseColor = vec4(0.0, 0.0 , 1.0, 0.5);" + - " colorVarying = diffuseColor ;" + - "}"; - - export const fragmentShaderSrcDebug = - "precision mediump float;" + - "varying lowp vec4 colorVarying;" + - "void main()" + - "{" + - " gl_FragColor = colorVarying;" + - "}"; + shaderProgram: WebGLProgram; // シェーダープログラムのアドレス + attributePositionLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(Position) + attributeTexCoordLocation: GLuint; // シェーダープログラムに渡す変数のアドレス(TexCoord) + uniformMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Matrix) + uniformClipMatrixLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ClipMatrix) + samplerTexture0Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture0) + samplerTexture1Location: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(Texture1) + uniformBaseColorLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(BaseColor) + uniformChannelFlagLocation: WebGLUniformLocation; // シェーダープログラムに渡す変数のアドレス(ChannelFlag) } - /** - * Cubismモデルを描画する直前のWebGLのステートを保持・復帰させるクラス - */ - export class CubismRendererProfile_WebGL + export enum ShaderNames { - - /** - * コンストラクタ - */ - public constructor() - { - this._lastVertexAttribArrayEnabled = new Array(4); - this._lastColorMask = new Array(4); - this._lastBlending = new Array(4); - } - - /** - * WebGLのステートを保持する - */ - public save(): void - { - //-- push state -- - this._lastArrayBufferBinding = this.gl.getParameter(this.gl.ARRAY_BUFFER_BINDING); - this._lastElementArrayBufferBinding = this.gl.getParameter(this.gl.ELEMENT_ARRAY_BUFFER_BINDING); - this._lastProgram = this.gl.getParameter(this.gl.CURRENT_PROGRAM); - - this._lastActiveTexture = this.gl.getParameter(this.gl.ACTIVE_TEXTURE); - this.gl.activeTexture(this.gl.TEXTURE1); // テクスチャユニット1をアクティブに(以降の設定対象とする) - this._lastTexture1Binding2D = this.gl.getParameter(this.gl.TEXTURE_BINDING_2D); - - this.gl.activeTexture(this.gl.TEXTURE0); // テクスチャユニット0をアクティブに(以降の設定対象とする) - this._lastTexture0Binding2D = this.gl.getParameter(this.gl.TEXTURE_BINDING_2D); - - this._lastVertexAttribArrayEnabled[0] = this.gl.getVertexAttrib(0, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - this._lastVertexAttribArrayEnabled[1] = this.gl.getVertexAttrib(1, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - this._lastVertexAttribArrayEnabled[2] = this.gl.getVertexAttrib(2, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - this._lastVertexAttribArrayEnabled[3] = this.gl.getVertexAttrib(3, this.gl.VERTEX_ATTRIB_ARRAY_ENABLED); - - this._lastScissorTest = this.gl.isEnabled(this.gl.SCISSOR_TEST); - this._lastStencilTest = this.gl.isEnabled(this.gl.STENCIL_TEST); - this._lastDepthTest = this.gl.isEnabled(this.gl.DEPTH_TEST); - this._lastCullFace = this.gl.isEnabled(this.gl.CULL_FACE); - this._lastBlend = this.gl.isEnabled(this.gl.BLEND); - - this._lastFrontFace = this.gl.getParameter(this.gl.FRONT_FACE); - - this._lastColorMask = this.gl.getParameter(this.gl.COLOR_WRITEMASK); - - // backup blending - this._lastBlending[0] = this.gl.getParameter(this.gl.BLEND_SRC_RGB); - this._lastBlending[1] = this.gl.getParameter(this.gl.BLEND_DST_RGB); - this._lastBlending[2] = this.gl.getParameter(this.gl.BLEND_SRC_ALPHA); - this._lastBlending[3] = this.gl.getParameter(this.gl.BLEND_DST_ALPHA); - } - - /** - * 保持したWebGLのステートを復帰させる - */ - public restore(): void - { - this.gl.useProgram(this._lastProgram); - - this.setGLEnableVertexAttribArray(0, this._lastVertexAttribArrayEnabled[0]); - this.setGLEnableVertexAttribArray(1, this._lastVertexAttribArrayEnabled[1]); - this.setGLEnableVertexAttribArray(2, this._lastVertexAttribArrayEnabled[2]); - this.setGLEnableVertexAttribArray(3, this._lastVertexAttribArrayEnabled[3]); - - this.setGLEnable(this.gl.SCISSOR_TEST, this._lastScissorTest); - this.setGLEnable(this.gl.STENCIL_TEST, this._lastStencilTest); - this.setGLEnable(this.gl.DEPTH_TEST, this._lastDepthTest); - this.setGLEnable(this.gl.CULL_FACE, this._lastCullFace); - this.setGLEnable(this.gl.BLEND, this._lastBlend); - - this.gl.frontFace(this._lastFrontFace); - - this.gl.colorMask(this._lastColorMask[0], this._lastColorMask[1], this._lastColorMask[2], this._lastColorMask[3]); - - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._lastArrayBufferBinding); // 前にバッファがバインドされていたら破棄する必要がある - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._lastElementArrayBufferBinding); - - this.gl.activeTexture(this.gl.TEXTURE1); // テクスチャユニット1を復元 - this.gl.bindTexture(this.gl.TEXTURE_2D, this._lastTexture1Binding2D); - - this.gl.activeTexture(this.gl.TEXTURE0); // テクスチャユニット0を復元 - this.gl.bindTexture(this.gl.TEXTURE_2D, this._lastTexture0Binding2D); - - this.gl.activeTexture(this._lastActiveTexture); - - // restore blending - this.gl.blendFuncSeparate(this._lastBlending[0], this._lastBlending[1], this._lastBlending[2], this._lastBlending[3]); - } - - /** - * WebGLの機能の有効・無効をセットする - * @param index 有効・無効にする機能 - * @param enabled trueなら有効にする - */ - private setGLEnable(index: GLenum, enabled: GLboolean): void - { - if(enabled == true) - { - this.gl.enable(index); - } - else - { - this.gl.disable(index); - } - } - - /** - * WebGLのVertex Attribute Array機能の有効・無効をセットする - * - * @param index 有効・無効にする機能 - * @param enabled trueなら有効にする - */ - private setGLEnableVertexAttribArray(index: GLuint, enabled: GLint): void - { - if(enabled) - { - this.gl.enableVertexAttribArray(index); - } - else - { - this.gl.disableVertexAttribArray(index); - } - } - - /** - * glの設定 - */ - public setGl(gl: WebGLRenderingContext): void - { - this.gl = gl; - } - - _lastArrayBufferBinding: GLint; // モデル描画直前の頂点バッファ - _lastElementArrayBufferBinding: GLint; // モデル描画直前のElementバッファ - _lastProgram: GLint; // モデル描画直前のシェーダプログラムバッファ - _lastActiveTexture: GLint; // モデル描画直前のアクティブなテクスチャ - _lastTexture0Binding2D: GLint; // モデル描画直前のテクスチャユニット0 - _lastTexture1Binding2D: GLint; // モデル描画直前のテクスチャユニット1 - _lastVertexAttribArrayEnabled: GLint[]; // モデル描画直前のGL_VERTEX_ATTRIB_ARRAY_ENABLEDパラメータ - _lastScissorTest: GLboolean; // モデル描画直前のGL_SCISSOR_TESTパラメータ - _lastBlend: GLboolean; // モデル描画直前のGL_BLENDパラメータ - _lastStencilTest: GLboolean; // モデル描画直前のGL_STENCIL_TESTパラメータ - _lastDepthTest: GLboolean; // モデル描画直前のGL_DEPTH_TESTパラメータ - _lastCullFace: GLboolean; // モデル描画直前のGL_CULL_FACEパラメータ - _lastFrontFace: GLint; // モデル描画直前のGL_FRONT_FACEパラメータ - _lastColorMask: GLboolean[]; // モデル描画直前のCOLOR_WRITEMASKパラメータ - _lastBlending: GLint[]; // モデル描画直前のカラーブレンディングパラメータ - - gl: WebGLRenderingContext; - } + // SetupMask + ShaderNames_SetupMask, + + // Normal + ShaderNames_NormalPremultipliedAlpha, + ShaderNames_NormalMaskedPremultipliedAlpha, + + // Add + ShaderNames_AddPremultipliedAlpha, + ShaderNames_AddMaskedPremultipledAlpha, + + // Mult + ShaderNames_MultPremultipliedAlpha, + ShaderNames_MultMaskedPremultipliedAlpha, + }; + + export const vertexShaderSrcSetupMask = + "attribute vec4 a_position;" + + "attribute vec2 a_texCoord;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_myPos;" + + "uniform mat4 u_clipMatrix;" + + "uniform sampler2D s_texture0;" + + "void main()" + + "{" + + " gl_Position = u_clipMatrix * a_position;" + + " v_myPos = u_clipMatrix * a_position;" + + " v_texCoord = a_texCoord;" + + " v_texCoord.y = 1.0 - v_texCoord.y;" + + "}"; + export const fragmentShaderSrcsetupMask = + "precision mediump float;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_myPos;" + + "uniform vec4 u_baseColor;" + + "uniform vec4 u_channelFlag;" + + "uniform sampler2D s_texture0;" + + "void main()" + + "{" + + " float isInside = " + + " step(u_baseColor.x, v_myPos.x/v_myPos.w)" + + " * step(u_baseColor.y, v_myPos.y/v_myPos.w)" + + " * step(v_myPos.x/v_myPos.w, u_baseColor.z)" + + " * step(v_myPos.y/v_myPos.w, u_baseColor.w);" + + " gl_FragColor = u_channelFlag * texture2D(s_texture0, v_texCoord).a * isInside;" + + "}"; + + //----- バーテックスシェーダプログラム ----- + // Normal & Add & Mult 共通 + export const vertexShaderSrc = + "attribute vec4 a_position;" + //v.vertex + "attribute vec2 a_texCoord;" + //v.texcoord + "varying vec2 v_texCoord;" + //v2f.texcoord + "uniform mat4 u_matrix;" + + "uniform sampler2D s_texture0;" + + "void main()" + + "{" + + " gl_Position = u_matrix * a_position;" + + " v_texCoord = a_texCoord;" + + " v_texCoord.y = 1.0 - v_texCoord.y;" + + "}"; + + // Normal & Add & Mult 共通(クリッピングされたものの描画用) + export const vertexShaderSrcMasked = + "attribute vec4 a_position;" + + "attribute vec2 a_texCoord;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_clipPos;" + + "uniform mat4 u_matrix;" + + "uniform mat4 u_clipMatrix;" + + "uniform sampler2D s_texture0;" + + "uniform sampler2D s_texture1;" + + "void main()" + + "{" + + " gl_Position = u_matrix * a_position;" + + " v_clipPos = u_clipMatrix * a_position;" + + " v_texCoord = a_texCoord;" + + " v_texCoord.y = 1.0 - v_texCoord.y;" + + "}"; + + //----- フラグメントシェーダプログラム ----- + // Normal & Add & Mult 共通 (PremultipliedAlpha) + export const fragmentShaderSrcPremultipliedAlpha = + "precision mediump float;" + + "varying vec2 v_texCoord;" + //v2f.texcoord + "uniform vec4 u_baseColor;" + + "uniform sampler2D s_texture0;" + //_MainTex + "void main()" + + "{" + + " gl_FragColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + + "}"; + + // Normal (クリッピングされたものの描画用、PremultipliedAlpha兼用) + export const fragmentShaderSrcMaskPremultipliedAlpha = + "precision mediump float;" + + "varying vec2 v_texCoord;" + + "varying vec4 v_clipPos;" + + "uniform vec4 u_baseColor;" + + "uniform vec4 u_channelFlag;" + + "uniform sampler2D s_texture0;" + + "uniform sampler2D s_texture1;" + + "void main()" + + "{" + + " vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" + + " vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" + + " float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" + + " col_formask = col_formask * maskVal;" + + " gl_FragColor = col_formask;" + + "}"; /** * WebGL用の描画命令を実装したクラス @@ -1727,9 +1451,13 @@ export namespace Live2DCubismFramework this._clippingContextBufferForDraw = null; this._clippingManager = new CubismClippingManager_WebGL(); this.firstDraw = true; - this._rendererProfile = new CubismRendererProfile_WebGL(); this._textures = new csmMap(); this._sortedDrawableIndexList = new csmVector(); + this._bufferData = { + vertex: WebGLBuffer = null, + uv: WebGLBuffer = null, + index: WebGLBuffer = null + }; // テクスチャ対応マップの容量を確保しておく this._textures.prepareCapacity(32, true); @@ -1743,6 +1471,15 @@ export namespace Live2DCubismFramework this._clippingManager.release(); this._clippingManager = void 0; this._clippingManager = null; + + this.gl.deleteBuffer(this._bufferData.vertex); + this._bufferData.vertex = null; + this.gl.deleteBuffer(this._bufferData.uv); + this._bufferData.uv = null; + this.gl.deleteBuffer(this._bufferData.index); + this._bufferData.index = null; + + this._bufferData = null; } /** @@ -1818,7 +1555,7 @@ export namespace Live2DCubismFramework */ public drawMesh(textureNo: number, indexCount: number, vertexCount: number, indexArray: Uint16Array, vertexArray: Float32Array, uvArray: Float32Array, - opacity: number, colorBlendMode: CubismRenderer.CubismBlendMode): void + opacity: number, colorBlendMode: CubismBlendMode): void { // 裏面描画の有効・無効 if(this.isCulling()) @@ -1832,7 +1569,7 @@ export namespace Live2DCubismFramework this.gl.frontFace(this.gl.CCW); // Cubism3 OpenGLはマスク・アートメッシュ共にCCWが表面 - let modelColorRGBA: CubismRenderer.CubismTextureColor = this.getModelColor(); + let modelColorRGBA: CubismTextureColor = this.getModelColor(); if(this.getClippingContextBufferForMask() == null) // マスク生成時以外 { @@ -1860,6 +1597,7 @@ export namespace Live2DCubismFramework CubismShader_WebGL.getInstance().setupShaderProgram( this, drawtexture, vertexCount, vertexArray, indexArray, uvArray, + this._bufferData, opacity, colorBlendMode, modelColorRGBA, this.isPremultipliedAlpha(), this.getMvpMatrix() ); @@ -1882,6 +1620,17 @@ export namespace Live2DCubismFramework CubismShader_WebGL.deleteInstance(); } + /** + * レンダーステートを設定する + * @param fbo アプリケーション側で指定しているフレームバッファ + * @param viewport ビューポート + */ + public setRenderState(fbo: WebGLFramebuffer, viewport: number[]): void + { + s_fbo = fbo; + s_viewport = viewport; + } + /** * 描画開始時の追加処理 * モデルを描画する前にクリッピングマスクに必要な処理を実装している @@ -1912,22 +1661,6 @@ export namespace Live2DCubismFramework this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null); } - /** - * モデル描画直前のWebGLのステートを保持する - */ - public saveProfile(): void - { - this._rendererProfile.save(); - } - - /** - * モデル描画直前のWebGLのステートを保持する - */ - public restoreProfile(): void - { - this._rendererProfile.restore(); - } - /** * マスクテクスチャに描画するクリッピングコンテキストをセットする */ @@ -1968,18 +1701,21 @@ export namespace Live2DCubismFramework public startUp(gl: WebGLRenderingContext): void { this.gl = gl; - this._rendererProfile.setGl(gl); this._clippingManager.setGL(gl); CubismShader_WebGL.getInstance().setGl(gl); } _textures: csmMap; // モデルが参照するテクスチャとレンダラでバインドしているテクスチャとのマップ _sortedDrawableIndexList: csmVector; // 描画オブジェクトのインデックスを描画順に並べたリスト - _rendererProfile: CubismRendererProfile_WebGL; // WebGLのステートを保持するオブジェクト _clippingManager: CubismClippingManager_WebGL; // クリッピングマスク管理オブジェクト _clippingContextBufferForMask: CubismClippingContext; // マスクテクスチャに描画するためのクリッピングコンテキスト _clippingContextBufferForDraw: CubismClippingContext; // 画面上描画するためのクリッピングコンテキスト firstDraw: boolean; + _bufferData: { + vertex: WebGLBuffer, + uv: WebGLBuffer, + index: WebGLBuffer + }; // 頂点バッファデータ gl: WebGLRenderingContext; // webglコンテキスト } diff --git a/Framework/type/csmmap.ts b/Framework/type/csmmap.ts index 6dad45f..d9f64ac 100644 --- a/Framework/type/csmmap.ts +++ b/Framework/type/csmmap.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -212,18 +212,18 @@ export namespace Live2DCubismFramework /** * コンテナの先頭要素を返す */ - public begin(): csmMap.iterator<_KeyT, _ValT> + public begin(): iterator<_KeyT, _ValT> { - let ite: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, 0); + let ite: iterator<_KeyT, _ValT> = new iterator<_KeyT, _ValT>(this, 0); return ite; } /** * コンテナの終端要素を返す */ - public end(): csmMap.iterator<_KeyT, _ValT> + public end(): iterator<_KeyT, _ValT> { - let ite: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, this._size); // 終了 + let ite: iterator<_KeyT, _ValT> = new iterator<_KeyT, _ValT>(this, this._size); // 終了 return ite; } @@ -232,7 +232,7 @@ export namespace Live2DCubismFramework * * @param ite 削除する要素 */ - public erase(ite: csmMap.iterator<_KeyT, _ValT>): csmMap.iterator<_KeyT, _ValT> + public erase(ite: iterator<_KeyT, _ValT>): iterator<_KeyT, _ValT> { let index: number = ite._index; if(index < 0 || this._size <= index) @@ -244,7 +244,7 @@ export namespace Live2DCubismFramework this._keyValues.splice(index, 1); --this._size; - let ite2: csmMap.iterator<_KeyT, _ValT> = new csmMap.iterator<_KeyT, _ValT>(this, index); // 終了 + let ite2: iterator<_KeyT, _ValT> = new iterator<_KeyT, _ValT>(this, index); // 終了 return ite2; } @@ -266,95 +266,93 @@ export namespace Live2DCubismFramework public _size: number; // コンテナの要素数 } - export namespace csmMap + + /** + * csmMapのイテレータ + */ + export class iterator<_KeyT, _ValT> { /** - * csmMapのイテレータ + * コンストラクタ */ - export class iterator<_KeyT, _ValT> + constructor(v?: csmMap<_KeyT, _ValT>, idx?: number) { - /** - * コンストラクタ - */ - constructor(v?: csmMap<_KeyT, _ValT>, idx?: number) - { - this._map = (v != undefined) - ? v - : new csmMap<_KeyT, _ValT>(); - - this._index = (idx != undefined) - ? idx - : 0; - } + this._map = (v != undefined) + ? v + : new csmMap<_KeyT, _ValT>(); - /** - * =演算子のオーバーロード - */ - public set(ite: iterator<_KeyT, _ValT>): iterator<_KeyT, _ValT> - { - this._index = ite._index; - this._map = ite._map; - return this; - } + this._index = (idx != undefined) + ? idx + : 0; + } - /** - * 前置き++演算子のオーバーロード - */ - public preIncrement(): iterator<_KeyT, _ValT> - { - ++this._index; - return this; - } + /** + * =演算子のオーバーロード + */ + public set(ite: iterator<_KeyT, _ValT>): iterator<_KeyT, _ValT> + { + this._index = ite._index; + this._map = ite._map; + return this; + } - /** - * 前置き--演算子のオーバーロード - */ - public preDecrement(): iterator<_KeyT, _ValT> - { - --this._index; - return this; - } + /** + * 前置き++演算子のオーバーロード + */ + public preIncrement(): iterator<_KeyT, _ValT> + { + ++this._index; + return this; + } - /** - * 後置き++演算子のオーバーロード - */ - public increment(): iterator<_KeyT, _ValT> - { - let iteold = new iterator<_KeyT, _ValT>(this._map, this._index++); // 古い値を保存 - this._map = iteold._map; - this._index = iteold._index; - return this; - } + /** + * 前置き--演算子のオーバーロード + */ + public preDecrement(): iterator<_KeyT, _ValT> + { + --this._index; + return this; + } - /** - * 後置き--演算子のオーバーロード - */ - public decrement(): iterator<_KeyT, _ValT> - { - let iteold = new iterator<_KeyT, _ValT>(this._map, this._index); // 古い値を保存 - this._map = iteold._map; - this._index = iteold._index; - return this; - } + /** + * 後置き++演算子のオーバーロード + */ + public increment(): iterator<_KeyT, _ValT> + { + let iteold = new iterator<_KeyT, _ValT>(this._map, this._index++); // 古い値を保存 + this._map = iteold._map; + this._index = iteold._index; + return this; + } - /** - * *演算子のオーバーロード - */ - public ptr(): csmPair<_KeyT, _ValT> - { - return this._map._keyValues[this._index]; - } + /** + * 後置き--演算子のオーバーロード + */ + public decrement(): iterator<_KeyT, _ValT> + { + let iteold = new iterator<_KeyT, _ValT>(this._map, this._index); // 古い値を保存 + this._map = iteold._map; + this._index = iteold._index; + return this; + } - /** - * !=演算 - */ - public notEqual(ite: iterator<_KeyT, _ValT>): boolean - { - return (this._index != ite._index) || (this._map != ite._map); - } + /** + * *演算子のオーバーロード + */ + public ptr(): csmPair<_KeyT, _ValT> + { + return this._map._keyValues[this._index]; + } - _index: number; // コンテナのインデックス値 - _map: csmMap<_KeyT, _ValT>; // コンテナ + /** + * !=演算 + */ + public notEqual(ite: iterator<_KeyT, _ValT>): boolean + { + return (this._index != ite._index) || (this._map != ite._map); } + + _index: number; // コンテナのインデックス値 + _map: csmMap<_KeyT, _ValT>; // コンテナ } } \ No newline at end of file diff --git a/Framework/type/csmrectf.ts b/Framework/type/csmrectf.ts index 0c8e30d..b79b0d0 100644 --- a/Framework/type/csmrectf.ts +++ b/Framework/type/csmrectf.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/type/csmstring.ts b/Framework/type/csmstring.ts index 23bc018..f56f291 100644 --- a/Framework/type/csmstring.ts +++ b/Framework/type/csmstring.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Framework/type/csmvector.ts b/Framework/type/csmvector.ts index 746d0a8..17ecb27 100644 --- a/Framework/type/csmvector.ts +++ b/Framework/type/csmvector.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -175,7 +175,7 @@ export namespace Live2DCubismFramework * @param begin 挿入するコンテナの開始位置 * @param end 挿入するコンテナの終端位置 */ - public insert(position: csmVector.iterator, begin: csmVector.iterator, end: csmVector.iterator): void + public insert(position: iterator, begin: iterator, end: iterator): void { let dstSi: number = position._index; let srcSi: number = begin._index; @@ -226,7 +226,7 @@ export namespace Live2DCubismFramework * コンテナから要素を削除して他の要素をシフトする * @param ite 削除する要素 */ - public erase(ite: csmVector.iterator): csmVector.iterator + public erase(ite: iterator): iterator { let index: number = ite._index; if(index < 0 || this._size <= index) @@ -238,7 +238,7 @@ export namespace Live2DCubismFramework this._ptr.splice(index, 1); --this._size; - let ite2: csmVector.iterator = new csmVector.iterator(this, index); // 終了 + let ite2: iterator = new iterator(this, index); // 終了 return ite2; } @@ -266,20 +266,20 @@ export namespace Live2DCubismFramework /** * コンテナの先頭要素を返す */ - public begin(): csmVector.iterator + public begin(): iterator { - let ite: csmVector.iterator = (this._size == 0) + let ite: iterator = (this._size == 0) ? this.end() - : new csmVector.iterator(this, 0); + : new iterator(this, 0); return ite; } /** * コンテナの終端要素を返す */ - public end(): csmVector.iterator + public end(): iterator { - let ite: csmVector.iterator = new csmVector.iterator(this, this._size); + let ite: iterator = new iterator(this, this._size); return ite; } @@ -300,97 +300,94 @@ export namespace Live2DCubismFramework static readonly s_defaultSize = 10; // コンテナ初期化のデフォルトサイズ } - export namespace csmVector + export class iterator { - export class iterator + /** + * コンストラクタ + */ + public constructor(v?: csmVector, index?: number) { - /** - * コンストラクタ - */ - public constructor(v?: csmVector, index?: number) - { - this._vector = (v != undefined) ? v : null; - this._index = (index != undefined) ? index : 0; - } - - /** - * 代入 - */ - public set(ite: iterator): iterator - { - this._index = ite._index; - this._vector = ite._vector; - return this; - } + this._vector = (v != undefined) ? v : null; + this._index = (index != undefined) ? index : 0; + } - /** - * 前置き++演算 - */ - public preIncrement(): iterator - { - ++this._index; - return this; - } - - /** - * 前置き--演算 - */ - public preDecrement(): iterator - { - --this._index; - return this; - } + /** + * 代入 + */ + public set(ite: iterator): iterator + { + this._index = ite._index; + this._vector = ite._vector; + return this; + } - /** - * 後置き++演算子 - */ - public increment(): iterator - { - let iteold = new iterator(this._vector, this._index++); - this._vector = iteold._vector; - this._index = iteold._index; - return this; - } + /** + * 前置き++演算 + */ + public preIncrement(): iterator + { + ++this._index; + return this; + } + + /** + * 前置き--演算 + */ + public preDecrement(): iterator + { + --this._index; + return this; + } - /** - * 後置き--演算子 - */ - public decrement(): iterator - { - let iteold = new iterator(this._vector, this._index--); // 古い値を保存 - this._vector = iteold._vector; - this._index = iteold._index; - return this; - } + /** + * 後置き++演算子 + */ + public increment(): iterator + { + let iteold = new iterator(this._vector, this._index++); + this._vector = iteold._vector; + this._index = iteold._index; + return this; + } - /** - * ptr - */ - public ptr(): T - { - return this._vector._ptr[this._index]; - } + /** + * 後置き--演算子 + */ + public decrement(): iterator + { + let iteold = new iterator(this._vector, this._index--); // 古い値を保存 + this._vector = iteold._vector; + this._index = iteold._index; + return this; + } - /** - * =演算子のオーバーロード - */ - public substitution(ite: iterator): iterator - { - this._index = ite._index; - this._vector = ite._vector; - return this; - } + /** + * ptr + */ + public ptr(): T + { + return this._vector._ptr[this._index]; + } - /** - * !=演算子のオーバーロード - */ - public notEqual(ite: iterator): boolean - { - return (this._index != ite._index) || (this._vector != ite._vector); - } + /** + * =演算子のオーバーロード + */ + public substitution(ite: iterator): iterator + { + this._index = ite._index; + this._vector = ite._vector; + return this; + } - _index: number; // コンテナのインデックス値 - _vector: csmVector; // コンテナ + /** + * !=演算子のオーバーロード + */ + public notEqual(ite: iterator): boolean + { + return (this._index != ite._index) || (this._vector != ite._vector); } + + _index: number; // コンテナのインデックス値 + _vector: csmVector; // コンテナ } } \ No newline at end of file diff --git a/Framework/utils/cubismdebug.ts b/Framework/utils/cubismdebug.ts index e8e8f4a..848e6e6 100644 --- a/Framework/utils/cubismdebug.ts +++ b/Framework/utils/cubismdebug.ts @@ -1,20 +1,20 @@ -/* +/* * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. */ -import {Live2DCubismFramework as live2dcubismframework, Option} from "../live2dcubismframework"; +import {Live2DCubismFramework as live2dcubismframework, LogLevel} from "../live2dcubismframework"; import CubismFramework = live2dcubismframework.CubismFramework; import { CSM_LOG_LEVEL, CSM_LOG_LEVEL_VERBOSE, CSM_LOG_LEVEL_DEBUG, CSM_LOG_LEVEL_INFO, CSM_LOG_LEVEL_WARNING, CSM_LOG_LEVEL_ERROR } from "../cubismframeworkconfig"; -export const CubismLogPrint = (level: Option.LogLevel, fmt: string, ... args: any[]) => +export const CubismLogPrint = (level: LogLevel, fmt: string, ... args: any[]) => { Live2DCubismFramework.CubismDebug.print(level, "[CSM]" + fmt, args); } -export const CubismLogPrintIn = (level: Option.LogLevel, fmt: string, ... args: any[]) => +export const CubismLogPrintIn = (level: LogLevel, fmt: string, ... args: any[]) => { CubismLogPrint(level, fmt + "\n", args); } @@ -35,85 +35,85 @@ if(CSM_LOG_LEVEL <= CSM_LOG_LEVEL_VERBOSE) { CubismLogVerbose = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Verbose, "[V]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Verbose, "[V]" + fmt, args); }; CubismLogDebug = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Debug, "[D]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Debug, "[D]" + fmt, args); }; CubismLogInfo = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Info, "[I]" + fmt, args); }; CubismLogWarning = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args); }; CubismLogError = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args); }; } else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_DEBUG) { CubismLogDebug = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Debug, "[D]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Debug, "[D]" + fmt, args); }; CubismLogInfo = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Info, "[I]" + fmt, args); }; CubismLogWarning = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args); }; CubismLogError = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args); }; } else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_INFO) { CubismLogInfo = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Info, "[I]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Info, "[I]" + fmt, args); }; CubismLogWarning = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args); }; CubismLogError = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args); }; } else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_WARNING) { CubismLogWarning = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Warning, "[W]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args); }; CubismLogError = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args); }; } else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_ERROR) { CubismLogError = (fmt: string, ... args: any[]) => { - CubismLogPrintIn(Option.LogLevel.LogLevel_Error, "[E]" + fmt, args); + CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args); }; } @@ -135,7 +135,7 @@ export namespace Live2DCubismFramework * @param format 書式付き文字列 * @param ... args 可変長引数 */ - public static print(logLevel: Option.LogLevel, format: string, ... args: any[]): void + public static print(logLevel: LogLevel, format: string, ... args: any[]): void { // オプションで設定されたログ出力レベルを下回る場合はログに出さない // if(logLevel < CubismFramework.getLoggingLevel()) @@ -169,7 +169,7 @@ export namespace Live2DCubismFramework * @param data ダンプするデータ * @param length ダンプする長さ */ - public static dumpBytes(logLevel: Option.LogLevel, data: Uint8Array, length: number): void + public static dumpBytes(logLevel: LogLevel, data: Uint8Array, length: number): void { for (let i: number = 0; i < length; i++) { diff --git a/Framework/utils/cubismjson.ts b/Framework/utils/cubismjson.ts index f28dfaf..4cc51ed 100644 --- a/Framework/utils/cubismjson.ts +++ b/Framework/utils/cubismjson.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -11,7 +11,9 @@ import {Live2DCubismFramework as csmvector} from "../type/csmvector"; import {CubismLogInfo} from "./cubismdebug"; import {strtod} from "../live2dcubismframework"; import csmVector = csmvector.csmVector; +import csmVector_iterator = csmvector.iterator; import csmMap = csmmap.csmMap; +import csmMap_iterator = csmmap.iterator; import csmString = csmstring.csmString; export namespace Live2DCubismFramework @@ -305,6 +307,29 @@ export namespace Live2DCubismFramework return this._root; } + /** + * UnicodeのバイナリをStringに変換・長い文字のスライスバージョン + */ + public LongArrayBufferToString(buffer: ArrayBuffer, len: number) : string + { + let tmp: string[] = []; + for (let p: number = 0; p < buffer.byteLength; p += len) + { + tmp.push(this.ArrayBufferToString(buffer.slice(p, p + len))); + } + + return tmp.join(""); + } + + /** + * UnicodeのバイナリをStringに変換 + */ + public ArrayBufferToString( buffer: ArrayBuffer ): string + { + // 8ビット変換 + return String.fromCharCode.apply("", new Uint8Array(buffer)); + } + /** * JSONのパースを実行する * @param buffer パース対象のデータバイト @@ -315,7 +340,7 @@ export namespace Live2DCubismFramework public parseBytes(buffer: ArrayBuffer, size: number): boolean { let endPos: number[] = new Array(1); // 参照渡しにするため配列 - let decodeBuffer: string = new TextDecoder('utf-8').decode(buffer); + let decodeBuffer: string = this.LongArrayBufferToString(buffer, 1024); this._root = this.parseValue(decodeBuffer, size, 0, endPos); if(this._error) @@ -1065,7 +1090,7 @@ export namespace Live2DCubismFramework */ public release(): void { - for(let ite: csmVector.iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.preIncrement()) + for(let ite: csmVector_iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.preIncrement()) { let v: Value = ite.ptr(); @@ -1092,7 +1117,7 @@ export namespace Live2DCubismFramework { let stringBuffer: string = indent + "[\n"; - for(let ite: csmVector.iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.increment()) + for(let ite: csmVector_iterator = this._array.begin(); ite.notEqual(this._array.end()); ite.increment()) { let v: Value = ite.ptr(); this._stringBuffer += indent + "" + v.getString(indent + " ") + "\n"; @@ -1151,7 +1176,7 @@ export namespace Live2DCubismFramework */ public release(): void { - const ite: csmMap.iterator = this._map.begin(); + const ite: csmMap_iterator = this._map.begin(); while(ite.notEqual(this._map.end())) { @@ -1182,7 +1207,7 @@ export namespace Live2DCubismFramework { this._stringBuffer = indent + "{\n"; - const ite: csmMap.iterator = this._map.begin(); + const ite: csmMap_iterator = this._map.begin(); while(ite.notEqual(this._map.end())) { const key = ite.ptr().first; @@ -1222,7 +1247,7 @@ export namespace Live2DCubismFramework { this._keys = new csmVector(); - const ite: csmMap.iterator = this._map.begin(); + const ite: csmMap_iterator = this._map.begin(); while(ite.notEqual(this._map.end())) { diff --git a/Framework/utils/cubismstring.ts b/Framework/utils/cubismstring.ts index fefcb03..c90bfab 100644 --- a/Framework/utils/cubismstring.ts +++ b/Framework/utils/cubismstring.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/README.md b/README.md index 65937f5..b5db70e 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,18 @@ F5で実行し、remote web site with sourcemapを選択します。 当リポジトリの変更履歴については[コミットログ](https://github.com/Live2D/CubismWebSamples/commits/master)を参照ください。 +# 動作確認環境 + +- Windows Chrome 70.0.3538.67 +- Windows Firefox 63.0 +- Windows Edge 17.17134 +- macOS Chrome 70.0.3538.77 +- macOS Firefox 63.0 +- macOS Safari 12.0 +- iOS Safari 12.0 +- Android Chrome 70.0.3538.64 + + # TODO 以下Core内関数の実装 diff --git a/Sample/TypeScript/Demo/src/lappdefine.ts b/Sample/TypeScript/Demo/src/lappdefine.ts index df53e09..a606e36 100644 --- a/Sample/TypeScript/Demo/src/lappdefine.ts +++ b/Sample/TypeScript/Demo/src/lappdefine.ts @@ -1,12 +1,11 @@ -/* +/* * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. */ -import {Live2DCubismFramework as live2dcubismframework, Option} from "../../../../Framework/live2dcubismframework"; -import Csm_CubismFramework_Option = Option; +import {LogLevel} from "../../../../Framework/live2dcubismframework"; /** * Sample Appで使用する定数 @@ -66,5 +65,5 @@ export namespace LAppDefine export const DebugTouchLogEnable: boolean = false; // Frameworkから出力するログのレベル設定 - export const CubismLoggingLevel: Csm_CubismFramework_Option.LogLevel = Csm_CubismFramework_Option.LogLevel.LogLevel_Verbose; + export const CubismLoggingLevel: LogLevel = LogLevel.LogLevel_Verbose; } \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/lappdelegate.ts b/Sample/TypeScript/Demo/src/lappdelegate.ts index 69e2f58..7278169 100644 --- a/Sample/TypeScript/Demo/src/lappdelegate.ts +++ b/Sample/TypeScript/Demo/src/lappdelegate.ts @@ -1,15 +1,14 @@ -/* +/* * 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 http://live2d.com/eula/live2d-open-software-license-agreement_en.html. */ -import {Live2DCubismFramework as live2dcubismframework, Option} from "../../../../Framework/live2dcubismframework"; +import {Live2DCubismFramework as live2dcubismframework, Option as Csm_Option} from "../../../../Framework/live2dcubismframework"; import {Live2DCubismFramework as cubismmatrix44} from "../../../../Framework/math/cubismmatrix44"; import Csm_CubismMatrix44 = cubismmatrix44.CubismMatrix44; import Csm_CubismFramework = live2dcubismframework.CubismFramework; -import Csm_Option = Option; import { LAppView } from "./lappview"; import { LAppPal } from "./lapppal"; import { LAppTextureManager } from "./lapptexturemanager"; @@ -18,6 +17,7 @@ import { LAppLive2DManager } from "./lapplive2dmanager"; export let canvas: HTMLCanvasElement = null; export let s_instance: LAppDelegate = null; export let gl: WebGLRenderingContext = null; +export let frameBuffer: WebGLFramebuffer = null; /** * アプリケーションクラス。 @@ -48,7 +48,7 @@ export class LAppDelegate { if(s_instance != null) { - s_instance = void 0; + s_instance.release(); } s_instance = null; @@ -74,18 +74,36 @@ export class LAppDelegate return false; } + if (!frameBuffer) + { + frameBuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); + } + // 透過設定 gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - // マウス関連コールバック関数登録 - canvas.onmousedown = onClickBegan; - canvas.onmousemove = onMouseMoved; - canvas.onmouseup = onClickEnded; + let supportTouch: boolean = 'ontouchend' in canvas; + + if(supportTouch) + { + // タッチ関連コールバック関数登録 + canvas.ontouchstart = onTouchBegan; + canvas.ontouchmove = onTouchMoved; + canvas.ontouchend = onTouchEnded; + canvas.ontouchcancel = onTouchCancel; + } + else + { + // マウス関連コールバック関数登録 + canvas.onmousedown = onClickBegan; + canvas.onmousemove = onMouseMoved; + canvas.onmouseup = onClickEnded; + } // AppViewの初期化 this._view.initialize(); - + // Cubism3の初期化 this.initializeCubism(); @@ -97,8 +115,11 @@ export class LAppDelegate */ public release(): void { - this._textureManager = void 0; - this._view = void 0; + this._textureManager.release(); + this._textureManager = null; + + this._view.release(); + this._view = null; // リソースを解放 LAppLive2DManager.releaseInstance(); @@ -115,6 +136,12 @@ export class LAppDelegate // メインループ let loop = () => { + // インスタンスの有無の確認 + if(s_instance == null) + { + return; + } + // 時間更新 LAppPal.updateTime(); @@ -132,13 +159,15 @@ export class LAppDelegate gl.clearDepth(1.0); - this._view.initializeSprite(); + // 透過設定 + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // 描画更新 this._view.render(); // ループのために再帰呼び出し - setTimeout(loop, 1000.0/60); + requestAnimationFrame(loop); }; loop(); } @@ -153,7 +182,7 @@ export class LAppDelegate if(vertexShaderId == null) { - console.log("failed to create vertexShader"); + LAppPal.printLog("failed to create vertexShader"); return null; } @@ -176,7 +205,7 @@ export class LAppDelegate if(fragmentShaderId == null) { - console.log("failed to create fragmentShader"); + LAppPal.printLog("failed to create fragmentShader"); return null; } @@ -197,6 +226,9 @@ export class LAppDelegate gl.attachShader(programId, vertexShaderId); gl.attachShader(programId, fragmentShaderId); + gl.deleteShader(vertexShaderId); + gl.deleteShader(fragmentShaderId); + // リンク gl.linkProgram(programId); @@ -213,22 +245,6 @@ export class LAppDelegate return this._view; } - /** - * アプリケーションを終了するかどうか。 - */ - public getIsEnd(): boolean - { - return this._isEnd; - } - - /** - * アプリケーションを終了する。 - */ - public appEnd(): void - { - this._isEnd = true; - } - public getTextureManager(): LAppTextureManager { return this._textureManager; @@ -267,6 +283,8 @@ export class LAppDelegate let projection: Csm_CubismMatrix44 = new Csm_CubismMatrix44(); LAppPal.updateTime(); + + this._view.initializeSprite(); } _cubismOption: Csm_Option; // Cubism3 Option @@ -278,20 +296,18 @@ export class LAppDelegate _textureManager: LAppTextureManager;// テクスチャマネージャー } - - /** * クリックしたときに呼ばれる。 */ function onClickBegan(e: MouseEvent): void { - LAppDelegate.getInstance()._captured = true; if(!LAppDelegate.getInstance()._view) { - console.log("view notfound"); + LAppPal.printLog("view notfound"); return; } - + LAppDelegate.getInstance()._captured = true; + let posX: number = e.pageX; let posY: number = e.pageY; @@ -303,21 +319,21 @@ function onClickBegan(e: MouseEvent): void */ function onMouseMoved(e: MouseEvent): void { - let rect = e.toElement.getBoundingClientRect(); - let posX: number = e.clientX - rect.left; - let posY: number = e.clientY - rect.top; - if(!LAppDelegate.getInstance()._captured) { return; } - + if(!LAppDelegate.getInstance()._view) { - console.log("view notfound"); + LAppPal.printLog("view notfound"); return; } + let rect = e.srcElement.getBoundingClientRect(); + let posX: number = e.clientX - rect.left; + let posY: number = e.clientY - rect.top; + LAppDelegate.getInstance()._view.onTouchesMoved(posX, posY); } @@ -327,14 +343,102 @@ function onMouseMoved(e: MouseEvent): void function onClickEnded(e: MouseEvent): void { LAppDelegate.getInstance()._captured = false; - let rect = e.toElement.getBoundingClientRect(); + if(!LAppDelegate.getInstance()._view) + { + LAppPal.printLog("view notfound"); + return; + } + + + let rect = e.srcElement.getBoundingClientRect(); let posX: number = e.clientX - rect.left; let posY: number = e.clientY - rect.top; + LAppDelegate.getInstance()._view.onTouchesEnded(posX, posY); +} + + +/** + * タッチしたときに呼ばれる。 + */ +function onTouchBegan(e: TouchEvent): void +{ + if(!LAppDelegate.getInstance()._view) + { + LAppPal.printLog("view notfound"); + return; + } + + LAppDelegate.getInstance()._captured = true; + + let posX = e.changedTouches[0].pageX; + let posY = e.changedTouches[0].pageY; + + LAppDelegate.getInstance()._view.onTouchesBegan(posX, posY); +} + +/** + * スワイプすると呼ばれる。 + */ +function onTouchMoved(e: TouchEvent): void +{ + if(!LAppDelegate.getInstance()._captured) + { + return; + } + + if(!LAppDelegate.getInstance()._view) + { + LAppPal.printLog("view notfound"); + return; + } + + let rect = e.srcElement.getBoundingClientRect(); + + let posX = e.changedTouches[0].clientX - rect.left; + let posY = e.changedTouches[0].clientY - rect.top; + + LAppDelegate.getInstance()._view.onTouchesMoved(posX, posY); +} + +/** + * タッチが終了したら呼ばれる。 + */ +function onTouchEnded(e: TouchEvent): void +{ + LAppDelegate.getInstance()._captured = false; + + if(!LAppDelegate.getInstance()._view) + { + LAppPal.printLog("view notfound"); + return; + } + + let rect = e.srcElement.getBoundingClientRect(); + + let posX = e.changedTouches[0].clientX - rect.left; + let posY = e.changedTouches[0].clientY - rect.top; + + LAppDelegate.getInstance()._view.onTouchesEnded(posX, posY); +} + +/** + * タッチがキャンセルされると呼ばれる。 + */ +function onTouchCancel(e: TouchEvent): void +{ + LAppDelegate.getInstance()._captured = false; + if(!LAppDelegate.getInstance()._view) { - console.log("view notfound"); + LAppPal.printLog("view notfound"); return; } + + let rect = e.srcElement.getBoundingClientRect(); + + let posX = e.changedTouches[0].clientX - rect.left; + let posY = e.changedTouches[0].clientY - rect.top; + LAppDelegate.getInstance()._view.onTouchesEnded(posX, posY); -} \ No newline at end of file +} diff --git a/Sample/TypeScript/Demo/src/lapplive2dmanager.ts b/Sample/TypeScript/Demo/src/lapplive2dmanager.ts index 2a1e12c..dd48da0 100644 --- a/Sample/TypeScript/Demo/src/lapplive2dmanager.ts +++ b/Sample/TypeScript/Demo/src/lapplive2dmanager.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -76,7 +76,8 @@ export class LAppLive2DManager { for(let i: number = 0; i < this._models.getSize(); i++) { - this._models.set(i, void 0); + this._models.at(i).release(); + this._models.set(i, null); } this._models.clear(); @@ -153,13 +154,13 @@ export class LAppLive2DManager projection.multiplyByMatrix(this._viewMatrix); } - const saveProjection: Csm_CubismMatrix44 = projection; + const saveProjection: Csm_CubismMatrix44 = projection.clone(); let modelCount: number = this._models.getSize(); for(let i: number = 0; i < modelCount; ++i) { let model: LAppModel = this.getModel(i); - projection = saveProjection; + projection = saveProjection.clone(); model.update(); model.draw(projection); // 参照渡しなのでprojectionは変質する。 diff --git a/Sample/TypeScript/Demo/src/lappmodel.ts b/Sample/TypeScript/Demo/src/lappmodel.ts index 4fcfff7..81ab76f 100644 --- a/Sample/TypeScript/Demo/src/lappmodel.ts +++ b/Sample/TypeScript/Demo/src/lappmodel.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -21,7 +21,8 @@ import {Live2DCubismFramework as cubismstring} from "../../../../Framework/utils import {Live2DCubismFramework as cubismmotion} from "../../../../Framework/motion/cubismmotion"; import {Live2DCubismFramework as cubismmotionqueuemanager} from "../../../../Framework/motion/cubismmotionqueuemanager"; import {Live2DCubismFramework as csmstring} from "../../../../Framework/type/csmstring"; -import {Live2DCubismFramework as csmrect} from "../../../../Framework/type/csmrectf"; +import {Live2DCubismFramework as csmrect } from "../../../../Framework/type/csmrectf"; +import { Live2DCubismFramework as CubismRenderer_WebGL } from "../../../../Framework/rendering/cubismrenderer_WebGL"; import {CubismLogInfo} from "../../../../Framework/utils/cubismdebug"; import csmRect = csmrect.csmRect; import csmString = csmstring.csmString; @@ -33,6 +34,7 @@ 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 CubismFramework = live2dcubismframework.CubismFramework; @@ -44,7 +46,7 @@ import CubismDefaultParameterId = cubismdefaultparameterid; import {LAppDefine} from "./lappdefine"; import {LAppPal} from "./lapppal"; -import {gl} from "./lappdelegate"; +import { gl, canvas, frameBuffer} from "./lappdelegate"; function createBuffer(path: string, callBack: any): void { @@ -323,12 +325,12 @@ export class LAppModel extends CubismUserModel { { this._breath = CubismBreath.create(); - let breathParameters: csmVector = new csmVector(); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleX, 0.0, 15.0, 6.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleY, 0.0, 8.0, 3.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamAngleZ, 0.0, 10.0, 5.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.BreathParameterData(this._idParamBodyAngleX, 0.0, 4.0, 15.5345, 0.5)); - breathParameters.pushBack(new CubismBreath.BreathParameterData(CubismFramework.getIdManager().getId(CubismDefaultParameterId.ParamBreath), 0.0, 0.5, 3.2345, 0.5)); + let 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; @@ -467,6 +469,9 @@ export class LAppModel extends CubismUserModel { */ private setupTextures(): void { + // iPhoneでのアルファ品質向上のためTypescriptではpremultipliedAlphaを採用 + let usePremultiply: boolean = true; + if(this._state == LoadStep.LoadTexture) { // テクスチャ読み込み用 @@ -500,6 +505,12 @@ export class LAppModel extends CubismUserModel { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + // Premult処理を行わせる + if(usePremultiply) + { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1); + } // テクスチャにピクセルを書き込む gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[modelTextureNumber]); @@ -519,7 +530,7 @@ export class LAppModel extends CubismUserModel { } img[modelTextureNumber].src = texturePath; - this.getRenderer().setIsPremultipliedAlpha(false); + this.getRenderer().setIsPremultipliedAlpha(usePremultiply); } this._state = LoadStep.WaitLoadTexture; @@ -907,6 +918,15 @@ export class LAppModel extends CubismUserModel { { if(this._model == null) return; + // キャンバスサイズを渡す + let viewport: number[] = [ + 0, + 0, + canvas.width, + canvas.height + ]; + + this.getRenderer().setRenderState(frameBuffer, viewport); this.getRenderer().drawModel(); } diff --git a/Sample/TypeScript/Demo/src/lapppal.ts b/Sample/TypeScript/Demo/src/lapppal.ts index fa5d819..0477e9f 100644 --- a/Sample/TypeScript/Demo/src/lapppal.ts +++ b/Sample/TypeScript/Demo/src/lapppal.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/Sample/TypeScript/Demo/src/lappsprite.ts b/Sample/TypeScript/Demo/src/lappsprite.ts index 7a7f37a..14e3f61 100644 --- a/Sample/TypeScript/Demo/src/lappsprite.ts +++ b/Sample/TypeScript/Demo/src/lappsprite.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -30,6 +30,39 @@ import { gl, canvas } from "./lappdelegate"; this._rect.up = (y + height * 0.5); this._rect.down = (y - height * 0.5); this._texture = textureId; + this._vertexBuffer = null; + this._uvBuffer = null; + this._indexBuffer = null; + + this._positionLocation = null; + this._uvLocation = null; + this._textureLocation = null; + + this._positionArray = null; + this._uvArray = null; + this._indexArray = null; + + this._firstDraw = true; + } + + /** + * 解放する。 + */ + public release(): void + { + this._rect = null; + + gl.deleteTexture(this._texture); + this._texture = null; + + gl.deleteBuffer(this._uvBuffer); + this._uvBuffer = null; + + gl.deleteBuffer(this._vertexBuffer); + this._vertexBuffer = null; + + gl.deleteBuffer(this._indexBuffer); + this._indexBuffer = null; } /** @@ -47,62 +80,94 @@ import { gl, canvas } from "./lappdelegate"; */ public render(programId: WebGLProgram): void { - if(!this._texture) + if(this._texture == null) { + // ロードが完了していない return; } - // 何番目のattribute変数か - let positionLocation = gl.getAttribLocation(programId, "position"); - let uvLocation = gl.getAttribLocation(programId, "uv"); - - let textureLocation: WebGLUniformLocation = null; - textureLocation = gl.getUniformLocation(programId, "texture"); - - // attribute属性を有効にする - gl.enableVertexAttribArray(positionLocation); - gl.enableVertexAttribArray(uvLocation); - - // uniform属性の登録 - gl.uniform1i(textureLocation, 0); - - const uvVertex: Float32Array = new Float32Array([ - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0 - ]); - let vuv: WebGLBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, vuv); - gl.bufferData(gl.ARRAY_BUFFER, uvVertex, gl.STATIC_DRAW); - + // 初回描画時 + if(this._firstDraw) + { + // 何番目のattribute変数か取得 + this._positionLocation = gl.getAttribLocation(programId, "position"); + gl.enableVertexAttribArray(this._positionLocation); + + this._uvLocation = gl.getAttribLocation(programId, "uv"); + gl.enableVertexAttribArray(this._uvLocation); + + // 何番目のuniform変数か取得 + this._textureLocation = gl.getUniformLocation(programId, "texture"); + + // uniform属性の登録 + gl.uniform1i(this._textureLocation, 0); + + // uvバッファ、座標初期化 + { + this._uvArray = [ + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0 + ]; + + // uvバッファを作成 + this._uvBuffer = gl.createBuffer(); + } + + // 頂点バッファ、座標初期化 + { + let maxWidth = canvas.width; + let maxHeight = canvas.height; + + // 頂点データ + this._positionArray = [ + (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), + (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), + (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5), + (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5) + ]; + + // 頂点バッファを作成 + this._vertexBuffer = gl.createBuffer(); + } + + // 頂点インデックスバッファ、初期化 + { + // インデックスデータ + this._indexArray = [ + 0, 1, 2, + 3, 2, 0 + ]; + + // インデックスバッファを作成 + this._indexBuffer = gl.createBuffer(); + } + + this._firstDraw = false; + } + + // UV座標登録 + gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._uvArray), gl.STATIC_DRAW); + // attribute属性を登録 - gl.vertexAttribPointer(uvLocation, 2, gl.FLOAT, false, 0, 0); - - // 画面サイズを取得する。 - let maxWidth, maxHeight; - maxWidth = canvas.width; - maxHeight = canvas.height; - - // 頂点データ - let positionVertex: Float32Array = new Float32Array([ - (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), - (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.up - maxHeight * 0.5) / (maxHeight * 0.5), - (this._rect.left - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5), - (this._rect.right - maxWidth * 0.5) / (maxWidth * 0.5), (this._rect.down - maxHeight * 0.5) / (maxHeight * 0.5) - ]); - - let vposition: WebGLBuffer = gl.createBuffer(); - gl.activeTexture(gl.TEXTURE0); - gl.bindBuffer(gl.ARRAY_BUFFER, vposition); - gl.bufferData(gl.ARRAY_BUFFER, positionVertex, gl.STATIC_DRAW); - + gl.vertexAttribPointer(this._uvLocation, 2, gl.FLOAT, false, 0, 0); + + // 頂点座標を登録 + gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._positionArray), gl.STATIC_DRAW); + // attribute属性を登録 - gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); - + gl.vertexAttribPointer(this._positionLocation, 2, gl.FLOAT, false, 0, 0); + + // 頂点インデックスを作成 + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this._indexArray), gl.DYNAMIC_DRAW); + // モデルの描画 gl.bindTexture(gl.TEXTURE_2D, this._texture); - gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); + gl.drawElements(gl.TRIANGLES, this._indexArray.length, gl.UNSIGNED_SHORT, 0); } /** @@ -123,8 +188,21 @@ import { gl, canvas } from "./lappdelegate"; return (pointX >= this._rect.left && pointX <= this._rect.right && y <= this._rect.up && y >= this._rect.down); } - _texture: WebGLTexture; // テクスチャ - _rect: Rect; // 矩形 + _texture: WebGLTexture; // テクスチャ + _vertexBuffer: WebGLBuffer; // 頂点バッファ + _uvBuffer: WebGLBuffer; // uv頂点バッファ + _indexBuffer: WebGLBuffer; // 頂点インデックスバッファ + _rect: Rect; // 矩形 + + _positionLocation: number; + _uvLocation: number; + _textureLocation: WebGLUniformLocation; + + _positionArray: number[]; + _uvArray: number[]; + _indexArray: number[]; + + _firstDraw: boolean; } diff --git a/Sample/TypeScript/Demo/src/lapptexturemanager.ts b/Sample/TypeScript/Demo/src/lapptexturemanager.ts index 5731b60..c2ac651 100644 --- a/Sample/TypeScript/Demo/src/lapptexturemanager.ts +++ b/Sample/TypeScript/Demo/src/lapptexturemanager.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -23,6 +23,15 @@ export class LAppTextureManager this._textures = new Csm_csmVector(); } + /** + * 解放する。 + */ + public release(): void + { + this._textures.clear(); + this._textures = null; + } + /** * プリマルチプライ処理 * @param red 画像のRed値 diff --git a/Sample/TypeScript/Demo/src/lappview.ts b/Sample/TypeScript/Demo/src/lappview.ts index 697f51f..3114947 100644 --- a/Sample/TypeScript/Demo/src/lappview.ts +++ b/Sample/TypeScript/Demo/src/lappview.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -12,19 +12,11 @@ import Csm_CubismMatrix44 = cubismMatrix44.CubismMatrix44; import { TouchManager } from "./touchmanager"; import { LAppDefine } from "./lappdefine"; import { LAppLive2DManager } from "./lapplive2dmanager"; -import { LAppDelegate, canvas} from "./lappdelegate"; +import { LAppDelegate, canvas, gl} from "./lappdelegate"; import { LAppSprite } from "./lappsprite"; import { TextureInfo } from "./lapptexturemanager"; import { LAppPal } from "./lapppal"; -enum LoadStep -{ - BackImage, - GearImage, - PowerImage, - CompleteLoad -} - /** * 描画クラス。 */ @@ -35,8 +27,6 @@ export class LAppView */ constructor() { - this._loadStep = LoadStep.BackImage; - this._programId = null; this._back = null; this._gear = null; @@ -85,15 +75,31 @@ export class LAppView ); } + /** + * 解放する + */ + public release(): void + { + this._viewMatrix = null; + this._touchManager = null; + this._deviceToScreen = null; + + this._gear.release(); + this._gear = null; + + this._back.release(); + this._back = null; + + gl.deleteProgram(this._programId); + this._programId = null; + } + /** * 描画する。 */ public render(): void { - if(this._loadStep != LoadStep.CompleteLoad) - { - return; - } + gl.useProgram(this._programId); if(this._back) { @@ -104,6 +110,8 @@ export class LAppView this._gear.render(this._programId); } + gl.flush(); + let live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance(); live2DManager.onUpdate(); @@ -114,9 +122,8 @@ export class LAppView */ public initializeSprite(): void { - let width: number, height: number; - width = canvas.width; - height = canvas.height; + let width: number = canvas.width; + let height: number = canvas.height; let textureManager = LAppDelegate.getInstance().getTextureManager(); const resourcesPath = LAppDefine.ResourcesPath; @@ -124,54 +131,36 @@ export class LAppView let imageName: string = ""; // 背景画像初期化 - if(this._loadStep == LoadStep.BackImage) + imageName = LAppDefine.BackImageName; + + // 非同期なのでコールバック関数を作成 + let initBackGroundTexture = (textureInfo: TextureInfo): void => { - imageName = LAppDefine.BackImageName; - - // 非同期なのでコールバック関数を作成 - let initBackGroundTexture = (textureInfo: TextureInfo): void => - { - let x: number = width * 0.5; - let y: number = height * 0.5; - - let fwidth = textureInfo.width * 2.0; - let fheight = height * 0.95; - this._back = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); - this._loadStep = LoadStep.GearImage; - } - let backGroundTexture: TextureInfo = textureManager.createTextureFromPngFile(resourcesPath + imageName, initBackGroundTexture); - - // 既に画像があれば直接初期化 - if(backGroundTexture != null) - { - initBackGroundTexture(backGroundTexture); - } - } + let x: number = width * 0.5; + let y: number = height * 0.5; + + let fwidth = textureInfo.width * 2.0; + let fheight = height * 0.95; + this._back = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); + }; + + textureManager.createTextureFromPngFile(resourcesPath + imageName, initBackGroundTexture); // 歯車画像初期化 - if(this._loadStep == LoadStep.GearImage) + imageName = LAppDefine.GearImageName; + let initGearTexture = (textureInfo: TextureInfo): void => { - imageName = LAppDefine.GearImageName; - let initGearTexture = (textureInfo: TextureInfo): void => - { - let x = width - textureInfo.width * 0.5; - let y = height - textureInfo.height * 0.5; - let fwidth = textureInfo.width; - let fheight = textureInfo.height; - this._gear = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); + let x = width - textureInfo.width * 0.5; + let y = height - textureInfo.height * 0.5; + let fwidth = textureInfo.width; + let fheight = textureInfo.height; + this._gear = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); + }; - this._loadStep = LoadStep.CompleteLoad; - } - let gearTexture: TextureInfo = textureManager.createTextureFromPngFile(resourcesPath + imageName, initGearTexture); - - // 既に画像があれば直接初期化 - if(gearTexture != null) - { - initGearTexture(gearTexture); - } - } + textureManager.createTextureFromPngFile(resourcesPath + imageName, initGearTexture); - if(this._loadStep == LoadStep.CompleteLoad) + // シェーダーを作成 + if(this._programId == null) { this._programId = LAppDelegate.getInstance().createShader(); } @@ -285,6 +274,4 @@ export class LAppView _gear: LAppSprite; // ギア画像 _changeModel: boolean; // モデル切り替えフラグ _isClick: boolean; // クリック中 - - _loadStep: number; } \ No newline at end of file diff --git a/Sample/TypeScript/Demo/src/main.ts b/Sample/TypeScript/Demo/src/main.ts index b587f2d..c9b8eb0 100644 --- a/Sample/TypeScript/Demo/src/main.ts +++ b/Sample/TypeScript/Demo/src/main.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -12,7 +12,6 @@ let main: any = () => // create the application instance if(LAppDelegate.getInstance().initialize() == false) { - console.log("application iniitalize"); return; } @@ -27,6 +26,5 @@ main(); */ window.onbeforeunload = () => { - LAppDelegate.getInstance().release(); LAppDelegate.releaseInstance(); }; diff --git a/Sample/TypeScript/Demo/src/touchmanager.ts b/Sample/TypeScript/Demo/src/touchmanager.ts index 96006a1..7ca0ba3 100644 --- a/Sample/TypeScript/Demo/src/touchmanager.ts +++ b/Sample/TypeScript/Demo/src/touchmanager.ts @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license diff --git a/package.json b/package.json index ec892ac..f411236 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "scripts": { - "build-framework": "npx webpack --config framework.webpack.config.js --mode development --module-bind 'ts=ts-loader' --resolve-extensions .ts,.js", - "watch-framework": "npx webpack --watch --config framework.webpack.config.js --mode development --module-bind 'ts=ts-loader' --resolve-extensions .ts,.js", - "build-sample": "npx webpack --config sample.webpack.config.js --mode development --module-bind 'ts=ts-loader' --resolve-extensions .ts,.js", - "watch-sample": "npx webpack --watch --config sample.webpack.config.js --mode development --module-bind 'ts=ts-loader' --resolve-extensions .ts,.js", + "build-framework": "npx webpack --config framework.webpack.config.js", + "watch-framework": "npx webpack --watch --config framework.webpack.config.js", + "build-sample": "npx webpack --config sample.webpack.config.js", + "watch-sample": "npx webpack --watch --config sample.webpack.config.js", "build-all": "npm-run-all build-framework build-sample", "watch-all": "npm-run-all watch-framework watch-sample" },