mirror of
https://github.com/chendishen/react-live2d.git
synced 2024-11-23 04:20:00 +08:00
添加了某些moc3模型的动作事件不完整的兼容运行
This commit is contained in:
parent
07afbc6c80
commit
57f9182de2
3
Demo/.babelrc
Normal file
3
Demo/.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env", "@babel/preset-react"]
|
||||
}
|
22
Demo/.eslintrc.yml
Normal file
22
Demo/.eslintrc.yml
Normal file
@ -0,0 +1,22 @@
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:@typescript-eslint/eslint-recommended
|
||||
- plugin:@typescript-eslint/recommended
|
||||
- plugin:@typescript-eslint/recommended-requiring-type-checking
|
||||
- plugin:prettier/recommended
|
||||
- prettier/@typescript-eslint
|
||||
plugins:
|
||||
- '@typescript-eslint'
|
||||
parser: '@typescript-eslint/parser'
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
ecmaVersion: 2020
|
||||
project: ./tsconfig.json
|
||||
rules:
|
||||
prettier/prettier:
|
||||
- error
|
||||
- singleQuote: true
|
||||
'@typescript-eslint/camelcase': warn
|
||||
'@typescript-eslint/no-use-before-define': off
|
||||
'@typescript-eslint/ban-ts-ignore': off
|
||||
'@typescript-eslint/unbound-method': off
|
8
Demo/.npmignore
Normal file
8
Demo/.npmignore
Normal file
@ -0,0 +1,8 @@
|
||||
# .npmignore
|
||||
src
|
||||
example
|
||||
.babelrc
|
||||
.gitignore
|
||||
webpack.config.js
|
||||
/Framework
|
||||
/Resources
|
31
Demo/Framework/.eslintrc.yml
Normal file
31
Demo/Framework/.eslintrc.yml
Normal file
@ -0,0 +1,31 @@
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:@typescript-eslint/eslint-recommended
|
||||
- plugin:@typescript-eslint/recommended
|
||||
- plugin:@typescript-eslint/recommended-requiring-type-checking
|
||||
- plugin:prettier/recommended
|
||||
- prettier/@typescript-eslint
|
||||
plugins:
|
||||
- '@typescript-eslint'
|
||||
parser: '@typescript-eslint/parser'
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
ecmaVersion: 2020
|
||||
project: ./tsconfig.json
|
||||
rules:
|
||||
prettier/prettier:
|
||||
- error
|
||||
- singleQuote: true
|
||||
'@typescript-eslint/camelcase': warn
|
||||
'@typescript-eslint/no-use-before-define': off
|
||||
no-empty-function: off
|
||||
'@typescript-eslint/no-empty-function':
|
||||
- error
|
||||
- allow:
|
||||
- constructors
|
||||
'@typescript-eslint/no-namespace': warn
|
||||
'no-fallthrough': warn
|
||||
'@typescript-eslint/unbound-method': off
|
||||
'no-inner-declarations': off
|
||||
'@typescript-eslint/class-name-casing': warn
|
||||
'prefer-const': warn
|
5
Demo/Framework/.vscode/extensions.json
vendored
Normal file
5
Demo/Framework/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"editorconfig.editorconfig"
|
||||
]
|
||||
}
|
39
Demo/Framework/.vscode/tasks.json
vendored
Normal file
39
Demo/Framework/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "install",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"group": "build",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"group": "test",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "lint",
|
||||
"group": "test",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "lint:fix",
|
||||
"group": "test",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "clear",
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
23
Demo/Framework/CHANGELOG.md
Normal file
23
Demo/Framework/CHANGELOG.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
|
||||
## [4-r.1] - 2020-01-30
|
||||
|
||||
### Added
|
||||
|
||||
* Add `.editorconfig`, `.gitattributes` and `.gitignore`.
|
||||
* Add document `README.md` and `CHANGELOG.md`.
|
||||
* Add `package.json` for development and build.
|
||||
* Add Prettier and ESLint for format and check code quolity.
|
||||
|
||||
### Changed
|
||||
|
||||
* Move source files to `/src` directory.
|
||||
* Reformat code using Prettier and ESLint.
|
||||
|
||||
|
||||
[4-r.1]: https://github.com/Live2D/CubismWebFramework/compare/ce2585a919ac6e99f64dd468933772c6f1abbcc7...4-r.1
|
39
Demo/Framework/LICENSE.md
Normal file
39
Demo/Framework/LICENSE.md
Normal file
@ -0,0 +1,39 @@
|
||||
## Definitions
|
||||
|
||||
### Live2D Cubism Components
|
||||
|
||||
Cubism Web Framework is included in Live2D Cubism Components.
|
||||
|
||||
Cubism Web Framework は Live2D Cubism Components に含まれます。
|
||||
|
||||
|
||||
## Cubism SDK Release License
|
||||
|
||||
*All business* users must obtain a Cubism SDK Release License. "Business" means an entity with the annual gross revenue more than ten million (10,000,000) JPY for the most recent fiscal year.
|
||||
|
||||
* [Cubism SDK Release License](https://www.live2d.com/en/download/cubism-sdk/release-license/)
|
||||
|
||||
直近会計年度の売上高が 1000 万円以上の事業者様がご利用になる場合は、Cubism SDK リリースライセンス(出版許諾契約)に同意していただく必要がございます。
|
||||
|
||||
* [Cubism SDK リリースライセンス](https://www.live2d.com/ja/download/cubism-sdk/release-license/)
|
||||
|
||||
|
||||
## Live2D Open Software License
|
||||
|
||||
Live2D Cubism Components is available under Live2D Open Software License.
|
||||
|
||||
* [Live2D Open Software License](https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html)
|
||||
* [Live2D Open Software 使用許諾契約書](https://www.live2d.com/eula/live2d-open-software-license-agreement_jp.html)
|
||||
|
||||
|
||||
## Live2D Proprietary Software License
|
||||
|
||||
Live2D Cubism Core is available under Live2D Proprietary Software License.
|
||||
|
||||
* [Live2D Proprietary Software License Agreement](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html)
|
||||
* [Live2D Proprietary Software 使用許諾契約書](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_jp.html)
|
||||
|
||||
|
||||
---
|
||||
|
||||
Please contact us from [here](https://www.live2d.jp/contact/) for more license information.
|
134
Demo/Framework/README.md
Normal file
134
Demo/Framework/README.md
Normal file
@ -0,0 +1,134 @@
|
||||
# Cubism Web Framework
|
||||
|
||||
Live2D Cubism 4 Editor で出力したモデルをアプリケーションで利用するためのフレームワークです。
|
||||
|
||||
モデルを表示、操作するための各種機能を提供します。
|
||||
モデルをロードするには Live2D Cubism Core ライブラリと組み合わせて使用します。
|
||||
|
||||
ビルドを行うことで、ブラウザで利用可能な JavaScript ライブラリとして利用することができます。
|
||||
|
||||
|
||||
## ライセンス
|
||||
|
||||
本 SDK を使用する前に、[ライセンス](LICENSE.md)をご確認ください。
|
||||
|
||||
|
||||
## 開発環境
|
||||
|
||||
### Node.js
|
||||
|
||||
* 13.7.0
|
||||
* 12.14.1
|
||||
* 10.18.1
|
||||
|
||||
### TypeScript
|
||||
|
||||
3.7.5
|
||||
|
||||
|
||||
## 開発環境構築
|
||||
|
||||
1. [Node.js] と [Visual Studio Code] をインストールします
|
||||
1. Visual Studio Code で本プロジェクトを開き、推奨拡張機能をインストールします
|
||||
* 拡張機能タブから `@recommended` と入力することで確認できます
|
||||
1. コマンドパレット(*View > Command Palette...*)で `>Tasks: Run Task` を入力してタスク一覧を表示します
|
||||
1. `npm: install` を選択して依存パッケージのダウンロードを行います
|
||||
|
||||
コマンドパレットのタスク一覧から各種コマンドを実行することができます。
|
||||
|
||||
NOTE: デバック用の設定は、`.vscode/tasks.json` に記述しています。
|
||||
|
||||
## タスク一覧
|
||||
|
||||
### `npm: build`
|
||||
|
||||
ソースファイルのビルドを行い、`dist` ディレクトリに出力します。
|
||||
|
||||
`tsconfig.json` を編集することで設定内容を変更できます。
|
||||
|
||||
### `npm: test`
|
||||
|
||||
TypeScript の型チェックテストを行います。
|
||||
|
||||
`tsconfig.json` を編集することで設定内容を変更できます。
|
||||
|
||||
### `npm: lint`
|
||||
|
||||
`src` ディレクトリ内の TypeScript ファイルの静的解析を行います。
|
||||
|
||||
`.eslintrc.yml` を編集することで設定内容を変更できます。
|
||||
|
||||
### `npm: lint:fix`
|
||||
|
||||
`src` ディレクトリ内の TypeScript ファイルの静的解析及び自動修正を行います。
|
||||
|
||||
`.eslintrc.yml` を編集することで設定内容を変更できます。
|
||||
|
||||
### `npm: clean`
|
||||
|
||||
ビルド成果物ディレクトリ(`dist`)を削除します。
|
||||
|
||||
|
||||
## コンポーネント
|
||||
|
||||
### effect
|
||||
|
||||
自動まばたきやリップシンクなど、モデルに対してモーション情報をエフェクト的に付加する機能を提供します。
|
||||
|
||||
### id
|
||||
|
||||
モデルに設定されたパラメータ名・パーツ名・Drawable名を独自の型で管理する機能を提供します。
|
||||
|
||||
### math
|
||||
|
||||
行列計算やベクトル計算など、モデルの操作や描画に必要な算術演算の機能を提供します。
|
||||
|
||||
### model
|
||||
|
||||
モデルを取り扱うための各種機能(生成、更新、破棄)を提供します。
|
||||
|
||||
### motion
|
||||
|
||||
モデルにモーションデータを適用するための各種機能(モーション再生、パラメータブレンド)を提供します。
|
||||
|
||||
### physics
|
||||
|
||||
モデルに物理演算による変形操作を適用するための機能を提供します。
|
||||
|
||||
### rendering
|
||||
|
||||
モデルを描画するためのグラフィックス命令を実装したレンダラを提供します。
|
||||
|
||||
### type
|
||||
|
||||
フレームワーク内で使用する型定義を提供します。
|
||||
|
||||
### utils
|
||||
|
||||
JSONパーサーやログ出力などのユーティリティ機能を提供します。
|
||||
|
||||
|
||||
## Live2D Cubism Core for Web
|
||||
|
||||
当リポジトリには Cubism Core for Web は同梱されていません。
|
||||
|
||||
[Cubism SDK for Web] からダウンロードしてください。
|
||||
|
||||
[Cubism SDK for Web]: https://www.live2d.com/download/cubism-sdk/download-web/
|
||||
|
||||
|
||||
## サンプル
|
||||
|
||||
標準的なアプリケーションの実装例は [CubismWebSamples] を参照ください。
|
||||
|
||||
[CubismWebSamples]: https://github.com/Live2D/CubismWebSamples
|
||||
|
||||
|
||||
## マニュアル
|
||||
|
||||
[Cubism SDK Manual](https://docs.live2d.com/cubism-sdk-manual/top/)
|
||||
|
||||
|
||||
## 変更履歴
|
||||
|
||||
当リポジトリの変更履歴については [CHANGELOG.md](CHANGELOG.md) を参照ください。
|
1155
Demo/Framework/package-lock.json
generated
Normal file
1155
Demo/Framework/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
Demo/Framework/package.json
Normal file
20
Demo/Framework/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "tsc --noEmit",
|
||||
"lint": "eslint src -f codeframe --ext .ts",
|
||||
"lint:fix": "eslint src -f codeframe --ext .ts --fix",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^2.18.0",
|
||||
"@typescript-eslint/parser": "^2.18.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-prettier": "^6.10.0",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"prettier": "^1.19.1",
|
||||
"rimraf": "^3.0.1",
|
||||
"typescript": "^3.7.5"
|
||||
}
|
||||
}
|
65
Demo/Framework/src/cubismdefaultparameterid.ts
Normal file
65
Demo/Framework/src/cubismdefaultparameterid.ts
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief パラメータIDのデフォルト値を保持する定数<br>
|
||||
* デフォルト値の仕様は以下のマニュアルに基づく<br>
|
||||
* https://docs.live2d.com/cubism-editor-manual/standard-parametor-list/
|
||||
*/
|
||||
export namespace Live2DCubismFramework {
|
||||
// パーツID
|
||||
export const HitAreaPrefix = 'HitArea';
|
||||
export const HitAreaHead = 'Head';
|
||||
export const HitAreaBody = 'Body';
|
||||
export const PartsIdCore = 'Parts01Core';
|
||||
export const PartsArmPrefix = 'Parts01Arm_';
|
||||
export const PartsArmLPrefix = 'Parts01ArmL_';
|
||||
export const PartsArmRPrefix = 'Parts01ArmR_';
|
||||
|
||||
// パラメータID
|
||||
export const ParamAngleX = 'ParamAngleX';
|
||||
export const ParamAngleY = 'ParamAngleY';
|
||||
export const ParamAngleZ = 'ParamAngleZ';
|
||||
export const ParamEyeLOpen = 'ParamEyeLOpen';
|
||||
export const ParamEyeLSmile = 'ParamEyeLSmile';
|
||||
export const ParamEyeROpen = 'ParamEyeROpen';
|
||||
export const ParamEyeRSmile = 'ParamEyeRSmile';
|
||||
export const ParamEyeBallX = 'ParamEyeBallX';
|
||||
export const ParamEyeBallY = 'ParamEyeBallY';
|
||||
export const ParamEyeBallForm = 'ParamEyeBallForm';
|
||||
export const ParamBrowLY = 'ParamBrowLY';
|
||||
export const ParamBrowRY = 'ParamBrowRY';
|
||||
export const ParamBrowLX = 'ParamBrowLX';
|
||||
export const ParamBrowRX = 'ParamBrowRX';
|
||||
export const ParamBrowLAngle = 'ParamBrowLAngle';
|
||||
export const ParamBrowRAngle = 'ParamBrowRAngle';
|
||||
export const ParamBrowLForm = 'ParamBrowLForm';
|
||||
export const ParamBrowRForm = 'ParamBrowRForm';
|
||||
export const ParamMouthForm = 'ParamMouthForm';
|
||||
export const ParamMouthOpenY = 'ParamMouthOpenY';
|
||||
export const ParamCheek = 'ParamCheek';
|
||||
export const ParamBodyAngleX = 'ParamBodyAngleX';
|
||||
export const ParamBodyAngleY = 'ParamBodyAngleY';
|
||||
export const ParamBodyAngleZ = 'ParamBodyAngleZ';
|
||||
export const ParamBreath = 'ParamBreath';
|
||||
export const ParamArmLA = 'ParamArmLA';
|
||||
export const ParamArmRA = 'ParamArmRA';
|
||||
export const ParamArmLB = 'ParamArmLB';
|
||||
export const ParamArmRB = 'ParamArmRB';
|
||||
export const ParamHandL = 'ParamHandL';
|
||||
export const ParamHandR = 'ParamHandR';
|
||||
export const ParamHairFront = 'ParamHairFront';
|
||||
export const ParamHairSide = 'ParamHairSide';
|
||||
export const ParamHairBack = 'ParamHairBack';
|
||||
export const ParamHairFluffy = 'ParamHairFluffy';
|
||||
export const ParamShoulderY = 'ParamShoulderY';
|
||||
export const ParamBustX = 'ParamBustX';
|
||||
export const ParamBustY = 'ParamBustY';
|
||||
export const ParamBaseX = 'ParamBaseX';
|
||||
export const ParamBaseY = 'ParamBaseY';
|
||||
export const ParamNONE = 'NONE:';
|
||||
}
|
32
Demo/Framework/src/cubismframeworkconfig.ts
Normal file
32
Demo/Framework/src/cubismframeworkconfig.ts
Normal file
@ -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 https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
//========================================================
|
||||
// ログ出力関数の設定
|
||||
//========================================================
|
||||
|
||||
//---------- ログ出力レベル 選択項目 定義 ----------
|
||||
// 詳細ログ出力設定
|
||||
export const CSM_LOG_LEVEL_VERBOSE = 0;
|
||||
// デバッグログ出力設定
|
||||
export const CSM_LOG_LEVEL_DEBUG = 1;
|
||||
// Infoログ出力設定
|
||||
export const CSM_LOG_LEVEL_INFO = 2;
|
||||
// 警告ログ出力設定
|
||||
export const CSM_LOG_LEVEL_WARNING = 3;
|
||||
// エラーログ出力設定
|
||||
export const CSM_LOG_LEVEL_ERROR = 4;
|
||||
// ログ出力オフ設定
|
||||
export const CSM_LOG_LEVEL_OFF = 5;
|
||||
|
||||
/**
|
||||
* ログ出力レベル設定。
|
||||
*
|
||||
* 強制的にログ出力レベルを変える時に定義を有効にする。
|
||||
* CSM_LOG_LEVEL_VERBOSE ~ CSM_LOG_LEVEL_OFF を選択する。
|
||||
*/
|
||||
export const CSM_LOG_LEVEL: number = CSM_LOG_LEVEL_VERBOSE;
|
845
Demo/Framework/src/cubismmodelsettingjson.ts
Normal file
845
Demo/Framework/src/cubismmodelsettingjson.ts
Normal file
@ -0,0 +1,845 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 { Live2DCubismFramework as csmvector } from './type/csmvector';
|
||||
import csmVector = csmvector.csmVector;
|
||||
import csmMap = csmmap.csmMap;
|
||||
import iterator = csmmap.iterator;
|
||||
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 = 'Version';
|
||||
const FileReferences = 'FileReferences';
|
||||
const Groups = 'Groups';
|
||||
const Layout = 'Layout';
|
||||
const HitAreas = 'HitAreas';
|
||||
|
||||
const Moc = 'Moc';
|
||||
const Textures = 'Textures';
|
||||
const Physics = 'Physics';
|
||||
const Pose = 'Pose';
|
||||
const Expressions = 'Expressions';
|
||||
const Motions = 'Motions';
|
||||
|
||||
const UserData = 'UserData';
|
||||
const Name = 'Name';
|
||||
const FilePath = 'File';
|
||||
const Id = 'Id';
|
||||
const Ids = 'Ids';
|
||||
const Target = 'Target';
|
||||
|
||||
// Motions
|
||||
const Idle = 'Idle';
|
||||
const TapBody = 'TapBody';
|
||||
const PinchIn = 'PinchIn';
|
||||
const PinchOut = 'PinchOut';
|
||||
const Shake = 'Shake';
|
||||
const FlickHead = 'FlickHead';
|
||||
const Parameter = 'Parameter';
|
||||
|
||||
const SoundPath = 'Sound';
|
||||
const FadeInTime = 'FadeInTime';
|
||||
const FadeOutTime = 'FadeOutTime';
|
||||
|
||||
// Layout
|
||||
const CenterX = 'CenterX';
|
||||
const CenterY = 'CenterY';
|
||||
const X = 'X';
|
||||
const Y = 'Y';
|
||||
const Width = 'Width';
|
||||
const Height = 'Height';
|
||||
|
||||
const LipSync = 'LipSync';
|
||||
const EyeBlink = 'EyeBlink';
|
||||
|
||||
const InitParameter = 'init_param';
|
||||
const InitPartsVisible = 'init_parts_visible';
|
||||
const Val = 'val';
|
||||
|
||||
enum FrequestNode {
|
||||
FrequestNode_Groups, // getRoot().getValueByString(Groups)
|
||||
FrequestNode_Moc, // getRoot().getValueByString(FileReferences).getValueByString(Moc)
|
||||
FrequestNode_Motions, // getRoot().getValueByString(FileReferences).getValueByString(Motions)
|
||||
FrequestNode_Expressions, // getRoot().getValueByString(FileReferences).getValueByString(Expressions)
|
||||
FrequestNode_Textures, // getRoot().getValueByString(FileReferences).getValueByString(Textures)
|
||||
FrequestNode_Physics, // getRoot().getValueByString(FileReferences).getValueByString(Physics)
|
||||
FrequestNode_Pose, // getRoot().getValueByString(FileReferences).getValueByString(Pose)
|
||||
FrequestNode_HitAreas // getRoot().getValueByString(HitAreas)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
if (this._json) {
|
||||
this._jsonValue = new csmVector<Value>();
|
||||
|
||||
// 順番はenum FrequestNodeと一致させる
|
||||
this._jsonValue.pushBack(this._json.getRoot().getValueByString(Groups));
|
||||
this._jsonValue.pushBack(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(Moc)
|
||||
);
|
||||
this._jsonValue.pushBack(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(Motions)
|
||||
);
|
||||
this._jsonValue.pushBack(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(Expressions)
|
||||
);
|
||||
this._jsonValue.pushBack(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(Textures)
|
||||
);
|
||||
this._jsonValue.pushBack(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(Physics)
|
||||
);
|
||||
this._jsonValue.pushBack(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(Pose)
|
||||
);
|
||||
this._jsonValue.pushBack(
|
||||
this._json.getRoot().getValueByString(HitAreas)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
public release(): void {
|
||||
CubismJson.delete(this._json);
|
||||
|
||||
this._jsonValue = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* CubismJsonオブジェクトを取得する
|
||||
*
|
||||
* @return CubismJson
|
||||
*/
|
||||
public GetJson(): CubismJson {
|
||||
return this._json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocファイルの名前を取得する
|
||||
* @return Mocファイルの名前
|
||||
*/
|
||||
public getModelFileName(): string {
|
||||
if (!this.isExistModelFile()) {
|
||||
return '';
|
||||
}
|
||||
return this._jsonValue.at(FrequestNode.FrequestNode_Moc).getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルが使用するテクスチャの数を取得する
|
||||
* テクスチャの数
|
||||
*/
|
||||
public getTextureCount(): number {
|
||||
if (!this.isExistTextureFiles()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._jsonValue.at(FrequestNode.FrequestNode_Textures).getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* テクスチャが配置されたディレクトリの名前を取得する
|
||||
* @return テクスチャが配置されたディレクトリの名前
|
||||
*/
|
||||
public getTextureDirectory(): string {
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Textures)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルが使用するテクスチャの名前を取得する
|
||||
* @param index 配列のインデックス値
|
||||
* @return テクスチャの名前
|
||||
*/
|
||||
public getTextureFileName(index: number): string {
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Textures)
|
||||
.getValueByIndex(index)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルに設定された当たり判定の数を取得する
|
||||
* @return モデルに設定された当たり判定の数
|
||||
*/
|
||||
public getHitAreasCount(): number {
|
||||
if (!this.isExistHitAreas()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._jsonValue.at(FrequestNode.FrequestNode_HitAreas).getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 当たり判定に設定されたIDを取得する
|
||||
*
|
||||
* @param index 配列のindex
|
||||
* @return 当たり判定に設定されたID
|
||||
*/
|
||||
public getHitAreaId(index: number): CubismIdHandle {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_HitAreas)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(Id)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当たり判定に設定された名前を取得する
|
||||
* @param index 配列のインデックス値
|
||||
* @return 当たり判定に設定された名前
|
||||
*/
|
||||
public getHitAreaName(index: number): string {
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_HitAreas)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(Name)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理演算設定ファイルの名前を取得する
|
||||
* @return 物理演算設定ファイルの名前
|
||||
*/
|
||||
public getPhysicsFileName(): string {
|
||||
if (!this.isExistPhysicsFile()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Physics)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* パーツ切り替え設定ファイルの名前を取得する
|
||||
* @return パーツ切り替え設定ファイルの名前
|
||||
*/
|
||||
public getPoseFileName(): string {
|
||||
if (!this.isExistPoseFile()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this._jsonValue.at(FrequestNode.FrequestNode_Pose).getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情設定ファイルの数を取得する
|
||||
* @return 表情設定ファイルの数
|
||||
*/
|
||||
public getExpressionCount(): number {
|
||||
if (!this.isExistExpressionFile()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Expressions)
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情設定ファイルを識別する名前(別名)を取得する
|
||||
* @param index 配列のインデックス値
|
||||
* @return 表情の名前
|
||||
*/
|
||||
public getExpressionName(index: number): string {
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Expressions)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(Name)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情設定ファイルの名前を取得する
|
||||
* @param index 配列のインデックス値
|
||||
* @return 表情設定ファイルの名前
|
||||
*/
|
||||
public getExpressionFileName(index: number): string {
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Expressions)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(FilePath)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーショングループの数を取得する
|
||||
* @return モーショングループの数
|
||||
*/
|
||||
public getMotionGroupCount(): number {
|
||||
if (!this.isExistMotionGroups()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getKeys()
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーショングループの名前を取得する
|
||||
* 获取动作组的名称
|
||||
* @param index 配列のインデックス値
|
||||
* @return モーショングループの名前
|
||||
* @param index 排列的索引值
|
||||
* @return 动作组的名称
|
||||
*/
|
||||
public getMotionGroupName(index: number): string {
|
||||
if (!this.isExistMotionGroups()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getKeys()
|
||||
.at(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* モーショングループに含まれるモーションの数を取得する
|
||||
* @param groupName モーショングループの名前
|
||||
* @return モーショングループの数
|
||||
*/
|
||||
public getMotionCount(groupName: string): number {
|
||||
if (!this.isExistMotionGroupName(groupName)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* グループ名とインデックス値からモーションファイル名を取得する
|
||||
* @param groupName モーショングループの名前
|
||||
* @param index 配列のインデックス値
|
||||
* @return モーションファイルの名前
|
||||
*/
|
||||
public getMotionFileName(groupName: string, index: number): string {
|
||||
if (!this.isExistMotionGroupName(groupName)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(FilePath)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションに対応するサウンドファイルの名前を取得する
|
||||
* @param groupName モーショングループの名前
|
||||
* @param index 配列のインデックス値
|
||||
* @return サウンドファイルの名前
|
||||
*/
|
||||
public getMotionSoundFileName(groupName: string, index: number): string {
|
||||
if (!this.isExistMotionSoundFile(groupName, index)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(SoundPath)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーション開始時のフェードイン処理時間を取得する
|
||||
* @param groupName モーショングループの名前
|
||||
* @param index 配列のインデックス値
|
||||
* @return フェードイン処理時間[秒]
|
||||
*/
|
||||
public getMotionFadeInTimeValue(groupName: string, index: number): number {
|
||||
if (!this.isExistMotionFadeIn(groupName, index)) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(FadeInTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーション終了時のフェードアウト処理時間を取得する
|
||||
* @param groupName モーショングループの名前
|
||||
* @param index 配列のインデックス値
|
||||
* @return フェードアウト処理時間[秒]
|
||||
*/
|
||||
public getMotionFadeOutTimeValue(groupName: string, index: number): number {
|
||||
if (!this.isExistMotionFadeOut(groupName, index)) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
return this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(FadeOutTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーデータのファイル名を取得する
|
||||
* @return ユーザーデータのファイル名
|
||||
*/
|
||||
public getUserDataFile(): string {
|
||||
if (!this.isExistUserDataFile()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(UserData)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* レイアウト情報を取得する
|
||||
* @param outLayoutMap csmMapクラスのインスタンス
|
||||
* @return true レイアウト情報が存在する
|
||||
* @return false レイアウト情報が存在しない
|
||||
*/
|
||||
public getLayoutMap(outLayoutMap: csmMap<string, number>): boolean {
|
||||
// 存在しない要素にアクセスするとエラーになるためValueがnullの場合はnullを代入する
|
||||
const map: csmMap<string, Value> = this._json
|
||||
.getRoot()
|
||||
.getValueByString(Layout)
|
||||
.getMap();
|
||||
|
||||
if (map == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let ret = false;
|
||||
|
||||
for (
|
||||
const ite: iterator<string, Value> = 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 = 0;
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._jsonValue.at(FrequestNode.FrequestNode_Groups).getSize();
|
||||
i++
|
||||
) {
|
||||
const refI: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Groups)
|
||||
.getValueByIndex(i);
|
||||
if (refI.isNull() || refI.isError()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (refI.getValueByString(Name).getRawString() == EyeBlink) {
|
||||
num = refI
|
||||
.getValueByString(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._jsonValue.at(FrequestNode.FrequestNode_Groups).getSize();
|
||||
i++
|
||||
) {
|
||||
const refI: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Groups)
|
||||
.getValueByIndex(i);
|
||||
if (refI.isNull() || refI.isError()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (refI.getValueByString(Name).getRawString() == EyeBlink) {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
refI
|
||||
.getValueByString(Ids)
|
||||
.getValueByIndex(index)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* リップシンクに関連付けられたパラメータの数を取得する
|
||||
* @return リップシンクに関連付けられたパラメータの数
|
||||
*/
|
||||
public getLipSyncParameterCount(): number {
|
||||
if (!this.isExistLipSyncParameters()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let num = 0;
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._jsonValue.at(FrequestNode.FrequestNode_Groups).getSize();
|
||||
i++
|
||||
) {
|
||||
const refI: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Groups)
|
||||
.getValueByIndex(i);
|
||||
if (refI.isNull() || refI.isError()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (refI.getValueByString(Name).getRawString() == LipSync) {
|
||||
num = refI
|
||||
.getValueByString(Ids)
|
||||
.getVector()
|
||||
.getSize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* リップシンクに関連付けられたパラメータの数を取得する
|
||||
* @param index 配列のインデックス値
|
||||
* @return パラメータID
|
||||
*/
|
||||
public getLipSyncParameterId(index: number): CubismIdHandle {
|
||||
if (!this.isExistLipSyncParameters()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._jsonValue.at(FrequestNode.FrequestNode_Groups).getSize();
|
||||
i++
|
||||
) {
|
||||
const refI: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Groups)
|
||||
.getValueByIndex(i);
|
||||
if (refI.isNull() || refI.isError()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (refI.getValueByString(Name).getRawString() == LipSync) {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
refI
|
||||
.getValueByString(Ids)
|
||||
.getValueByIndex(index)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルファイルのキーが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistModelFile(): boolean {
|
||||
const node: Value = this._jsonValue.at(FrequestNode.FrequestNode_Moc);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* テクスチャファイルのキーが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistTextureFiles(): boolean {
|
||||
const node: Value = this._jsonValue.at(
|
||||
FrequestNode.FrequestNode_Textures
|
||||
);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 当たり判定のキーが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistHitAreas(): boolean {
|
||||
const node: Value = this._jsonValue.at(
|
||||
FrequestNode.FrequestNode_HitAreas
|
||||
);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理演算ファイルのキーが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistPhysicsFile(): boolean {
|
||||
const node: Value = this._jsonValue.at(FrequestNode.FrequestNode_Physics);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* ポーズ設定ファイルのキーが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistPoseFile(): boolean {
|
||||
const node: Value = this._jsonValue.at(FrequestNode.FrequestNode_Pose);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情設定ファイルのキーが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistExpressionFile(): boolean {
|
||||
const node: Value = this._jsonValue.at(
|
||||
FrequestNode.FrequestNode_Expressions
|
||||
);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーショングループのキーが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistMotionGroups(): boolean {
|
||||
const node: Value = this._jsonValue.at(FrequestNode.FrequestNode_Motions);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 引数で指定したモーショングループのキーが存在するかどうかを確認する
|
||||
* @param groupName グループ名
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistMotionGroupName(groupName: string): boolean {
|
||||
const node: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 引数で指定したモーションに対応するサウンドファイルのキーが存在するかどうかを確認する
|
||||
* @param groupName グループ名
|
||||
* @param index 配列のインデックス値
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistMotionSoundFile(groupName: string, index: number): boolean {
|
||||
const node: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(SoundPath);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 引数で指定したモーションに対応するフェードイン時間のキーが存在するかどうかを確認する
|
||||
* @param groupName グループ名
|
||||
* @param index 配列のインデックス値
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistMotionFadeIn(groupName: string, index: number): boolean {
|
||||
const node: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(FadeInTime);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 引数で指定したモーションに対応するフェードアウト時間のキーが存在するかどうかを確認する
|
||||
* @param groupName グループ名
|
||||
* @param index 配列のインデックス値
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistMotionFadeOut(groupName: string, index: number): boolean {
|
||||
const node: Value = this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Motions)
|
||||
.getValueByString(groupName)
|
||||
.getValueByIndex(index)
|
||||
.getValueByString(FadeOutTime);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* UserDataのファイル名が存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistUserDataFile(): boolean {
|
||||
const node: Value = this._json
|
||||
.getRoot()
|
||||
.getValueByString(FileReferences)
|
||||
.getValueByString(UserData);
|
||||
return !node.isNull() && !node.isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 目ぱちに対応付けられたパラメータが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistEyeBlinkParameters(): boolean {
|
||||
if (
|
||||
this._jsonValue.at(FrequestNode.FrequestNode_Groups).isNull() ||
|
||||
this._jsonValue.at(FrequestNode.FrequestNode_Groups).isError()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._jsonValue.at(FrequestNode.FrequestNode_Groups).getSize();
|
||||
++i
|
||||
) {
|
||||
if (
|
||||
this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Groups)
|
||||
.getValueByIndex(i)
|
||||
.getValueByString(Name)
|
||||
.getRawString() == EyeBlink
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* リップシンクに対応付けられたパラメータが存在するかどうかを確認する
|
||||
* @return true キーが存在する
|
||||
* @return false キーが存在しない
|
||||
*/
|
||||
private isExistLipSyncParameters(): boolean {
|
||||
if (
|
||||
this._jsonValue.at(FrequestNode.FrequestNode_Groups).isNull() ||
|
||||
this._jsonValue.at(FrequestNode.FrequestNode_Groups).isError()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._jsonValue.at(FrequestNode.FrequestNode_Groups).getSize();
|
||||
++i
|
||||
) {
|
||||
if (
|
||||
this._jsonValue
|
||||
.at(FrequestNode.FrequestNode_Groups)
|
||||
.getValueByIndex(i)
|
||||
.getValueByString(Name)
|
||||
.getRawString() == LipSync
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _json: CubismJson;
|
||||
private _jsonValue: csmVector<Value>;
|
||||
}
|
||||
}
|
124
Demo/Framework/src/effect/cubismbreath.ts
Normal file
124
Demo/Framework/src/effect/cubismbreath.ts
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 {
|
||||
if (instance != null) {
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 呼吸のパラメータの紐づけ
|
||||
* @param breathParameters 呼吸を紐づけたいパラメータのリスト
|
||||
*/
|
||||
public setParameters(
|
||||
breathParameters: csmVector<BreathParameterData>
|
||||
): void {
|
||||
this._breathParameters = breathParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 呼吸に紐づいているパラメータの取得
|
||||
* @return 呼吸に紐づいているパラメータのリスト
|
||||
*/
|
||||
public getParameters(): csmVector<BreathParameterData> {
|
||||
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 = 0; i < this._breathParameters.getSize(); ++i) {
|
||||
const data: 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<BreathParameterData>; // 呼吸にひもづいているパラメータのリスト
|
||||
_currentTime: number; // 積算時間[秒]
|
||||
}
|
||||
|
||||
/**
|
||||
* 呼吸のパラメータ情報
|
||||
*/
|
||||
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; // パラメータへの重み
|
||||
}
|
||||
}
|
232
Demo/Framework/src/effect/cubismeyeblink.ts
Normal file
232
Demo/Framework/src/effect/cubismeyeblink.ts
Normal file
@ -0,0 +1,232 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 {
|
||||
if (eyeBlink != null) {
|
||||
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<CubismIdHandle>): void {
|
||||
this._parameterIds = parameterIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* まばたきさせるパラメータIDのリストの取得
|
||||
* @return パラメータIDのリスト
|
||||
*/
|
||||
public getParameterIds(): csmVector<CubismIdHandle> {
|
||||
return this._parameterIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルのパラメータの更新
|
||||
* @param model 対象のモデル
|
||||
* @param deltaTimeSeconds デルタ時間[秒]
|
||||
*/
|
||||
public updateParameters(
|
||||
model: CubismModel,
|
||||
deltaTimeSeconds: number
|
||||
): void {
|
||||
this._userTimeSeconds += deltaTimeSeconds;
|
||||
let parameterValue: number;
|
||||
let t = 0.0;
|
||||
|
||||
switch (this._blinkingState) {
|
||||
case EyeState.EyeState_Closing:
|
||||
t =
|
||||
(this._userTimeSeconds - this._stateStartTimeSeconds) /
|
||||
this._closingSeconds;
|
||||
|
||||
if (t >= 1.0) {
|
||||
t = 1.0;
|
||||
this._blinkingState = EyeState.EyeState_Closed;
|
||||
this._stateStartTimeSeconds = this._userTimeSeconds;
|
||||
}
|
||||
|
||||
parameterValue = 1.0 - t;
|
||||
|
||||
break;
|
||||
case EyeState.EyeState_Closed:
|
||||
t =
|
||||
(this._userTimeSeconds - this._stateStartTimeSeconds) /
|
||||
this._closedSeconds;
|
||||
|
||||
if (t >= 1.0) {
|
||||
this._blinkingState = EyeState.EyeState_Opening;
|
||||
this._stateStartTimeSeconds = this._userTimeSeconds;
|
||||
}
|
||||
|
||||
parameterValue = 0.0;
|
||||
|
||||
break;
|
||||
case EyeState.EyeState_Opening:
|
||||
t =
|
||||
(this._userTimeSeconds - this._stateStartTimeSeconds) /
|
||||
this._openingSeconds;
|
||||
|
||||
if (t >= 1.0) {
|
||||
t = 1.0;
|
||||
this._blinkingState = EyeState.EyeState_Interval;
|
||||
this._nextBlinkingTime = this.determinNextBlinkingTiming();
|
||||
}
|
||||
|
||||
parameterValue = t;
|
||||
|
||||
break;
|
||||
case EyeState.EyeState_Interval:
|
||||
if (this._nextBlinkingTime < this._userTimeSeconds) {
|
||||
this._blinkingState = EyeState.EyeState_Closing;
|
||||
this._stateStartTimeSeconds = this._userTimeSeconds;
|
||||
}
|
||||
|
||||
parameterValue = 1.0;
|
||||
|
||||
break;
|
||||
case EyeState.EyeState_First:
|
||||
default:
|
||||
this._blinkingState = EyeState.EyeState_Interval;
|
||||
this._nextBlinkingTime = this.determinNextBlinkingTiming();
|
||||
|
||||
parameterValue = 1.0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CubismEyeBlink.CloseIfZero) {
|
||||
parameterValue = -parameterValue;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._parameterIds.getSize(); ++i) {
|
||||
model.setParameterValueById(this._parameterIds.at(i), parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
* @param modelSetting モデルの設定情報
|
||||
*/
|
||||
public constructor(modelSetting: ICubismModelSetting) {
|
||||
this._blinkingState = 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<CubismIdHandle>();
|
||||
|
||||
if (modelSetting == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 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<CubismIdHandle>; // 操作対象のパラメータのIDのリスト
|
||||
_nextBlinkingTime: number; // 次のまばたきの時刻[秒]
|
||||
_stateStartTimeSeconds: number; // 現在の状態が開始した時刻[秒]
|
||||
_blinkingIntervalSeconds: number; // まばたきの間隔[秒]
|
||||
_closingSeconds: number; // まぶたを閉じる動作の所要時間[秒]
|
||||
_closedSeconds: number; // まぶたを閉じている動作の所要時間[秒]
|
||||
_openingSeconds: number; // まぶたを開く動作の所要時間[秒]
|
||||
_userTimeSeconds: number; // デルタ時間の積算値[秒]
|
||||
|
||||
/**
|
||||
* IDで指定された目のパラメータが、0のときに閉じるなら true 、1の時に閉じるなら false 。
|
||||
*/
|
||||
static readonly CloseIfZero: boolean = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* まばたきの状態
|
||||
*
|
||||
* まばたきの状態を表す列挙型
|
||||
*/
|
||||
export enum EyeState {
|
||||
EyeState_First = 0, // 初期状態
|
||||
EyeState_Interval, // まばたきしていない状態
|
||||
EyeState_Closing, // まぶたが閉じていく途中の状態
|
||||
EyeState_Closed, // まぶたが閉じている状態
|
||||
EyeState_Opening // まぶたが開いていく途中の状態
|
||||
}
|
||||
}
|
405
Demo/Framework/src/effect/cubismpose.ts
Normal file
405
Demo/Framework/src/effect/cubismpose.ts
Normal file
@ -0,0 +1,405 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 iterator = csmvector.iterator;
|
||||
import CubismModel = cubismmodel.CubismModel;
|
||||
import CubismFramework = cubismframework.CubismFramework;
|
||||
import CubismJson = cubismjson.CubismJson;
|
||||
import Value = cubismjson.Value;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
const Epsilon = 0.001;
|
||||
const DefaultFadeInSeconds = 0.5;
|
||||
|
||||
// Pose.jsonのタグ
|
||||
const FadeIn = 'FadeInTime';
|
||||
const Link = 'Link';
|
||||
const Groups = 'Groups';
|
||||
const Id = 'Id';
|
||||
|
||||
/**
|
||||
* パーツの不透明度の設定
|
||||
*
|
||||
* パーツの不透明度の管理と設定を行う。
|
||||
*/
|
||||
export class CubismPose {
|
||||
/**
|
||||
* インスタンスの作成
|
||||
* @param pose3json pose3.jsonのデータ
|
||||
* @param size pose3.jsonのデータのサイズ[byte]
|
||||
* @return 作成されたインスタンス
|
||||
*/
|
||||
public static create(pose3json: ArrayBuffer, size: number): CubismPose {
|
||||
const ret: CubismPose = new CubismPose();
|
||||
const json: CubismJson = CubismJson.create(pose3json, size);
|
||||
const root: Value = json.getRoot();
|
||||
|
||||
// フェード時間の指定
|
||||
if (!root.getValueByString(FadeIn).isNull()) {
|
||||
ret._fadeTimeSeconds = root
|
||||
.getValueByString(FadeIn)
|
||||
.toFloat(DefaultFadeInSeconds);
|
||||
|
||||
if (ret._fadeTimeSeconds <= 0.0) {
|
||||
ret._fadeTimeSeconds = DefaultFadeInSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
// パーツグループ
|
||||
const poseListInfo: Value = root.getValueByString(Groups);
|
||||
const poseCount: number = poseListInfo.getSize();
|
||||
|
||||
for (let poseIndex = 0; poseIndex < poseCount; ++poseIndex) {
|
||||
const idListInfo: Value = poseListInfo.getValueByIndex(poseIndex);
|
||||
const idCount: number = idListInfo.getSize();
|
||||
let groupCount = 0;
|
||||
|
||||
for (let groupIndex = 0; groupIndex < idCount; ++groupIndex) {
|
||||
const partInfo: Value = idListInfo.getValueByIndex(groupIndex);
|
||||
const partData: PartData = new PartData();
|
||||
const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(
|
||||
partInfo.getValueByString(Id).getRawString()
|
||||
);
|
||||
|
||||
partData.partId = parameterId;
|
||||
|
||||
// リンクするパーツの設定
|
||||
if (!partInfo.getValueByString(Link).isNull()) {
|
||||
const linkListInfo: Value = partInfo.getValueByString(Link);
|
||||
const linkCount: number = linkListInfo.getSize();
|
||||
|
||||
for (let linkIndex = 0; linkIndex < linkCount; ++linkIndex) {
|
||||
const linkPart: PartData = new PartData();
|
||||
const linkId: CubismIdHandle = CubismFramework.getIdManager().getId(
|
||||
linkListInfo.getValueByIndex(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 {
|
||||
if (pose != null) {
|
||||
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 = 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 = 0;
|
||||
|
||||
for (let i = 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 = 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 = 0;
|
||||
groupIndex < this._partGroups.getSize();
|
||||
++groupIndex
|
||||
) {
|
||||
const partData: 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 = 0;
|
||||
linkIndex < partData.link.getSize();
|
||||
++linkIndex
|
||||
) {
|
||||
const linkPart: 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 = -1;
|
||||
let newOpacity = 1.0;
|
||||
|
||||
const phi = 0.5;
|
||||
const backOpacityThreshold = 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<PartData>();
|
||||
this._partGroupCounts = new csmVector<number>();
|
||||
}
|
||||
|
||||
_partGroups: csmVector<PartData>; // パーツグループ
|
||||
_partGroupCounts: csmVector<number>; // それぞれのパーツグループの個数
|
||||
_fadeTimeSeconds: number; // フェード時間[秒]
|
||||
_lastModel: CubismModel; // 前回操作したモデル
|
||||
}
|
||||
|
||||
/**
|
||||
* パーツにまつわるデータを管理
|
||||
*/
|
||||
export class PartData {
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
constructor(v?: PartData) {
|
||||
this.parameterIndex = 0;
|
||||
this.partIndex = 0;
|
||||
this.link = new csmVector<PartData>();
|
||||
|
||||
if (v != undefined) {
|
||||
this.partId = v.partId;
|
||||
|
||||
for (
|
||||
const ite: iterator<PartData> = 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: iterator<PartData> = 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 {
|
||||
const clonePartData: PartData = new PartData();
|
||||
|
||||
clonePartData.partId = this.partId;
|
||||
clonePartData.parameterIndex = this.parameterIndex;
|
||||
clonePartData.partIndex = this.partIndex;
|
||||
clonePartData.link = new csmVector<PartData>();
|
||||
|
||||
for (
|
||||
let ite: iterator<PartData> = 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<PartData>; // 連動するパラメータ
|
||||
}
|
||||
}
|
45
Demo/Framework/src/icubismallcator.ts
Normal file
45
Demo/Framework/src/icubismallcator.ts
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
199
Demo/Framework/src/icubismmodelsetting.ts
Normal file
199
Demo/Framework/src/icubismmodelsetting.ts
Normal file
@ -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 https://www.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<string, number>): 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;
|
||||
}
|
||||
}
|
73
Demo/Framework/src/id/cubismid.ts
Normal file
73
Demo/Framework/src/id/cubismid.ts
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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;
|
||||
}
|
118
Demo/Framework/src/id/cubismidmanager.ts
Normal file
118
Demo/Framework/src/id/cubismidmanager.ts
Normal file
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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<CubismId>();
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
public release(): void {
|
||||
for (let i = 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 = 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 = 0; i < this._ids.getSize(); ++i) {
|
||||
if (
|
||||
this._ids
|
||||
.at(i)
|
||||
.getString()
|
||||
.isEqual(id)
|
||||
) {
|
||||
return this._ids.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private _ids: csmVector<CubismId>; // 登録されているIDのリスト
|
||||
}
|
||||
}
|
272
Demo/Framework/src/live2dcubismframework.ts
Normal file
272
Demo/Framework/src/live2dcubismframework.ts
Normal file
@ -0,0 +1,272 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 = 0;
|
||||
for (let i = 1; ; i++) {
|
||||
const testC: string = s.slice(i - 1, i);
|
||||
|
||||
// 指数・マイナスの可能性があるのでスキップする
|
||||
if (testC == 'e' || testC == '-' || testC == 'E') {
|
||||
continue;
|
||||
} // 文字列の範囲を広げていく
|
||||
|
||||
const test: string = s.substring(0, i);
|
||||
const 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 = false;
|
||||
let s_isInitialized = false;
|
||||
let s_option: Option = null;
|
||||
let s_cubismIdManager: CubismIdManager = null;
|
||||
|
||||
/**
|
||||
* Framework内で使う定数の宣言
|
||||
*/
|
||||
export namespace Constant {
|
||||
export const vertexOffset = 0; // メッシュ頂点のオフセット値
|
||||
export const vertexStep = 2; // メッシュ頂点のステップ値
|
||||
}
|
||||
|
||||
export function csmDelete<T>(address: T): void {
|
||||
if (!address) {
|
||||
return;
|
||||
}
|
||||
|
||||
address = void 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Live2D Cubism SDK Original Workflow SDKのエントリポイント
|
||||
* 利用開始時はCubismFramework.initialize()を呼び、CubismFramework.dispose()で終了する。
|
||||
*/
|
||||
export class CubismFramework {
|
||||
/**
|
||||
* Cubism FrameworkのAPIを使用可能にする。
|
||||
* APIを実行する前に必ずこの関数を実行すること。
|
||||
* 一度準備が完了して以降は、再び実行しても内部処理がスキップされます。
|
||||
*
|
||||
* @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) {
|
||||
Live2DCubismCore.Logging.csmSetLogFunction(s_option.logFunction);
|
||||
}
|
||||
|
||||
s_isStarted = true;
|
||||
|
||||
// Live2D Cubism Coreバージョン情報を表示
|
||||
if (s_isStarted) {
|
||||
const version: number = Live2DCubismCore.Version.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: {0}.{1}.{2} ({3})`,
|
||||
('00' + major).slice(-2),
|
||||
('00' + minor).slice(-2),
|
||||
('0000' + patch).slice(-4),
|
||||
versionNumber
|
||||
);
|
||||
}
|
||||
|
||||
CubismLogInfo('CubismFramework.startUp() is complete.');
|
||||
|
||||
return s_isStarted;
|
||||
}
|
||||
|
||||
/**
|
||||
* StartUp()で初期化したCubismFrameworkの各パラメータをクリアします。
|
||||
* Dispose()したCubismFrameworkを再利用する際に利用してください。
|
||||
*/
|
||||
public static cleanUp(): void {
|
||||
s_isStarted = false;
|
||||
s_isInitialized = false;
|
||||
s_option = null;
|
||||
s_cubismIdManager = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cubism Framework内のリソースを初期化してモデルを表示可能な状態にします。<br>
|
||||
* 再度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 = null;
|
||||
|
||||
// レンダラの静的リソース(シェーダプログラム他)を解放する
|
||||
CubismRenderer.staticRelease();
|
||||
|
||||
s_isInitialized = false;
|
||||
|
||||
CubismLogInfo('CubismFramework.dispose() is complete.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cubism FrameworkのAPIを使用する準備が完了したかどうか
|
||||
* @return APIを使用する準備が完了していればtrueが返ります。
|
||||
*/
|
||||
public static isStarted(): boolean {
|
||||
return s_isStarted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cubism Frameworkのリソース初期化がすでに行われているかどうか
|
||||
* @return リソース確保が完了していればtrueが返ります
|
||||
*/
|
||||
public static isInitialized(): boolean {
|
||||
return s_isInitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Core APIにバインドしたログ関数を実行する
|
||||
*
|
||||
* @praram message ログメッセージ
|
||||
*/
|
||||
public static coreLogFunction(message: string): void {
|
||||
// Return if logging not possible.
|
||||
if (!Live2DCubismCore.Logging.csmGetLogFunction()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Live2DCubismCore.Logging.csmGetLogFunction()(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 現在のログ出力レベル設定の値を返す。
|
||||
*
|
||||
* @return 現在のログ出力レベル設定の値
|
||||
*/
|
||||
public static getLoggingLevel(): LogLevel {
|
||||
if (s_option != null) {
|
||||
return s_option.loggingLevel;
|
||||
}
|
||||
return LogLevel.LogLevel_Off;
|
||||
}
|
||||
|
||||
/**
|
||||
* IDマネージャのインスタンスを取得する
|
||||
* @return CubismManagerクラスのインスタンス
|
||||
*/
|
||||
public static getIdManager(): CubismIdManager {
|
||||
return s_cubismIdManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静的クラスとして使用する
|
||||
* インスタンス化させない
|
||||
*/
|
||||
private constructor() {}
|
||||
}
|
||||
}
|
||||
|
||||
export class Option {
|
||||
logFunction: Live2DCubismCore.csmLogFunction; // ログ出力の関数オブジェクト
|
||||
loggingLevel: LogLevel; // ログ出力レベルの設定
|
||||
}
|
||||
|
||||
/**
|
||||
* ログ出力のレベル
|
||||
*/
|
||||
export enum LogLevel {
|
||||
LogLevel_Verbose = 0, // 詳細ログ
|
||||
LogLevel_Debug, // デバッグログ
|
||||
LogLevel_Info, // Infoログ
|
||||
LogLevel_Warning, // 警告ログ
|
||||
LogLevel_Error, // エラーログ
|
||||
LogLevel_Off // ログ出力無効
|
||||
}
|
195
Demo/Framework/src/math/cubismmath.ts
Normal file
195
Demo/Framework/src/math/cubismmath.ts
Normal file
@ -0,0 +1,195 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 {
|
||||
const ret: CubismVector2 = new CubismVector2();
|
||||
|
||||
ret.x = this.sin(totalAngle);
|
||||
ret.y = this.cos(totalAngle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
private constructor() {}
|
||||
}
|
||||
}
|
308
Demo/Framework/src/math/cubismmatrix44.ts
Normal file
308
Demo/Framework/src/math/cubismmatrix44.ts
Normal file
@ -0,0 +1,308 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
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 {
|
||||
const 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
|
||||
]);
|
||||
|
||||
const n = 4;
|
||||
|
||||
for (let i = 0; i < n; ++i) {
|
||||
for (let j = 0; j < n; ++j) {
|
||||
for (let k = 0; k < n; ++k) {
|
||||
c[j + i * 4] += a[k + i * 4] * b[j + k * 4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 16; ++i) {
|
||||
dst[i] = c[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 単位行列に初期化する
|
||||
*/
|
||||
public loadIdentity(): void {
|
||||
const 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 {
|
||||
const 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 {
|
||||
const 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* オブジェクトのコピーを生成する
|
||||
*/
|
||||
public clone(): CubismMatrix44 {
|
||||
const cloneMatrix: CubismMatrix44 = new CubismMatrix44();
|
||||
|
||||
for (let i = 0; i < this._tr.length; i++) {
|
||||
cloneMatrix._tr[i] = this._tr[i];
|
||||
}
|
||||
|
||||
return cloneMatrix;
|
||||
}
|
||||
|
||||
protected _tr: Float32Array; // 4x4行列データ
|
||||
}
|
||||
}
|
223
Demo/Framework/src/math/cubismmodelmatrix.ts
Normal file
223
Demo/Framework/src/math/cubismmodelmatrix.ts
Normal file
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as csmmap } from '../type/csmmap';
|
||||
import { Live2DCubismFramework as cubismmatrix44 } from './cubismmatrix44';
|
||||
import csmMap = csmmap.csmMap;
|
||||
import iterator = csmmap.iterator;
|
||||
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;
|
||||
|
||||
this.setHeight(1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 横幅を設定
|
||||
*
|
||||
* @param w 横幅
|
||||
*/
|
||||
public setWidth(w: number): void {
|
||||
const scaleX: number = w / this._width;
|
||||
const scaleY: number = scaleX;
|
||||
this.scale(scaleX*2.6, scaleY*2.6);
|
||||
}
|
||||
|
||||
/**
|
||||
* 縦幅を設定
|
||||
* @param h 縦幅
|
||||
*/
|
||||
public setHeight(h: number): void {
|
||||
const scaleX: number = h / this._height;
|
||||
const scaleY: number = scaleX;
|
||||
this.scale(scaleX*2.6, scaleY*2.6);
|
||||
}
|
||||
|
||||
/**
|
||||
* 位置を設定
|
||||
*
|
||||
* @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<string, number>): 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: iterator<string, number> = 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: iterator<string, number> = 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; // 縦幅
|
||||
}
|
||||
}
|
164
Demo/Framework/src/math/cubismtargetpoint.ts
Normal file
164
Demo/Framework/src/math/cubismtargetpoint.ts
Normal file
@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as cubismmath } from './cubismmath';
|
||||
import CubismMath = cubismmath.CubismMath;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
const FrameRate = 30;
|
||||
const Epsilon = 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 = 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; // デルタ時間の積算値[秒]
|
||||
}
|
||||
}
|
163
Demo/Framework/src/math/cubismvector2.ts
Normal file
163
Demo/Framework/src/math/cubismvector2.ts
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
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 {
|
||||
const 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 {
|
||||
const 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 {
|
||||
const 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 {
|
||||
const 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);
|
||||
}
|
||||
}
|
||||
}
|
337
Demo/Framework/src/math/cubismviewmatrix.ts
Normal file
337
Demo/Framework/src/math/cubismviewmatrix.ts
Normal file
@ -0,0 +1,337 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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];
|
||||
}
|
||||
|
||||
const 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 {
|
||||
const maxScale: number = this.getMaxScale();
|
||||
const minScale: number = this.getMinScale();
|
||||
|
||||
const 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];
|
||||
}
|
||||
}
|
||||
|
||||
const 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
|
||||
]);
|
||||
|
||||
const 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
|
||||
]);
|
||||
|
||||
const 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; // 拡大率の最小値
|
||||
}
|
||||
}
|
100
Demo/Framework/src/model/cubismmoc.ts
Normal file
100
Demo/Framework/src/model/cubismmoc.ts
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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;
|
||||
const 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;
|
||||
|
||||
const model: Live2DCubismCore.Model = Live2DCubismCore.Model.fromMoc(
|
||||
this._moc
|
||||
);
|
||||
|
||||
if (model) {
|
||||
cubismModel = new CubismModel(model);
|
||||
cubismModel.initialize();
|
||||
|
||||
++this._modelCount;
|
||||
}
|
||||
|
||||
return cubismModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルを削除する
|
||||
*/
|
||||
deleteModel(model: CubismModel): void {
|
||||
if (model != null) {
|
||||
model.release();
|
||||
model = null;
|
||||
--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データから作られたモデルの個数
|
||||
}
|
||||
}
|
822
Demo/Framework/src/model/cubismmodel.ts
Normal file
822
Demo/Framework/src/model/cubismmodel.ts
Normal file
@ -0,0 +1,822 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 CubismBlendMode = cubismrenderer.CubismBlendMode;
|
||||
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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): CubismBlendMode {
|
||||
const constantFlags = this._model.drawables.constantFlags;
|
||||
|
||||
return Live2DCubismCore.Utils.hasBlendAdditiveBit(
|
||||
constantFlags[drawableIndex]
|
||||
)
|
||||
? CubismBlendMode.CubismBlendMode_Additive
|
||||
: Live2DCubismCore.Utils.hasBlendMultiplicativeBit(
|
||||
constantFlags[drawableIndex]
|
||||
)
|
||||
? CubismBlendMode.CubismBlendMode_Multiplicative
|
||||
: CubismBlendMode.CubismBlendMode_Normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drawableのマスクの反転使用の取得
|
||||
*
|
||||
* Drawableのマスク使用時の反転設定を取得する。
|
||||
* マスクを使用しない場合は無視される。
|
||||
*
|
||||
* @param drawableIndex Drawableのインデックス
|
||||
* @return Drawableの反転設定
|
||||
*/
|
||||
public getDrawableInvertedMaskBit(drawableIndex: number): boolean {
|
||||
const constantFlags: Uint8Array = this._model.drawables.constantFlags;
|
||||
|
||||
return Live2DCubismCore.Utils.hasIsInvertedMaskBit(
|
||||
constantFlags[drawableIndex]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = 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 = 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;
|
||||
|
||||
this._parameterIds.prepareCapacity(parameterCount);
|
||||
for (let i = 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;
|
||||
|
||||
this._partIds.prepareCapacity(partCount);
|
||||
for (let i = 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;
|
||||
|
||||
this._drawableIds.prepareCapacity(drawableCount);
|
||||
for (let i = 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<number>();
|
||||
this._parameterIds = new csmVector<CubismIdHandle>();
|
||||
this._drawableIds = new csmVector<CubismIdHandle>();
|
||||
this._partIds = new csmVector<CubismIdHandle>();
|
||||
|
||||
this._notExistPartId = new csmMap<CubismIdHandle, number>();
|
||||
this._notExistParameterId = new csmMap<CubismIdHandle, number>();
|
||||
this._notExistParameterValues = new csmMap<number, number>();
|
||||
this._notExistPartOpacities = new csmMap<number, number>();
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
public release(): void {
|
||||
this._model.release();
|
||||
this._model = null;
|
||||
}
|
||||
|
||||
private _notExistPartOpacities: csmMap<number, number>; // 存在していないパーツの不透明度のリスト
|
||||
private _notExistPartId: csmMap<CubismIdHandle, number>; // 存在していないパーツIDのリスト
|
||||
|
||||
private _notExistParameterValues: csmMap<number, number>; // 存在していないパラメータの値のリスト
|
||||
private _notExistParameterId: csmMap<CubismIdHandle, number>; // 存在していないパラメータIDのリスト
|
||||
|
||||
private _savedParameters: csmVector<number>; // 保存されたパラメータ
|
||||
|
||||
private _model: Live2DCubismCore.Model; // モデル
|
||||
|
||||
private _parameterValues: Float32Array; // パラメータの値のリスト
|
||||
private _parameterMaximumValues: Float32Array; // パラメータの最大値のリスト
|
||||
private _parameterMinimumValues: Float32Array; // パラメータの最小値のリスト
|
||||
|
||||
private _partOpacities: Float32Array; // パーツの不透明度のリスト
|
||||
|
||||
private _parameterIds: csmVector<CubismIdHandle>;
|
||||
private _partIds: csmVector<CubismIdHandle>;
|
||||
private _drawableIds: csmVector<CubismIdHandle>;
|
||||
}
|
||||
}
|
136
Demo/Framework/src/model/cubismmodeluserdata.ts
Normal file
136
Demo/Framework/src/model/cubismmodeluserdata.ts
Normal file
@ -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 https://www.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 = '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 {
|
||||
const ret: CubismModelUserData = new CubismModelUserData();
|
||||
|
||||
ret.parseUserData(buffer, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* インスタンスを破棄する
|
||||
*
|
||||
* @param modelUserData 破棄するインスタンス
|
||||
*/
|
||||
public static delete(modelUserData: CubismModelUserData): void {
|
||||
if (modelUserData != null) {
|
||||
modelUserData.release();
|
||||
modelUserData = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ArtMeshのユーザーデータのリストの取得
|
||||
*
|
||||
* @return ユーザーデータリスト
|
||||
*/
|
||||
public getArtMeshUserDatas(): csmVector<CubismModelUserDataNode> {
|
||||
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 = 0; i < nodeCount; i++) {
|
||||
const 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<CubismModelUserDataNode>();
|
||||
this._artMeshUserDataNode = new csmVector<CubismModelUserDataNode>();
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*
|
||||
* ユーザーデータ構造体配列を解放する
|
||||
*/
|
||||
public release(): void {
|
||||
for (let i = 0; i < this._userDataNodes.getSize(); ++i) {
|
||||
this._userDataNodes.set(i, null);
|
||||
}
|
||||
|
||||
this._userDataNodes = null;
|
||||
}
|
||||
|
||||
private _userDataNodes: csmVector<CubismModelUserDataNode>; // ユーザーデータ構造体配列
|
||||
private _artMeshUserDataNode: csmVector<CubismModelUserDataNode>; // 閲覧リストの保持
|
||||
}
|
||||
}
|
114
Demo/Framework/src/model/cubismmodeluserdatajson.ts
Normal file
114
Demo/Framework/src/model/cubismmodeluserdatajson.ts
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 = 'Meta';
|
||||
const UserDataCount = 'UserDataCount';
|
||||
const TotalUserDataSize = 'TotalUserDataSize';
|
||||
const UserData = 'UserData';
|
||||
const Target = 'Target';
|
||||
const Id = 'Id';
|
||||
const Value = '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()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(UserDataCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーデータ総文字列数の取得
|
||||
*
|
||||
* @return ユーザーデータ総文字列数
|
||||
*/
|
||||
public getTotalUserDataSize(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalUserDataSize)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーデータのタイプの取得
|
||||
*
|
||||
* @return ユーザーデータのタイプ
|
||||
*/
|
||||
public getUserDataTargetType(i: number): string {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(UserData)
|
||||
.getValueByIndex(i)
|
||||
.getValueByString(Target)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーデータのターゲットIDの取得
|
||||
*
|
||||
* @param i インデックス
|
||||
* @return ユーザーデータターゲットID
|
||||
*/
|
||||
public getUserDataId(i: number): CubismIdHandle {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(UserData)
|
||||
.getValueByIndex(i)
|
||||
.getValueByString(Id)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーデータの文字列の取得
|
||||
*
|
||||
* @param i インデックス
|
||||
* @return ユーザーデータ
|
||||
*/
|
||||
public getUserDataValue(i: number): string {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(UserData)
|
||||
.getValueByIndex(i)
|
||||
.getValueByString(Value)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
private _json: CubismJson;
|
||||
}
|
||||
}
|
453
Demo/Framework/src/model/cubismusermodel.ts
Normal file
453
Demo/Framework/src/model/cubismusermodel.ts
Normal file
@ -0,0 +1,453 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 FinishedMotionCallback = acubismmotion.FinishedMotionCallback;
|
||||
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 モーションの名前
|
||||
* @param onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数
|
||||
* @return モーションクラス
|
||||
*/
|
||||
public loadMotion = (
|
||||
buffer: ArrayBuffer,
|
||||
size: number,
|
||||
name: string,
|
||||
onFinishedMotionHandler?: FinishedMotionCallback
|
||||
) => CubismMotion.create(buffer, size, onFinishedMotionHandler);
|
||||
|
||||
/**
|
||||
* 表情データの読み込み
|
||||
* @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 = 1; j < count; ++j) {
|
||||
const x = vertices[Constant.vertexOffset + j * Constant.vertexStep];
|
||||
const 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 != null) {
|
||||
this._renderer.release();
|
||||
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 {
|
||||
const 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() {
|
||||
if (this._motionManager != null) {
|
||||
this._motionManager.release();
|
||||
this._motionManager = null;
|
||||
}
|
||||
|
||||
if (this._expressionManager != null) {
|
||||
this._expressionManager.release();
|
||||
this._expressionManager = null;
|
||||
}
|
||||
|
||||
if (this._moc != null) {
|
||||
this._moc.deleteModel(this._model);
|
||||
this._moc.release();
|
||||
this._moc = null;
|
||||
}
|
||||
|
||||
this._modelMatrix = null;
|
||||
|
||||
CubismPose.delete(this._pose);
|
||||
CubismEyeBlink.delete(this._eyeBlink);
|
||||
CubismBreath.delete(this._breath);
|
||||
|
||||
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; // レンダラ
|
||||
}
|
||||
}
|
278
Demo/Framework/src/motion/acubismmotion.ts
Normal file
278
Demo/Framework/src/motion/acubismmotion.ts
Normal file
@ -0,0 +1,278 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 {
|
||||
/** モーション再生終了コールバック関数定義 */
|
||||
export type FinishedMotionCallback = (self: ACubismMotion) => void;
|
||||
|
||||
/**
|
||||
* モーションの抽象基底クラス
|
||||
*
|
||||
* モーションの抽象基底クラス。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<csmString>();
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
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<csmString> {
|
||||
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;
|
||||
|
||||
/**
|
||||
* モーション再生終了コールバックの登録
|
||||
*
|
||||
* モーション再生終了コールバックを登録する。
|
||||
* isFinishedフラグを設定するタイミングで呼び出される。
|
||||
* 以下の状態の際には呼び出されない:
|
||||
* 1. 再生中のモーションが「ループ」として設定されているとき
|
||||
* 2. コールバックが登録されていない時
|
||||
*
|
||||
* @param onFinishedMotionHandler モーション再生終了コールバック関数
|
||||
*/
|
||||
public setFinishedMotionHandler = (
|
||||
onFinishedMotionHandler: FinishedMotionCallback
|
||||
) => (this._onFinishedMotion = onFinishedMotionHandler);
|
||||
|
||||
/**
|
||||
* モーション再生終了コールバックの取得
|
||||
*
|
||||
* モーション再生終了コールバックを取得する。
|
||||
*
|
||||
* @return 登録されているモーション再生終了コールバック関数
|
||||
*/
|
||||
public getFinishedMotionHandler = () => this._onFinishedMotion;
|
||||
|
||||
public _fadeInSeconds: number; // フェードインにかかる時間[秒]
|
||||
public _fadeOutSeconds: number; // フェードアウトにかかる時間[秒]
|
||||
public _weight: number; // モーションの重み
|
||||
public _offsetSeconds: number; // モーション再生の開始時間[秒]
|
||||
|
||||
public _firedEventValues: csmVector<csmString>;
|
||||
|
||||
// モーション再生終了コールバック関数
|
||||
public _onFinishedMotion?: FinishedMotionCallback;
|
||||
}
|
||||
}
|
199
Demo/Framework/src/motion/cubismexpressionmotion.ts
Normal file
199
Demo/Framework/src/motion/cubismexpressionmotion.ts
Normal file
@ -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 https://www.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 = 'FadeInTime';
|
||||
const ExpressionKeyFadeOut = 'FadeOutTime';
|
||||
const ExpressionKeyParameters = 'Parameters';
|
||||
const ExpressionKeyId = 'Id';
|
||||
const ExpressionKeyValue = 'Value';
|
||||
const ExpressionKeyBlend = 'Blend';
|
||||
const BlendValueAdd = 'Add';
|
||||
const BlendValueMultiply = 'Multiply';
|
||||
const BlendValueOverwrite = 'Overwrite';
|
||||
const DefaultFadeTime = 1.0;
|
||||
|
||||
/**
|
||||
* 表情のモーション
|
||||
*
|
||||
* 表情のモーションクラス。
|
||||
*/
|
||||
export class CubismExpressionMotion extends ACubismMotion {
|
||||
/**
|
||||
* インスタンスを作成する。
|
||||
* @param buffer expファイルが読み込まれているバッファ
|
||||
* @param size バッファのサイズ
|
||||
* @return 作成されたインスタンス
|
||||
*/
|
||||
public static create(
|
||||
buffer: ArrayBuffer,
|
||||
size: number
|
||||
): CubismExpressionMotion {
|
||||
const expression: CubismExpressionMotion = new CubismExpressionMotion();
|
||||
|
||||
const json: CubismJson = CubismJson.create(buffer, size);
|
||||
const root: Value = json.getRoot();
|
||||
|
||||
expression.setFadeInTime(
|
||||
root.getValueByString(ExpressionKeyFadeIn).toFloat(DefaultFadeTime)
|
||||
); // フェードイン
|
||||
expression.setFadeOutTime(
|
||||
root.getValueByString(ExpressionKeyFadeOut).toFloat(DefaultFadeTime)
|
||||
); // フェードアウト
|
||||
|
||||
// 各パラメータについて
|
||||
const parameterCount = root
|
||||
.getValueByString(ExpressionKeyParameters)
|
||||
.getSize();
|
||||
expression._parameters.prepareCapacity(parameterCount);
|
||||
|
||||
for (let i = 0; i < parameterCount; ++i) {
|
||||
const param: Value = root
|
||||
.getValueByString(ExpressionKeyParameters)
|
||||
.getValueByIndex(i);
|
||||
const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(
|
||||
param.getValueByString(ExpressionKeyId).getRawString()
|
||||
); // パラメータID
|
||||
|
||||
const value: number = param
|
||||
.getValueByString(ExpressionKeyValue)
|
||||
.toFloat(); // 値
|
||||
|
||||
// 計算方法の設定
|
||||
let blendType: ExpressionBlendType;
|
||||
|
||||
if (
|
||||
param.getValueByString(ExpressionKeyBlend).isNull() ||
|
||||
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||
BlendValueAdd
|
||||
) {
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Add;
|
||||
} else if (
|
||||
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||
BlendValueMultiply
|
||||
) {
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Multiply;
|
||||
} else if (
|
||||
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||
BlendValueOverwrite
|
||||
) {
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Overwrite;
|
||||
} else {
|
||||
// その他 仕様にない値を設定した時は加算モードにすることで復旧
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Add;
|
||||
}
|
||||
|
||||
// 設定オブジェクトを作成してリストに追加する
|
||||
const item: ExpressionParameter = new 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 = 0; i < this._parameters.getSize(); ++i) {
|
||||
const parameter: ExpressionParameter = this._parameters.at(i);
|
||||
|
||||
switch (parameter.blendType) {
|
||||
case ExpressionBlendType.ExpressionBlendType_Add: {
|
||||
model.addParameterValueById(
|
||||
parameter.parameterId,
|
||||
parameter.value,
|
||||
weight
|
||||
);
|
||||
break;
|
||||
}
|
||||
case ExpressionBlendType.ExpressionBlendType_Multiply: {
|
||||
model.multiplyParameterValueById(
|
||||
parameter.parameterId,
|
||||
parameter.value,
|
||||
weight
|
||||
);
|
||||
break;
|
||||
}
|
||||
case ExpressionBlendType.ExpressionBlendType_Overwrite: {
|
||||
model.setParameterValueById(
|
||||
parameter.parameterId,
|
||||
parameter.value,
|
||||
weight
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// 仕様にない値を設定した時はすでに加算モードになっている
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._parameters = new csmVector<ExpressionParameter>();
|
||||
}
|
||||
|
||||
_parameters: csmVector<ExpressionParameter>; // 表情のパラメータ情報リスト
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情パラメータ値の計算方式
|
||||
*/
|
||||
export enum ExpressionBlendType {
|
||||
ExpressionBlendType_Add = 0, // 加算
|
||||
ExpressionBlendType_Multiply = 1, // 乗算
|
||||
ExpressionBlendType_Overwrite = 2 // 上書き
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情のパラメータ情報
|
||||
*/
|
||||
export class ExpressionParameter {
|
||||
parameterId: CubismIdHandle; // パラメータID
|
||||
blendType: ExpressionBlendType; // パラメータの演算種類
|
||||
value: number; // 値
|
||||
}
|
||||
}
|
965
Demo/Framework/src/motion/cubismmotion.ts
Normal file
965
Demo/Framework/src/motion/cubismmotion.ts
Normal file
@ -0,0 +1,965 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 FinishedMotionCallback = acubismmotion.FinishedMotionCallback;
|
||||
import CubismMotionJson = cubismmotionjson.CubismMotionJson;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
const EffectNameEyeBlink = 'EyeBlink';
|
||||
const EffectNameLipSync = 'LipSync';
|
||||
const TargetNameModel = 'Model';
|
||||
const TargetNameParameter = 'Parameter';
|
||||
const TargetNamePartOpacity = 'PartOpacity';
|
||||
|
||||
function lerpPoints(
|
||||
a: CubismMotionPoint,
|
||||
b: CubismMotionPoint,
|
||||
t: number
|
||||
): CubismMotionPoint {
|
||||
const 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 = -1;
|
||||
const totalSegmentCount: number =
|
||||
curve.baseSegmentIndex + curve.segmentCount;
|
||||
let pointPosition = 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 バッファのサイズ
|
||||
* @param onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数
|
||||
* @return 作成されたインスタンス
|
||||
*/
|
||||
public static create(
|
||||
buffer: ArrayBuffer,
|
||||
size: number,
|
||||
onFinishedMotionHandler?: FinishedMotionCallback
|
||||
): CubismMotion {
|
||||
const ret = new CubismMotion();
|
||||
|
||||
ret.parse(buffer, size);
|
||||
ret._sourceFrameRate = ret._motionData.fps;
|
||||
ret._loopDurationSeconds = ret._motionData.duration;
|
||||
ret._onFinishedMotion = onFinishedMotionHandler;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
const curves: csmVector<CubismMotionCurve> = 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 = 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 = 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 = 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 = 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 = 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 {
|
||||
if (this._onFinishedMotion) {
|
||||
this._onFinishedMotion(this);
|
||||
}
|
||||
|
||||
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 {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 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 {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 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 {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 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 {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 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<CubismIdHandle>,
|
||||
lipSyncParameterIds: csmVector<CubismIdHandle>
|
||||
): 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 = 0;
|
||||
let totalSegmentCount = 0;
|
||||
|
||||
// Curves
|
||||
for (
|
||||
let curveCount = 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 = 0;
|
||||
segmentPosition < json.getMotionCurveSegmentCount(curveCount);
|
||||
|
||||
) {
|
||||
if (segmentPosition == 0) {
|
||||
this._motionData.segments.at(
|
||||
totalSegmentCount
|
||||
).basePointIndex = totalPointCount;
|
||||
if(this._motionData.points.at(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;
|
||||
|
||||
// 修改最后点
|
||||
if(this._motionData.points.at(totalPointCount)){
|
||||
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;
|
||||
|
||||
// 修改最后点
|
||||
if(this._motionData.points.at(totalPointCount)){
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 1
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 2
|
||||
);
|
||||
}
|
||||
|
||||
// 修改最后点
|
||||
if(this._motionData.points.at(totalPointCount + 1)){
|
||||
this._motionData.points.at(
|
||||
totalPointCount + 1
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 3
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount + 1
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 4
|
||||
);
|
||||
}
|
||||
|
||||
// 修改最后点
|
||||
if(this._motionData.points.at(totalPointCount + 2)){
|
||||
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;
|
||||
|
||||
// 修改最后点
|
||||
if(this._motionData.points.at(totalPointCount)){
|
||||
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;
|
||||
|
||||
// 修改最后点
|
||||
if(this._motionData.points.at(totalPointCount)){
|
||||
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 = 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<csmString> {
|
||||
this._firedEventValues.updateSize(0);
|
||||
|
||||
// イベントの発火チェック
|
||||
for (let u = 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<CubismIdHandle>; // 自動まばたきを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。
|
||||
public _lipSyncParameterIds: csmVector<CubismIdHandle>; // リップシンクを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。
|
||||
|
||||
public _modelCurveIdEyeBlink: CubismIdHandle; // モデルが持つ自動まばたき用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
||||
public _modelCurveIdLipSync: CubismIdHandle; // モデルが持つリップシンク用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
||||
}
|
||||
}
|
140
Demo/Framework/src/motion/cubismmotioninternal.ts
Normal file
140
Demo/Framework/src/motion/cubismmotioninternal.ts
Normal file
@ -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 https://www.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 = 0.0; // 時間[秒]
|
||||
value = 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 = 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<CubismMotionCurve>();
|
||||
this.segments = new csmVector<CubismMotionSegment>();
|
||||
this.points = new csmVector<CubismMotionPoint>();
|
||||
this.events = new csmVector<CubismMotionEvent>();
|
||||
}
|
||||
|
||||
duration: number; // モーションの長さ[秒]
|
||||
loop: boolean; // ループするかどうか
|
||||
curveCount: number; // カーブの個数
|
||||
eventCount: number; // UserDataの個数
|
||||
fps: number; // フレームレート
|
||||
curves: csmVector<CubismMotionCurve>; // カーブのリスト
|
||||
segments: csmVector<CubismMotionSegment>; // セグメントのリスト
|
||||
points: csmVector<CubismMotionPoint>; // ポイントのリスト
|
||||
events: csmVector<CubismMotionEvent>; // イベントのリスト
|
||||
}
|
||||
}
|
359
Demo/Framework/src/motion/cubismmotionjson.ts
Normal file
359
Demo/Framework/src/motion/cubismmotionjson.ts
Normal file
@ -0,0 +1,359 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 = 'Meta';
|
||||
const Duration = 'Duration';
|
||||
const Loop = 'Loop';
|
||||
const CurveCount = 'CurveCount';
|
||||
const Fps = 'Fps';
|
||||
const TotalSegmentCount = 'TotalSegmentCount';
|
||||
const TotalPointCount = 'TotalPointCount';
|
||||
const Curves = 'Curves';
|
||||
const Target = 'Target';
|
||||
const Id = 'Id';
|
||||
const FadeInTime = 'FadeInTime';
|
||||
const FadeOutTime = 'FadeOutTime';
|
||||
const Segments = 'Segments';
|
||||
const UserData = 'UserData';
|
||||
const UserDataCount = 'UserDataCount';
|
||||
const TotalUserDataSize = 'TotalUserDataSize';
|
||||
const Time = 'Time';
|
||||
const Value = '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()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(Duration)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのループ情報の取得
|
||||
* @return true ループする
|
||||
* @return false ループしない
|
||||
*/
|
||||
public isMotionLoop(): boolean {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(Loop)
|
||||
.toBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションカーブの個数の取得
|
||||
* @return モーションカーブの個数
|
||||
*/
|
||||
public getMotionCurveCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(CurveCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフレームレートの取得
|
||||
* @return フレームレート[FPS]
|
||||
*/
|
||||
public getMotionFps(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(Fps)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのセグメントの総合計の取得
|
||||
* @return モーションのセグメントの取得
|
||||
*/
|
||||
public getMotionTotalSegmentCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalSegmentCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブの制御店の総合計の取得
|
||||
* @return モーションのカーブの制御点の総合計
|
||||
*/
|
||||
public getMotionTotalPointCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalPointCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードイン時間の存在
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionFadeInTime(): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeInTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードアウト時間の存在
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionFadeOutTime(): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeOutTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードイン時間の取得
|
||||
* @return フェードイン時間[秒]
|
||||
*/
|
||||
public getMotionFadeInTime(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeInTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードアウト時間の取得
|
||||
* @return フェードアウト時間[秒]
|
||||
*/
|
||||
public getMotionFadeOutTime(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeOutTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブの種類の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return カーブの種類
|
||||
*/
|
||||
public getMotionCurveTarget(curveIndex: number): string {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Target)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのIDの取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return カーブのID
|
||||
*/
|
||||
public getMotionCurveId(curveIndex: number): CubismIdHandle {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Id)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードイン時間の存在
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionCurveFadeInTime(curveIndex: number): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeInTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードアウト時間の存在
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionCurveFadeOutTime(curveIndex: number): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeOutTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードイン時間の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return フェードイン時間[秒]
|
||||
*/
|
||||
public getMotionCurveFadeInTime(curveIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeInTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードアウト時間の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return フェードアウト時間[秒]
|
||||
*/
|
||||
public getMotionCurveFadeOutTime(curveIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeOutTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのセグメントの個数を取得する
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return モーションのカーブのセグメントの個数
|
||||
*/
|
||||
public getMotionCurveSegmentCount(curveIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Segments)
|
||||
.getVector()
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのセグメントの値の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @param segmentIndex セグメントのインデックス
|
||||
* @return セグメントの値
|
||||
*/
|
||||
public getMotionCurveSegment(
|
||||
curveIndex: number,
|
||||
segmentIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Segments)
|
||||
.getValueByIndex(segmentIndex)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの個数の取得
|
||||
* @return イベントの個数
|
||||
*/
|
||||
public getEventCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(UserDataCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの総文字数の取得
|
||||
* @return イベントの総文字数
|
||||
*/
|
||||
public getTotalEventValueSize(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalUserDataSize)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの時間の取得
|
||||
* @param userDataIndex イベントのインデックス
|
||||
* @return イベントの時間[秒]
|
||||
*/
|
||||
public getEventTime(userDataIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(UserData)
|
||||
.getValueByIndex(userDataIndex)
|
||||
.getValueByString(Time)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの取得
|
||||
* @param userDataIndex イベントのインデックス
|
||||
* @return イベントの文字列
|
||||
*/
|
||||
public getEventValue(userDataIndex: number): csmString {
|
||||
return new csmString(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(UserData)
|
||||
.getValueByIndex(userDataIndex)
|
||||
.getValueByString(Value)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
_json: CubismJson; // motion3.jsonのデータ
|
||||
}
|
||||
}
|
124
Demo/Framework/src/motion/cubismmotionmanager.ts
Normal file
124
Demo/Framework/src/motion/cubismmotionmanager.ts
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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になる。モーションファイルを別スレッドで読み込むときの機能。
|
||||
}
|
||||
}
|
219
Demo/Framework/src/motion/cubismmotionqueueentry.ts
Normal file
219
Demo/Framework/src/motion/cubismmotionqueueentry.ts
Normal file
@ -0,0 +1,219 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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; // インスタンスごとに一意の値を持つ識別番号
|
||||
}
|
||||
}
|
347
Demo/Framework/src/motion/cubismmotionqueuemanager.ts
Normal file
347
Demo/Framework/src/motion/cubismmotionqueuemanager.ts
Normal file
@ -0,0 +1,347 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 iterator = csmvector.iterator;
|
||||
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<CubismMotionQueueEntry>();
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ
|
||||
*/
|
||||
public release(): void {
|
||||
for (let i = 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 = 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: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
|
||||
) {
|
||||
let motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
continue;
|
||||
}
|
||||
|
||||
const 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: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
ite.increment()
|
||||
) {
|
||||
const motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber &&
|
||||
!motionQueueEntry.isFinished()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全てのモーションを停止する
|
||||
*/
|
||||
public stopAllMotions(): void {
|
||||
// ------- 処理を行う -------
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
|
||||
for (
|
||||
let ite: iterator<CubismMotionQueueEntry> = 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: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
ite.preIncrement()
|
||||
) {
|
||||
const 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 = false;
|
||||
|
||||
// ------- 処理を行う --------
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
|
||||
for (
|
||||
let ite: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
|
||||
) {
|
||||
let motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
continue;
|
||||
}
|
||||
|
||||
const 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<csmString> = motion.getFiredEvent(
|
||||
motionQueueEntry.getLastCheckEventTime() -
|
||||
motionQueueEntry.getStartTime(),
|
||||
userTimeSeconds - motionQueueEntry.getStartTime()
|
||||
);
|
||||
|
||||
for (let i = 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<CubismMotionQueueEntry>; // モーション
|
||||
_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;
|
||||
}
|
949
Demo/Framework/src/physics/cubismphysics.ts
Normal file
949
Demo/Framework/src/physics/cubismphysics.ts
Normal file
@ -0,0 +1,949 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 = 'X';
|
||||
const PhysicsTypeTagY = 'Y';
|
||||
const PhysicsTypeTagAngle = 'Angle';
|
||||
|
||||
// Constant of air resistance.
|
||||
const AirResistance = 5.0;
|
||||
|
||||
// Constant of maximum weight of input and output ratio.
|
||||
const MaximumWeight = 100.0;
|
||||
|
||||
// Constant of threshold of movement.
|
||||
const MovementThreshold = 0.001;
|
||||
|
||||
/**
|
||||
* 物理演算クラス
|
||||
*/
|
||||
export class CubismPhysics {
|
||||
/**
|
||||
* インスタンスの作成
|
||||
* @param buffer physics3.jsonが読み込まれているバッファ
|
||||
* @param size バッファのサイズ
|
||||
* @return 作成されたインスタンス
|
||||
*/
|
||||
public static create(buffer: ArrayBuffer, size: number): CubismPhysics {
|
||||
const ret: CubismPhysics = new CubismPhysics();
|
||||
|
||||
ret.parse(buffer, size);
|
||||
ret._physicsRig.gravity.y = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* インスタンスを破棄する
|
||||
* @param physics 破棄するインスタンス
|
||||
*/
|
||||
public static delete(physics: CubismPhysics): void {
|
||||
if (physics != null) {
|
||||
physics.release();
|
||||
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;
|
||||
const 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 = 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 = 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 = 0; i < currentSetting.outputCount; ++i) {
|
||||
const particleIndex = currentOutput[i].vertexIndex;
|
||||
|
||||
if (
|
||||
particleIndex < 1 ||
|
||||
particleIndex >= currentSetting.particleCount
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentOutput[i].destinationParameterIndex == -1) {
|
||||
currentOutput[
|
||||
i
|
||||
].destinationParameterIndex = model.getParameterIndex(
|
||||
currentOutput[i].destination.id
|
||||
);
|
||||
}
|
||||
|
||||
const translation: 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
|
||||
);
|
||||
|
||||
const destinationParameterIndex: number =
|
||||
currentOutput[i].destinationParameterIndex;
|
||||
const outParameterValue: Float32Array =
|
||||
!Float32Array.prototype.slice &&
|
||||
'subarray' in Float32Array.prototype
|
||||
? JSON.parse(
|
||||
JSON.stringify(
|
||||
parameterValue.subarray(destinationParameterIndex)
|
||||
)
|
||||
) // 値渡しするため、JSON.parse, JSON.stringify
|
||||
: parameterValue.slice(destinationParameterIndex);
|
||||
|
||||
updateOutputParameterValue(
|
||||
outParameterValue,
|
||||
parameterMinimumValue[destinationParameterIndex],
|
||||
parameterMaximumValue[destinationParameterIndex],
|
||||
outputValue,
|
||||
currentOutput[i]
|
||||
);
|
||||
|
||||
// 値を反映
|
||||
for (
|
||||
let offset: number = destinationParameterIndex, outParamIndex = 0;
|
||||
offset < parameterValue.length;
|
||||
offset++, outParamIndex++
|
||||
) {
|
||||
parameterValue[offset] = outParameterValue[outParamIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* オプションの設定
|
||||
* @param options オプション
|
||||
*/
|
||||
public setOptions(options: Options): void {
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* オプションの取得
|
||||
* @return オプション
|
||||
*/
|
||||
public getOption(): Options {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
public constructor() {
|
||||
this._physicsRig = null;
|
||||
|
||||
// set default options
|
||||
this._options = new 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 = 0,
|
||||
outputIndex = 0,
|
||||
particleIndex = 0;
|
||||
|
||||
for (let i = 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 = 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 = 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 = 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 = 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 = 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: Options; // オプション
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理演算のオプション
|
||||
*/
|
||||
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 = 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 {
|
||||
const maxValue: number = CubismMath.max(min, max);
|
||||
const 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 = 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 = 0.0;
|
||||
|
||||
const maxValue: number = CubismMath.max(parameterMaximum, parameterMinimum);
|
||||
|
||||
if (maxValue < value) {
|
||||
value = maxValue;
|
||||
}
|
||||
|
||||
const minValue: number = CubismMath.min(parameterMaximum, parameterMinimum);
|
||||
|
||||
if (minValue > value) {
|
||||
value = minValue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
225
Demo/Framework/src/physics/cubismphysicsinternal.ts
Normal file
225
Demo/Framework/src/physics/cubismphysicsinternal.ts
Normal file
@ -0,0 +1,225 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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<CubismPhysicsSubRig>();
|
||||
this.inputs = new csmVector<CubismPhysicsInput>();
|
||||
this.outputs = new csmVector<CubismPhysicsOutput>();
|
||||
this.particles = new csmVector<CubismPhysicsParticle>();
|
||||
this.gravity = new CubismVector2(0, 0);
|
||||
this.wind = new CubismVector2(0, 0);
|
||||
}
|
||||
|
||||
subRigCount: number; // 物理演算の物理点の個数
|
||||
settings: csmVector<CubismPhysicsSubRig>; // 物理演算の物理点の管理のリスト
|
||||
inputs: csmVector<CubismPhysicsInput>; // 物理演算の入力のリスト
|
||||
outputs: csmVector<CubismPhysicsOutput>; // 物理演算の出力のリスト
|
||||
particles: csmVector<CubismPhysicsParticle>; // 物理演算の物理点のリスト
|
||||
gravity: CubismVector2; // 重力
|
||||
wind: CubismVector2; // 風
|
||||
}
|
||||
}
|
649
Demo/Framework/src/physics/cubismphysicsjson.ts
Normal file
649
Demo/Framework/src/physics/cubismphysicsjson.ts
Normal file
@ -0,0 +1,649 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 = 'Position';
|
||||
const X = 'X';
|
||||
const Y = 'Y';
|
||||
const Angle = 'Angle';
|
||||
const Type = 'Type';
|
||||
const Id = 'Id';
|
||||
|
||||
// Meta
|
||||
const Meta = 'Meta';
|
||||
const EffectiveForces = 'EffectiveForces';
|
||||
const TotalInputCount = 'TotalInputCount';
|
||||
const TotalOutputCount = 'TotalOutputCount';
|
||||
const PhysicsSettingCount = 'PhysicsSettingCount';
|
||||
const Gravity = 'Gravity';
|
||||
const Wind = 'Wind';
|
||||
const VertexCount = 'VertexCount';
|
||||
|
||||
// PhysicsSettings
|
||||
const PhysicsSettings = 'PhysicsSettings';
|
||||
const Normalization = 'Normalization';
|
||||
const Minimum = 'Minimum';
|
||||
const Maximum = 'Maximum';
|
||||
const Default = 'Default';
|
||||
const Reflect = 'Reflect';
|
||||
const Weight = 'Weight';
|
||||
|
||||
// Input
|
||||
const Input = 'Input';
|
||||
const Source = 'Source';
|
||||
|
||||
// Output
|
||||
const Output = 'Output';
|
||||
const Scale = 'Scale';
|
||||
const VertexIndex = 'VertexIndex';
|
||||
const Destination = 'Destination';
|
||||
|
||||
// Particle
|
||||
const Vertices = 'Vertices';
|
||||
const Mobility = 'Mobility';
|
||||
const Delay = 'Delay';
|
||||
const Radius = 'Radius';
|
||||
const Acceleration = '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 {
|
||||
const ret: CubismVector2 = new CubismVector2(0, 0);
|
||||
ret.x = this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(EffectiveForces)
|
||||
.getValueByString(Gravity)
|
||||
.getValueByString(X)
|
||||
.toFloat();
|
||||
ret.y = this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(EffectiveForces)
|
||||
.getValueByString(Gravity)
|
||||
.getValueByString(Y)
|
||||
.toFloat();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 風の取得
|
||||
* @return 風
|
||||
*/
|
||||
public getWind(): CubismVector2 {
|
||||
const ret: CubismVector2 = new CubismVector2(0, 0);
|
||||
ret.x = this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(EffectiveForces)
|
||||
.getValueByString(Wind)
|
||||
.getValueByString(X)
|
||||
.toFloat();
|
||||
ret.y = this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(EffectiveForces)
|
||||
.getValueByString(Wind)
|
||||
.getValueByString(Y)
|
||||
.toFloat();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理店の管理の個数の取得
|
||||
* @return 物理店の管理の個数
|
||||
*/
|
||||
public getSubRigCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(PhysicsSettingCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入力の総合計の取得
|
||||
* @return 入力の総合計
|
||||
*/
|
||||
public getTotalInputCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalInputCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力の総合計の取得
|
||||
* @return 出力の総合計
|
||||
*/
|
||||
public getTotalOutputCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalOutputCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理点の個数の取得
|
||||
* @return 物理点の個数
|
||||
*/
|
||||
public getVertexCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(VertexCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 正規化された位置の最小値の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @return 正規化された位置の最小値
|
||||
*/
|
||||
public getNormalizationPositionMinimumValue(
|
||||
physicsSettingIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Normalization)
|
||||
.getValueByString(Position)
|
||||
.getValueByString(Minimum)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 正規化された位置の最大値の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @return 正規化された位置の最大値
|
||||
*/
|
||||
public getNormalizationPositionMaximumValue(
|
||||
physicsSettingIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Normalization)
|
||||
.getValueByString(Position)
|
||||
.getValueByString(Maximum)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 正規化された位置のデフォルト値の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @return 正規化された位置のデフォルト値
|
||||
*/
|
||||
public getNormalizationPositionDefaultValue(
|
||||
physicsSettingIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Normalization)
|
||||
.getValueByString(Position)
|
||||
.getValueByString(Default)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 正規化された角度の最小値の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @return 正規化された角度の最小値
|
||||
*/
|
||||
public getNormalizationAngleMinimumValue(
|
||||
physicsSettingIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Normalization)
|
||||
.getValueByString(Angle)
|
||||
.getValueByString(Minimum)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 正規化された角度の最大値の取得
|
||||
* @param physicsSettingIndex
|
||||
* @return 正規化された角度の最大値
|
||||
*/
|
||||
public getNormalizationAngleMaximumValue(
|
||||
physicsSettingIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Normalization)
|
||||
.getValueByString(Angle)
|
||||
.getValueByString(Maximum)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 正規化された角度のデフォルト値の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @return 正規化された角度のデフォルト値
|
||||
*/
|
||||
public getNormalizationAngleDefaultValue(
|
||||
physicsSettingIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Normalization)
|
||||
.getValueByString(Angle)
|
||||
.getValueByString(Default)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入力の個数の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @return 入力の個数
|
||||
*/
|
||||
public getInputCount(physicsSettingIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Input)
|
||||
.getVector()
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入力の重みの取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param inputIndex 入力のインデックス
|
||||
* @return 入力の重み
|
||||
*/
|
||||
public getInputWeight(
|
||||
physicsSettingIndex: number,
|
||||
inputIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Input)
|
||||
.getValueByIndex(inputIndex)
|
||||
.getValueByString(Weight)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入力の反転の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param inputIndex 入力のインデックス
|
||||
* @return 入力の反転
|
||||
*/
|
||||
public getInputReflect(
|
||||
physicsSettingIndex: number,
|
||||
inputIndex: number
|
||||
): boolean {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Input)
|
||||
.getValueByIndex(inputIndex)
|
||||
.getValueByString(Reflect)
|
||||
.toBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入力の種類の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param inputIndex 入力のインデックス
|
||||
* @return 入力の種類
|
||||
*/
|
||||
public getInputType(
|
||||
physicsSettingIndex: number,
|
||||
inputIndex: number
|
||||
): string {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Input)
|
||||
.getValueByIndex(inputIndex)
|
||||
.getValueByString(Type)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入力元のIDの取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param inputIndex 入力のインデックス
|
||||
* @return 入力元のID
|
||||
*/
|
||||
public getInputSourceId(
|
||||
physicsSettingIndex: number,
|
||||
inputIndex: number
|
||||
): CubismIdHandle {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Input)
|
||||
.getValueByIndex(inputIndex)
|
||||
.getValueByString(Source)
|
||||
.getValueByString(Id)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力の個数の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @return 出力の個数
|
||||
*/
|
||||
public getOutputCount(physicsSettingIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Output)
|
||||
.getVector()
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力の物理点のインデックスの取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param outputIndex 出力のインデックス
|
||||
* @return 出力の物理点のインデックス
|
||||
*/
|
||||
public getOutputVertexIndex(
|
||||
physicsSettingIndex: number,
|
||||
outputIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Output)
|
||||
.getValueByIndex(outputIndex)
|
||||
.getValueByString(VertexIndex)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力の角度のスケールを取得する
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param outputIndex 出力のインデックス
|
||||
* @return 出力の角度のスケール
|
||||
*/
|
||||
public getOutputAngleScale(
|
||||
physicsSettingIndex: number,
|
||||
outputIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Output)
|
||||
.getValueByIndex(outputIndex)
|
||||
.getValueByString(Scale)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力の重みの取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param outputIndex 出力のインデックス
|
||||
* @return 出力の重み
|
||||
*/
|
||||
public getOutputWeight(
|
||||
physicsSettingIndex: number,
|
||||
outputIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Output)
|
||||
.getValueByIndex(outputIndex)
|
||||
.getValueByString(Weight)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力先のIDの取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param outputIndex 出力のインデックス
|
||||
* @return 出力先のID
|
||||
*/
|
||||
public getOutputDestinationId(
|
||||
physicsSettingIndex: number,
|
||||
outputIndex: number
|
||||
): CubismIdHandle {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Output)
|
||||
.getValueByIndex(outputIndex)
|
||||
.getValueByString(Destination)
|
||||
.getValueByString(Id)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力の種類の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param outputIndex 出力のインデックス
|
||||
* @return 出力の種類
|
||||
*/
|
||||
public getOutputType(
|
||||
physicsSettingIndex: number,
|
||||
outputIndex: number
|
||||
): string {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Output)
|
||||
.getValueByIndex(outputIndex)
|
||||
.getValueByString(Type)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出力の反転の取得
|
||||
* @param physicsSettingIndex 物理演算のインデックス
|
||||
* @param outputIndex 出力のインデックス
|
||||
* @return 出力の反転
|
||||
*/
|
||||
public getOutputReflect(
|
||||
physicsSettingIndex: number,
|
||||
outputIndex: number
|
||||
): boolean {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Output)
|
||||
.getValueByIndex(outputIndex)
|
||||
.getValueByString(Reflect)
|
||||
.toBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理点の個数の取得
|
||||
* @param physicsSettingIndex 物理演算男設定のインデックス
|
||||
* @return 物理点の個数
|
||||
*/
|
||||
public getParticleCount(physicsSettingIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Vertices)
|
||||
.getVector()
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理点の動きやすさの取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param vertexIndex 物理点のインデックス
|
||||
* @return 物理点の動きやすさ
|
||||
*/
|
||||
public getParticleMobility(
|
||||
physicsSettingIndex: number,
|
||||
vertexIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Vertices)
|
||||
.getValueByIndex(vertexIndex)
|
||||
.getValueByString(Mobility)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理点の遅れの取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param vertexIndex 物理点のインデックス
|
||||
* @return 物理点の遅れ
|
||||
*/
|
||||
public getParticleDelay(
|
||||
physicsSettingIndex: number,
|
||||
vertexIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Vertices)
|
||||
.getValueByIndex(vertexIndex)
|
||||
.getValueByString(Delay)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理点の加速度の取得
|
||||
* @param physicsSettingIndex 物理演算の設定
|
||||
* @param vertexIndex 物理点のインデックス
|
||||
* @return 物理点の加速度
|
||||
*/
|
||||
public getParticleAcceleration(
|
||||
physicsSettingIndex: number,
|
||||
vertexIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Vertices)
|
||||
.getValueByIndex(vertexIndex)
|
||||
.getValueByString(Acceleration)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理点の距離の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param vertexIndex 物理点のインデックス
|
||||
* @return 物理点の距離
|
||||
*/
|
||||
public getParticleRadius(
|
||||
physicsSettingIndex: number,
|
||||
vertexIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Vertices)
|
||||
.getValueByIndex(vertexIndex)
|
||||
.getValueByString(Radius)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物理点の位置の取得
|
||||
* @param physicsSettingIndex 物理演算の設定のインデックス
|
||||
* @param vertexInde 物理点のインデックス
|
||||
* @return 物理点の位置
|
||||
*/
|
||||
public getParticlePosition(
|
||||
physicsSettingIndex: number,
|
||||
vertexIndex: number
|
||||
): CubismVector2 {
|
||||
const ret: CubismVector2 = new CubismVector2(0, 0);
|
||||
ret.x = this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Vertices)
|
||||
.getValueByIndex(vertexIndex)
|
||||
.getValueByString(Position)
|
||||
.getValueByString(X)
|
||||
.toFloat();
|
||||
ret.y = this._json
|
||||
.getRoot()
|
||||
.getValueByString(PhysicsSettings)
|
||||
.getValueByIndex(physicsSettingIndex)
|
||||
.getValueByString(Vertices)
|
||||
.getValueByIndex(vertexIndex)
|
||||
.getValueByString(Position)
|
||||
.getValueByString(Y)
|
||||
.toFloat();
|
||||
return ret;
|
||||
}
|
||||
|
||||
_json: CubismJson; // physics3.jsonデータ
|
||||
}
|
||||
}
|
267
Demo/Framework/src/rendering/cubismrenderer.ts
Normal file
267
Demo/Framework/src/rendering/cubismrenderer.ts
Normal file
@ -0,0 +1,267 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as 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 = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* レンダラの初期化処理を実行する
|
||||
* 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる
|
||||
* @param model モデルのインスタンス
|
||||
*/
|
||||
public initialize(model: CubismModel): void {
|
||||
this._model = model;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルを描画する
|
||||
*/
|
||||
public drawModel(): void {
|
||||
if (this.getModel() == null) return;
|
||||
|
||||
this.doDrawModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(): 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 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 カラーブレンディングのタイプ
|
||||
* @param invertedMask マスク使用時のマスクの反転使用
|
||||
*/
|
||||
public abstract drawMesh(
|
||||
textureNo: number,
|
||||
indexCount: number,
|
||||
vertexCount: number,
|
||||
indexArray: Uint16Array,
|
||||
vertexArray: Float32Array,
|
||||
uvArray: Float32Array,
|
||||
opacity: number,
|
||||
colorBlendMode: CubismBlendMode,
|
||||
invertedMask: boolean
|
||||
): void;
|
||||
|
||||
/**
|
||||
* レンダラが保持する静的なリソースを開放する
|
||||
*/
|
||||
public static staticRelease: Function;
|
||||
|
||||
protected _mvpMatrix4x4: CubismMatrix44; // Model-View-Projection 行列
|
||||
protected _modelColor: CubismTextureColor; // モデル自体のカラー(RGBA)
|
||||
protected _isCulling: boolean; // カリングが有効ならtrue
|
||||
protected _isPremultipliedAlpha: boolean; // 乗算済みαならtrue
|
||||
protected _anisortopy: any; // テクスチャの異方性フィルタリングのパラメータ
|
||||
protected _model: CubismModel; // レンダリング対象のモデル
|
||||
}
|
||||
|
||||
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; // αチャンネル
|
||||
}
|
||||
}
|
2259
Demo/Framework/src/rendering/cubismrenderer_webgl.ts
Normal file
2259
Demo/Framework/src/rendering/cubismrenderer_webgl.ts
Normal file
File diff suppressed because it is too large
Load Diff
307
Demo/Framework/src/type/csmmap.ts
Normal file
307
Demo/Framework/src/type/csmmap.ts
Normal file
@ -0,0 +1,307 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import { 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 = [];
|
||||
this._dummyValue = null;
|
||||
this._size = 0;
|
||||
} else {
|
||||
this._keyValues = new Array(size);
|
||||
this._size = size;
|
||||
}
|
||||
} else {
|
||||
this._keyValues = [];
|
||||
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 = 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 = 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 = 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 = [];
|
||||
|
||||
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(): iterator<_KeyT, _ValT> {
|
||||
const ite: iterator<_KeyT, _ValT> = new iterator<_KeyT, _ValT>(this, 0);
|
||||
return ite;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンテナの終端要素を返す
|
||||
*/
|
||||
public end(): iterator<_KeyT, _ValT> {
|
||||
const ite: iterator<_KeyT, _ValT> = new iterator<_KeyT, _ValT>(
|
||||
this,
|
||||
this._size
|
||||
); // 終了
|
||||
return ite;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンテナから要素を削除する
|
||||
*
|
||||
* @param ite 削除する要素
|
||||
*/
|
||||
public erase(ite: iterator<_KeyT, _ValT>): iterator<_KeyT, _ValT> {
|
||||
const index: number = ite._index;
|
||||
if (index < 0 || this._size <= index) {
|
||||
return ite; // 削除範囲外
|
||||
}
|
||||
|
||||
// 削除
|
||||
this._keyValues.splice(index, 1);
|
||||
--this._size;
|
||||
|
||||
const ite2: iterator<_KeyT, _ValT> = new 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; // コンテナの要素数
|
||||
}
|
||||
|
||||
/**
|
||||
* csmMap<T>のイテレータ
|
||||
*/
|
||||
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> {
|
||||
const iteold = new iterator<_KeyT, _ValT>(this._map, this._index++); // 古い値を保存
|
||||
this._map = iteold._map;
|
||||
this._index = iteold._index;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 後置き--演算子のオーバーロード
|
||||
*/
|
||||
public decrement(): iterator<_KeyT, _ValT> {
|
||||
const 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>; // コンテナ
|
||||
}
|
||||
}
|
83
Demo/Framework/src/type/csmrectf.ts
Normal file
83
Demo/Framework/src/type/csmrectf.ts
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
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; // 高さ
|
||||
}
|
||||
}
|
101
Demo/Framework/src/type/csmstring.ts
Normal file
101
Demo/Framework/src/type/csmstring.ts
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
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 {
|
||||
for (let i = 0; i < length; i++) {
|
||||
this.append(v);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字列の長さをバイト数で取得する
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
348
Demo/Framework/src/type/csmvector.ts
Normal file
348
Demo/Framework/src/type/csmvector.ts
Normal file
@ -0,0 +1,348 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
/**
|
||||
* ベクター型(可変配列型)
|
||||
*/
|
||||
export class csmVector<T> {
|
||||
/**
|
||||
* 引数付きコンストラクタ
|
||||
* @param iniitalCapacity 初期化後のキャパシティ。データサイズは_capacity * sizeof(T)
|
||||
* @param zeroClear trueなら初期化時に確保した領域を0で埋める
|
||||
*/
|
||||
constructor(initialCapacity = 0) {
|
||||
if (initialCapacity < 1) {
|
||||
this._ptr = [];
|
||||
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 = 0): T[] {
|
||||
const ret: T[] = new Array<T>();
|
||||
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 {
|
||||
const curSize = this._size;
|
||||
|
||||
if (curSize < newSize) {
|
||||
this.prepareCapacity(newSize); // capacity更新
|
||||
}
|
||||
|
||||
for (let i = 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 = true
|
||||
): void {
|
||||
const 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
|
||||
//---
|
||||
const sub = this._size - newSize;
|
||||
this._ptr.splice(this._size - sub, sub); // 不要なので破棄する
|
||||
}
|
||||
this._size = newSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンテナにコンテナ要素を挿入する
|
||||
* @param position 挿入する位置
|
||||
* @param begin 挿入するコンテナの開始位置
|
||||
* @param end 挿入するコンテナの終端位置
|
||||
*/
|
||||
public insert(
|
||||
position: iterator<T>,
|
||||
begin: iterator<T>,
|
||||
end: iterator<T>
|
||||
): void {
|
||||
let dstSi: number = position._index;
|
||||
const srcSi: number = begin._index;
|
||||
const srcEi: number = end._index;
|
||||
|
||||
const addCount: number = srcEi - srcSi;
|
||||
|
||||
this.prepareCapacity(this._size + addCount);
|
||||
|
||||
// 挿入用の既存データをシフトして隙間を作る
|
||||
const addSize = this._size - dstSi;
|
||||
if (addSize > 0) {
|
||||
for (let i = 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: iterator<T>): iterator<T> {
|
||||
const index: number = ite._index;
|
||||
if (index < 0 || this._size <= index) {
|
||||
return ite; // 削除範囲外
|
||||
}
|
||||
|
||||
// 削除
|
||||
this._ptr.splice(index, 1);
|
||||
--this._size;
|
||||
|
||||
const ite2: iterator<T> = new iterator<T>(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(): iterator<T> {
|
||||
const ite: iterator<T> =
|
||||
this._size == 0 ? this.end() : new iterator<T>(this, 0);
|
||||
return ite;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンテナの終端要素を返す
|
||||
*/
|
||||
public end(): iterator<T> {
|
||||
const ite: iterator<T> = new iterator<T>(this, this._size);
|
||||
return ite;
|
||||
}
|
||||
|
||||
public getOffset(offset: number): csmVector<T> {
|
||||
const newVector = new csmVector<T>();
|
||||
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 class iterator<T> {
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
public constructor(v?: csmVector<T>, index?: number) {
|
||||
this._vector = v != undefined ? v : null;
|
||||
this._index = index != undefined ? index : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 代入
|
||||
*/
|
||||
public set(ite: iterator<T>): iterator<T> {
|
||||
this._index = ite._index;
|
||||
this._vector = ite._vector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置き++演算
|
||||
*/
|
||||
public preIncrement(): iterator<T> {
|
||||
++this._index;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置き--演算
|
||||
*/
|
||||
public preDecrement(): iterator<T> {
|
||||
--this._index;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 後置き++演算子
|
||||
*/
|
||||
public increment(): iterator<T> {
|
||||
const iteold = new iterator<T>(this._vector, this._index++);
|
||||
this._vector = iteold._vector;
|
||||
this._index = iteold._index;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 後置き--演算子
|
||||
*/
|
||||
public decrement(): iterator<T> {
|
||||
const iteold = new iterator<T>(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<T>): iterator<T> {
|
||||
this._index = ite._index;
|
||||
this._vector = ite._vector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* !=演算子のオーバーロード
|
||||
*/
|
||||
public notEqual(ite: iterator<T>): boolean {
|
||||
return this._index != ite._index || this._vector != ite._vector;
|
||||
}
|
||||
|
||||
_index: number; // コンテナのインデックス値
|
||||
_vector: csmVector<T>; // コンテナ
|
||||
}
|
||||
}
|
166
Demo/Framework/src/utils/cubismdebug.ts
Normal file
166
Demo/Framework/src/utils/cubismdebug.ts
Normal file
@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
import {
|
||||
Live2DCubismFramework as cubismframework,
|
||||
LogLevel
|
||||
} from '../live2dcubismframework';
|
||||
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: LogLevel, fmt: string, args: any[]) => {
|
||||
Live2DCubismFramework.CubismDebug.print(level, '[CSM]' + fmt, args);
|
||||
};
|
||||
|
||||
export const CubismLogPrintIn = (level: LogLevel, fmt: string, args: any[]) => {
|
||||
CubismLogPrint(level, fmt + '\n', args);
|
||||
};
|
||||
|
||||
export const CSM_ASSERT = (expr: any) => {
|
||||
console.assert(expr);
|
||||
};
|
||||
|
||||
export let CubismLogVerbose: (fmt: string, ...args: any[]) => void;
|
||||
export let CubismLogDebug: (fmt: string, ...args: any[]) => void;
|
||||
export let CubismLogInfo: (fmt: string, ...args: any[]) => void;
|
||||
export let CubismLogWarning: (fmt: string, ...args: any[]) => void;
|
||||
export let CubismLogError: (fmt: string, ...args: any[]) => void;
|
||||
|
||||
if (CSM_LOG_LEVEL <= CSM_LOG_LEVEL_VERBOSE) {
|
||||
CubismLogVerbose = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Verbose, '[V]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogDebug = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Debug, '[D]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogInfo = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Info, '[I]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogWarning = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Warning, '[W]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogError = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Error, '[E]' + fmt, args);
|
||||
};
|
||||
} else if (CSM_LOG_LEVEL == CSM_LOG_LEVEL_DEBUG) {
|
||||
CubismLogDebug = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Debug, '[D]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogInfo = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Info, '[I]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogWarning = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Warning, '[W]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogError = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Error, '[E]' + fmt, args);
|
||||
};
|
||||
} else if (CSM_LOG_LEVEL == CSM_LOG_LEVEL_INFO) {
|
||||
CubismLogInfo = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Info, '[I]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogWarning = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Warning, '[W]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogError = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Error, '[E]' + fmt, args);
|
||||
};
|
||||
} else if (CSM_LOG_LEVEL == CSM_LOG_LEVEL_WARNING) {
|
||||
CubismLogWarning = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Warning, '[W]' + fmt, args);
|
||||
};
|
||||
|
||||
CubismLogError = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(LogLevel.LogLevel_Error, '[E]' + fmt, args);
|
||||
};
|
||||
} else if (CSM_LOG_LEVEL == CSM_LOG_LEVEL_ERROR) {
|
||||
CubismLogError = (fmt: string, ...args: any[]) => {
|
||||
CubismLogPrintIn(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: LogLevel,
|
||||
format: string,
|
||||
args?: any[]
|
||||
): void {
|
||||
// オプションで設定されたログ出力レベルを下回る場合はログに出さない
|
||||
if (logLevel < cubismframework.CubismFramework.getLoggingLevel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const logPrint: Live2DCubismCore.csmLogFunction =
|
||||
cubismframework.CubismFramework.coreLogFunction;
|
||||
|
||||
if (!logPrint) return;
|
||||
|
||||
const buffer: string = format.replace(/\{(\d+)\}/g, (m, k) => {
|
||||
return args[k];
|
||||
});
|
||||
logPrint(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* データから指定した長さだけダンプ出力する。
|
||||
* CubismFramework.initialize()時にオプションで設定されたログ出力レベルを下回る場合はログに出さない。
|
||||
*
|
||||
* @param logLevel ログレベルの設定
|
||||
* @param data ダンプするデータ
|
||||
* @param length ダンプする長さ
|
||||
*/
|
||||
public static dumpBytes(
|
||||
logLevel: LogLevel,
|
||||
data: Uint8Array,
|
||||
length: number
|
||||
): void {
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (i % 16 == 0 && i > 0) this.print(logLevel, '\n');
|
||||
else if (i % 8 == 0 && i > 0) this.print(logLevel, ' ');
|
||||
this.print(logLevel, '{0} ', [data[i] & 0xff]);
|
||||
}
|
||||
|
||||
this.print(logLevel, '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* private コンストラクタ
|
||||
*/
|
||||
private constructor() {}
|
||||
}
|
||||
}
|
||||
|
||||
//------------ LIVE2D NAMESPACE ------------
|
1246
Demo/Framework/src/utils/cubismjson.ts
Normal file
1246
Demo/Framework/src/utils/cubismjson.ts
Normal file
File diff suppressed because it is too large
Load Diff
123
Demo/Framework/src/utils/cubismstring.ts
Normal file
123
Demo/Framework/src/utils/cubismstring.ts
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
export class CubismString {
|
||||
/**
|
||||
* 標準出力の書式を適用した文字列を取得する。
|
||||
* @param format 標準出力の書式指定文字列
|
||||
* @param ...args 書式指定文字列に渡す文字列
|
||||
* @return 書式を適用した文字列
|
||||
*/
|
||||
public static getFormatedString(format: string, ...args: any[]): string {
|
||||
const 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 = false; // マイナスフラグ
|
||||
let period = false;
|
||||
let v1 = 0;
|
||||
|
||||
//負号の確認
|
||||
let c: number = parseInt(string[i]);
|
||||
if (c < 0) {
|
||||
minus = true;
|
||||
i++;
|
||||
}
|
||||
|
||||
//整数部の確認
|
||||
for (; i < length; i++) {
|
||||
const 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 = 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() {}
|
||||
}
|
||||
}
|
22
Demo/Framework/tsconfig.json
Normal file
22
Demo/Framework/tsconfig.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"outDir": "./dist",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"../Core/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
BIN
Demo/Resources/Haru/Haru.2048/texture_00.png
Normal file
BIN
Demo/Resources/Haru/Haru.2048/texture_00.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
BIN
Demo/Resources/Haru/Haru.2048/texture_01.png
Normal file
BIN
Demo/Resources/Haru/Haru.2048/texture_01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
BIN
Demo/Resources/Haru/Haru.moc3
Normal file
BIN
Demo/Resources/Haru/Haru.moc3
Normal file
Binary file not shown.
55
Demo/Resources/Haru/Haru.model3.json
Normal file
55
Demo/Resources/Haru/Haru.model3.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"Version": 3,
|
||||
"FileReferences": {
|
||||
"Moc": "Haru.moc3",
|
||||
"Textures": [
|
||||
"Haru.2048/texture_00.png",
|
||||
"Haru.2048/texture_01.png"
|
||||
],
|
||||
"Pose": "Haru.pose3.json",
|
||||
"Expressions": [
|
||||
{"Name":"f00","File":"expressions/F01.exp3.json"},
|
||||
{"Name":"f01","File":"expressions/F02.exp3.json"},
|
||||
{"Name":"f02","File":"expressions/F03.exp3.json"},
|
||||
{"Name":"f03","File":"expressions/F04.exp3.json"},
|
||||
{"Name":"f04","File":"expressions/F05.exp3.json"},
|
||||
{"Name":"f05","File":"expressions/F06.exp3.json"},
|
||||
{"Name":"f06","File":"expressions/F07.exp3.json"},
|
||||
{"Name":"f07","File":"expressions/F08.exp3.json"}
|
||||
],
|
||||
"Motions": {
|
||||
"Idle": [
|
||||
{"File":"motions/haru_g_idle.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5},
|
||||
{"File":"motions/haru_g_m15.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5}
|
||||
],
|
||||
"TapBody": [
|
||||
{"File":"motions/haru_g_m06.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5},
|
||||
{"File":"motions/haru_g_m09.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5},
|
||||
{"File":"motions/haru_g_m20.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5},
|
||||
{"File":"motions/haru_g_m26.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5}
|
||||
]
|
||||
},
|
||||
"UserData": "Haru.userdata3.json"
|
||||
},
|
||||
"Groups": [
|
||||
{
|
||||
"Target": "Parameter",
|
||||
"Name": "LipSync",
|
||||
"Ids": [
|
||||
"ParamMouthOpenY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Target": "Parameter",
|
||||
"Name": "EyeBlink",
|
||||
"Ids": [
|
||||
"ParamEyeLOpen",
|
||||
"ParamEyeROpen"
|
||||
]
|
||||
}
|
||||
],
|
||||
"HitAreas": [
|
||||
{"Name":"Head", "Id":"HitArea"},
|
||||
{"Name":"Body", "Id":"HitArea2"}
|
||||
]
|
||||
}
|
25
Demo/Resources/Haru/Haru.pose3.json
Normal file
25
Demo/Resources/Haru/Haru.pose3.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"Type": "Live2D Pose",
|
||||
"Groups": [
|
||||
[
|
||||
{
|
||||
"Id": "Part01ArmLB001",
|
||||
"Link": []
|
||||
},
|
||||
{
|
||||
"Id": "Part01ArmRA001",
|
||||
"Link": []
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"Id": "Part01ArmRB001",
|
||||
"Link": []
|
||||
},
|
||||
{
|
||||
"Id": "Part01ArmLA001",
|
||||
"Link": []
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
24
Demo/Resources/Haru/Haru.userdata3.json
Normal file
24
Demo/Resources/Haru/Haru.userdata3.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"Version": 3,
|
||||
"Meta": {
|
||||
"UserDataCount": 3,
|
||||
"TotalUserDataSize": 9
|
||||
},
|
||||
"UserData": [
|
||||
{
|
||||
"Target": "ArtMesh",
|
||||
"Id": "D_PSD_27",
|
||||
"Value": "tai"
|
||||
},
|
||||
{
|
||||
"Target": "ArtMesh",
|
||||
"Id": "D_PSD_25",
|
||||
"Value": "tai"
|
||||
},
|
||||
{
|
||||
"Target": "ArtMesh",
|
||||
"Id": "D_PSD_24",
|
||||
"Value": "tai"
|
||||
}
|
||||
]
|
||||
}
|
10
Demo/Resources/Haru/expressions/F01.exp3.json
Normal file
10
Demo/Resources/Haru/expressions/F01.exp3.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamMouthForm",
|
||||
"Value": 0.27,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
35
Demo/Resources/Haru/expressions/F02.exp3.json
Normal file
35
Demo/Resources/Haru/expressions/F02.exp3.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamBrowLY",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRY",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLForm",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRForm",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamMouthOpenY",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeForm",
|
||||
"Value": 0.54,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
55
Demo/Resources/Haru/expressions/F03.exp3.json
Normal file
55
Demo/Resources/Haru/expressions/F03.exp3.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamBrowLY",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRY",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLX",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRX",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRAngle",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLForm",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRForm",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamMouthForm",
|
||||
"Value": -2,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamMouthOpenY",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeForm",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
60
Demo/Resources/Haru/expressions/F04.exp3.json
Normal file
60
Demo/Resources/Haru/expressions/F04.exp3.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamEyeLOpen",
|
||||
"Value": 0.8,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeROpen",
|
||||
"Value": 0.8,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLY",
|
||||
"Value": -0.56,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRY",
|
||||
"Value": -0.56,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRX",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLAngle",
|
||||
"Value": 0.35,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRAngle",
|
||||
"Value": 0.35,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLForm",
|
||||
"Value": -0.74,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRForm",
|
||||
"Value": -0.74,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamMouthForm",
|
||||
"Value": -1.76,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeForm",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
35
Demo/Resources/Haru/expressions/F05.exp3.json
Normal file
35
Demo/Resources/Haru/expressions/F05.exp3.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamEyeLOpen",
|
||||
"Value": 0,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeLSmile",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeROpen",
|
||||
"Value": 0,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeRSmile",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLY",
|
||||
"Value": 0.32,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRY",
|
||||
"Value": 0.32,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
35
Demo/Resources/Haru/expressions/F06.exp3.json
Normal file
35
Demo/Resources/Haru/expressions/F06.exp3.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamEyeLOpen",
|
||||
"Value": 2,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeROpen",
|
||||
"Value": 2,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLY",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRY",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamMouthForm",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeBallForm",
|
||||
"Value": -0.65,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
65
Demo/Resources/Haru/expressions/F07.exp3.json
Normal file
65
Demo/Resources/Haru/expressions/F07.exp3.json
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamEyeLOpen",
|
||||
"Value": 0.89,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeROpen",
|
||||
"Value": 0.89,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLY",
|
||||
"Value": -0.56,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRY",
|
||||
"Value": -0.56,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLX",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRX",
|
||||
"Value": -1,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLAngle",
|
||||
"Value": 0.35,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRAngle",
|
||||
"Value": 0.35,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLForm",
|
||||
"Value": -0.74,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRForm",
|
||||
"Value": -0.74,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamMouthForm",
|
||||
"Value": -0.46,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamTere",
|
||||
"Value": 1,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
30
Demo/Resources/Haru/expressions/F08.exp3.json
Normal file
30
Demo/Resources/Haru/expressions/F08.exp3.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"Type": "Live2D Expression",
|
||||
"Parameters": [
|
||||
{
|
||||
"Id": "ParamEyeLOpen",
|
||||
"Value": 0.8,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamEyeROpen",
|
||||
"Value": 0.8,
|
||||
"Blend": "Multiply"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowLForm",
|
||||
"Value": -0.33,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamBrowRForm",
|
||||
"Value": -0.33,
|
||||
"Blend": "Add"
|
||||
},
|
||||
{
|
||||
"Id": "ParamMouthForm",
|
||||
"Value": -1.76,
|
||||
"Blend": "Add"
|
||||
}
|
||||
]
|
||||
}
|
2282
Demo/Resources/Haru/motions/haru_g_idle.motion3.json
Normal file
2282
Demo/Resources/Haru/motions/haru_g_idle.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1211
Demo/Resources/Haru/motions/haru_g_m01.motion3.json
Normal file
1211
Demo/Resources/Haru/motions/haru_g_m01.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1236
Demo/Resources/Haru/motions/haru_g_m02.motion3.json
Normal file
1236
Demo/Resources/Haru/motions/haru_g_m02.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1757
Demo/Resources/Haru/motions/haru_g_m03.motion3.json
Normal file
1757
Demo/Resources/Haru/motions/haru_g_m03.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2506
Demo/Resources/Haru/motions/haru_g_m04.motion3.json
Normal file
2506
Demo/Resources/Haru/motions/haru_g_m04.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1463
Demo/Resources/Haru/motions/haru_g_m05.motion3.json
Normal file
1463
Demo/Resources/Haru/motions/haru_g_m05.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1561
Demo/Resources/Haru/motions/haru_g_m06.motion3.json
Normal file
1561
Demo/Resources/Haru/motions/haru_g_m06.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1519
Demo/Resources/Haru/motions/haru_g_m07.motion3.json
Normal file
1519
Demo/Resources/Haru/motions/haru_g_m07.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1603
Demo/Resources/Haru/motions/haru_g_m08.motion3.json
Normal file
1603
Demo/Resources/Haru/motions/haru_g_m08.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2713
Demo/Resources/Haru/motions/haru_g_m09.motion3.json
Normal file
2713
Demo/Resources/Haru/motions/haru_g_m09.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
3728
Demo/Resources/Haru/motions/haru_g_m10.motion3.json
Normal file
3728
Demo/Resources/Haru/motions/haru_g_m10.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1477
Demo/Resources/Haru/motions/haru_g_m11.motion3.json
Normal file
1477
Demo/Resources/Haru/motions/haru_g_m11.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2374
Demo/Resources/Haru/motions/haru_g_m12.motion3.json
Normal file
2374
Demo/Resources/Haru/motions/haru_g_m12.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1155
Demo/Resources/Haru/motions/haru_g_m13.motion3.json
Normal file
1155
Demo/Resources/Haru/motions/haru_g_m13.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2198
Demo/Resources/Haru/motions/haru_g_m14.motion3.json
Normal file
2198
Demo/Resources/Haru/motions/haru_g_m14.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1381
Demo/Resources/Haru/motions/haru_g_m15.motion3.json
Normal file
1381
Demo/Resources/Haru/motions/haru_g_m15.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1939
Demo/Resources/Haru/motions/haru_g_m16.motion3.json
Normal file
1939
Demo/Resources/Haru/motions/haru_g_m16.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1659
Demo/Resources/Haru/motions/haru_g_m17.motion3.json
Normal file
1659
Demo/Resources/Haru/motions/haru_g_m17.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1365
Demo/Resources/Haru/motions/haru_g_m18.motion3.json
Normal file
1365
Demo/Resources/Haru/motions/haru_g_m18.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1127
Demo/Resources/Haru/motions/haru_g_m19.motion3.json
Normal file
1127
Demo/Resources/Haru/motions/haru_g_m19.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2499
Demo/Resources/Haru/motions/haru_g_m20.motion3.json
Normal file
2499
Demo/Resources/Haru/motions/haru_g_m20.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2590
Demo/Resources/Haru/motions/haru_g_m21.motion3.json
Normal file
2590
Demo/Resources/Haru/motions/haru_g_m21.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2986
Demo/Resources/Haru/motions/haru_g_m22.motion3.json
Normal file
2986
Demo/Resources/Haru/motions/haru_g_m22.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1743
Demo/Resources/Haru/motions/haru_g_m23.motion3.json
Normal file
1743
Demo/Resources/Haru/motions/haru_g_m23.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1876
Demo/Resources/Haru/motions/haru_g_m24.motion3.json
Normal file
1876
Demo/Resources/Haru/motions/haru_g_m24.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
1827
Demo/Resources/Haru/motions/haru_g_m25.motion3.json
Normal file
1827
Demo/Resources/Haru/motions/haru_g_m25.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
2492
Demo/Resources/Haru/motions/haru_g_m26.motion3.json
Normal file
2492
Demo/Resources/Haru/motions/haru_g_m26.motion3.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Demo/Resources/Hiyori/Hiyori.2048/texture_00.png
Normal file
BIN
Demo/Resources/Hiyori/Hiyori.2048/texture_00.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
BIN
Demo/Resources/Hiyori/Hiyori.2048/texture_01.png
Normal file
BIN
Demo/Resources/Hiyori/Hiyori.2048/texture_01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 MiB |
BIN
Demo/Resources/Hiyori/Hiyori.moc3
Normal file
BIN
Demo/Resources/Hiyori/Hiyori.moc3
Normal file
Binary file not shown.
92
Demo/Resources/Hiyori/Hiyori.model3.json
Normal file
92
Demo/Resources/Hiyori/Hiyori.model3.json
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
"Version": 3,
|
||||
"FileReferences": {
|
||||
"Moc": "Hiyori.moc3",
|
||||
"Textures": [
|
||||
"Hiyori.2048/texture_00.png",
|
||||
"Hiyori.2048/texture_01.png"
|
||||
],
|
||||
"Physics": "Hiyori.physics3.json",
|
||||
"Pose": "Hiyori.pose3.json",
|
||||
"UserData": "Hiyori.userdata3.json",
|
||||
"Motions": {
|
||||
"Idle": [
|
||||
{
|
||||
"File": "motions/Hiyori_m01.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m02.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m03.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m05.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m06.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m07.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m08.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m09.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
},
|
||||
{
|
||||
"File": "motions/Hiyori_m10.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
}
|
||||
],
|
||||
"TapBody": [
|
||||
{
|
||||
"File": "motions/Hiyori_m04.motion3.json",
|
||||
"FadeInTime": 0.5,
|
||||
"FadeOutTime": 0.5
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Groups": [
|
||||
{
|
||||
"Target": "Parameter",
|
||||
"Name": "LipSync",
|
||||
"Ids": [
|
||||
"ParamMouthOpenY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Target": "Parameter",
|
||||
"Name": "EyeBlink",
|
||||
"Ids": [
|
||||
"ParamEyeLOpen",
|
||||
"ParamEyeROpen"
|
||||
]
|
||||
}
|
||||
],
|
||||
"HitAreas": [
|
||||
{
|
||||
"Id": "HitArea",
|
||||
"Name": "Body"
|
||||
}
|
||||
]
|
||||
}
|
1569
Demo/Resources/Hiyori/Hiyori.physics3.json
Normal file
1569
Demo/Resources/Hiyori/Hiyori.physics3.json
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user