Compare commits
10 Commits
375c664d63
...
ff606d5bee
Author | SHA1 | Date |
---|---|---|
wada | ff606d5bee | |
wada | ae7a189f98 | |
wada | 6971f204ce | |
wada | a37b93d49a | |
wada | 2289dd088b | |
wada | 00275677be | |
wada | e3df50532b | |
wada | e115df6e1e | |
wada | 4e14ef622d | |
wada | 55b7a9233e |
|
@ -15,6 +15,7 @@ rules:
|
||||||
prettier/prettier:
|
prettier/prettier:
|
||||||
- error
|
- error
|
||||||
- singleQuote: true
|
- singleQuote: true
|
||||||
|
trailingComma: none
|
||||||
camelcase: "off"
|
camelcase: "off"
|
||||||
'@typescript-eslint/naming-convention':
|
'@typescript-eslint/naming-convention':
|
||||||
- warn
|
- warn
|
||||||
|
@ -58,6 +59,8 @@ rules:
|
||||||
'@typescript-eslint/no-unsafe-member-access': off
|
'@typescript-eslint/no-unsafe-member-access': off
|
||||||
'@typescript-eslint/no-unsafe-argument': off
|
'@typescript-eslint/no-unsafe-argument': off
|
||||||
'@typescript-eslint/no-unsafe-call': off
|
'@typescript-eslint/no-unsafe-call': off
|
||||||
|
'@typescript-eslint/no-explicit-any': off
|
||||||
|
'@typescript-eslint/no-unused-vars': off
|
||||||
'no-inner-declarations': off
|
'no-inner-declarations': off
|
||||||
'no-global-assign': off
|
'no-global-assign': off
|
||||||
'prefer-const': warn
|
'prefer-const': warn
|
||||||
|
|
136
CHANGELOG.md
136
CHANGELOG.md
|
@ -5,6 +5,132 @@ 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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
|
||||||
|
## [5-r.1-beta.2] - 2023-09-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add a comment for clarity for the function whose usage is not intuitive.
|
||||||
|
|
||||||
|
|
||||||
|
## [5-r.1-beta.1] - 2023-08-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add the function to get the ID of a given parameter.(`CubismModel.getParameterId`)
|
||||||
|
* Add the `CubismExpressionMotionManager` class.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Change the visibility of the `CubismId` constructor to private.
|
||||||
|
* Please use `CubismFramework.getIdManager().getId()` to get `CubismId`.
|
||||||
|
* Change the word `DrawMesh` to `DrawMeshWebGL`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix a bug that the value applied by multiply was not appropriate during expression transitions.
|
||||||
|
* Fix the structure of the class in renderer.
|
||||||
|
* Fix a issue where `ARRAY_BUFFER` was used on multiple targets.
|
||||||
|
* Separate shader class from `cubismrenderer` class.
|
||||||
|
* Separate the high precision mask process from the clipping mask setup process.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
* Remove several arguments of `DrawMesh` function.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.7] - 2023-05-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add compiler options `noImplicitAny` and `useUnknownInCatchVariables` to `tsconfig.json`.
|
||||||
|
* Add some function for checking consistency of MOC3.
|
||||||
|
* Add the function of checking consistency on reviving a MOC3. (`CubismMoc::Create`)
|
||||||
|
* Add a function to parse the opacity from `.motion3.json`.
|
||||||
|
* Add some functions to change Multiply and Screen colors on a per part basis.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Change access specifier for `CubismExpressionMotion`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix to support added compiler options `noImplicitAny` and `useUnknownInCatchVariables`.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.6.2] - 2023-03-16
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix some problems related to Cubism Core.
|
||||||
|
* See `CHANGELOG.md` in Core.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.6.1] - 2023-03-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add function to validate MOC3 files.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.6] - 2023-02-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add support for high-precision masks.
|
||||||
|
* The number of render textures used can now be increased arbitrarily.
|
||||||
|
* The maximum number of masks when using multiple render textures has been increased to "number of render textures * 32".
|
||||||
|
* Add API to allow users to configure culling.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Change to not reference `CubismClippingManager_WebGL` on models that do not use clipping masks.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix a crash when a `WebGLRenderingContext` is not registered with `Cubism Renderer_WebGL`.
|
||||||
|
* It now displays a warning and does not draw models.
|
||||||
|
* Fix a bug when displaying a model with culling set, some of the other drawn images are missing.
|
||||||
|
* Fix a bug that caused update information for some models not to be updated when multiple models are displayed.
|
||||||
|
* Call the function to extend the initial memory with CubismFramework.initialize(). See `CHANGELOG.md` in Core.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.5] - 2022-09-08
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add the multilingual supported documents.
|
||||||
|
* Add immediate stabilization of physics.
|
||||||
|
* Implemented a process to switch between `CubismJson` parsing and `JSON.parse()`.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.5-beta.5] - 2022-08-04
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix `csmGetMocVersion` function argument.
|
||||||
|
* Fix a bug in which processing was interrupted when an invalid vertex was specified in the middle of a physics operation.
|
||||||
|
* Fix crash with exception when reading .moc3 files of unsupported versions.
|
||||||
|
* Fix physics system input to be split by the physics setting time.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.5-beta.4] - 2022-07-07
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Add a function to get the latest .moc3 Version and the .moc3 Version of the loaded model.
|
||||||
|
* Add a function to get the type of parameters of the model.
|
||||||
|
* Add a function to get the parent part of the model's Drawable.
|
||||||
|
|
||||||
|
|
||||||
|
## [4-r.5-beta.3] - 2022-06-16
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* `getDrawableTextureIndices` function in `CubismModel` has been renamed to `getDrawableTextureIndex` because the name was not correct.
|
||||||
|
* `getDrawableTextureIndices` function is marked as deprecated.
|
||||||
|
* Fix physics system behaviour when exists Physics Fps Setting in .physics3.json.
|
||||||
|
|
||||||
|
|
||||||
## [4-r.5-beta.2] - 2022-06-02
|
## [4-r.5-beta.2] - 2022-06-02
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -89,6 +215,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
* Reformat code using Prettier and ESLint.
|
* Reformat code using Prettier and ESLint.
|
||||||
|
|
||||||
|
|
||||||
|
[5-r.1-beta.2]: https://github.com/Live2D/CubismWebFramework/compare/5-r.1-beta.1...5-r.1-beta.2
|
||||||
|
[5-r.1-beta.1]: https://github.com/Live2D/CubismWebFramework/compare/4-r.7...5-r.1-beta.1
|
||||||
|
[4-r.7]: https://github.com/Live2D/CubismWebFramework/compare/4-r.6.2...4-r.7
|
||||||
|
[4-r.6.2]: https://github.com/Live2D/CubismWebFramework/compare/4-r.6.1...4-r.6.2
|
||||||
|
[4-r.6.1]: https://github.com/Live2D/CubismWebFramework/compare/4-r.6...4-r.6.1
|
||||||
|
[4-r.6]: https://github.com/Live2D/CubismWebFramework/compare/4-r.5...4-r.6
|
||||||
|
[4-r.5]: https://github.com/Live2D/CubismWebFramework/compare/4-r.5-beta.5...4-r.5
|
||||||
|
[4-r.5-beta.5]: https://github.com/Live2D/CubismWebFramework/compare/4-r.5-beta.4...4-r.5-beta.5
|
||||||
|
[4-r.5-beta.4]: https://github.com/Live2D/CubismWebFramework/compare/4-r.5-beta.3...4-r.5-beta.4
|
||||||
|
[4-r.5-beta.3]: https://github.com/Live2D/CubismWebFramework/compare/4-r.5-beta.2...4-r.5-beta.3
|
||||||
[4-r.5-beta.2]: https://github.com/Live2D/CubismWebFramework/compare/4-r.5-beta.1...4-r.5-beta.2
|
[4-r.5-beta.2]: https://github.com/Live2D/CubismWebFramework/compare/4-r.5-beta.1...4-r.5-beta.2
|
||||||
[4-r.5-beta.1]: https://github.com/Live2D/CubismWebFramework/compare/4-r.4...4-r.5-beta.1
|
[4-r.5-beta.1]: https://github.com/Live2D/CubismWebFramework/compare/4-r.4...4-r.5-beta.1
|
||||||
[4-r.4]: https://github.com/Live2D/CubismWebFramework/compare/4-r.3...4-r.4
|
[4-r.4]: https://github.com/Live2D/CubismWebFramework/compare/4-r.3...4-r.4
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
[English](README.md) / [日本語](README.ja.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Cubism Web Framework
|
||||||
|
|
||||||
|
Live2D Cubism Editor で出力したモデルをアプリケーションで利用するためのフレームワークです。
|
||||||
|
|
||||||
|
モデルを表示、操作するための各種機能を提供します。
|
||||||
|
モデルをロードするには Live2D Cubism Core ライブラリと組み合わせて使用します。
|
||||||
|
|
||||||
|
ビルドを行うことで、ブラウザで利用可能な JavaScript ライブラリとして利用することができます。
|
||||||
|
|
||||||
|
|
||||||
|
## ライセンス
|
||||||
|
|
||||||
|
本 SDK を使用する前に、[ライセンス](LICENSE.md)をご確認ください。
|
||||||
|
|
||||||
|
|
||||||
|
## Cubism 5新機能や過去バージョンとの互換性について
|
||||||
|
|
||||||
|
本 SDK はCubism 5に対応した製品です。
|
||||||
|
|
||||||
|
Cubism 5 Editorに搭載された新機能のSDK対応については [こちら](https://docs.live2d.com/cubism-sdk-manual/cubism-5-new-functions/)をご確認ください。
|
||||||
|
|
||||||
|
過去バージョンのCubism SDKとの互換性については [こちら](https://docs.live2d.com/cubism-sdk-manual/compatibility-with-cubism-5/)をご確認ください。
|
||||||
|
|
||||||
|
|
||||||
|
## 開発環境
|
||||||
|
|
||||||
|
### Node.js
|
||||||
|
|
||||||
|
* 20.7.0
|
||||||
|
* 18.18.0
|
||||||
|
|
||||||
|
|
||||||
|
### TypeScript
|
||||||
|
|
||||||
|
5.2.2
|
||||||
|
|
||||||
|
|
||||||
|
## 開発環境構築
|
||||||
|
|
||||||
|
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) を参照ください。
|
||||||
|
|
||||||
|
|
||||||
|
## プロジェクトへの貢献
|
||||||
|
|
||||||
|
プロジェクトに貢献する方法はたくさんあります。バグのログの記録、このGitHubでのプルリクエストの送信、Live2Dコミュニティでの問題の報告と提案の作成です。
|
||||||
|
|
||||||
|
### フォークとプルリクエスト
|
||||||
|
|
||||||
|
修正、改善、さらには新機能をもたらすかどうかにかかわらず、プルリクエストに感謝します。ただし、ラッパーは可能な限り軽量で浅くなるように設計されているため、バグ修正とメモリ/パフォーマンスの改善のみを行う必要があることに注意してください。メインリポジトリを可能な限りクリーンに保つために、必要に応じて個人用フォークと機能ブランチを作成してください。
|
||||||
|
|
||||||
|
### バグ
|
||||||
|
|
||||||
|
Live2Dコミュニティでは、問題のレポートと機能リクエストを定期的にチェックしています。バグレポートを提出する前に、Live2Dコミュニティで検索して、問題のレポートまたは機能リクエストがすでに投稿されているかどうかを確認してください。問題がすでに存在する場合は、関連するコメントを追記してください。
|
||||||
|
|
||||||
|
### 提案
|
||||||
|
|
||||||
|
SDKの将来についてのフィードバックにも関心があります。Live2Dコミュニティで提案や機能のリクエストを送信できます。このプロセスをより効果的にするために、それらをより明確に定義するのに役立つより多くの情報を含めるようお願いしています。
|
||||||
|
|
||||||
|
|
||||||
|
## フォーラム
|
||||||
|
|
||||||
|
ユーザー同士でCubism SDKの活用方法の提案や質問をしたい場合は、是非フォーラムをご活用ください。
|
||||||
|
|
||||||
|
- [Live2D 公式クリエイターズフォーラム](https://creatorsforum.live2d.com/)
|
||||||
|
- [Live2D Creator's Forum(English)](https://community.live2d.com/)
|
131
README.md
131
README.md
|
@ -1,144 +1,171 @@
|
||||||
|
[English](README.md) / [日本語](README.ja.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Cubism Web Framework
|
# Cubism Web Framework
|
||||||
|
|
||||||
Live2D Cubism 4 Editor で出力したモデルをアプリケーションで利用するためのフレームワークです。
|
This is a framework for using models output by Live2D Cubism Editor in applications.
|
||||||
|
|
||||||
モデルを表示、操作するための各種機能を提供します。
|
It provides various functions for displaying and manipulating the model.
|
||||||
モデルをロードするには Live2D Cubism Core ライブラリと組み合わせて使用します。
|
It is used in conjunction with the Live2D Cubism Core library to load the model.
|
||||||
|
|
||||||
ビルドを行うことで、ブラウザで利用可能な JavaScript ライブラリとして利用することができます。
|
You can use it as a JavaScript library that can be used in the browser by building.
|
||||||
|
|
||||||
|
|
||||||
## ライセンス
|
## License
|
||||||
|
|
||||||
本 SDK を使用する前に、[ライセンス](LICENSE.md)をご確認ください。
|
Please check the [license](LICENSE.md) before using this SDK.
|
||||||
|
|
||||||
|
|
||||||
## 開発環境
|
## Compatibility with Cubism 5 new features and previous Cubism SDK versions
|
||||||
|
|
||||||
|
This SDK is compatible with Cubism 5.
|
||||||
|
|
||||||
|
For SDK compatibility with new features in Cubism 5 Editor, please refer to [here](https://docs.live2d.com/en/cubism-sdk-manual/cubism-5-new-functions/).
|
||||||
|
|
||||||
|
For compatibility with previous versions of Cubism SDK, please refer to [here](https://docs.live2d.com/en/cubism-sdk-manual/compatibility-with-cubism-5/).
|
||||||
|
|
||||||
|
|
||||||
|
## Development environment
|
||||||
|
|
||||||
### Node.js
|
### Node.js
|
||||||
|
|
||||||
* 18.1.0
|
* 20.7.0
|
||||||
* 17.9.0
|
* 18.18.0
|
||||||
* 16.15.0
|
|
||||||
* 14.19.2
|
|
||||||
|
|
||||||
|
|
||||||
### TypeScript
|
### TypeScript
|
||||||
|
|
||||||
4.6.4
|
5.2.2
|
||||||
|
|
||||||
|
|
||||||
## 開発環境構築
|
## Development environment construction
|
||||||
|
|
||||||
1. [Node.js] と [Visual Studio Code] をインストールします
|
1. Install [Node.js] and [Visual Studio Code]
|
||||||
1. Visual Studio Code で本プロジェクトを開き、推奨拡張機能をインストールします
|
1. Open this project in Visual Studio Code and install the recommended extensions
|
||||||
* 拡張機能タブから `@recommended` と入力することで確認できます
|
* You can check them by typing `@recommended` from the Extensions tab
|
||||||
1. コマンドパレット(*View > Command Palette...*)で `>Tasks: Run Task` を入力してタスク一覧を表示します
|
1. Enter `>Tasks: Run Task` in the command palette (*View > Command Palette...*) to display the task list
|
||||||
1. `npm: install` を選択して依存パッケージのダウンロードを行います
|
1. Select `npm: install` to download the dependent packages
|
||||||
|
|
||||||
コマンドパレットのタスク一覧から各種コマンドを実行することができます。
|
You can execute various commands from the task list on the command palette.
|
||||||
|
|
||||||
NOTE: デバック用の設定は、`.vscode/tasks.json` に記述しています。
|
NOTE: Settings for debugging are described in `.vscode/tasks.json`.
|
||||||
|
|
||||||
## タスク一覧
|
## Task list
|
||||||
|
|
||||||
### `npm: build`
|
### `npm: build`
|
||||||
|
|
||||||
ソースファイルのビルドを行い、`dist` ディレクトリに出力します。
|
Builds the source file and outputs to the `dist` directory.
|
||||||
|
|
||||||
`tsconfig.json` を編集することで設定内容を変更できます。
|
You can change the settings by editing `tsconfig.json`.
|
||||||
|
|
||||||
### `npm: test`
|
### `npm: test`
|
||||||
|
|
||||||
TypeScript の型チェックテストを行います。
|
Performs a TypeScript type check test.
|
||||||
|
|
||||||
`tsconfig.json` を編集することで設定内容を変更できます。
|
You can change the settings by editing `tsconfig.json`.
|
||||||
|
|
||||||
### `npm: lint`
|
### `npm: lint`
|
||||||
|
|
||||||
`src` ディレクトリ内の TypeScript ファイルの静的解析を行います。
|
Performs static analysis of TypeScript files in the `src` directory.
|
||||||
|
|
||||||
`.eslintrc.yml` を編集することで設定内容を変更できます。
|
You can change the settings by editing `.eslintrc.yml`.
|
||||||
|
|
||||||
### `npm: lint:fix`
|
### `npm: lint:fix`
|
||||||
|
|
||||||
`src` ディレクトリ内の TypeScript ファイルの静的解析及び自動修正を行います。
|
Performs static analysis and automatic modification of TypeScript files in the `src` directory.
|
||||||
|
|
||||||
`.eslintrc.yml` を編集することで設定内容を変更できます。
|
You can change the settings by editing `.eslintrc.yml`.
|
||||||
|
|
||||||
### `npm: clean`
|
### `npm: clean`
|
||||||
|
|
||||||
ビルド成果物ディレクトリ(`dist`)を削除します。
|
Deletes the build deliverable directory (`dist`).
|
||||||
|
|
||||||
|
|
||||||
## コンポーネント
|
## Components
|
||||||
|
|
||||||
### effect
|
### effect
|
||||||
|
|
||||||
自動まばたきやリップシンクなど、モデルに対してモーション情報をエフェクト的に付加する機能を提供します。
|
Provides functions such as automatic blinking and lip sync to add motion information as an effect to the model.
|
||||||
|
|
||||||
### id
|
### id
|
||||||
|
|
||||||
モデルに設定されたパラメータ名・パーツ名・Drawable名を独自の型で管理する機能を提供します。
|
Provides functions to manage the parameter name, part name, and Drawable name set in the model with unique types.
|
||||||
|
|
||||||
### math
|
### math
|
||||||
|
|
||||||
行列計算やベクトル計算など、モデルの操作や描画に必要な算術演算の機能を提供します。
|
Provides arithmetic functions required for manipulating and drawing the model, such as matrix and vector calculations.
|
||||||
|
|
||||||
### model
|
### model
|
||||||
|
|
||||||
モデルを取り扱うための各種機能(生成、更新、破棄)を提供します。
|
Provides various functions (generate, update, destroy) for handling the model.
|
||||||
|
|
||||||
### motion
|
### motion
|
||||||
|
|
||||||
モデルにモーションデータを適用するための各種機能(モーション再生、パラメータブレンド)を提供します。
|
Provides various functions (motion playback, parameter blending) for applying motion data to the model.
|
||||||
|
|
||||||
### physics
|
### physics
|
||||||
|
|
||||||
モデルに物理演算による変形操作を適用するための機能を提供します。
|
Provides functions for applying transformation manipulations due to physics to the model.
|
||||||
|
|
||||||
### rendering
|
### rendering
|
||||||
|
|
||||||
モデルを描画するためのグラフィックス命令を実装したレンダラを提供します。
|
Provides a renderer that implements graphics instructions for drawing the model.
|
||||||
|
|
||||||
### type
|
### type
|
||||||
|
|
||||||
フレームワーク内で使用する型定義を提供します。
|
Provides type definitions for use within the framework.
|
||||||
|
|
||||||
### utils
|
### utils
|
||||||
|
|
||||||
JSONパーサーやログ出力などのユーティリティ機能を提供します。
|
Provides utility functions such as JSON parser and log output.
|
||||||
|
|
||||||
|
|
||||||
## Live2D Cubism Core for Web
|
## Live2D Cubism Core for Web
|
||||||
|
|
||||||
当リポジトリには Cubism Core for Web は同梱されていません。
|
Cubism Core for Web is not included in this repository.
|
||||||
|
|
||||||
[Cubism SDK for Web] からダウンロードしてください。
|
Please download it from the [Cubism SDK for Web].
|
||||||
|
|
||||||
[Cubism SDK for Web]: https://www.live2d.com/download/cubism-sdk/download-web/
|
[Cubism SDK for Web]: https://www.live2d.com/download/cubism-sdk/download-web/
|
||||||
|
|
||||||
|
|
||||||
## サンプル
|
## Samples
|
||||||
|
|
||||||
標準的なアプリケーションの実装例は [CubismWebSamples] を参照ください。
|
Please refer to [CubismWebSamples] for implementation examples of standard applications.
|
||||||
|
|
||||||
[CubismWebSamples]: https://github.com/Live2D/CubismWebSamples
|
[CubismWebSamples]: https://github.com/Live2D/CubismWebSamples
|
||||||
|
|
||||||
|
|
||||||
## マニュアル
|
## Manual
|
||||||
|
|
||||||
[Cubism SDK Manual](https://docs.live2d.com/cubism-sdk-manual/top/)
|
[Cubism SDK Manual](https://docs.live2d.com/cubism-sdk-manual/top/)
|
||||||
|
|
||||||
|
|
||||||
## 変更履歴
|
## Changelog
|
||||||
|
|
||||||
当リポジトリの変更履歴については [CHANGELOG.md](CHANGELOG.md) を参照ください。
|
Please refer to [CHANGELOG.md](CHANGELOG.md) for the changelog of this repository.
|
||||||
|
|
||||||
|
|
||||||
## コミュニティ
|
## Contributing
|
||||||
|
|
||||||
ユーザー同士でCubism SDKの活用方法の提案や質問をしたい場合は、是非コミュニティをご活用ください。
|
There are many ways to contribute to the project: logging bugs, submitting pull requests on this GitHub, and reporting issues and making suggestions in Live2D Community.
|
||||||
|
|
||||||
- [Live2D 公式コミュニティ](https://creatorsforum.live2d.com/)
|
### Forking And Pull Requests
|
||||||
- [Live2D community(English)](https://community.live2d.com/)
|
|
||||||
|
We very much appreciate your pull requests, whether they bring fixes, improvements, or even new features. Note, however, that the wrapper is designed to be as lightweight and shallow as possible and should therefore only be subject to bug fixes and memory/performance improvements. To keep the main repository as clean as possible, create a personal fork and feature branches there as needed.
|
||||||
|
|
||||||
|
### Bugs
|
||||||
|
|
||||||
|
We are regularly checking issue-reports and feature requests at Live2D Community. Before filing a bug report, please do a search in Live2D Community to see if the issue-report or feature request has already been posted. If you find your issue already exists, make relevant comments and add your reaction.
|
||||||
|
|
||||||
|
### Suggestions
|
||||||
|
|
||||||
|
We're also interested in your feedback for the future of the SDK. You can submit a suggestion or feature request at Live2D Community. To make this process more effective, we're asking that you include more information to help define them more clearly.
|
||||||
|
|
||||||
|
|
||||||
|
## Forum
|
||||||
|
|
||||||
|
If you want to suggest or ask questions about how to use the Cubism SDK between users, please use the forum.
|
||||||
|
|
||||||
|
- [Live2D Creator's Forum](https://community.live2d.com/)
|
||||||
|
- [Live2D 公式クリエイターズフォーラム (Japanese)](https://creatorsforum.live2d.com/)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
|
@ -8,13 +8,13 @@
|
||||||
"clean": "rimraf dist"
|
"clean": "rimraf dist"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^5.23.0",
|
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||||
"@typescript-eslint/parser": "^5.23.0",
|
"@typescript-eslint/parser": "^6.7.2",
|
||||||
"eslint": "^8.15.0",
|
"eslint": "^8.49.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
"prettier": "^2.6.2",
|
"prettier": "^3.0.3",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^5.0.1",
|
||||||
"typescript": "^4.6.4"
|
"typescript": "^5.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ export const CubismDefaultParameterId = Object.freeze<Record<string, string>>({
|
||||||
ParamBustY: 'ParamBustY',
|
ParamBustY: 'ParamBustY',
|
||||||
ParamBaseX: 'ParamBaseX',
|
ParamBaseX: 'ParamBaseX',
|
||||||
ParamBaseY: 'ParamBaseY',
|
ParamBaseY: 'ParamBaseY',
|
||||||
ParamNONE: 'NONE:',
|
ParamNONE: 'NONE:'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -73,7 +73,7 @@ enum FrequestNode {
|
||||||
FrequestNode_Textures, // getRoot().getValueByString(FileReferences).getValueByString(Textures)
|
FrequestNode_Textures, // getRoot().getValueByString(FileReferences).getValueByString(Textures)
|
||||||
FrequestNode_Physics, // getRoot().getValueByString(FileReferences).getValueByString(Physics)
|
FrequestNode_Physics, // getRoot().getValueByString(FileReferences).getValueByString(Physics)
|
||||||
FrequestNode_Pose, // getRoot().getValueByString(FileReferences).getValueByString(Pose)
|
FrequestNode_Pose, // getRoot().getValueByString(FileReferences).getValueByString(Pose)
|
||||||
FrequestNode_HitAreas, // getRoot().getValueByString(HitAreas)
|
FrequestNode_HitAreas // getRoot().getValueByString(HitAreas)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -219,7 +219,7 @@ export enum EyeState {
|
||||||
EyeState_Interval, // まばたきしていない状態
|
EyeState_Interval, // まばたきしていない状態
|
||||||
EyeState_Closing, // まぶたが閉じていく途中の状態
|
EyeState_Closing, // まぶたが閉じていく途中の状態
|
||||||
EyeState_Closed, // まぶたが閉じている状態
|
EyeState_Closed, // まぶたが閉じている状態
|
||||||
EyeState_Opening, // まぶたが開いていく途中の状態
|
EyeState_Opening // まぶたが開いていく途中の状態
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -11,8 +11,23 @@ import { csmString } from '../type/csmstring';
|
||||||
* パラメータ名・パーツ名・Drawable名を保持
|
* パラメータ名・パーツ名・Drawable名を保持
|
||||||
*
|
*
|
||||||
* パラメータ名・パーツ名・Drawable名を保持するクラス。
|
* パラメータ名・パーツ名・Drawable名を保持するクラス。
|
||||||
|
*
|
||||||
|
* @note 指定したID文字列からCubismIdを取得する際はこのクラスの生成メソッドを呼ばず、
|
||||||
|
* CubismIdManager().getId(id)を使用してください
|
||||||
*/
|
*/
|
||||||
export class CubismId {
|
export class CubismId {
|
||||||
|
/**
|
||||||
|
* 内部で使用するCubismIdクラス生成メソッド
|
||||||
|
*
|
||||||
|
* @param id ID文字列
|
||||||
|
* @returns CubismId
|
||||||
|
* @note 指定したID文字列からCubismIdを取得する際は
|
||||||
|
* CubismIdManager().getId(id)を使用してください
|
||||||
|
*/
|
||||||
|
public static _createIdInternal(id: string | csmString) {
|
||||||
|
return new CubismId(id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID名を取得する
|
* ID名を取得する
|
||||||
*/
|
*/
|
||||||
|
@ -20,18 +35,6 @@ export class CubismId {
|
||||||
return this._id;
|
return this._id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* コンストラクタ
|
|
||||||
*/
|
|
||||||
public constructor(id: string | csmString) {
|
|
||||||
if (typeof id === 'string') {
|
|
||||||
this._id = new csmString(id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* idを比較
|
* idを比較
|
||||||
* @param c 比較するid
|
* @param c 比較するid
|
||||||
|
@ -64,6 +67,20 @@ export class CubismId {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* プライベートコンストラクタ
|
||||||
|
*
|
||||||
|
* @note ユーザーによる生成は許可しません
|
||||||
|
*/
|
||||||
|
private constructor(id: string | csmString) {
|
||||||
|
if (typeof id === 'string') {
|
||||||
|
this._id = new csmString(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._id = id;
|
||||||
|
}
|
||||||
|
|
||||||
private _id: csmString; // ID名
|
private _id: csmString; // ID名
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ export class CubismIdManager {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = new CubismId(id);
|
result = CubismId._createIdInternal(id);
|
||||||
this._ids.pushBack(result);
|
this._ids.pushBack(result);
|
||||||
} else {
|
} else {
|
||||||
return this.registerId(id.s);
|
return this.registerId(id.s);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { CubismRenderer } from './rendering/cubismrenderer';
|
||||||
import {
|
import {
|
||||||
CSM_ASSERT,
|
CSM_ASSERT,
|
||||||
CubismLogInfo,
|
CubismLogInfo,
|
||||||
CubismLogWarning,
|
CubismLogWarning
|
||||||
} from './utils/cubismdebug';
|
} from './utils/cubismdebug';
|
||||||
import { Value } from './utils/cubismjson';
|
import { Value } from './utils/cubismjson';
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ let s_cubismIdManager: CubismIdManager = null;
|
||||||
*/
|
*/
|
||||||
export const Constant = Object.freeze<Record<string, number>>({
|
export const Constant = Object.freeze<Record<string, number>>({
|
||||||
vertexOffset: 0, // メッシュ頂点のオフセット値
|
vertexOffset: 0, // メッシュ頂点のオフセット値
|
||||||
vertexStep: 2, // メッシュ頂点のステップ値
|
vertexStep: 2 // メッシュ頂点のステップ値
|
||||||
});
|
});
|
||||||
|
|
||||||
export function csmDelete<T>(address: T): void {
|
export function csmDelete<T>(address: T): void {
|
||||||
|
@ -131,8 +131,13 @@ export class CubismFramework {
|
||||||
/**
|
/**
|
||||||
* Cubism Framework内のリソースを初期化してモデルを表示可能な状態にします。<br>
|
* Cubism Framework内のリソースを初期化してモデルを表示可能な状態にします。<br>
|
||||||
* 再度Initialize()するには先にDispose()を実行する必要があります。
|
* 再度Initialize()するには先にDispose()を実行する必要があります。
|
||||||
|
*
|
||||||
|
* @param memorySize 初期化時メモリ量 [byte(s)]
|
||||||
|
* 複数モデル表示時などにモデルが更新されない際に使用してください。
|
||||||
|
* 指定する際は必ず1024*1024*16 byte(16MB)以上の値を指定してください。
|
||||||
|
* それ以外はすべて1024*1024*16 byteに丸めます。
|
||||||
*/
|
*/
|
||||||
public static initialize(): void {
|
public static initialize(memorySize = 0): void {
|
||||||
CSM_ASSERT(s_isStarted);
|
CSM_ASSERT(s_isStarted);
|
||||||
if (!s_isStarted) {
|
if (!s_isStarted) {
|
||||||
CubismLogWarning('CubismFramework is not started.');
|
CubismLogWarning('CubismFramework is not started.');
|
||||||
|
@ -154,6 +159,12 @@ export class CubismFramework {
|
||||||
|
|
||||||
s_cubismIdManager = new CubismIdManager();
|
s_cubismIdManager = new CubismIdManager();
|
||||||
|
|
||||||
|
// --- HACK: 初期化時メモリ量の拡張(単位byte) ---
|
||||||
|
// 複数モデル表示時などにモデルが更新されない際に使用してください。
|
||||||
|
// 指定する際は必ず1024*1024*16 byte(16MB)以上の値を指定してください。
|
||||||
|
// それ以外はすべて1024*1024*16 byteに丸めます。
|
||||||
|
Live2DCubismCore.Memory.initializeAmountOfMemory(memorySize);
|
||||||
|
|
||||||
s_isInitialized = true;
|
s_isInitialized = true;
|
||||||
|
|
||||||
CubismLogInfo('CubismFramework.initialize() is complete.');
|
CubismLogInfo('CubismFramework.initialize() is complete.');
|
||||||
|
@ -263,7 +274,7 @@ export enum LogLevel {
|
||||||
LogLevel_Info, // Infoログ
|
LogLevel_Info, // Infoログ
|
||||||
LogLevel_Warning, // 警告ログ
|
LogLevel_Warning, // 警告ログ
|
||||||
LogLevel_Error, // エラーログ
|
LogLevel_Error, // エラーログ
|
||||||
LogLevel_Off, // ログ出力無効
|
LogLevel_Off // ログ出力無効
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -33,7 +33,7 @@ export class CubismMatrix44 {
|
||||||
): void {
|
): void {
|
||||||
const c: Float32Array = new Float32Array([
|
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, 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;
|
const n = 4;
|
||||||
|
@ -57,7 +57,7 @@ export class CubismMatrix44 {
|
||||||
public loadIdentity(): void {
|
public loadIdentity(): void {
|
||||||
const c: Float32Array = new Float32Array([
|
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, 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,
|
1.0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.setMatrix(c);
|
this.setMatrix(c);
|
||||||
|
@ -175,7 +175,7 @@ export class CubismMatrix44 {
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
CubismMatrix44.multiply(tr1, this._tr, this._tr);
|
CubismMatrix44.multiply(tr1, this._tr, this._tr);
|
||||||
|
@ -235,7 +235,7 @@ export class CubismMatrix44 {
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
CubismMatrix44.multiply(tr1, this._tr, this._tr);
|
CubismMatrix44.multiply(tr1, this._tr, this._tr);
|
||||||
|
@ -253,8 +253,10 @@ export class CubismMatrix44 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 現在の行列に行列を乗算
|
* 引数で与えられた行列にこの行列を乗算する。
|
||||||
|
* (引数で与えられた行列) * (この行列)
|
||||||
*
|
*
|
||||||
|
* @note 関数名と実際の計算内容に乖離があるため、今後計算順が修正される可能性があります。
|
||||||
* @param m 行列
|
* @param m 行列
|
||||||
*/
|
*/
|
||||||
public multiplyByMatrix(m: CubismMatrix44): void {
|
public multiplyByMatrix(m: CubismMatrix44): void {
|
||||||
|
|
|
@ -14,7 +14,10 @@ export class CubismVector2 {
|
||||||
/**
|
/**
|
||||||
* コンストラクタ
|
* コンストラクタ
|
||||||
*/
|
*/
|
||||||
public constructor(public x?: number, public y?: number) {
|
public constructor(
|
||||||
|
public x?: number,
|
||||||
|
public y?: number
|
||||||
|
) {
|
||||||
this.x = x == undefined ? 0.0 : x;
|
this.x = x == undefined ? 0.0 : x;
|
||||||
|
|
||||||
this.y = y == undefined ? 0.0 : y;
|
this.y = y == undefined ? 0.0 : y;
|
||||||
|
|
|
@ -72,7 +72,7 @@ export class CubismViewMatrix extends CubismMatrix44 {
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
CubismMatrix44.multiply(tr1, this._tr, this._tr);
|
CubismMatrix44.multiply(tr1, this._tr, this._tr);
|
||||||
|
@ -117,7 +117,7 @@ export class CubismViewMatrix extends CubismMatrix44 {
|
||||||
cx,
|
cx,
|
||||||
cy,
|
cy,
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const tr2: Float32Array = new Float32Array([
|
const tr2: Float32Array = new Float32Array([
|
||||||
|
@ -136,7 +136,7 @@ export class CubismViewMatrix extends CubismMatrix44 {
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const tr3: Float32Array = new Float32Array([
|
const tr3: Float32Array = new Float32Array([
|
||||||
|
@ -155,7 +155,7 @@ export class CubismViewMatrix extends CubismMatrix44 {
|
||||||
-cx,
|
-cx,
|
||||||
-cy,
|
-cy,
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
CubismMatrix44.multiply(tr3, this._tr, this._tr);
|
CubismMatrix44.multiply(tr3, this._tr, this._tr);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CSM_ASSERT } from '../utils/cubismdebug';
|
import { CSM_ASSERT, CubismLogError } from '../utils/cubismdebug';
|
||||||
import { CubismModel } from './cubismmodel';
|
import { CubismModel } from './cubismmodel';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,13 +17,32 @@ export class CubismMoc {
|
||||||
/**
|
/**
|
||||||
* Mocデータの作成
|
* Mocデータの作成
|
||||||
*/
|
*/
|
||||||
public static create(mocBytes: ArrayBuffer): CubismMoc {
|
public static create(
|
||||||
|
mocBytes: ArrayBuffer,
|
||||||
|
shouldCheckMocConsistency: boolean
|
||||||
|
): CubismMoc {
|
||||||
let cubismMoc: CubismMoc = null;
|
let cubismMoc: CubismMoc = null;
|
||||||
|
|
||||||
|
if (shouldCheckMocConsistency) {
|
||||||
|
// .moc3の整合性を確認
|
||||||
|
const consistency = this.hasMocConsistency(mocBytes);
|
||||||
|
|
||||||
|
if (!consistency) {
|
||||||
|
// 整合性が確認できなければ処理しない
|
||||||
|
CubismLogError(`Inconsistent MOC3.`);
|
||||||
|
return cubismMoc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const moc: Live2DCubismCore.Moc =
|
const moc: Live2DCubismCore.Moc =
|
||||||
Live2DCubismCore.Moc.fromArrayBuffer(mocBytes);
|
Live2DCubismCore.Moc.fromArrayBuffer(mocBytes);
|
||||||
|
|
||||||
if (moc) {
|
if (moc) {
|
||||||
cubismMoc = new CubismMoc(moc);
|
cubismMoc = new CubismMoc(moc);
|
||||||
|
cubismMoc._mocVersion = Live2DCubismCore.Version.csmGetMocVersion(
|
||||||
|
moc,
|
||||||
|
mocBytes
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cubismMoc;
|
return cubismMoc;
|
||||||
|
@ -79,6 +98,7 @@ export class CubismMoc {
|
||||||
private constructor(moc: Live2DCubismCore.Moc) {
|
private constructor(moc: Live2DCubismCore.Moc) {
|
||||||
this._moc = moc;
|
this._moc = moc;
|
||||||
this._modelCount = 0;
|
this._modelCount = 0;
|
||||||
|
this._mocVersion = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,8 +111,32 @@ export class CubismMoc {
|
||||||
this._moc = null;
|
this._moc = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最新の.moc3 Versionを取得
|
||||||
|
*/
|
||||||
|
public getLatestMocVersion(): number {
|
||||||
|
return Live2DCubismCore.Version.csmGetLatestMocVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 読み込んだモデルの.moc3 Versionを取得
|
||||||
|
*/
|
||||||
|
public getMocVersion(): number {
|
||||||
|
return this._mocVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* .moc3 の整合性を検証する
|
||||||
|
*/
|
||||||
|
public static hasMocConsistency(mocBytes: ArrayBuffer): boolean {
|
||||||
|
const isConsistent =
|
||||||
|
Live2DCubismCore.Moc.prototype.hasMocConsistency(mocBytes);
|
||||||
|
return isConsistent === 1 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
_moc: Live2DCubismCore.Moc; // Mocデータ
|
_moc: Live2DCubismCore.Moc; // Mocデータ
|
||||||
_modelCount: number; // Mocデータから作られたモデルの個数
|
_modelCount: number; // Mocデータから作られたモデルの個数
|
||||||
|
_mocVersion: number; // 読み込んだモデルの.moc3 Version
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { CubismIdHandle } from '../id/cubismid';
|
||||||
import { CubismFramework } from '../live2dcubismframework';
|
import { CubismFramework } from '../live2dcubismframework';
|
||||||
import {
|
import {
|
||||||
CubismBlendMode,
|
CubismBlendMode,
|
||||||
CubismTextureColor,
|
CubismTextureColor
|
||||||
} from '../rendering/cubismrenderer';
|
} from '../rendering/cubismrenderer';
|
||||||
import { csmMap } from '../type/csmmap';
|
import { csmMap } from '../type/csmmap';
|
||||||
import { csmVector } from '../type/csmvector';
|
import { csmVector } from '../type/csmvector';
|
||||||
|
@ -20,8 +20,50 @@ import { CSM_ASSERT } from '../utils/cubismdebug';
|
||||||
* その色を保持する構造体
|
* その色を保持する構造体
|
||||||
*/
|
*/
|
||||||
export class DrawableColorData {
|
export class DrawableColorData {
|
||||||
isOverwritten = false;
|
constructor(
|
||||||
Color: CubismTextureColor = new CubismTextureColor();
|
isOverwritten = false,
|
||||||
|
color: CubismTextureColor = new CubismTextureColor()
|
||||||
|
) {
|
||||||
|
this.isOverwritten = isOverwritten;
|
||||||
|
this.Color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOverwritten: boolean;
|
||||||
|
public Color: CubismTextureColor;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief テクスチャの色をRGBAで扱うための構造体
|
||||||
|
*/
|
||||||
|
export class PartColorData {
|
||||||
|
constructor(
|
||||||
|
isOverwritten = false,
|
||||||
|
color: CubismTextureColor = new CubismTextureColor()
|
||||||
|
) {
|
||||||
|
this.isOverwritten = isOverwritten;
|
||||||
|
this.Color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOverwritten: boolean;
|
||||||
|
public Color: CubismTextureColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* テクスチャのカリング設定を管理するための構造体
|
||||||
|
*/
|
||||||
|
export class DrawableCullingData {
|
||||||
|
/**
|
||||||
|
* コンストラクタ
|
||||||
|
*
|
||||||
|
* @param isOverwritten
|
||||||
|
* @param isCulling
|
||||||
|
*/
|
||||||
|
public constructor(isOverwritten = false, isCulling = false) {
|
||||||
|
this.isOverwritten = isOverwritten;
|
||||||
|
this.isCulling = isCulling;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOverwritten: boolean;
|
||||||
|
public isCulling: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +82,18 @@ export class CubismModel {
|
||||||
this._model.drawables.resetDynamicFlags();
|
this._model.drawables.resetDynamicFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PixelsPerUnitを取得する
|
||||||
|
* @returns PixelsPerUnit
|
||||||
|
*/
|
||||||
|
public getPixelsPerUnit(): number {
|
||||||
|
if (this._model == null) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._model.canvasinfo.PixelsPerUnit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* キャンバスの幅を取得する
|
* キャンバスの幅を取得する
|
||||||
*/
|
*/
|
||||||
|
@ -183,6 +237,150 @@ export class CubismModel {
|
||||||
this._userScreenColors.at(index).Color.B = b;
|
this._userScreenColors.at(index).Color.B = b;
|
||||||
this._userScreenColors.at(index).Color.A = a;
|
this._userScreenColors.at(index).Color.A = a;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* partの乗算色を取得する
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @returns 指定したpartの乗算色
|
||||||
|
*/
|
||||||
|
public getPartMultiplyColor(partIndex: number): CubismTextureColor {
|
||||||
|
return this._userPartMultiplyColors.at(partIndex).Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* partのスクリーン色を取得する
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @returns 指定したpartのスクリーン色
|
||||||
|
*/
|
||||||
|
public getPartScreenColor(partIndex: number): CubismTextureColor {
|
||||||
|
return this._userPartScreenColors.at(partIndex).Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* partのOverwriteColor setter関数
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param r 設定する色のR値
|
||||||
|
* @param g 設定する色のG値
|
||||||
|
* @param b 設定する色のB値
|
||||||
|
* @param a 設定する色のA値
|
||||||
|
* @param partColors 設定するpartのカラーデータ配列
|
||||||
|
* @param drawableColors partに関連するDrawableのカラーデータ配列
|
||||||
|
*/
|
||||||
|
public setPartColor(
|
||||||
|
partIndex: number,
|
||||||
|
r: number,
|
||||||
|
g: number,
|
||||||
|
b: number,
|
||||||
|
a: number,
|
||||||
|
partColors: csmVector<PartColorData>,
|
||||||
|
drawableColors: csmVector<DrawableColorData>
|
||||||
|
) {
|
||||||
|
partColors.at(partIndex).Color.R = r;
|
||||||
|
partColors.at(partIndex).Color.G = g;
|
||||||
|
partColors.at(partIndex).Color.B = b;
|
||||||
|
partColors.at(partIndex).Color.A = a;
|
||||||
|
|
||||||
|
if (partColors.at(partIndex).isOverwritten) {
|
||||||
|
for (
|
||||||
|
let i = 0;
|
||||||
|
i < this._partChildDrawables.at(partIndex).getSize();
|
||||||
|
++i
|
||||||
|
) {
|
||||||
|
const drawableIndex = this._partChildDrawables.at(partIndex).at(i);
|
||||||
|
drawableColors.at(drawableIndex).Color.R = r;
|
||||||
|
drawableColors.at(drawableIndex).Color.G = g;
|
||||||
|
drawableColors.at(drawableIndex).Color.B = b;
|
||||||
|
drawableColors.at(drawableIndex).Color.A = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 乗算色をセットする
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param color 設定する乗算色(CubismTextureColor)
|
||||||
|
*/
|
||||||
|
public setPartMultiplyColorByTextureColor(
|
||||||
|
partIndex: number,
|
||||||
|
color: CubismTextureColor
|
||||||
|
) {
|
||||||
|
this.setPartMultiplyColorByRGBA(
|
||||||
|
partIndex,
|
||||||
|
color.R,
|
||||||
|
color.G,
|
||||||
|
color.B,
|
||||||
|
color.A
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 乗算色をセットする
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param r 設定する乗算色のR値
|
||||||
|
* @param g 設定する乗算色のG値
|
||||||
|
* @param b 設定する乗算色のB値
|
||||||
|
* @param a 設定する乗算色のA値
|
||||||
|
*/
|
||||||
|
public setPartMultiplyColorByRGBA(
|
||||||
|
partIndex: number,
|
||||||
|
r: number,
|
||||||
|
g: number,
|
||||||
|
b: number,
|
||||||
|
a: number
|
||||||
|
) {
|
||||||
|
this.setPartColor(
|
||||||
|
partIndex,
|
||||||
|
r,
|
||||||
|
g,
|
||||||
|
b,
|
||||||
|
a,
|
||||||
|
this._userPartMultiplyColors,
|
||||||
|
this._userMultiplyColors
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* スクリーン色をセットする
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param color 設定するスクリーン色(CubismTextureColor)
|
||||||
|
*/
|
||||||
|
public setPartScreenColorByTextureColor(
|
||||||
|
partIndex: number,
|
||||||
|
color: CubismTextureColor
|
||||||
|
) {
|
||||||
|
this.setPartScreenColorByRGBA(
|
||||||
|
partIndex,
|
||||||
|
color.R,
|
||||||
|
color.G,
|
||||||
|
color.B,
|
||||||
|
color.A
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* スクリーン色をセットする
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param r 設定するスクリーン色のR値
|
||||||
|
* @param g 設定するスクリーン色のG値
|
||||||
|
* @param b 設定するスクリーン色のB値
|
||||||
|
* @param a 設定するスクリーン色のA値
|
||||||
|
*/
|
||||||
|
public setPartScreenColorByRGBA(
|
||||||
|
partIndex: number,
|
||||||
|
r: number,
|
||||||
|
g: number,
|
||||||
|
b: number,
|
||||||
|
a: number
|
||||||
|
) {
|
||||||
|
this.setPartColor(
|
||||||
|
partIndex,
|
||||||
|
r,
|
||||||
|
g,
|
||||||
|
b,
|
||||||
|
a,
|
||||||
|
this._userPartScreenColors,
|
||||||
|
this._userScreenColors
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SDKから指定したモデルの乗算色を上書きするか
|
* SDKから指定したモデルの乗算色を上書きするか
|
||||||
|
@ -239,7 +437,7 @@ export class CubismModel {
|
||||||
public getOverwriteFlagForDrawableScreenColors(
|
public getOverwriteFlagForDrawableScreenColors(
|
||||||
drawableindex: number
|
drawableindex: number
|
||||||
): boolean {
|
): boolean {
|
||||||
return this._userMultiplyColors.at(drawableindex).isOverwritten;
|
return this._userScreenColors.at(drawableindex).isOverwritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -266,6 +464,188 @@ export class CubismModel {
|
||||||
this._userScreenColors.at(drawableindex).isOverwritten = value;
|
this._userScreenColors.at(drawableindex).isOverwritten = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDKからpartの乗算色を上書きするか
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @returns true -> SDKからの情報を優先する
|
||||||
|
* false -> モデルに設定されている色情報を使用
|
||||||
|
*/
|
||||||
|
public getOverwriteColorForPartMultiplyColors(partIndex: number) {
|
||||||
|
return this._userPartMultiplyColors.at(partIndex).isOverwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDKからpartのスクリーン色を上書きするか
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @returns true -> SDKからの情報を優先する
|
||||||
|
* false -> モデルに設定されている色情報を使用
|
||||||
|
*/
|
||||||
|
public getOverwriteColorForPartScreenColors(partIndex: number) {
|
||||||
|
return this._userPartScreenColors.at(partIndex).isOverwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* partのOverwriteFlag setter関数
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param value true -> SDKからの情報を優先する
|
||||||
|
* false -> モデルに設定されている色情報を使用
|
||||||
|
* @param partColors 設定するpartのカラーデータ配列
|
||||||
|
* @param drawableColors partに関連するDrawableのカラーデータ配列
|
||||||
|
*/
|
||||||
|
public setOverwriteColorForPartColors(
|
||||||
|
partIndex: number,
|
||||||
|
value: boolean,
|
||||||
|
partColors: csmVector<PartColorData>,
|
||||||
|
drawableColors: csmVector<DrawableColorData>
|
||||||
|
) {
|
||||||
|
partColors.at(partIndex).isOverwritten = value;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._partChildDrawables.at(partIndex).getSize(); ++i) {
|
||||||
|
const drawableIndex = this._partChildDrawables.at(partIndex).at(i);
|
||||||
|
drawableColors.at(drawableIndex).isOverwritten = value;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
drawableColors.at(drawableIndex).Color.R =
|
||||||
|
partColors.at(partIndex).Color.R;
|
||||||
|
drawableColors.at(drawableIndex).Color.G =
|
||||||
|
partColors.at(partIndex).Color.G;
|
||||||
|
drawableColors.at(drawableIndex).Color.B =
|
||||||
|
partColors.at(partIndex).Color.B;
|
||||||
|
drawableColors.at(drawableIndex).Color.A =
|
||||||
|
partColors.at(partIndex).Color.A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDKからpartのスクリーン色を上書きするかをセットする
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param value true -> SDKからの情報を優先する
|
||||||
|
* false -> モデルに設定されている色情報を使用
|
||||||
|
*/
|
||||||
|
public setOverwriteColorForPartMultiplyColors(
|
||||||
|
partIndex: number,
|
||||||
|
value: boolean
|
||||||
|
) {
|
||||||
|
this._userPartMultiplyColors.at(partIndex).isOverwritten = value;
|
||||||
|
this.setOverwriteColorForPartColors(
|
||||||
|
partIndex,
|
||||||
|
value,
|
||||||
|
this._userPartMultiplyColors,
|
||||||
|
this._userMultiplyColors
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDKからpartのスクリーン色を上書きするかをセットする
|
||||||
|
* @param partIndex partのインデックス
|
||||||
|
* @param value true -> SDKからの情報を優先する
|
||||||
|
* false -> モデルに設定されている色情報を使用
|
||||||
|
*/
|
||||||
|
public setOverwriteColorForPartScreenColors(
|
||||||
|
partIndex: number,
|
||||||
|
value: boolean
|
||||||
|
) {
|
||||||
|
this._userPartScreenColors.at(partIndex).isOverwritten = value;
|
||||||
|
this.setOverwriteColorForPartColors(
|
||||||
|
partIndex,
|
||||||
|
value,
|
||||||
|
this._userPartScreenColors,
|
||||||
|
this._userScreenColors
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drawableのカリング情報を取得する。
|
||||||
|
*
|
||||||
|
* @param drawableIndex Drawableのインデックス
|
||||||
|
* @return Drawableのカリング情報
|
||||||
|
*/
|
||||||
|
public getDrawableCulling(drawableIndex: number): boolean {
|
||||||
|
if (
|
||||||
|
this.getOverwriteFlagForModelCullings() ||
|
||||||
|
this.getOverwriteFlagForDrawableCullings(drawableIndex)
|
||||||
|
) {
|
||||||
|
return this._userCullings.at(drawableIndex).isCulling;
|
||||||
|
}
|
||||||
|
|
||||||
|
const constantFlags = this._model.drawables.constantFlags;
|
||||||
|
return !Live2DCubismCore.Utils.hasIsDoubleSidedBit(
|
||||||
|
constantFlags[drawableIndex]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drawableのカリング情報を設定する。
|
||||||
|
*
|
||||||
|
* @param drawableIndex Drawableのインデックス
|
||||||
|
* @param isCulling カリング情報
|
||||||
|
*/
|
||||||
|
public setDrawableCulling(drawableIndex: number, isCulling: boolean): void {
|
||||||
|
this._userCullings.at(drawableIndex).isCulling = isCulling;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDKからモデル全体のカリング設定を上書きするか。
|
||||||
|
*
|
||||||
|
* @retval true -> SDK上のカリング設定を使用
|
||||||
|
* @retval false -> モデルのカリング設定を使用
|
||||||
|
*/
|
||||||
|
public getOverwriteFlagForModelCullings(): boolean {
|
||||||
|
return this._isOverwrittenCullings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDKからモデル全体のカリング設定を上書きするかを設定する。
|
||||||
|
*
|
||||||
|
* @param isOverwrittenCullings SDK上のカリング設定を使うならtrue、モデルのカリング設定を使うならfalse
|
||||||
|
*/
|
||||||
|
public setOverwriteFlagForModelCullings(
|
||||||
|
isOverwrittenCullings: boolean
|
||||||
|
): void {
|
||||||
|
this._isOverwrittenCullings = isOverwrittenCullings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param drawableIndex Drawableのインデックス
|
||||||
|
* @retval true -> SDK上のカリング設定を使用
|
||||||
|
* @retval false -> モデルのカリング設定を使用
|
||||||
|
*/
|
||||||
|
public getOverwriteFlagForDrawableCullings(drawableIndex: number): boolean {
|
||||||
|
return this._userCullings.at(drawableIndex).isOverwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param drawableIndex Drawableのインデックス
|
||||||
|
* @param isOverwrittenCullings SDK上のカリング設定を使うならtrue、モデルのカリング設定を使うならfalse
|
||||||
|
*/
|
||||||
|
public setOverwriteFlagForDrawableCullings(
|
||||||
|
drawableIndex: number,
|
||||||
|
isOverwrittenCullings: boolean
|
||||||
|
): void {
|
||||||
|
this._userCullings.at(drawableIndex).isOverwritten = isOverwrittenCullings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* モデルの不透明度を取得する
|
||||||
|
*
|
||||||
|
* @returns 不透明度の値
|
||||||
|
*/
|
||||||
|
public getModelOapcity(): number {
|
||||||
|
return this._modelOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* モデルの不透明度を設定する
|
||||||
|
*
|
||||||
|
* @param value 不透明度の値
|
||||||
|
*/
|
||||||
|
public setModelOapcity(value: number) {
|
||||||
|
this._modelOpacity = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* モデルを取得
|
* モデルを取得
|
||||||
*/
|
*/
|
||||||
|
@ -301,6 +681,17 @@ export class CubismModel {
|
||||||
return partIndex;
|
return partIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* パーツのIDを取得する。
|
||||||
|
*
|
||||||
|
* @param partIndex 取得するパーツのインデックス
|
||||||
|
* @return パーツのID
|
||||||
|
*/
|
||||||
|
public getPartId(partIndex: number): CubismIdHandle {
|
||||||
|
const partId = this._model.parts.ids[partIndex];
|
||||||
|
return CubismFramework.getIdManager().getId(partId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* パーツの個数の取得
|
* パーツの個数の取得
|
||||||
* @return パーツの個数
|
* @return パーツの個数
|
||||||
|
@ -416,6 +807,18 @@ export class CubismModel {
|
||||||
return this._model.parameters.count;
|
return this._model.parameters.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* パラメータの種類の取得
|
||||||
|
* @param parameterIndex パラメータのインデックス
|
||||||
|
* @return csmParameterType_Normal -> 通常のパラメータ
|
||||||
|
* csmParameterType_BlendShape -> ブレンドシェイプパラメータ
|
||||||
|
*/
|
||||||
|
public getParameterType(
|
||||||
|
parameterIndex: number
|
||||||
|
): Live2DCubismCore.csmParameterType {
|
||||||
|
return this._model.parameters.types[parameterIndex];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* パラメータの最大値の取得
|
* パラメータの最大値の取得
|
||||||
* @param parameterIndex パラメータのインデックス
|
* @param parameterIndex パラメータのインデックス
|
||||||
|
@ -443,6 +846,18 @@ export class CubismModel {
|
||||||
return this._model.parameters.defaultValues[parameterIndex];
|
return this._model.parameters.defaultValues[parameterIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定したパラメータindexのIDを取得
|
||||||
|
*
|
||||||
|
* @param parameterIndex パラメータのインデックス
|
||||||
|
* @returns パラメータID
|
||||||
|
*/
|
||||||
|
public getParameterId(parameterIndex: number): CubismIdHandle {
|
||||||
|
return CubismFramework.getIdManager().getId(
|
||||||
|
this._model.parameters.ids[parameterIndex]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* パラメータの値の取得
|
* パラメータの値の取得
|
||||||
* @param parameterIndex パラメータのインデックス
|
* @param parameterIndex パラメータのインデックス
|
||||||
|
@ -646,11 +1061,23 @@ export class CubismModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* 関数名が誤っていたため、代替となる getDrawableTextureIndex を追加し、この関数は非推奨となりました。
|
||||||
|
*
|
||||||
* Drawableのテクスチャインデックスリストの取得
|
* Drawableのテクスチャインデックスリストの取得
|
||||||
* @param drawableIndex Drawableのインデックス
|
* @param drawableIndex Drawableのインデックス
|
||||||
* @return drawableのテクスチャインデックスリスト
|
* @return drawableのテクスチャインデックスリスト
|
||||||
*/
|
*/
|
||||||
public getDrawableTextureIndices(drawableIndex: number): number {
|
public getDrawableTextureIndices(drawableIndex: number): number {
|
||||||
|
return this.getDrawableTextureIndex(drawableIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drawableのテクスチャインデックスの取得
|
||||||
|
* @param drawableIndex Drawableのインデックス
|
||||||
|
* @return drawableのテクスチャインデックス
|
||||||
|
*/
|
||||||
|
public getDrawableTextureIndex(drawableIndex: number): number {
|
||||||
const textureIndices: Int32Array = this._model.drawables.textureIndices;
|
const textureIndices: Int32Array = this._model.drawables.textureIndices;
|
||||||
return textureIndices[drawableIndex];
|
return textureIndices[drawableIndex];
|
||||||
}
|
}
|
||||||
|
@ -704,7 +1131,7 @@ export class CubismModel {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drawableの頂点インデックスリストの取得
|
* Drawableの頂点インデックスリストの取得
|
||||||
* @param drarableIndex Drawableのインデックス
|
* @param drawableIndex Drawableのインデックス
|
||||||
* @return drawableの頂点インデックスリスト
|
* @return drawableの頂点インデックスリスト
|
||||||
*/
|
*/
|
||||||
public getDrawableVertexIndices(drawableIndex: number): Uint16Array {
|
public getDrawableVertexIndices(drawableIndex: number): Uint16Array {
|
||||||
|
@ -777,16 +1204,12 @@ export class CubismModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drawableのカリング情報の取得
|
* Drawableの親パーツのインデックスの取得
|
||||||
* @param drawableIndex Drawableのインデックス
|
* @param drawableIndex Drawableのインデックス
|
||||||
* @return drawableのカリング情報
|
* @return drawableの親パーツのインデックス
|
||||||
*/
|
*/
|
||||||
public getDrawableCulling(drawableIndex: number): boolean {
|
public getDrawableParentPartIndex(drawableIndex: number): number {
|
||||||
const constantFlags = this._model.drawables.constantFlags;
|
return this._model.drawables.parentPartIndices[drawableIndex];
|
||||||
|
|
||||||
return !Live2DCubismCore.Utils.hasIsDoubleSidedBit(
|
|
||||||
constantFlags[drawableIndex]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -982,9 +1405,9 @@ export class CubismModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const partCount: number = this._model.parts.count;
|
||||||
{
|
{
|
||||||
const partIds: string[] = this._model.parts.ids;
|
const partIds: string[] = this._model.parts.ids;
|
||||||
const partCount: number = this._model.parts.count;
|
|
||||||
|
|
||||||
this._partIds.prepareCapacity(partCount);
|
this._partIds.prepareCapacity(partCount);
|
||||||
for (let i = 0; i < partCount; ++i) {
|
for (let i = 0; i < partCount; ++i) {
|
||||||
|
@ -992,31 +1415,98 @@ export class CubismModel {
|
||||||
CubismFramework.getIdManager().getId(partIds[i])
|
CubismFramework.getIdManager().getId(partIds[i])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._userPartMultiplyColors.prepareCapacity(partCount);
|
||||||
|
this._userPartScreenColors.prepareCapacity(partCount);
|
||||||
|
|
||||||
|
this._partChildDrawables.prepareCapacity(partCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const drawableIds: string[] = this._model.drawables.ids;
|
const drawableIds: string[] = this._model.drawables.ids;
|
||||||
const drawableCount: number = this._model.drawables.count;
|
const drawableCount: number = this._model.drawables.count;
|
||||||
|
|
||||||
this._userMultiplyColors = new csmVector<DrawableColorData>();
|
this._userMultiplyColors.prepareCapacity(drawableCount);
|
||||||
this._userMultiplyColors.updateSize(
|
this._userScreenColors.prepareCapacity(drawableCount);
|
||||||
drawableCount,
|
|
||||||
DrawableColorData,
|
// カリング設定
|
||||||
true
|
this._userCullings.prepareCapacity(drawableCount);
|
||||||
|
const userCulling: DrawableCullingData = new DrawableCullingData(
|
||||||
|
false,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
this._userScreenColors = new csmVector<DrawableColorData>();
|
// Part
|
||||||
this._userScreenColors.updateSize(drawableCount, DrawableColorData, true);
|
{
|
||||||
|
for (let i = 0; i < partCount; ++i) {
|
||||||
|
const multiplyColor: CubismTextureColor = new CubismTextureColor(
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
const screenColor: CubismTextureColor = new CubismTextureColor(
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
|
||||||
this._drawableIds.prepareCapacity(drawableCount);
|
const userMultiplyColor: PartColorData = new PartColorData(
|
||||||
for (let i = 0; i < drawableCount; ++i) {
|
false,
|
||||||
this._drawableIds.pushBack(
|
multiplyColor
|
||||||
CubismFramework.getIdManager().getId(drawableIds[i])
|
);
|
||||||
);
|
const userScreenColor: PartColorData = new PartColorData(
|
||||||
|
false,
|
||||||
|
screenColor
|
||||||
|
);
|
||||||
|
|
||||||
// shaderに影響しない色で初期化
|
this._userPartMultiplyColors.pushBack(userMultiplyColor);
|
||||||
this.setMultiplyColorByRGBA(i, 1.0, 1.0, 1.0, 1.0);
|
this._userPartScreenColors.pushBack(userScreenColor);
|
||||||
this.setScreenColorByRGBA(i, 0.0, 0.0, 0.0, 1.0);
|
this._partChildDrawables.pushBack(new csmVector<number>());
|
||||||
|
this._partChildDrawables.at(i).prepareCapacity(drawableCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drawables
|
||||||
|
{
|
||||||
|
for (let i = 0; i < drawableCount; ++i) {
|
||||||
|
const multiplyColor: CubismTextureColor = new CubismTextureColor(
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
const screenColor: CubismTextureColor = new CubismTextureColor(
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
const userMultiplyColor: DrawableColorData = new DrawableColorData(
|
||||||
|
false,
|
||||||
|
multiplyColor
|
||||||
|
);
|
||||||
|
const userScreenColor: DrawableColorData = new DrawableColorData(
|
||||||
|
false,
|
||||||
|
screenColor
|
||||||
|
);
|
||||||
|
|
||||||
|
this._drawableIds.pushBack(
|
||||||
|
CubismFramework.getIdManager().getId(drawableIds[i])
|
||||||
|
);
|
||||||
|
|
||||||
|
this._userMultiplyColors.pushBack(userMultiplyColor);
|
||||||
|
this._userScreenColors.pushBack(userScreenColor);
|
||||||
|
|
||||||
|
this._userCullings.pushBack(userCulling);
|
||||||
|
|
||||||
|
const parentIndex = this.getDrawableParentPartIndex(i);
|
||||||
|
if (parentIndex >= 0) {
|
||||||
|
this._partChildDrawables.at(parentIndex).pushBack(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1037,8 +1527,15 @@ export class CubismModel {
|
||||||
this._partIds = new csmVector<CubismIdHandle>();
|
this._partIds = new csmVector<CubismIdHandle>();
|
||||||
this._isOverwrittenModelMultiplyColors = false;
|
this._isOverwrittenModelMultiplyColors = false;
|
||||||
this._isOverwrittenModelScreenColors = false;
|
this._isOverwrittenModelScreenColors = false;
|
||||||
this._userMultiplyColors = null;
|
this._isOverwrittenCullings = false;
|
||||||
this._userScreenColors = null;
|
this._modelOpacity = 1.0;
|
||||||
|
|
||||||
|
this._userMultiplyColors = new csmVector<DrawableColorData>();
|
||||||
|
this._userScreenColors = new csmVector<DrawableColorData>();
|
||||||
|
this._userCullings = new csmVector<DrawableCullingData>();
|
||||||
|
this._userPartMultiplyColors = new csmVector<PartColorData>();
|
||||||
|
this._userPartScreenColors = new csmVector<PartColorData>();
|
||||||
|
this._partChildDrawables = new csmVector<csmVector<number>>();
|
||||||
|
|
||||||
this._notExistPartId = new csmMap<CubismIdHandle, number>();
|
this._notExistPartId = new csmMap<CubismIdHandle, number>();
|
||||||
this._notExistParameterId = new csmMap<CubismIdHandle, number>();
|
this._notExistParameterId = new csmMap<CubismIdHandle, number>();
|
||||||
|
@ -1066,6 +1563,9 @@ export class CubismModel {
|
||||||
private _isOverwrittenModelScreenColors: boolean; // SDK上でモデル全体のスクリーン色を上書きするか判定するフラグ
|
private _isOverwrittenModelScreenColors: boolean; // SDK上でモデル全体のスクリーン色を上書きするか判定するフラグ
|
||||||
private _userMultiplyColors: csmVector<DrawableColorData>; // Drawableごとに設定する乗算色と上書きフラグを管理するリスト
|
private _userMultiplyColors: csmVector<DrawableColorData>; // Drawableごとに設定する乗算色と上書きフラグを管理するリスト
|
||||||
private _userScreenColors: csmVector<DrawableColorData>; // Drawableごとに設定するスクリーン色と上書きフラグを管理するリスト
|
private _userScreenColors: csmVector<DrawableColorData>; // Drawableごとに設定するスクリーン色と上書きフラグを管理するリスト
|
||||||
|
private _userPartScreenColors: csmVector<PartColorData>; // Part 乗算色の配列
|
||||||
|
private _userPartMultiplyColors: csmVector<PartColorData>; // Part スクリーン色の配列
|
||||||
|
private _partChildDrawables: csmVector<csmVector<number>>; // Partの子DrawableIndexの配列
|
||||||
|
|
||||||
private _model: Live2DCubismCore.Model; // モデル
|
private _model: Live2DCubismCore.Model; // モデル
|
||||||
|
|
||||||
|
@ -1075,9 +1575,14 @@ export class CubismModel {
|
||||||
|
|
||||||
private _partOpacities: Float32Array; // パーツの不透明度のリスト
|
private _partOpacities: Float32Array; // パーツの不透明度のリスト
|
||||||
|
|
||||||
|
private _modelOpacity: number; // モデルの不透明度
|
||||||
|
|
||||||
private _parameterIds: csmVector<CubismIdHandle>;
|
private _parameterIds: csmVector<CubismIdHandle>;
|
||||||
private _partIds: csmVector<CubismIdHandle>;
|
private _partIds: csmVector<CubismIdHandle>;
|
||||||
private _drawableIds: csmVector<CubismIdHandle>;
|
private _drawableIds: csmVector<CubismIdHandle>;
|
||||||
|
|
||||||
|
private _isOverwrittenCullings: boolean; // モデルのカリング設定をすべて上書きするか?
|
||||||
|
private _userCullings: csmVector<DrawableCullingData>; // カリング設定の配列
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { CubismModelMatrix } from '../math/cubismmodelmatrix';
|
||||||
import { CubismTargetPoint } from '../math/cubismtargetpoint';
|
import { CubismTargetPoint } from '../math/cubismtargetpoint';
|
||||||
import { ACubismMotion, FinishedMotionCallback } from '../motion/acubismmotion';
|
import { ACubismMotion, FinishedMotionCallback } from '../motion/acubismmotion';
|
||||||
import { CubismExpressionMotion } from '../motion/cubismexpressionmotion';
|
import { CubismExpressionMotion } from '../motion/cubismexpressionmotion';
|
||||||
|
import { CubismExpressionMotionManager } from '../motion/cubismexpressionmotionmanager';
|
||||||
import { CubismMotion } from '../motion/cubismmotion';
|
import { CubismMotion } from '../motion/cubismmotion';
|
||||||
import { CubismMotionManager } from '../motion/cubismmotionmanager';
|
import { CubismMotionManager } from '../motion/cubismmotionmanager';
|
||||||
import { CubismMotionQueueManager } from '../motion/cubismmotionqueuemanager';
|
import { CubismMotionQueueManager } from '../motion/cubismmotionqueuemanager';
|
||||||
|
@ -127,16 +128,22 @@ export class CubismUserModel {
|
||||||
*
|
*
|
||||||
* @param buffer moc3ファイルが読み込まれているバッファ
|
* @param buffer moc3ファイルが読み込まれているバッファ
|
||||||
*/
|
*/
|
||||||
public loadModel(buffer: ArrayBuffer) {
|
public loadModel(buffer: ArrayBuffer, shouldCheckMocConsistency = false) {
|
||||||
this._moc = CubismMoc.create(buffer);
|
this._moc = CubismMoc.create(buffer, shouldCheckMocConsistency);
|
||||||
this._model = this._moc.createModel();
|
|
||||||
this._model.saveParameters();
|
|
||||||
|
|
||||||
if (this._moc == null || this._model == null) {
|
if (this._moc == null) {
|
||||||
|
CubismLogError('Failed to CubismMoc.create().');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._model = this._moc.createModel();
|
||||||
|
|
||||||
|
if (this._model == null) {
|
||||||
CubismLogError('Failed to CreateModel().');
|
CubismLogError('Failed to CreateModel().');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._model.saveParameters();
|
||||||
this._modelMatrix = new CubismModelMatrix(
|
this._modelMatrix = new CubismModelMatrix(
|
||||||
this._model.getCanvasWidth(),
|
this._model.getCanvasWidth(),
|
||||||
this._model.getCanvasHeight()
|
this._model.getCanvasHeight()
|
||||||
|
@ -271,14 +278,15 @@ export class CubismUserModel {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* レンダラを作成して初期化を実行する
|
* レンダラを作成して初期化を実行する
|
||||||
|
* @param maskBufferCount バッファの生成数
|
||||||
*/
|
*/
|
||||||
public createRenderer(): void {
|
public createRenderer(maskBufferCount = 1): void {
|
||||||
if (this._renderer) {
|
if (this._renderer) {
|
||||||
this.deleteRenderer();
|
this.deleteRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._renderer = new CubismRenderer_WebGL();
|
this._renderer = new CubismRenderer_WebGL();
|
||||||
this._renderer.initialize(this._model);
|
this._renderer.initialize(this._model, maskBufferCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -352,6 +360,7 @@ export class CubismUserModel {
|
||||||
this._accelerationX = 0.0;
|
this._accelerationX = 0.0;
|
||||||
this._accelerationY = 0.0;
|
this._accelerationY = 0.0;
|
||||||
this._accelerationZ = 0.0;
|
this._accelerationZ = 0.0;
|
||||||
|
this._mocConsistency = false;
|
||||||
this._debugMode = false;
|
this._debugMode = false;
|
||||||
this._renderer = null;
|
this._renderer = null;
|
||||||
|
|
||||||
|
@ -363,7 +372,7 @@ export class CubismUserModel {
|
||||||
);
|
);
|
||||||
|
|
||||||
// 表情マネージャーを作成
|
// 表情マネージャーを作成
|
||||||
this._expressionManager = new CubismMotionManager();
|
this._expressionManager = new CubismExpressionMotionManager();
|
||||||
|
|
||||||
// ドラッグによるアニメーション
|
// ドラッグによるアニメーション
|
||||||
this._dragManager = new CubismTargetPoint();
|
this._dragManager = new CubismTargetPoint();
|
||||||
|
@ -407,7 +416,7 @@ export class CubismUserModel {
|
||||||
protected _model: CubismModel; // Modelインスタンス
|
protected _model: CubismModel; // Modelインスタンス
|
||||||
|
|
||||||
protected _motionManager: CubismMotionManager; // モーション管理
|
protected _motionManager: CubismMotionManager; // モーション管理
|
||||||
protected _expressionManager: CubismMotionManager; // 表情管理
|
protected _expressionManager: CubismExpressionMotionManager; // 表情管理
|
||||||
protected _eyeBlink: CubismEyeBlink; // 自動まばたき
|
protected _eyeBlink: CubismEyeBlink; // 自動まばたき
|
||||||
protected _breath: CubismBreath; // 呼吸
|
protected _breath: CubismBreath; // 呼吸
|
||||||
protected _modelMatrix: CubismModelMatrix; // モデル行列
|
protected _modelMatrix: CubismModelMatrix; // モデル行列
|
||||||
|
@ -426,6 +435,7 @@ export class CubismUserModel {
|
||||||
protected _accelerationX: number; // X軸方向の加速度
|
protected _accelerationX: number; // X軸方向の加速度
|
||||||
protected _accelerationY: number; // Y軸方向の加速度
|
protected _accelerationY: number; // Y軸方向の加速度
|
||||||
protected _accelerationZ: number; // Z軸方向の加速度
|
protected _accelerationZ: number; // Z軸方向の加速度
|
||||||
|
protected _mocConsistency: boolean; // MOC3一貫性検証するかどうか
|
||||||
protected _debugMode: boolean; // デバッグモードかどうか
|
protected _debugMode: boolean; // デバッグモードかどうか
|
||||||
|
|
||||||
private _renderer: CubismRenderer_WebGL; // レンダラ
|
private _renderer: CubismRenderer_WebGL; // レンダラ
|
||||||
|
|
|
@ -78,6 +78,38 @@ export abstract class ACubismMotion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fadeWeight = this.updateFadeWeight(motionQueueEntry, userTimeSeconds);
|
||||||
|
|
||||||
|
//---- 全てのパラメータIDをループする ----
|
||||||
|
this.doUpdateParameters(
|
||||||
|
model,
|
||||||
|
userTimeSeconds,
|
||||||
|
fadeWeight,
|
||||||
|
motionQueueEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
// 後処理
|
||||||
|
// 終了時刻を過ぎたら終了フラグを立てる(CubismMotionQueueManager)
|
||||||
|
if (
|
||||||
|
motionQueueEntry.getEndTime() > 0 &&
|
||||||
|
motionQueueEntry.getEndTime() < userTimeSeconds
|
||||||
|
) {
|
||||||
|
motionQueueEntry.setIsFinished(true); // 終了
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief モデルのウェイト更新
|
||||||
|
*
|
||||||
|
* モーションのウェイトを更新する。
|
||||||
|
*
|
||||||
|
* @param[in] motionQueueEntry CubismMotionQueueManagerで管理されているモーション
|
||||||
|
* @param[in] userTimeSeconds デルタ時間の積算値[秒]
|
||||||
|
*/
|
||||||
|
public updateFadeWeight(
|
||||||
|
motionQueueEntry: CubismMotionQueueEntry,
|
||||||
|
userTimeSeconds: number
|
||||||
|
): number {
|
||||||
let fadeWeight: number = this._weight; // 現在の値と掛け合わせる割合
|
let fadeWeight: number = this._weight; // 現在の値と掛け合わせる割合
|
||||||
|
|
||||||
//---- フェードイン・アウトの処理 ----
|
//---- フェードイン・アウトの処理 ----
|
||||||
|
@ -104,22 +136,7 @@ export abstract class ACubismMotion {
|
||||||
|
|
||||||
CSM_ASSERT(0.0 <= fadeWeight && fadeWeight <= 1.0);
|
CSM_ASSERT(0.0 <= fadeWeight && fadeWeight <= 1.0);
|
||||||
|
|
||||||
//---- 全てのパラメータIDをループする ----
|
return fadeWeight;
|
||||||
this.doUpdateParameters(
|
|
||||||
model,
|
|
||||||
userTimeSeconds,
|
|
||||||
fadeWeight,
|
|
||||||
motionQueueEntry
|
|
||||||
);
|
|
||||||
|
|
||||||
// 後処理
|
|
||||||
// 終了時刻を過ぎたら終了フラグを立てる(CubismMotionQueueManager)
|
|
||||||
if (
|
|
||||||
motionQueueEntry.getEndTime() > 0 &&
|
|
||||||
motionQueueEntry.getEndTime() < userTimeSeconds
|
|
||||||
) {
|
|
||||||
motionQueueEntry.setIsFinished(true); // 終了
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,6 +275,46 @@ export abstract class ACubismMotion {
|
||||||
*/
|
*/
|
||||||
public getFinishedMotionHandler = () => this._onFinishedMotion;
|
public getFinishedMotionHandler = () => this._onFinishedMotion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 透明度のカーブが存在するかどうかを確認する
|
||||||
|
*
|
||||||
|
* @returns true -> キーが存在する
|
||||||
|
* false -> キーが存在しない
|
||||||
|
*/
|
||||||
|
public isExistModelOpacity(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 透明度のカーブのインデックスを返す
|
||||||
|
*
|
||||||
|
* @returns success:透明度のカーブのインデックス
|
||||||
|
*/
|
||||||
|
public getModelOpacityIndex(): number {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 透明度のIdを返す
|
||||||
|
*
|
||||||
|
* @param index モーションカーブのインデックス
|
||||||
|
* @returns success:透明度のId
|
||||||
|
*/
|
||||||
|
public getModelOpacityId(index: number): CubismIdHandle {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定時間の透明度の値を返す
|
||||||
|
*
|
||||||
|
* @returns success:モーションの現在時間におけるOpacityの値
|
||||||
|
*
|
||||||
|
* @note 更新後の値を取るにはUpdateParameters() の後に呼び出す。
|
||||||
|
*/
|
||||||
|
protected getModelOpacityValue(): number {
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
public _fadeInSeconds: number; // フェードインにかかる時間[秒]
|
public _fadeInSeconds: number; // フェードインにかかる時間[秒]
|
||||||
public _fadeOutSeconds: number; // フェードアウトにかかる時間[秒]
|
public _fadeOutSeconds: number; // フェードアウトにかかる時間[秒]
|
||||||
public _weight: number; // モーションの重み
|
public _weight: number; // モーションの重み
|
||||||
|
@ -271,6 +328,7 @@ export abstract class ACubismMotion {
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
import * as $ from './acubismmotion';
|
import * as $ from './acubismmotion';
|
||||||
|
import { CubismIdHandle } from '../id/cubismid';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
export namespace Live2DCubismFramework {
|
export namespace Live2DCubismFramework {
|
||||||
export const ACubismMotion = $.ACubismMotion;
|
export const ACubismMotion = $.ACubismMotion;
|
||||||
|
|
|
@ -31,6 +31,9 @@ const DefaultFadeTime = 1.0;
|
||||||
* 表情のモーションクラス。
|
* 表情のモーションクラス。
|
||||||
*/
|
*/
|
||||||
export class CubismExpressionMotion extends ACubismMotion {
|
export class CubismExpressionMotion extends ACubismMotion {
|
||||||
|
static readonly DefaultAdditiveValue = 0.0; // 加算適用の初期値
|
||||||
|
static readonly DefaultMultiplyValue = 1.0; // 乗算適用の初期値
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* インスタンスを作成する。
|
* インスタンスを作成する。
|
||||||
* @param buffer expファイルが読み込まれているバッファ
|
* @param buffer expファイルが読み込まれているバッファ
|
||||||
|
@ -42,69 +45,7 @@ export class CubismExpressionMotion extends ACubismMotion {
|
||||||
size: number
|
size: number
|
||||||
): CubismExpressionMotion {
|
): CubismExpressionMotion {
|
||||||
const expression: CubismExpressionMotion = new CubismExpressionMotion();
|
const expression: CubismExpressionMotion = new CubismExpressionMotion();
|
||||||
|
expression.parse(buffer, size);
|
||||||
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;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +66,7 @@ export class CubismExpressionMotion extends ACubismMotion {
|
||||||
const parameter: ExpressionParameter = this._parameters.at(i);
|
const parameter: ExpressionParameter = this._parameters.at(i);
|
||||||
|
|
||||||
switch (parameter.blendType) {
|
switch (parameter.blendType) {
|
||||||
case ExpressionBlendType.ExpressionBlendType_Add: {
|
case ExpressionBlendType.Additive: {
|
||||||
model.addParameterValueById(
|
model.addParameterValueById(
|
||||||
parameter.parameterId,
|
parameter.parameterId,
|
||||||
parameter.value,
|
parameter.value,
|
||||||
|
@ -133,7 +74,7 @@ export class CubismExpressionMotion extends ACubismMotion {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExpressionBlendType.ExpressionBlendType_Multiply: {
|
case ExpressionBlendType.Multiply: {
|
||||||
model.multiplyParameterValueById(
|
model.multiplyParameterValueById(
|
||||||
parameter.parameterId,
|
parameter.parameterId,
|
||||||
parameter.value,
|
parameter.value,
|
||||||
|
@ -141,7 +82,7 @@ export class CubismExpressionMotion extends ACubismMotion {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExpressionBlendType.ExpressionBlendType_Overwrite: {
|
case ExpressionBlendType.Overwrite: {
|
||||||
model.setParameterValueById(
|
model.setParameterValueById(
|
||||||
parameter.parameterId,
|
parameter.parameterId,
|
||||||
parameter.value,
|
parameter.value,
|
||||||
|
@ -157,24 +98,261 @@ export class CubismExpressionMotion extends ACubismMotion {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* コンストラクタ
|
* @brief 表情によるモデルのパラメータの計算
|
||||||
|
*
|
||||||
|
* モデルの表情に関するパラメータを計算する。
|
||||||
|
*
|
||||||
|
* @param[in] model 対象のモデル
|
||||||
|
* @param[in] userTimeSeconds デルタ時間の積算値[秒]
|
||||||
|
* @param[in] motionQueueEntry CubismMotionQueueManagerで管理されているモーション
|
||||||
|
* @param[in] expressionParameterValues モデルに適用する各パラメータの値
|
||||||
|
* @param[in] expressionIndex 表情のインデックス
|
||||||
*/
|
*/
|
||||||
constructor() {
|
public calculateExpressionParameters(
|
||||||
super();
|
model: CubismModel,
|
||||||
|
userTimeSeconds: number,
|
||||||
|
motionQueueEntry: CubismMotionQueueEntry,
|
||||||
|
expressionParameterValues: csmVector<ExpressionParameterValue>,
|
||||||
|
expressionIndex: number
|
||||||
|
) {
|
||||||
|
if (!motionQueueEntry.isAvailable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this._parameters = new csmVector<ExpressionParameter>();
|
if (!motionQueueEntry.isStarted()) {
|
||||||
|
motionQueueEntry.setIsStarted(true);
|
||||||
|
motionQueueEntry.setStartTime(userTimeSeconds - this._offsetSeconds); // モーションの開始時刻を記録
|
||||||
|
motionQueueEntry.setFadeInStartTime(userTimeSeconds); // フェードインの開始時刻
|
||||||
|
|
||||||
|
const duration = this.getDuration();
|
||||||
|
|
||||||
|
if (motionQueueEntry.getEndTime() < 0.0) {
|
||||||
|
// 開始していないうちに終了設定している場合がある
|
||||||
|
motionQueueEntry.setEndTime(
|
||||||
|
duration <= 0.0 ? -1 : motionQueueEntry.getStartTime() + duration
|
||||||
|
);
|
||||||
|
// duration == -1 の場合はループする
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fadeWeight = this.updateFadeWeight(motionQueueEntry, userTimeSeconds);
|
||||||
|
|
||||||
|
// モデルに適用する値を計算
|
||||||
|
for (let i = 0; i < expressionParameterValues.getSize(); ++i) {
|
||||||
|
const expressionParameterValue = expressionParameterValues.at(i);
|
||||||
|
|
||||||
|
if (expressionParameterValue.parameterId == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentParameterValue = (expressionParameterValue.overwriteValue =
|
||||||
|
model.getParameterValueById(expressionParameterValue.parameterId));
|
||||||
|
|
||||||
|
const expressionParameters = this.getExpressionParameters();
|
||||||
|
let parameterIndex = -1;
|
||||||
|
for (let j = 0; j < expressionParameters.getSize(); ++j) {
|
||||||
|
if (
|
||||||
|
expressionParameterValue.parameterId !=
|
||||||
|
expressionParameters.at(j).parameterId
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
parameterIndex = j;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再生中のExpressionが参照していないパラメータは初期値を適用
|
||||||
|
if (parameterIndex < 0) {
|
||||||
|
if (expressionIndex == 0) {
|
||||||
|
expressionParameterValue.additiveValue =
|
||||||
|
CubismExpressionMotion.DefaultAdditiveValue;
|
||||||
|
expressionParameterValue.multiplyValue =
|
||||||
|
CubismExpressionMotion.DefaultMultiplyValue;
|
||||||
|
expressionParameterValue.overwriteValue = currentParameterValue;
|
||||||
|
} else {
|
||||||
|
expressionParameterValue.additiveValue = this.calculateValue(
|
||||||
|
expressionParameterValue.additiveValue,
|
||||||
|
CubismExpressionMotion.DefaultAdditiveValue
|
||||||
|
);
|
||||||
|
expressionParameterValue.multiplyValue = this.calculateValue(
|
||||||
|
expressionParameterValue.multiplyValue,
|
||||||
|
CubismExpressionMotion.DefaultMultiplyValue
|
||||||
|
);
|
||||||
|
expressionParameterValue.overwriteValue = this.calculateValue(
|
||||||
|
expressionParameterValue.overwriteValue,
|
||||||
|
currentParameterValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 値を計算
|
||||||
|
const value = expressionParameters.at(parameterIndex).value;
|
||||||
|
let newAdditiveValue, newMultiplyValue, newOverwriteValue;
|
||||||
|
switch (expressionParameters.at(parameterIndex).blendType) {
|
||||||
|
case ExpressionBlendType.Additive:
|
||||||
|
newAdditiveValue = value;
|
||||||
|
newMultiplyValue = CubismExpressionMotion.DefaultMultiplyValue;
|
||||||
|
newOverwriteValue = currentParameterValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExpressionBlendType.Multiply:
|
||||||
|
newAdditiveValue = CubismExpressionMotion.DefaultAdditiveValue;
|
||||||
|
newMultiplyValue = value;
|
||||||
|
newOverwriteValue = currentParameterValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExpressionBlendType.Overwrite:
|
||||||
|
newAdditiveValue = CubismExpressionMotion.DefaultAdditiveValue;
|
||||||
|
newMultiplyValue = CubismExpressionMotion.DefaultMultiplyValue;
|
||||||
|
newOverwriteValue = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expressionIndex == 0) {
|
||||||
|
expressionParameterValue.additiveValue = newAdditiveValue;
|
||||||
|
expressionParameterValue.multiplyValue = newMultiplyValue;
|
||||||
|
expressionParameterValue.overwriteValue = newOverwriteValue;
|
||||||
|
} else {
|
||||||
|
expressionParameterValue.additiveValue =
|
||||||
|
expressionParameterValue.additiveValue * (1.0 - this._fadeWeight) +
|
||||||
|
newAdditiveValue * this._fadeWeight;
|
||||||
|
expressionParameterValue.multiplyValue =
|
||||||
|
expressionParameterValue.multiplyValue * (1.0 - this._fadeWeight) +
|
||||||
|
newMultiplyValue * this._fadeWeight;
|
||||||
|
expressionParameterValue.overwriteValue =
|
||||||
|
expressionParameterValue.overwriteValue * (1.0 - this._fadeWeight) +
|
||||||
|
newOverwriteValue * this._fadeWeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_parameters: csmVector<ExpressionParameter>; // 表情のパラメータ情報リスト
|
/**
|
||||||
|
* @brief 表情が参照しているパラメータを取得
|
||||||
|
*
|
||||||
|
* 表情が参照しているパラメータを取得する
|
||||||
|
*
|
||||||
|
* @return 表情パラメータ
|
||||||
|
*/
|
||||||
|
public getExpressionParameters() {
|
||||||
|
return this._parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 表情のフェードの値を取得
|
||||||
|
*
|
||||||
|
* 現在の表情のフェードのウェイト値を取得する
|
||||||
|
*
|
||||||
|
* @returns 表情のフェードのウェイト値
|
||||||
|
*/
|
||||||
|
public getFadeWeight() {
|
||||||
|
return this._fadeWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected parse(buffer: ArrayBuffer, size: number) {
|
||||||
|
const json: CubismJson = CubismJson.create(buffer, size);
|
||||||
|
const root: Value = json.getRoot();
|
||||||
|
|
||||||
|
this.setFadeInTime(
|
||||||
|
root.getValueByString(ExpressionKeyFadeIn).toFloat(DefaultFadeTime)
|
||||||
|
); // フェードイン
|
||||||
|
this.setFadeOutTime(
|
||||||
|
root.getValueByString(ExpressionKeyFadeOut).toFloat(DefaultFadeTime)
|
||||||
|
); // フェードアウト
|
||||||
|
|
||||||
|
// 各パラメータについて
|
||||||
|
const parameterCount = root
|
||||||
|
.getValueByString(ExpressionKeyParameters)
|
||||||
|
.getSize();
|
||||||
|
this._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.Additive;
|
||||||
|
} else if (
|
||||||
|
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||||
|
BlendValueMultiply
|
||||||
|
) {
|
||||||
|
blendType = ExpressionBlendType.Multiply;
|
||||||
|
} else if (
|
||||||
|
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||||
|
BlendValueOverwrite
|
||||||
|
) {
|
||||||
|
blendType = ExpressionBlendType.Overwrite;
|
||||||
|
} else {
|
||||||
|
// その他 仕様にない値を設定した時は加算モードにすることで復旧
|
||||||
|
blendType = ExpressionBlendType.Additive;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 設定オブジェクトを作成してリストに追加する
|
||||||
|
const item: ExpressionParameter = new ExpressionParameter();
|
||||||
|
|
||||||
|
item.parameterId = parameterId;
|
||||||
|
item.blendType = blendType;
|
||||||
|
item.value = value;
|
||||||
|
|
||||||
|
this._parameters.pushBack(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
CubismJson.delete(json); // JSONデータは不要になったら削除する
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ブレンド計算
|
||||||
|
*
|
||||||
|
* 入力された値でブレンド計算をする。
|
||||||
|
*
|
||||||
|
* @param source 現在の値
|
||||||
|
* @param destination 適用する値
|
||||||
|
* @param weight ウェイト
|
||||||
|
* @returns 計算結果
|
||||||
|
*/
|
||||||
|
public calculateValue(source: number, destination: number): number {
|
||||||
|
return source * (1.0 - this._fadeWeight) + destination * this._fadeWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* コンストラクタ
|
||||||
|
*/
|
||||||
|
protected constructor() {
|
||||||
|
super();
|
||||||
|
this._parameters = new csmVector<ExpressionParameter>();
|
||||||
|
this._fadeWeight = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _parameters: csmVector<ExpressionParameter>; // 表情のパラメータ情報リスト
|
||||||
|
private _fadeWeight: number; // 表情の現在のウェイト
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表情パラメータ値の計算方式
|
* 表情パラメータ値の計算方式
|
||||||
*/
|
*/
|
||||||
export enum ExpressionBlendType {
|
export enum ExpressionBlendType {
|
||||||
ExpressionBlendType_Add = 0, // 加算
|
Additive = 0, // 加算
|
||||||
ExpressionBlendType_Multiply = 1, // 乗算
|
Multiply = 1, // 乗算
|
||||||
ExpressionBlendType_Overwrite = 2, // 上書き
|
Overwrite = 2 // 上書き
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,6 +366,8 @@ export class ExpressionParameter {
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
import * as $ from './cubismexpressionmotion';
|
import * as $ from './cubismexpressionmotion';
|
||||||
|
import { ExpressionParameterValue } from './cubismexpressionmotionmanager';
|
||||||
|
import { CubismDefaultParameterId } from '../cubismdefaultparameterid';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
export namespace Live2DCubismFramework {
|
export namespace Live2DCubismFramework {
|
||||||
export const CubismExpressionMotion = $.CubismExpressionMotion;
|
export const CubismExpressionMotion = $.CubismExpressionMotion;
|
||||||
|
|
|
@ -0,0 +1,267 @@
|
||||||
|
import { CubismId, CubismIdHandle } from '../id/cubismid';
|
||||||
|
import { csmDelete } from '../live2dcubismframework';
|
||||||
|
import { CubismModel } from '../model/cubismmodel';
|
||||||
|
import { csmVector, iterator } from '../type/csmvector';
|
||||||
|
import { ACubismMotion } from './acubismmotion';
|
||||||
|
import { CubismExpressionMotion } from './cubismexpressionmotion';
|
||||||
|
import { CubismMotionQueueEntry } from './cubismmotionqueueentry';
|
||||||
|
import {
|
||||||
|
CubismMotionQueueEntryHandle,
|
||||||
|
CubismMotionQueueManager
|
||||||
|
} from './cubismmotionqueuemanager';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief パラメータに適用する表情の値を持たせる構造体
|
||||||
|
*/
|
||||||
|
export class ExpressionParameterValue {
|
||||||
|
parameterId: CubismIdHandle; // パラメーターID
|
||||||
|
additiveValue: number; // 加算値
|
||||||
|
multiplyValue: number; // 乗算値
|
||||||
|
overwriteValue: number; // 上書き値
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 表情モーションの管理
|
||||||
|
*
|
||||||
|
* 表情モーションの管理をおこなうクラス。
|
||||||
|
*/
|
||||||
|
export class CubismExpressionMotionManager extends CubismMotionQueueManager {
|
||||||
|
/**
|
||||||
|
* コンストラクタ
|
||||||
|
*/
|
||||||
|
public constructor() {
|
||||||
|
super();
|
||||||
|
this._currentPriority = 0;
|
||||||
|
this._reservePriority = 0;
|
||||||
|
this._expressionParameterValues = new csmVector<ExpressionParameterValue>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* デストラクタ相当の処理
|
||||||
|
*/
|
||||||
|
public release(): void {
|
||||||
|
if (this._expressionParameterValues) {
|
||||||
|
csmDelete(this._expressionParameterValues);
|
||||||
|
this._expressionParameterValues = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 再生中のモーションの優先度の取得
|
||||||
|
*
|
||||||
|
* 再生中のモーションの優先度を取得する。
|
||||||
|
*
|
||||||
|
* @returns モーションの優先度
|
||||||
|
*/
|
||||||
|
public getCurrentPriority(): number {
|
||||||
|
return this._currentPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 予約中のモーションの優先度の取得
|
||||||
|
*
|
||||||
|
* 予約中のモーションの優先度を取得する。
|
||||||
|
*
|
||||||
|
* @return モーションの優先度
|
||||||
|
*/
|
||||||
|
public getReservePriority(): number {
|
||||||
|
return this._reservePriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 予約中のモーションの優先度の設定
|
||||||
|
*
|
||||||
|
* 予約中のモーションの優先度を設定する。
|
||||||
|
*
|
||||||
|
* @param[in] priority 優先度
|
||||||
|
*/
|
||||||
|
public setReservePriority(priority: number) {
|
||||||
|
this._reservePriority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 優先度を設定してモーションの開始
|
||||||
|
*
|
||||||
|
* 優先度を設定してモーションを開始する。
|
||||||
|
*
|
||||||
|
* @param[in] motion モーション
|
||||||
|
* @param[in] autoDelete 再生が終了したモーションのインスタンスを削除するならtrue
|
||||||
|
* @param[in] priority 優先度
|
||||||
|
* @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」
|
||||||
|
*/
|
||||||
|
public startMotionPriority(
|
||||||
|
motion: ACubismMotion,
|
||||||
|
autoDelete: boolean,
|
||||||
|
priority: number
|
||||||
|
): CubismMotionQueueEntryHandle {
|
||||||
|
if (priority == this.getReservePriority()) {
|
||||||
|
this.setReservePriority(0);
|
||||||
|
}
|
||||||
|
this._currentPriority = priority;
|
||||||
|
|
||||||
|
return this.startMotion(motion, autoDelete, this._userTimeSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief モーションの更新
|
||||||
|
*
|
||||||
|
* モーションを更新して、モデルにパラメータ値を反映する。
|
||||||
|
*
|
||||||
|
* @param[in] model 対象のモデル
|
||||||
|
* @param[in] deltaTimeSeconds デルタ時間[秒]
|
||||||
|
* @retval true 更新されている
|
||||||
|
* @retval false 更新されていない
|
||||||
|
*/
|
||||||
|
public updateMotion(model: CubismModel, deltaTimeSeconds: number): boolean {
|
||||||
|
this._userTimeSeconds += deltaTimeSeconds;
|
||||||
|
let updated = false;
|
||||||
|
const motions = this.getCubismMotionQueueEntries();
|
||||||
|
|
||||||
|
let expressionWeight = 0.0;
|
||||||
|
let expressionIndex = 0;
|
||||||
|
|
||||||
|
// ------- 処理を行う --------
|
||||||
|
// 既にモーションがあれば終了フラグを立てる
|
||||||
|
for (
|
||||||
|
let ite: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||||
|
ite.notEqual(this._motions.end());
|
||||||
|
|
||||||
|
) {
|
||||||
|
const motionQueueEntry = ite.ptr();
|
||||||
|
|
||||||
|
if (motionQueueEntry == null) {
|
||||||
|
ite = motions.erase(ite); //削除
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const expressionMotion = <CubismExpressionMotion>(
|
||||||
|
motionQueueEntry.getCubismMotion()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (expressionMotion == null) {
|
||||||
|
csmDelete(motionQueueEntry);
|
||||||
|
ite = motions.erase(ite); //削除
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const expressionParameters = expressionMotion.getExpressionParameters();
|
||||||
|
|
||||||
|
if (motionQueueEntry.isAvailable()) {
|
||||||
|
// 再生中のExpressionが参照しているパラメータをすべてリストアップ
|
||||||
|
for (let i = 0; i < expressionParameters.getSize(); ++i) {
|
||||||
|
if (expressionParameters.at(i).parameterId == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = -1;
|
||||||
|
// リストにパラメータIDが存在するか検索
|
||||||
|
for (let j = 0; j < this._expressionParameterValues.getSize(); ++j) {
|
||||||
|
if (
|
||||||
|
this._expressionParameterValues.at(j).parameterId !=
|
||||||
|
expressionParameters.at(i).parameterId
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// パラメータがリストに存在しないなら新規追加
|
||||||
|
const item: ExpressionParameterValue = new ExpressionParameterValue();
|
||||||
|
item.parameterId = expressionParameters.at(i).parameterId;
|
||||||
|
item.additiveValue = CubismExpressionMotion.DefaultAdditiveValue;
|
||||||
|
item.multiplyValue = CubismExpressionMotion.DefaultMultiplyValue;
|
||||||
|
item.overwriteValue = model.getParameterValueById(item.parameterId);
|
||||||
|
this._expressionParameterValues.pushBack(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------ 値を計算する ------
|
||||||
|
expressionMotion.calculateExpressionParameters(
|
||||||
|
model,
|
||||||
|
this._userTimeSeconds,
|
||||||
|
motionQueueEntry,
|
||||||
|
this._expressionParameterValues,
|
||||||
|
expressionIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
expressionWeight +=
|
||||||
|
expressionMotion.getFadeInTime() == 0.0
|
||||||
|
? 1.0
|
||||||
|
: CubismMath.getEasingSine(
|
||||||
|
(this._userTimeSeconds - motionQueueEntry.getFadeInStartTime()) /
|
||||||
|
expressionMotion.getFadeInTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
updated = true;
|
||||||
|
|
||||||
|
if (motionQueueEntry.isTriggeredFadeOut()) {
|
||||||
|
// フェードアウト開始
|
||||||
|
motionQueueEntry.startFadeOut(
|
||||||
|
motionQueueEntry.getFadeOutSeconds(),
|
||||||
|
this._userTimeSeconds
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ite.preIncrement();
|
||||||
|
++expressionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- 最新のExpressionのフェードが完了していればそれ以前を削除する ------
|
||||||
|
if (motions.getSize() > 1) {
|
||||||
|
const expressionMotion = <CubismExpressionMotion>(
|
||||||
|
motions.at(motions.getSize() - 1).getCubismMotion()
|
||||||
|
);
|
||||||
|
if (expressionMotion.getFadeWeight() >= 1.0) {
|
||||||
|
// 配列の最後の要素は削除しない
|
||||||
|
for (let i = motions.getSize() - 2; i >= 0; --i) {
|
||||||
|
const motionQueueEntry = motions.at(i);
|
||||||
|
csmDelete(motionQueueEntry);
|
||||||
|
motions.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expressionWeight > 1.0) {
|
||||||
|
expressionWeight = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// モデルに各値を適用
|
||||||
|
for (let i = 0; i < this._expressionParameterValues.getSize(); ++i) {
|
||||||
|
const expressionParameterValue = this._expressionParameterValues.at(i);
|
||||||
|
model.setParameterValueById(
|
||||||
|
expressionParameterValue.parameterId,
|
||||||
|
(expressionParameterValue.overwriteValue +
|
||||||
|
expressionParameterValue.additiveValue) *
|
||||||
|
expressionParameterValue.multiplyValue,
|
||||||
|
expressionWeight
|
||||||
|
);
|
||||||
|
|
||||||
|
expressionParameterValue.additiveValue =
|
||||||
|
CubismExpressionMotion.DefaultAdditiveValue;
|
||||||
|
expressionParameterValue.multiplyValue =
|
||||||
|
CubismExpressionMotion.DefaultMultiplyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _expressionParameterValues: csmVector<ExpressionParameterValue>; ///< モデルに適用する各パラメータの値
|
||||||
|
private _currentPriority: number; ///< 現在再生中のモーションの優先度
|
||||||
|
private _reservePriority: number; ///< 再生予定のモーションの優先度。再生中は0になる。モーションファイルを別スレッドで読み込むときの機能。
|
||||||
|
private _startExpressionTime: number; ///< 表情の再生開始時刻
|
||||||
|
}
|
||||||
|
|
||||||
|
// Namespace definition for compatibility.
|
||||||
|
import * as $ from './cubismexpressionmotionmanager';
|
||||||
|
import { CubismMath } from '../math/cubismmath';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
export namespace Live2DCubismFramework {
|
||||||
|
export const CubismExpressionMotionManager = $.CubismExpressionMotionManager;
|
||||||
|
export type CubismExpressionMotionManager = $.CubismExpressionMotionManager;
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ import { csmVector } from '../type/csmvector';
|
||||||
import {
|
import {
|
||||||
CSM_ASSERT,
|
CSM_ASSERT,
|
||||||
CubismLogDebug,
|
CubismLogDebug,
|
||||||
CubismLogWarning,
|
CubismLogWarning
|
||||||
} from '../utils/cubismdebug';
|
} from '../utils/cubismdebug';
|
||||||
import { ACubismMotion, FinishedMotionCallback } from './acubismmotion';
|
import { ACubismMotion, FinishedMotionCallback } from './acubismmotion';
|
||||||
import {
|
import {
|
||||||
|
@ -24,7 +24,7 @@ import {
|
||||||
CubismMotionEvent,
|
CubismMotionEvent,
|
||||||
CubismMotionPoint,
|
CubismMotionPoint,
|
||||||
CubismMotionSegment,
|
CubismMotionSegment,
|
||||||
CubismMotionSegmentType,
|
CubismMotionSegmentType
|
||||||
} from './cubismmotioninternal';
|
} from './cubismmotioninternal';
|
||||||
import { CubismMotionJson, EvaluationOptionFlag } from './cubismmotionjson';
|
import { CubismMotionJson, EvaluationOptionFlag } from './cubismmotionjson';
|
||||||
import { CubismMotionQueueEntry } from './cubismmotionqueueentry';
|
import { CubismMotionQueueEntry } from './cubismmotionqueueentry';
|
||||||
|
@ -35,6 +35,9 @@ const TargetNameModel = 'Model';
|
||||||
const TargetNameParameter = 'Parameter';
|
const TargetNameParameter = 'Parameter';
|
||||||
const TargetNamePartOpacity = 'PartOpacity';
|
const TargetNamePartOpacity = 'PartOpacity';
|
||||||
|
|
||||||
|
// Id
|
||||||
|
const IdNameOpacity = 'Opacity';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cubism SDK R2 以前のモーションを再現させるなら true 、アニメータのモーションを正しく再現するなら false 。
|
* Cubism SDK R2 以前のモーションを再現させるなら true 、アニメータのモーションを正しく再現するなら false 。
|
||||||
*/
|
*/
|
||||||
|
@ -209,7 +212,7 @@ function evaluateCurve(
|
||||||
// Get first point of next segment.
|
// Get first point of next segment.
|
||||||
pointPosition =
|
pointPosition =
|
||||||
motionData.segments.at(i).basePointIndex +
|
motionData.segments.at(i).basePointIndex +
|
||||||
(motionData.segments.at(i).segmentType ==
|
((motionData.segments.at(i).segmentType as CubismMotionSegmentType) ==
|
||||||
CubismMotionSegmentType.CubismMotionSegmentType_Bezier
|
CubismMotionSegmentType.CubismMotionSegmentType_Bezier
|
||||||
? 3
|
? 3
|
||||||
: 1);
|
: 1);
|
||||||
|
@ -284,6 +287,11 @@ export class CubismMotion extends ACubismMotion {
|
||||||
CubismFramework.getIdManager().getId(EffectNameLipSync);
|
CubismFramework.getIdManager().getId(EffectNameLipSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._modelCurveIdOpacity == null) {
|
||||||
|
this._modelCurveIdOpacity =
|
||||||
|
CubismFramework.getIdManager().getId(IdNameOpacity);
|
||||||
|
}
|
||||||
|
|
||||||
let timeOffsetSeconds: number =
|
let timeOffsetSeconds: number =
|
||||||
userTimeSeconds - motionQueueEntry.getStartTime();
|
userTimeSeconds - motionQueueEntry.getStartTime();
|
||||||
|
|
||||||
|
@ -357,6 +365,9 @@ export class CubismMotion extends ACubismMotion {
|
||||||
eyeBlinkValue = value;
|
eyeBlinkValue = value;
|
||||||
} else if (curves.at(c).id == this._modelCurveIdLipSync) {
|
} else if (curves.at(c).id == this._modelCurveIdLipSync) {
|
||||||
lipSyncValue = value;
|
lipSyncValue = value;
|
||||||
|
} else if (curves.at(c).id == this._modelCurveIdOpacity) {
|
||||||
|
this._modelOpacity = value;
|
||||||
|
model.setModelOapcity(this.getModelOpacityValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,8 +707,10 @@ export class CubismMotion extends ACubismMotion {
|
||||||
this._motionData = null;
|
this._motionData = null;
|
||||||
this._modelCurveIdEyeBlink = null;
|
this._modelCurveIdEyeBlink = null;
|
||||||
this._modelCurveIdLipSync = null;
|
this._modelCurveIdLipSync = null;
|
||||||
|
this._modelCurveIdOpacity = null;
|
||||||
this._eyeBlinkParameterIds = null;
|
this._eyeBlinkParameterIds = null;
|
||||||
this._lipSyncParameterIds = null;
|
this._lipSyncParameterIds = null;
|
||||||
|
this._modelOpacity = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -971,6 +984,81 @@ export class CubismMotion extends ACubismMotion {
|
||||||
return this._firedEventValues;
|
return this._firedEventValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 透明度のカーブが存在するかどうかを確認する
|
||||||
|
*
|
||||||
|
* @returns true -> キーが存在する
|
||||||
|
* false -> キーが存在しない
|
||||||
|
*/
|
||||||
|
public isExistModelOpacity(): boolean {
|
||||||
|
for (let i = 0; i < this._motionData.curveCount; i++) {
|
||||||
|
const curve: CubismMotionCurve = this._motionData.curves.at(i);
|
||||||
|
|
||||||
|
if (curve.type != CubismMotionCurveTarget.CubismMotionCurveTarget_Model) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curve.id.getString().s.localeCompare(IdNameOpacity) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 透明度のカーブのインデックスを返す
|
||||||
|
*
|
||||||
|
* @returns success:透明度のカーブのインデックス
|
||||||
|
*/
|
||||||
|
public getModelOpacityIndex(): number {
|
||||||
|
if (this.isExistModelOpacity()) {
|
||||||
|
for (let i = 0; i < this._motionData.curveCount; i++) {
|
||||||
|
const curve: CubismMotionCurve = this._motionData.curves.at(i);
|
||||||
|
|
||||||
|
if (
|
||||||
|
curve.type != CubismMotionCurveTarget.CubismMotionCurveTarget_Model
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curve.id.getString().s.localeCompare(IdNameOpacity) == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 透明度のIdを返す
|
||||||
|
*
|
||||||
|
* @param index モーションカーブのインデックス
|
||||||
|
* @returns success:透明度のカーブのインデックス
|
||||||
|
*/
|
||||||
|
public getModelOpacityId(index: number): CubismIdHandle {
|
||||||
|
if (index != -1) {
|
||||||
|
const curve: CubismMotionCurve = this._motionData.curves.at(index);
|
||||||
|
|
||||||
|
if (curve.type == CubismMotionCurveTarget.CubismMotionCurveTarget_Model) {
|
||||||
|
if (curve.id.getString().s.localeCompare(IdNameOpacity) == 0) {
|
||||||
|
return CubismFramework.getIdManager().getId(curve.id.getString().s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 現在時間の透明度の値を返す
|
||||||
|
*
|
||||||
|
* @returns success:モーションの当該時間におけるOpacityの値
|
||||||
|
*/
|
||||||
|
public getModelOpacityValue(): number {
|
||||||
|
return this._modelOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
public _sourceFrameRate: number; // ロードしたファイルのFPS。記述が無ければデフォルト値15fpsとなる
|
public _sourceFrameRate: number; // ロードしたファイルのFPS。記述が無ければデフォルト値15fpsとなる
|
||||||
public _loopDurationSeconds: number; // mtnファイルで定義される一連のモーションの長さ
|
public _loopDurationSeconds: number; // mtnファイルで定義される一連のモーションの長さ
|
||||||
public _isLoop: boolean; // ループするか?
|
public _isLoop: boolean; // ループするか?
|
||||||
|
@ -984,6 +1072,9 @@ export class CubismMotion extends ACubismMotion {
|
||||||
|
|
||||||
public _modelCurveIdEyeBlink: CubismIdHandle; // モデルが持つ自動まばたき用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
public _modelCurveIdEyeBlink: CubismIdHandle; // モデルが持つ自動まばたき用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
||||||
public _modelCurveIdLipSync: CubismIdHandle; // モデルが持つリップシンク用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
public _modelCurveIdLipSync: CubismIdHandle; // モデルが持つリップシンク用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
||||||
|
public _modelCurveIdOpacity: CubismIdHandle; // モデルが持つ不透明度用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
||||||
|
|
||||||
|
public _modelOpacity: number; // モーションから取得した不透明度
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { csmVector } from '../type/csmvector';
|
||||||
export enum CubismMotionCurveTarget {
|
export enum CubismMotionCurveTarget {
|
||||||
CubismMotionCurveTarget_Model, // モデルに対して
|
CubismMotionCurveTarget_Model, // モデルに対して
|
||||||
CubismMotionCurveTarget_Parameter, // パラメータに対して
|
CubismMotionCurveTarget_Parameter, // パラメータに対して
|
||||||
CubismMotionCurveTarget_PartOpacity, // パーツの不透明度に対して
|
CubismMotionCurveTarget_PartOpacity // パーツの不透明度に対して
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +29,7 @@ export enum CubismMotionSegmentType {
|
||||||
CubismMotionSegmentType_Linear = 0, // リニア
|
CubismMotionSegmentType_Linear = 0, // リニア
|
||||||
CubismMotionSegmentType_Bezier = 1, // ベジェ曲線
|
CubismMotionSegmentType_Bezier = 1, // ベジェ曲線
|
||||||
CubismMotionSegmentType_Stepped = 2, // ステップ
|
CubismMotionSegmentType_Stepped = 2, // ステップ
|
||||||
CubismMotionSegmentType_InverseStepped = 3, // インバースステップ
|
CubismMotionSegmentType_InverseStepped = 3 // インバースステップ
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import { CubismIdHandle } from '../id/cubismid';
|
import { CubismIdHandle } from '../id/cubismid';
|
||||||
import { CubismFramework } from '../live2dcubismframework';
|
import { CubismFramework } from '../live2dcubismframework';
|
||||||
import { csmString } from '../type/csmstring';
|
import { csmString } from '../type/csmstring';
|
||||||
import { CubismJson } from '../utils/cubismjson';
|
import { CubismJson, JsonMap } from '../utils/cubismjson';
|
||||||
|
|
||||||
// JSON keys
|
// JSON keys
|
||||||
const Meta = 'Meta';
|
const Meta = 'Meta';
|
||||||
|
@ -76,7 +76,7 @@ export class CubismMotionJson {
|
||||||
.toBoolean();
|
.toBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getEvaluationOptionFlag(flagType: number): boolean {
|
public getEvaluationOptionFlag(flagType: EvaluationOptionFlag): boolean {
|
||||||
if (
|
if (
|
||||||
EvaluationOptionFlag.EvaluationOptionFlag_AreBeziersRistricted == flagType
|
EvaluationOptionFlag.EvaluationOptionFlag_AreBeziersRistricted == flagType
|
||||||
) {
|
) {
|
||||||
|
@ -371,7 +371,7 @@ export class CubismMotionJson {
|
||||||
* @brief ベジェカーブの解釈方法のフラグタイプ
|
* @brief ベジェカーブの解釈方法のフラグタイプ
|
||||||
*/
|
*/
|
||||||
export enum EvaluationOptionFlag {
|
export enum EvaluationOptionFlag {
|
||||||
EvaluationOptionFlag_AreBeziersRistricted = 0, ///< ベジェハンドルの規制状態
|
EvaluationOptionFlag_AreBeziersRistricted = 0 ///< ベジェハンドルの規制状態
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { CubismModel } from '../model/cubismmodel';
|
||||||
import { ACubismMotion } from './acubismmotion';
|
import { ACubismMotion } from './acubismmotion';
|
||||||
import {
|
import {
|
||||||
CubismMotionQueueEntryHandle,
|
CubismMotionQueueEntryHandle,
|
||||||
CubismMotionQueueManager,
|
CubismMotionQueueManager
|
||||||
} from './cubismmotionqueuemanager';
|
} from './cubismmotionqueuemanager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -226,6 +226,15 @@ export class CubismMotionQueueEntry {
|
||||||
return this._fadeOutSeconds;
|
return this._fadeOutSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* モーションの取得
|
||||||
|
*
|
||||||
|
* @return モーション
|
||||||
|
*/
|
||||||
|
public getCubismMotion(): ACubismMotion {
|
||||||
|
return this._motion;
|
||||||
|
}
|
||||||
|
|
||||||
_autoDelete: boolean; // 自動削除
|
_autoDelete: boolean; // 自動削除
|
||||||
_motion: ACubismMotion; // モーション
|
_motion: ACubismMotion; // モーション
|
||||||
|
|
||||||
|
|
|
@ -184,12 +184,24 @@ export class CubismMotionQueueManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定したCubismMotionQueueEntryの取得
|
* @brief CubismMotionQueueEntryの配列の取得
|
||||||
|
*
|
||||||
|
* CubismMotionQueueEntryの配列を取得する。
|
||||||
|
*
|
||||||
|
* @return CubismMotionQueueEntryの配列へのポインタ
|
||||||
|
* @retval NULL 見つからなかった
|
||||||
|
*/
|
||||||
|
public getCubismMotionQueueEntries(): csmVector<CubismMotionQueueEntry> {
|
||||||
|
return this._motions;
|
||||||
|
}
|
||||||
|
|
||||||
* @param motionQueueEntryNumber モーションの識別番号
|
/**
|
||||||
* @return 指定したCubismMotionQueueEntry
|
* 指定したCubismMotionQueueEntryの取得
|
||||||
* @return null 見つからなかった
|
|
||||||
*/
|
* @param motionQueueEntryNumber モーションの識別番号
|
||||||
|
* @return 指定したCubismMotionQueueEntry
|
||||||
|
* @return null 見つからなかった
|
||||||
|
*/
|
||||||
public getCubismMotionQueueEntry(
|
public getCubismMotionQueueEntry(
|
||||||
motionQueueEntryNumber: any
|
motionQueueEntryNumber: any
|
||||||
): CubismMotionQueueEntry {
|
): CubismMotionQueueEntry {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import { CubismMath } from '../math/cubismmath';
|
import { CubismMath } from '../math/cubismmath';
|
||||||
import { CubismVector2 } from '../math/cubismvector2';
|
import { CubismVector2 } from '../math/cubismvector2';
|
||||||
|
import { csmVector } from '../type/csmvector';
|
||||||
import { CubismModel } from '../model/cubismmodel';
|
import { CubismModel } from '../model/cubismmodel';
|
||||||
import {
|
import {
|
||||||
CubismPhysicsInput,
|
CubismPhysicsInput,
|
||||||
|
@ -16,7 +17,7 @@ import {
|
||||||
CubismPhysicsRig,
|
CubismPhysicsRig,
|
||||||
CubismPhysicsSource,
|
CubismPhysicsSource,
|
||||||
CubismPhysicsSubRig,
|
CubismPhysicsSubRig,
|
||||||
CubismPhysicsTargetType,
|
CubismPhysicsTargetType
|
||||||
} from './cubismphysicsinternal';
|
} from './cubismphysicsinternal';
|
||||||
import { CubismPhysicsJson } from './cubismphysicsjson';
|
import { CubismPhysicsJson } from './cubismphysicsjson';
|
||||||
|
|
||||||
|
@ -34,6 +35,9 @@ const MaximumWeight = 100.0;
|
||||||
// Constant of threshold of movement.
|
// Constant of threshold of movement.
|
||||||
const MovementThreshold = 0.001;
|
const MovementThreshold = 0.001;
|
||||||
|
|
||||||
|
// Constant of maximum allowed delta time
|
||||||
|
const MaxDeltaTime = 5.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 物理演算クラス
|
* 物理演算クラス
|
||||||
*/
|
*/
|
||||||
|
@ -64,196 +68,6 @@ export class CubismPhysics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 物理演算の評価
|
|
||||||
* @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[i].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をパースする。
|
* physics3.jsonをパースする。
|
||||||
* @param physicsJson physics3.jsonが読み込まれているバッファ
|
* @param physicsJson physics3.jsonが読み込まれているバッファ
|
||||||
|
@ -268,6 +82,8 @@ export class CubismPhysics {
|
||||||
this._physicsRig.wind = json.getWind();
|
this._physicsRig.wind = json.getWind();
|
||||||
this._physicsRig.subRigCount = json.getSubRigCount();
|
this._physicsRig.subRigCount = json.getSubRigCount();
|
||||||
|
|
||||||
|
this._physicsRig.fps = json.getFps();
|
||||||
|
|
||||||
this._physicsRig.settings.updateSize(
|
this._physicsRig.settings.updateSize(
|
||||||
this._physicsRig.subRigCount,
|
this._physicsRig.subRigCount,
|
||||||
CubismPhysicsSubRig,
|
CubismPhysicsSubRig,
|
||||||
|
@ -289,6 +105,9 @@ export class CubismPhysics {
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this._currentRigOutputs.clear();
|
||||||
|
this._previousRigOutputs.clear();
|
||||||
|
|
||||||
let inputIndex = 0,
|
let inputIndex = 0,
|
||||||
outputIndex = 0,
|
outputIndex = 0,
|
||||||
particleIndex = 0;
|
particleIndex = 0;
|
||||||
|
@ -326,19 +145,22 @@ export class CubismPhysics {
|
||||||
CubismPhysicsSource.CubismPhysicsSource_X;
|
CubismPhysicsSource.CubismPhysicsSource_X;
|
||||||
this._physicsRig.inputs.at(
|
this._physicsRig.inputs.at(
|
||||||
inputIndex + j
|
inputIndex + j
|
||||||
).getNormalizedParameterValue = getInputTranslationXFromNormalizedParameterValue;
|
).getNormalizedParameterValue =
|
||||||
|
getInputTranslationXFromNormalizedParameterValue;
|
||||||
} else if (json.getInputType(i, j) == PhysicsTypeTagY) {
|
} else if (json.getInputType(i, j) == PhysicsTypeTagY) {
|
||||||
this._physicsRig.inputs.at(inputIndex + j).type =
|
this._physicsRig.inputs.at(inputIndex + j).type =
|
||||||
CubismPhysicsSource.CubismPhysicsSource_Y;
|
CubismPhysicsSource.CubismPhysicsSource_Y;
|
||||||
this._physicsRig.inputs.at(
|
this._physicsRig.inputs.at(
|
||||||
inputIndex + j
|
inputIndex + j
|
||||||
).getNormalizedParameterValue = getInputTranslationYFromNormalizedParamterValue;
|
).getNormalizedParameterValue =
|
||||||
|
getInputTranslationYFromNormalizedParamterValue;
|
||||||
} else if (json.getInputType(i, j) == PhysicsTypeTagAngle) {
|
} else if (json.getInputType(i, j) == PhysicsTypeTagAngle) {
|
||||||
this._physicsRig.inputs.at(inputIndex + j).type =
|
this._physicsRig.inputs.at(inputIndex + j).type =
|
||||||
CubismPhysicsSource.CubismPhysicsSource_Angle;
|
CubismPhysicsSource.CubismPhysicsSource_Angle;
|
||||||
this._physicsRig.inputs.at(
|
this._physicsRig.inputs.at(
|
||||||
inputIndex + j
|
inputIndex + j
|
||||||
).getNormalizedParameterValue = getInputAngleFromNormalizedParameterValue;
|
).getNormalizedParameterValue =
|
||||||
|
getInputAngleFromNormalizedParameterValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._physicsRig.inputs.at(inputIndex + j).source.targetType =
|
this._physicsRig.inputs.at(inputIndex + j).source.targetType =
|
||||||
|
@ -352,7 +174,21 @@ export class CubismPhysics {
|
||||||
this._physicsRig.settings.at(i).outputCount = json.getOutputCount(i);
|
this._physicsRig.settings.at(i).outputCount = json.getOutputCount(i);
|
||||||
this._physicsRig.settings.at(i).baseOutputIndex = outputIndex;
|
this._physicsRig.settings.at(i).baseOutputIndex = outputIndex;
|
||||||
|
|
||||||
|
const currentRigOutput = new PhysicsOutput();
|
||||||
|
currentRigOutput.outputs.resize(
|
||||||
|
this._physicsRig.settings.at(i).outputCount
|
||||||
|
);
|
||||||
|
|
||||||
|
const previousRigOutput = new PhysicsOutput();
|
||||||
|
previousRigOutput.outputs.resize(
|
||||||
|
this._physicsRig.settings.at(i).outputCount
|
||||||
|
);
|
||||||
|
|
||||||
for (let j = 0; j < this._physicsRig.settings.at(i).outputCount; ++j) {
|
for (let j = 0; j < this._physicsRig.settings.at(i).outputCount; ++j) {
|
||||||
|
// initialize
|
||||||
|
currentRigOutput.outputs.set(j, 0.0);
|
||||||
|
previousRigOutput.outputs.set(j, 0.0);
|
||||||
|
|
||||||
this._physicsRig.outputs.at(outputIndex + j).destinationParameterIndex =
|
this._physicsRig.outputs.at(outputIndex + j).destinationParameterIndex =
|
||||||
-1;
|
-1;
|
||||||
this._physicsRig.outputs.at(outputIndex + j).vertexIndex =
|
this._physicsRig.outputs.at(outputIndex + j).vertexIndex =
|
||||||
|
@ -393,6 +229,10 @@ export class CubismPhysics {
|
||||||
this._physicsRig.outputs.at(outputIndex + j).reflect =
|
this._physicsRig.outputs.at(outputIndex + j).reflect =
|
||||||
json.getOutputReflect(i, j);
|
json.getOutputReflect(i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._currentRigOutputs.pushBack(currentRigOutput);
|
||||||
|
this._previousRigOutputs.pushBack(previousRigOutput);
|
||||||
|
|
||||||
outputIndex += this._physicsRig.settings.at(i).outputCount;
|
outputIndex += this._physicsRig.settings.at(i).outputCount;
|
||||||
|
|
||||||
// Particle
|
// Particle
|
||||||
|
@ -422,6 +262,541 @@ export class CubismPhysics {
|
||||||
json = null;
|
json = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 現在のパラメータ値で物理演算が安定化する状態を演算する。
|
||||||
|
* @param model 物理演算の結果を適用するモデル
|
||||||
|
*/
|
||||||
|
public stabilization(model: CubismModel): void {
|
||||||
|
let totalAngle: { angle: number };
|
||||||
|
let weight: number;
|
||||||
|
let radAngle: number;
|
||||||
|
let outputValue: number;
|
||||||
|
const totalTranslation: CubismVector2 = new CubismVector2();
|
||||||
|
let currentSetting: CubismPhysicsSubRig;
|
||||||
|
let currentInputs: CubismPhysicsInput[];
|
||||||
|
let currentOutputs: CubismPhysicsOutput[];
|
||||||
|
let currentParticles: CubismPhysicsParticle[];
|
||||||
|
|
||||||
|
let parameterValues: Float32Array;
|
||||||
|
let parameterMaximumValues: Float32Array;
|
||||||
|
let parameterMinimumValues: Float32Array;
|
||||||
|
let parameterDefaultValues: Float32Array;
|
||||||
|
|
||||||
|
parameterValues = model.getModel().parameters.values;
|
||||||
|
parameterMaximumValues = model.getModel().parameters.maximumValues;
|
||||||
|
parameterMinimumValues = model.getModel().parameters.minimumValues;
|
||||||
|
parameterDefaultValues = model.getModel().parameters.defaultValues;
|
||||||
|
|
||||||
|
if ((this._parameterCaches?.length ?? 0) < model.getParameterCount()) {
|
||||||
|
this._parameterCaches = new Float32Array(model.getParameterCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this._parameterInputCaches?.length ?? 0) < model.getParameterCount()) {
|
||||||
|
this._parameterInputCaches = new Float32Array(model.getParameterCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < model.getParameterCount(); ++j) {
|
||||||
|
this._parameterCaches[j] = parameterValues[j];
|
||||||
|
this._parameterInputCaches[j] = parameterValues[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
currentInputs = this._physicsRig.inputs.get(
|
||||||
|
currentSetting.baseInputIndex
|
||||||
|
);
|
||||||
|
currentOutputs = 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 = currentInputs[i].weight / MaximumWeight;
|
||||||
|
|
||||||
|
if (currentInputs[i].sourceParameterIndex == -1) {
|
||||||
|
currentInputs[i].sourceParameterIndex = model.getParameterIndex(
|
||||||
|
currentInputs[i].source.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentInputs[i].getNormalizedParameterValue(
|
||||||
|
totalTranslation,
|
||||||
|
totalAngle,
|
||||||
|
parameterValues[currentInputs[i].sourceParameterIndex],
|
||||||
|
parameterMinimumValues[currentInputs[i].sourceParameterIndex],
|
||||||
|
parameterMaximumValues[currentInputs[i].sourceParameterIndex],
|
||||||
|
parameterDefaultValues[currentInputs[i].sourceParameterIndex],
|
||||||
|
currentSetting.normalizationPosition,
|
||||||
|
currentSetting.normalizationAngle,
|
||||||
|
currentInputs[i].reflect,
|
||||||
|
weight
|
||||||
|
);
|
||||||
|
|
||||||
|
this._parameterCaches[currentInputs[i].sourceParameterIndex] =
|
||||||
|
parameterValues[currentInputs[i].sourceParameterIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
updateParticlesForStabilization(
|
||||||
|
currentParticles,
|
||||||
|
currentSetting.particleCount,
|
||||||
|
totalTranslation,
|
||||||
|
totalAngle.angle,
|
||||||
|
this._options.wind,
|
||||||
|
MovementThreshold * currentSetting.normalizationPosition.maximum
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update output parameters.
|
||||||
|
for (let i = 0; i < currentSetting.outputCount; ++i) {
|
||||||
|
const particleIndex = currentOutputs[i].vertexIndex;
|
||||||
|
|
||||||
|
if (currentOutputs[i].destinationParameterIndex == -1) {
|
||||||
|
currentOutputs[i].destinationParameterIndex = model.getParameterIndex(
|
||||||
|
currentOutputs[i].destination.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
particleIndex < 1 ||
|
||||||
|
particleIndex >= currentSetting.particleCount
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let translation: CubismVector2 = new CubismVector2();
|
||||||
|
translation = currentParticles[particleIndex].position.substract(
|
||||||
|
currentParticles[particleIndex - 1].position
|
||||||
|
);
|
||||||
|
|
||||||
|
outputValue = currentOutputs[i].getValue(
|
||||||
|
translation,
|
||||||
|
currentParticles,
|
||||||
|
particleIndex,
|
||||||
|
currentOutputs[i].reflect,
|
||||||
|
this._options.gravity
|
||||||
|
);
|
||||||
|
|
||||||
|
this._currentRigOutputs.at(settingIndex).outputs.set(i, outputValue);
|
||||||
|
this._previousRigOutputs.at(settingIndex).outputs.set(i, outputValue);
|
||||||
|
|
||||||
|
const destinationParameterIndex: number =
|
||||||
|
currentOutputs[i].destinationParameterIndex;
|
||||||
|
|
||||||
|
const outParameterCaches: Float32Array =
|
||||||
|
!Float32Array.prototype.slice && 'subarray' in Float32Array.prototype
|
||||||
|
? JSON.parse(
|
||||||
|
JSON.stringify(
|
||||||
|
parameterValues.subarray(destinationParameterIndex)
|
||||||
|
)
|
||||||
|
) // 値渡しするため、JSON.parse, JSON.stringify
|
||||||
|
: parameterValues.slice(destinationParameterIndex);
|
||||||
|
|
||||||
|
updateOutputParameterValue(
|
||||||
|
outParameterCaches,
|
||||||
|
parameterMinimumValues[destinationParameterIndex],
|
||||||
|
parameterMaximumValues[destinationParameterIndex],
|
||||||
|
outputValue,
|
||||||
|
currentOutputs[i]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 値を反映
|
||||||
|
for (
|
||||||
|
let offset: number = destinationParameterIndex, outParamIndex = 0;
|
||||||
|
offset < this._parameterCaches.length;
|
||||||
|
offset++, outParamIndex++
|
||||||
|
) {
|
||||||
|
parameterValues[offset] = this._parameterCaches[offset] =
|
||||||
|
outParameterCaches[outParamIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物理演算の評価
|
||||||
|
*
|
||||||
|
* Pendulum interpolation weights
|
||||||
|
*
|
||||||
|
* 振り子の計算結果は保存され、パラメータへの出力は保存された前回の結果で補間されます。
|
||||||
|
* The result of the pendulum calculation is saved and
|
||||||
|
* the output to the parameters is interpolated with the saved previous result of the pendulum calculation.
|
||||||
|
*
|
||||||
|
* 図で示すと[1]と[2]で補間されます。
|
||||||
|
* The figure shows the interpolation between [1] and [2].
|
||||||
|
*
|
||||||
|
* 補間の重みは最新の振り子計算タイミングと次回のタイミングの間で見た現在時間で決定する。
|
||||||
|
* The weight of the interpolation are determined by the current time seen between
|
||||||
|
* the latest pendulum calculation timing and the next timing.
|
||||||
|
*
|
||||||
|
* 図で示すと[2]と[4]の間でみた(3)の位置の重みになる。
|
||||||
|
* Figure shows the weight of position (3) as seen between [2] and [4].
|
||||||
|
*
|
||||||
|
* 解釈として振り子計算のタイミングと重み計算のタイミングがズレる。
|
||||||
|
* As an interpretation, the pendulum calculation and weights are misaligned.
|
||||||
|
*
|
||||||
|
* physics3.jsonにFPS情報が存在しない場合は常に前の振り子状態で設定される。
|
||||||
|
* If there is no FPS information in physics3.json, it is always set in the previous pendulum state.
|
||||||
|
*
|
||||||
|
* この仕様は補間範囲を逸脱したことが原因の震えたような見た目を回避を目的にしている。
|
||||||
|
* The purpose of this specification is to avoid the quivering appearance caused by deviations from the interpolation range.
|
||||||
|
*
|
||||||
|
* ------------ time -------------->
|
||||||
|
*
|
||||||
|
* |+++++|------| <- weight
|
||||||
|
* ==[1]====#=====[2]---(3)----(4)
|
||||||
|
* ^ output contents
|
||||||
|
*
|
||||||
|
* 1:_previousRigOutputs
|
||||||
|
* 2:_currentRigOutputs
|
||||||
|
* 3:_currentRemainTime (now rendering)
|
||||||
|
* 4:next particles timing
|
||||||
|
* @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 currentInputs: CubismPhysicsInput[];
|
||||||
|
let currentOutputs: CubismPhysicsOutput[];
|
||||||
|
let currentParticles: CubismPhysicsParticle[];
|
||||||
|
|
||||||
|
if (0.0 >= deltaTimeSeconds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parameterValues: Float32Array;
|
||||||
|
let parameterMaximumValues: Float32Array;
|
||||||
|
let parameterMinimumValues: Float32Array;
|
||||||
|
let parameterDefaultValues: Float32Array;
|
||||||
|
|
||||||
|
let physicsDeltaTime: number;
|
||||||
|
this._currentRemainTime += deltaTimeSeconds;
|
||||||
|
if (this._currentRemainTime > MaxDeltaTime) {
|
||||||
|
this._currentRemainTime = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
parameterValues = model.getModel().parameters.values;
|
||||||
|
parameterMaximumValues = model.getModel().parameters.maximumValues;
|
||||||
|
parameterMinimumValues = model.getModel().parameters.minimumValues;
|
||||||
|
parameterDefaultValues = model.getModel().parameters.defaultValues;
|
||||||
|
|
||||||
|
if ((this._parameterCaches?.length ?? 0) < model.getParameterCount()) {
|
||||||
|
this._parameterCaches = new Float32Array(model.getParameterCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this._parameterInputCaches?.length ?? 0) < model.getParameterCount()) {
|
||||||
|
this._parameterInputCaches = new Float32Array(model.getParameterCount());
|
||||||
|
for (let j = 0; j < model.getParameterCount(); ++j) {
|
||||||
|
this._parameterInputCaches[j] = parameterValues[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._physicsRig.fps > 0.0) {
|
||||||
|
physicsDeltaTime = 1.0 / this._physicsRig.fps;
|
||||||
|
} else {
|
||||||
|
physicsDeltaTime = deltaTimeSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (this._currentRemainTime >= physicsDeltaTime) {
|
||||||
|
// copyRigOutputs _currentRigOutputs to _previousRigOutputs
|
||||||
|
for (
|
||||||
|
let settingIndex = 0;
|
||||||
|
settingIndex < this._physicsRig.subRigCount;
|
||||||
|
++settingIndex
|
||||||
|
) {
|
||||||
|
currentSetting = this._physicsRig.settings.at(settingIndex);
|
||||||
|
currentOutputs = this._physicsRig.outputs.get(
|
||||||
|
currentSetting.baseOutputIndex
|
||||||
|
);
|
||||||
|
for (let i = 0; i < currentSetting.outputCount; ++i) {
|
||||||
|
this._previousRigOutputs
|
||||||
|
.at(settingIndex)
|
||||||
|
.outputs.set(
|
||||||
|
i,
|
||||||
|
this._currentRigOutputs.at(settingIndex).outputs.at(i)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 入力キャッシュとパラメータで線形補間してUpdateParticlesするタイミングでの入力を計算する。
|
||||||
|
// Calculate the input at the timing to UpdateParticles by linear interpolation with the _parameterInputCache and parameterValue.
|
||||||
|
// _parameterCacheはグループ間での値の伝搬の役割があるので_parameterInputCacheとの分離が必要。
|
||||||
|
// _parameterCache needs to be separated from _parameterInputCache because of its role in propagating values between groups.
|
||||||
|
const inputWeight = physicsDeltaTime / this._currentRemainTime;
|
||||||
|
for (let j = 0; j < model.getParameterCount(); ++j) {
|
||||||
|
this._parameterCaches[j] =
|
||||||
|
this._parameterInputCaches[j] * (1.0 - inputWeight) +
|
||||||
|
parameterValues[j] * inputWeight;
|
||||||
|
this._parameterInputCaches[j] = this._parameterCaches[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
currentInputs = this._physicsRig.inputs.get(
|
||||||
|
currentSetting.baseInputIndex
|
||||||
|
);
|
||||||
|
currentOutputs = 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 = currentInputs[i].weight / MaximumWeight;
|
||||||
|
|
||||||
|
if (currentInputs[i].sourceParameterIndex == -1) {
|
||||||
|
currentInputs[i].sourceParameterIndex = model.getParameterIndex(
|
||||||
|
currentInputs[i].source.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentInputs[i].getNormalizedParameterValue(
|
||||||
|
totalTranslation,
|
||||||
|
totalAngle,
|
||||||
|
this._parameterCaches[currentInputs[i].sourceParameterIndex],
|
||||||
|
parameterMinimumValues[currentInputs[i].sourceParameterIndex],
|
||||||
|
parameterMaximumValues[currentInputs[i].sourceParameterIndex],
|
||||||
|
parameterDefaultValues[currentInputs[i].sourceParameterIndex],
|
||||||
|
currentSetting.normalizationPosition,
|
||||||
|
currentSetting.normalizationAngle,
|
||||||
|
currentInputs[i].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,
|
||||||
|
physicsDeltaTime,
|
||||||
|
AirResistance
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update output parameters.
|
||||||
|
for (let i = 0; i < currentSetting.outputCount; ++i) {
|
||||||
|
const particleIndex = currentOutputs[i].vertexIndex;
|
||||||
|
|
||||||
|
if (currentOutputs[i].destinationParameterIndex == -1) {
|
||||||
|
currentOutputs[i].destinationParameterIndex =
|
||||||
|
model.getParameterIndex(currentOutputs[i].destination.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
particleIndex < 1 ||
|
||||||
|
particleIndex >= currentSetting.particleCount
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = currentOutputs[i].getValue(
|
||||||
|
translation,
|
||||||
|
currentParticles,
|
||||||
|
particleIndex,
|
||||||
|
currentOutputs[i].reflect,
|
||||||
|
this._options.gravity
|
||||||
|
);
|
||||||
|
|
||||||
|
this._currentRigOutputs.at(settingIndex).outputs.set(i, outputValue);
|
||||||
|
|
||||||
|
const destinationParameterIndex: number =
|
||||||
|
currentOutputs[i].destinationParameterIndex;
|
||||||
|
const outParameterCaches: Float32Array =
|
||||||
|
!Float32Array.prototype.slice &&
|
||||||
|
'subarray' in Float32Array.prototype
|
||||||
|
? JSON.parse(
|
||||||
|
JSON.stringify(
|
||||||
|
this._parameterCaches.subarray(destinationParameterIndex)
|
||||||
|
)
|
||||||
|
) // 値渡しするため、JSON.parse, JSON.stringify
|
||||||
|
: this._parameterCaches.slice(destinationParameterIndex);
|
||||||
|
|
||||||
|
updateOutputParameterValue(
|
||||||
|
outParameterCaches,
|
||||||
|
parameterMinimumValues[destinationParameterIndex],
|
||||||
|
parameterMaximumValues[destinationParameterIndex],
|
||||||
|
outputValue,
|
||||||
|
currentOutputs[i]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 値を反映
|
||||||
|
for (
|
||||||
|
let offset: number = destinationParameterIndex, outParamIndex = 0;
|
||||||
|
offset < this._parameterCaches.length;
|
||||||
|
offset++, outParamIndex++
|
||||||
|
) {
|
||||||
|
this._parameterCaches[offset] = outParameterCaches[outParamIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._currentRemainTime -= physicsDeltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const alpha: number = this._currentRemainTime / physicsDeltaTime;
|
||||||
|
this.interpolate(model, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物理演算結果の適用
|
||||||
|
* 振り子演算の最新の結果と一つ前の結果から指定した重みで適用する。
|
||||||
|
* @param model 物理演算の結果を適用するモデル
|
||||||
|
* @param weight 最新結果の重み
|
||||||
|
*/
|
||||||
|
public interpolate(model: CubismModel, weight: number): void {
|
||||||
|
let currentOutputs: CubismPhysicsOutput[];
|
||||||
|
let currentSetting: CubismPhysicsSubRig;
|
||||||
|
let parameterValues: Float32Array;
|
||||||
|
let parameterMaximumValues: Float32Array;
|
||||||
|
let parameterMinimumValues: Float32Array;
|
||||||
|
|
||||||
|
parameterValues = model.getModel().parameters.values;
|
||||||
|
parameterMaximumValues = model.getModel().parameters.maximumValues;
|
||||||
|
parameterMinimumValues = model.getModel().parameters.minimumValues;
|
||||||
|
|
||||||
|
for (
|
||||||
|
let settingIndex = 0;
|
||||||
|
settingIndex < this._physicsRig.subRigCount;
|
||||||
|
++settingIndex
|
||||||
|
) {
|
||||||
|
currentSetting = this._physicsRig.settings.at(settingIndex);
|
||||||
|
currentOutputs = this._physicsRig.outputs.get(
|
||||||
|
currentSetting.baseOutputIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load input parameters.
|
||||||
|
for (let i = 0; i < currentSetting.outputCount; ++i) {
|
||||||
|
if (currentOutputs[i].destinationParameterIndex == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const destinationParameterIndex: number =
|
||||||
|
currentOutputs[i].destinationParameterIndex;
|
||||||
|
const outParameterValues: Float32Array =
|
||||||
|
!Float32Array.prototype.slice && 'subarray' in Float32Array.prototype
|
||||||
|
? JSON.parse(
|
||||||
|
JSON.stringify(
|
||||||
|
parameterValues.subarray(destinationParameterIndex)
|
||||||
|
)
|
||||||
|
) // 値渡しするため、JSON.parse, JSON.stringify
|
||||||
|
: parameterValues.slice(destinationParameterIndex);
|
||||||
|
|
||||||
|
updateOutputParameterValue(
|
||||||
|
outParameterValues,
|
||||||
|
parameterMinimumValues[destinationParameterIndex],
|
||||||
|
parameterMaximumValues[destinationParameterIndex],
|
||||||
|
this._previousRigOutputs.at(settingIndex).outputs.at(i) *
|
||||||
|
(1 - weight) +
|
||||||
|
this._currentRigOutputs.at(settingIndex).outputs.at(i) * weight,
|
||||||
|
currentOutputs[i]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 値を反映
|
||||||
|
for (
|
||||||
|
let offset: number = destinationParameterIndex, outParamIndex = 0;
|
||||||
|
offset < parameterValues.length;
|
||||||
|
offset++, outParamIndex++
|
||||||
|
) {
|
||||||
|
parameterValues[offset] = outParameterValues[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.0;
|
||||||
|
this._options.wind.x = 0.0;
|
||||||
|
this._options.wind.y = 0.0;
|
||||||
|
this._currentRigOutputs = new csmVector<PhysicsOutput>();
|
||||||
|
this._previousRigOutputs = new csmVector<PhysicsOutput>();
|
||||||
|
this._currentRemainTime = 0.0;
|
||||||
|
this._parameterCaches = null;
|
||||||
|
this._parameterInputCaches = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* デストラクタ相当の処理
|
||||||
|
*/
|
||||||
|
public release(): void {
|
||||||
|
this._physicsRig = void 0;
|
||||||
|
this._physicsRig = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初期化する
|
* 初期化する
|
||||||
*/
|
*/
|
||||||
|
@ -449,7 +824,7 @@ export class CubismPhysics {
|
||||||
strand[0].velocity = new CubismVector2(0.0, 0.0);
|
strand[0].velocity = new CubismVector2(0.0, 0.0);
|
||||||
strand[0].force = new CubismVector2(0.0, 0.0);
|
strand[0].force = new CubismVector2(0.0, 0.0);
|
||||||
|
|
||||||
// Initialize paritcles.
|
// Initialize particles.
|
||||||
for (let i = 1; i < currentSetting.particleCount; ++i) {
|
for (let i = 1; i < currentSetting.particleCount; ++i) {
|
||||||
radius = new CubismVector2(0.0, 0.0);
|
radius = new CubismVector2(0.0, 0.0);
|
||||||
radius.y = strand[i].radius;
|
radius.y = strand[i].radius;
|
||||||
|
@ -475,6 +850,14 @@ export class CubismPhysics {
|
||||||
|
|
||||||
_physicsRig: CubismPhysicsRig; // 物理演算のデータ
|
_physicsRig: CubismPhysicsRig; // 物理演算のデータ
|
||||||
_options: Options; // オプション
|
_options: Options; // オプション
|
||||||
|
|
||||||
|
_currentRigOutputs: csmVector<PhysicsOutput>; ///< 最新の振り子計算の結果
|
||||||
|
_previousRigOutputs: csmVector<PhysicsOutput>; ///< 一つ前の振り子計算の結果
|
||||||
|
|
||||||
|
_currentRemainTime: number; ///< 物理演算が処理していない時間
|
||||||
|
|
||||||
|
_parameterCaches: Float32Array; ///< Evaluateで利用するパラメータのキャッシュ
|
||||||
|
_parameterInputCaches: Float32Array; ///< UpdateParticlesが動くときの入力をキャッシュ
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -490,6 +873,17 @@ export class Options {
|
||||||
wind: CubismVector2; // 風の方向
|
wind: CubismVector2; // 風の方向
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* パラメータに適用する前の物理演算の出力結果
|
||||||
|
*/
|
||||||
|
export class PhysicsOutput {
|
||||||
|
constructor() {
|
||||||
|
this.outputs = new csmVector<number>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs: csmVector<number>; // 物理演算出力結果
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets sign.
|
* Gets sign.
|
||||||
*
|
*
|
||||||
|
@ -773,6 +1167,66 @@ function updateParticles(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates particles for stabilization.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
function updateParticlesForStabilization(
|
||||||
|
strand: CubismPhysicsParticle[],
|
||||||
|
strandCount: number,
|
||||||
|
totalTranslation: CubismVector2,
|
||||||
|
totalAngle: number,
|
||||||
|
windDirection: CubismVector2,
|
||||||
|
thresholdValue: number
|
||||||
|
) {
|
||||||
|
let totalRadian: number;
|
||||||
|
let currentGravity: CubismVector2;
|
||||||
|
let force: 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
|
||||||
|
);
|
||||||
|
|
||||||
|
strand[i].velocity = new CubismVector2(0.0, 0.0);
|
||||||
|
force = strand[i].force;
|
||||||
|
force.normalize();
|
||||||
|
|
||||||
|
force = force.multiplyByScaler(strand[i].radius);
|
||||||
|
strand[i].position = strand[i - 1].position.add(force);
|
||||||
|
|
||||||
|
if (CubismMath.abs(strand[i].position.x) < thresholdValue) {
|
||||||
|
strand[i].position.x = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strand[i].force = new CubismVector2(0.0, 0.0);
|
||||||
|
strand[i].lastGravity = new CubismVector2(
|
||||||
|
currentGravity.x,
|
||||||
|
currentGravity.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates output parameter value.
|
* Updates output parameter value.
|
||||||
* @param parameterValue Target parameter value.
|
* @param parameterValue Target parameter value.
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { csmVector } from '../type/csmvector';
|
||||||
* 物理演算の適用先の種類
|
* 物理演算の適用先の種類
|
||||||
*/
|
*/
|
||||||
export enum CubismPhysicsTargetType {
|
export enum CubismPhysicsTargetType {
|
||||||
CubismPhysicsTargetType_Parameter, // パラメータに対して適用
|
CubismPhysicsTargetType_Parameter // パラメータに対して適用
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ export enum CubismPhysicsTargetType {
|
||||||
export enum CubismPhysicsSource {
|
export enum CubismPhysicsSource {
|
||||||
CubismPhysicsSource_X, // X軸の位置から
|
CubismPhysicsSource_X, // X軸の位置から
|
||||||
CubismPhysicsSource_Y, // Y軸の位置から
|
CubismPhysicsSource_Y, // Y軸の位置から
|
||||||
CubismPhysicsSource_Angle, // 角度から
|
CubismPhysicsSource_Angle // 角度から
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -208,6 +208,7 @@ export class CubismPhysicsRig {
|
||||||
this.particles = new csmVector<CubismPhysicsParticle>();
|
this.particles = new csmVector<CubismPhysicsParticle>();
|
||||||
this.gravity = new CubismVector2(0, 0);
|
this.gravity = new CubismVector2(0, 0);
|
||||||
this.wind = new CubismVector2(0, 0);
|
this.wind = new CubismVector2(0, 0);
|
||||||
|
this.fps = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
subRigCount: number; // 物理演算の物理点の個数
|
subRigCount: number; // 物理演算の物理点の個数
|
||||||
|
@ -217,6 +218,7 @@ export class CubismPhysicsRig {
|
||||||
particles: csmVector<CubismPhysicsParticle>; // 物理演算の物理点のリスト
|
particles: csmVector<CubismPhysicsParticle>; // 物理演算の物理点のリスト
|
||||||
gravity: CubismVector2; // 重力
|
gravity: CubismVector2; // 重力
|
||||||
wind: CubismVector2; // 風
|
wind: CubismVector2; // 風
|
||||||
|
fps: number; //物理演算動作FPS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
|
|
|
@ -27,6 +27,7 @@ const PhysicsSettingCount = 'PhysicsSettingCount';
|
||||||
const Gravity = 'Gravity';
|
const Gravity = 'Gravity';
|
||||||
const Wind = 'Wind';
|
const Wind = 'Wind';
|
||||||
const VertexCount = 'VertexCount';
|
const VertexCount = 'VertexCount';
|
||||||
|
const Fps = 'Fps';
|
||||||
|
|
||||||
// PhysicsSettings
|
// PhysicsSettings
|
||||||
const PhysicsSettings = 'PhysicsSettings';
|
const PhysicsSettings = 'PhysicsSettings';
|
||||||
|
@ -120,6 +121,18 @@ export class CubismPhysicsJson {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物理演算設定FPSの取得
|
||||||
|
* @return 物理演算設定FPS
|
||||||
|
*/
|
||||||
|
public getFps(): number {
|
||||||
|
return this._json
|
||||||
|
.getRoot()
|
||||||
|
.getValueByString(Meta)
|
||||||
|
.getValueByString(Fps)
|
||||||
|
.toFloat(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 物理店の管理の個数の取得
|
* 物理店の管理の個数の取得
|
||||||
* @return 物理店の管理の個数
|
* @return 物理店の管理の個数
|
||||||
|
|
|
@ -0,0 +1,706 @@
|
||||||
|
/**
|
||||||
|
* 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 { Constant } from '../live2dcubismframework';
|
||||||
|
import { csmVector } from '../type/csmvector';
|
||||||
|
import { csmRect } from '../type/csmrectf';
|
||||||
|
import { CubismMatrix44 } from '../math/cubismmatrix44';
|
||||||
|
import { CubismModel } from '../model/cubismmodel';
|
||||||
|
import { CubismClippingContext, CubismTextureColor } from './cubismrenderer';
|
||||||
|
import { CubismLogError, CubismLogWarning } from '../utils/cubismdebug';
|
||||||
|
|
||||||
|
const ColorChannelCount = 4; // 実験時に1チャンネルの場合は1、RGBだけの場合は3、アルファも含める場合は4
|
||||||
|
const ClippingMaskMaxCountOnDefault = 36; // 通常のフレームバッファ一枚あたりのマスク最大数
|
||||||
|
const ClippingMaskMaxCountOnMultiRenderTexture = 32; // フレームバッファが2枚以上ある場合のフレームバッファ一枚あたりのマスク最大数
|
||||||
|
|
||||||
|
export type ClippingContextConstructor<
|
||||||
|
T_ClippingContext extends CubismClippingContext
|
||||||
|
> = new (
|
||||||
|
manager: CubismClippingManager<T_ClippingContext>,
|
||||||
|
drawableMasks: Int32Array,
|
||||||
|
drawableMaskCounts: number
|
||||||
|
) => T_ClippingContext;
|
||||||
|
|
||||||
|
export interface ICubismClippingManager {
|
||||||
|
getClippingMaskBufferSize(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class CubismClippingManager<
|
||||||
|
T_ClippingContext extends CubismClippingContext
|
||||||
|
> implements ICubismClippingManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* コンストラクタ
|
||||||
|
*/
|
||||||
|
public constructor(
|
||||||
|
clippingContextFactory: ClippingContextConstructor<T_ClippingContext>
|
||||||
|
) {
|
||||||
|
this._renderTextureCount = 0;
|
||||||
|
this._clippingMaskBufferSize = 256;
|
||||||
|
this._clippingContextListForMask = new csmVector<T_ClippingContext>();
|
||||||
|
this._clippingContextListForDraw = new csmVector<T_ClippingContext>();
|
||||||
|
this._channelColors = new csmVector<CubismTextureColor>();
|
||||||
|
this._tmpBoundsOnModel = new csmRect();
|
||||||
|
this._tmpMatrix = new CubismMatrix44();
|
||||||
|
this._tmpMatrixForMask = new CubismMatrix44();
|
||||||
|
this._tmpMatrixForDraw = new CubismMatrix44();
|
||||||
|
|
||||||
|
this._clippingContexttConstructor = clippingContextFactory;
|
||||||
|
|
||||||
|
let tmp: CubismTextureColor = new CubismTextureColor();
|
||||||
|
tmp.R = 1.0;
|
||||||
|
tmp.G = 0.0;
|
||||||
|
tmp.B = 0.0;
|
||||||
|
tmp.A = 0.0;
|
||||||
|
this._channelColors.pushBack(tmp);
|
||||||
|
|
||||||
|
tmp = new CubismTextureColor();
|
||||||
|
tmp.R = 0.0;
|
||||||
|
tmp.G = 1.0;
|
||||||
|
tmp.B = 0.0;
|
||||||
|
tmp.A = 0.0;
|
||||||
|
this._channelColors.pushBack(tmp);
|
||||||
|
|
||||||
|
tmp = new CubismTextureColor();
|
||||||
|
tmp.R = 0.0;
|
||||||
|
tmp.G = 0.0;
|
||||||
|
tmp.B = 1.0;
|
||||||
|
tmp.A = 0.0;
|
||||||
|
this._channelColors.pushBack(tmp);
|
||||||
|
|
||||||
|
tmp = new CubismTextureColor();
|
||||||
|
tmp.R = 0.0;
|
||||||
|
tmp.G = 0.0;
|
||||||
|
tmp.B = 0.0;
|
||||||
|
tmp.A = 1.0;
|
||||||
|
this._channelColors.pushBack(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* デストラクタ相当の処理
|
||||||
|
*/
|
||||||
|
public release(): void {
|
||||||
|
for (let i = 0; i < this._clippingContextListForMask.getSize(); i++) {
|
||||||
|
if (this._clippingContextListForMask.at(i)) {
|
||||||
|
this._clippingContextListForMask.at(i).release();
|
||||||
|
this._clippingContextListForMask.set(i, void 0);
|
||||||
|
}
|
||||||
|
this._clippingContextListForMask.set(i, null);
|
||||||
|
}
|
||||||
|
this._clippingContextListForMask = null;
|
||||||
|
|
||||||
|
// _clippingContextListForDrawは_clippingContextListForMaskにあるインスタンスを指している。上記の処理により要素ごとのDELETEは不要。
|
||||||
|
for (let i = 0; i < this._clippingContextListForDraw.getSize(); i++) {
|
||||||
|
this._clippingContextListForDraw.set(i, null);
|
||||||
|
}
|
||||||
|
this._clippingContextListForDraw = null;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._channelColors.getSize(); i++) {
|
||||||
|
this._channelColors.set(i, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._channelColors = null;
|
||||||
|
|
||||||
|
if (this._clearedFrameBufferFlags != null) {
|
||||||
|
this._clearedFrameBufferFlags.clear();
|
||||||
|
}
|
||||||
|
this._clearedFrameBufferFlags = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* マネージャの初期化処理
|
||||||
|
* クリッピングマスクを使う描画オブジェクトの登録を行う
|
||||||
|
* @param model モデルのインスタンス
|
||||||
|
* @param renderTextureCount バッファの生成数
|
||||||
|
*/
|
||||||
|
public initialize(model: CubismModel, renderTextureCount: number): void {
|
||||||
|
// レンダーテクスチャの合計枚数の設定
|
||||||
|
// 1以上の整数でない場合はそれぞれ警告を出す
|
||||||
|
if (renderTextureCount % 1 != 0) {
|
||||||
|
CubismLogWarning(
|
||||||
|
'The number of render textures must be specified as an integer. The decimal point is rounded down and corrected to an integer.'
|
||||||
|
);
|
||||||
|
// 小数点以下を除去
|
||||||
|
renderTextureCount = ~~renderTextureCount;
|
||||||
|
}
|
||||||
|
if (renderTextureCount < 1) {
|
||||||
|
CubismLogWarning(
|
||||||
|
'The number of render textures must be an integer greater than or equal to 1. Set the number of render textures to 1.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 負の値が使われている場合は強制的に1枚と設定する
|
||||||
|
this._renderTextureCount = renderTextureCount < 1 ? 1 : renderTextureCount;
|
||||||
|
|
||||||
|
this._clearedFrameBufferFlags = new csmVector<boolean>(
|
||||||
|
this._renderTextureCount
|
||||||
|
);
|
||||||
|
|
||||||
|
// クリッピングマスクを使う描画オブジェクトをすべて登録する
|
||||||
|
// クリッピングマスクは、通常数個程度に限定して使うものとする
|
||||||
|
for (let i = 0; i < model.getDrawableCount(); i++) {
|
||||||
|
if (model.getDrawableMaskCounts()[i] <= 0) {
|
||||||
|
// クリッピングマスクが使用されていないアートメッシュ(多くの場合使用しない)
|
||||||
|
this._clippingContextListForDraw.pushBack(null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 既にあるClipContextと同じかチェックする
|
||||||
|
let clippingContext: T_ClippingContext = this.findSameClip(
|
||||||
|
model.getDrawableMasks()[i],
|
||||||
|
model.getDrawableMaskCounts()[i]
|
||||||
|
);
|
||||||
|
if (clippingContext == null) {
|
||||||
|
// 同一のマスクが存在していない場合は生成する
|
||||||
|
|
||||||
|
clippingContext = new this._clippingContexttConstructor(
|
||||||
|
this,
|
||||||
|
model.getDrawableMasks()[i],
|
||||||
|
model.getDrawableMaskCounts()[i]
|
||||||
|
);
|
||||||
|
this._clippingContextListForMask.pushBack(clippingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
clippingContext.addClippedDrawable(i);
|
||||||
|
|
||||||
|
this._clippingContextListForDraw.pushBack(clippingContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 既にマスクを作っているかを確認
|
||||||
|
* 作っている様であれば該当するクリッピングマスクのインスタンスを返す
|
||||||
|
* 作っていなければNULLを返す
|
||||||
|
* @param drawableMasks 描画オブジェクトをマスクする描画オブジェクトのリスト
|
||||||
|
* @param drawableMaskCounts 描画オブジェクトをマスクする描画オブジェクトの数
|
||||||
|
* @return 該当するクリッピングマスクが存在すればインスタンスを返し、なければNULLを返す
|
||||||
|
*/
|
||||||
|
public findSameClip(
|
||||||
|
drawableMasks: Int32Array,
|
||||||
|
drawableMaskCounts: number
|
||||||
|
): T_ClippingContext {
|
||||||
|
// 作成済みClippingContextと一致するか確認
|
||||||
|
for (let i = 0; i < this._clippingContextListForMask.getSize(); i++) {
|
||||||
|
const clippingContext: T_ClippingContext =
|
||||||
|
this._clippingContextListForMask.at(i);
|
||||||
|
const count: number = clippingContext._clippingIdCount;
|
||||||
|
|
||||||
|
// 個数が違う場合は別物
|
||||||
|
if (count != drawableMaskCounts) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sameCount = 0;
|
||||||
|
|
||||||
|
// 同じIDを持つか確認。配列の数が同じなので、一致した個数が同じなら同じ物を持つとする
|
||||||
|
for (let j = 0; j < count; j++) {
|
||||||
|
const clipId: number = clippingContext._clippingIdList[j];
|
||||||
|
|
||||||
|
for (let k = 0; k < count; k++) {
|
||||||
|
if (drawableMasks[k] == clipId) {
|
||||||
|
sameCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sameCount == count) {
|
||||||
|
return clippingContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // 見つからなかった
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 高精細マスク処理用の行列を計算する
|
||||||
|
* @param model モデルのインスタンス
|
||||||
|
* @param isRightHanded 処理が右手系であるか
|
||||||
|
*/
|
||||||
|
public setupMatrixForHighPrecision(
|
||||||
|
model: CubismModel,
|
||||||
|
isRightHanded: boolean
|
||||||
|
): void {
|
||||||
|
// 全てのクリッピングを用意する
|
||||||
|
// 同じクリップ(複数の場合はまとめて一つのクリップ)を使う場合は1度だけ設定する
|
||||||
|
let usingClipCount = 0;
|
||||||
|
for (
|
||||||
|
let clipIndex = 0;
|
||||||
|
clipIndex < this._clippingContextListForMask.getSize();
|
||||||
|
clipIndex++
|
||||||
|
) {
|
||||||
|
// 1つのクリッピングマスクに関して
|
||||||
|
const cc: T_ClippingContext =
|
||||||
|
this._clippingContextListForMask.at(clipIndex);
|
||||||
|
|
||||||
|
// このクリップを利用する描画オブジェクト群全体を囲む矩形を計算
|
||||||
|
this.calcClippedDrawTotalBounds(model, cc);
|
||||||
|
|
||||||
|
if (cc._isUsing) {
|
||||||
|
usingClipCount++; // 使用中としてカウント
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// マスク行列作成処理
|
||||||
|
if (usingClipCount > 0) {
|
||||||
|
this.setupLayoutBounds(0);
|
||||||
|
|
||||||
|
// サイズがレンダーテクスチャの枚数と合わない場合は合わせる
|
||||||
|
if (this._clearedFrameBufferFlags.getSize() != this._renderTextureCount) {
|
||||||
|
this._clearedFrameBufferFlags.clear();
|
||||||
|
for (let i = 0; i < this._renderTextureCount; i++) {
|
||||||
|
this._clearedFrameBufferFlags.pushBack(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// マスクのクリアフラグを毎フレーム開始時に初期化
|
||||||
|
for (let i = 0; i < this._renderTextureCount; i++) {
|
||||||
|
this._clearedFrameBufferFlags.set(i, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 実際にマスクを生成する
|
||||||
|
// 全てのマスクをどの様にレイアウトして描くかを決定し、ClipContext , ClippedDrawContext に記憶する
|
||||||
|
for (
|
||||||
|
let clipIndex = 0;
|
||||||
|
clipIndex < this._clippingContextListForMask.getSize();
|
||||||
|
clipIndex++
|
||||||
|
) {
|
||||||
|
// --- 実際に1つのマスクを描く ---
|
||||||
|
const clipContext: T_ClippingContext =
|
||||||
|
this._clippingContextListForMask.at(clipIndex);
|
||||||
|
const allClippedDrawRect: csmRect = clipContext._allClippedDrawRect; //このマスクを使う、全ての描画オブジェクトの論理座標上の囲み矩形
|
||||||
|
const layoutBoundsOnTex01 = clipContext._layoutBounds; //この中にマスクを収める
|
||||||
|
const MARGIN = 0.05;
|
||||||
|
let scaleX = 0.0;
|
||||||
|
let scaleY = 0.0;
|
||||||
|
const ppu: number = model.getPixelsPerUnit();
|
||||||
|
const maskPixelSize: number = clipContext
|
||||||
|
.getClippingManager()
|
||||||
|
.getClippingMaskBufferSize();
|
||||||
|
const physicalMaskWidth: number =
|
||||||
|
layoutBoundsOnTex01.width * maskPixelSize;
|
||||||
|
const physicalMaskHeight: number =
|
||||||
|
layoutBoundsOnTex01.height * maskPixelSize;
|
||||||
|
|
||||||
|
this._tmpBoundsOnModel.setRect(allClippedDrawRect);
|
||||||
|
if (this._tmpBoundsOnModel.width * ppu > physicalMaskWidth) {
|
||||||
|
this._tmpBoundsOnModel.expand(allClippedDrawRect.width * MARGIN, 0.0);
|
||||||
|
scaleX = layoutBoundsOnTex01.width / this._tmpBoundsOnModel.width;
|
||||||
|
} else {
|
||||||
|
scaleX = ppu / physicalMaskWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._tmpBoundsOnModel.height * ppu > physicalMaskHeight) {
|
||||||
|
this._tmpBoundsOnModel.expand(
|
||||||
|
0.0,
|
||||||
|
allClippedDrawRect.height * MARGIN
|
||||||
|
);
|
||||||
|
scaleY = layoutBoundsOnTex01.height / this._tmpBoundsOnModel.height;
|
||||||
|
} else {
|
||||||
|
scaleY = ppu / physicalMaskHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// マスク生成時に使う行列を求める
|
||||||
|
this.createMatrixForMask(
|
||||||
|
isRightHanded,
|
||||||
|
layoutBoundsOnTex01,
|
||||||
|
scaleX,
|
||||||
|
scaleY
|
||||||
|
);
|
||||||
|
|
||||||
|
clipContext._matrixForMask.setMatrix(this._tmpMatrixForMask.getArray());
|
||||||
|
clipContext._matrixForDraw.setMatrix(this._tmpMatrixForDraw.getArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* マスク作成・描画用の行列を作成する。
|
||||||
|
* @param isRightHanded 座標を右手系として扱うかを指定
|
||||||
|
* @param layoutBoundsOnTex01 マスクを収める領域
|
||||||
|
* @param scaleX 描画オブジェクトの伸縮率
|
||||||
|
* @param scaleY 描画オブジェクトの伸縮率
|
||||||
|
*/
|
||||||
|
public createMatrixForMask(
|
||||||
|
isRightHanded: boolean,
|
||||||
|
layoutBoundsOnTex01: csmRect,
|
||||||
|
scaleX: number,
|
||||||
|
scaleY: number
|
||||||
|
): void {
|
||||||
|
this._tmpMatrix.loadIdentity();
|
||||||
|
{
|
||||||
|
// Layout0..1 を -1..1に変換
|
||||||
|
this._tmpMatrix.translateRelative(-1.0, -1.0);
|
||||||
|
this._tmpMatrix.scaleRelative(2.0, 2.0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// view to Layout0..1
|
||||||
|
this._tmpMatrix.translateRelative(
|
||||||
|
layoutBoundsOnTex01.x,
|
||||||
|
layoutBoundsOnTex01.y
|
||||||
|
); //new = [translate]
|
||||||
|
this._tmpMatrix.scaleRelative(scaleX, scaleY); //new = [translate][scale]
|
||||||
|
this._tmpMatrix.translateRelative(
|
||||||
|
-this._tmpBoundsOnModel.x,
|
||||||
|
-this._tmpBoundsOnModel.y
|
||||||
|
); //new = [translate][scale][translate]
|
||||||
|
}
|
||||||
|
// tmpMatrixForMask が計算結果
|
||||||
|
this._tmpMatrixForMask.setMatrix(this._tmpMatrix.getArray());
|
||||||
|
|
||||||
|
this._tmpMatrix.loadIdentity();
|
||||||
|
{
|
||||||
|
this._tmpMatrix.translateRelative(
|
||||||
|
layoutBoundsOnTex01.x,
|
||||||
|
layoutBoundsOnTex01.y * (isRightHanded ? -1.0 : 1.0)
|
||||||
|
); //new = [translate]
|
||||||
|
this._tmpMatrix.scaleRelative(
|
||||||
|
scaleX,
|
||||||
|
scaleY * (isRightHanded ? -1.0 : 1.0)
|
||||||
|
); //new = [translate][scale]
|
||||||
|
this._tmpMatrix.translateRelative(
|
||||||
|
-this._tmpBoundsOnModel.x,
|
||||||
|
-this._tmpBoundsOnModel.y
|
||||||
|
); //new = [translate][scale][translate]
|
||||||
|
}
|
||||||
|
|
||||||
|
this._tmpMatrixForDraw.setMatrix(this._tmpMatrix.getArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* クリッピングコンテキストを配置するレイアウト
|
||||||
|
* 指定された数のレンダーテクスチャを極力いっぱいに使ってマスクをレイアウトする
|
||||||
|
* マスクグループの数が4以下ならRGBA各チャンネルに一つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する。
|
||||||
|
*
|
||||||
|
* @param usingClipCount 配置するクリッピングコンテキストの数
|
||||||
|
*/
|
||||||
|
public setupLayoutBounds(usingClipCount: number): void {
|
||||||
|
const useClippingMaskMaxCount =
|
||||||
|
this._renderTextureCount <= 1
|
||||||
|
? ClippingMaskMaxCountOnDefault
|
||||||
|
: ClippingMaskMaxCountOnMultiRenderTexture * this._renderTextureCount;
|
||||||
|
|
||||||
|
if (usingClipCount <= 0 || usingClipCount > useClippingMaskMaxCount) {
|
||||||
|
if (usingClipCount > useClippingMaskMaxCount) {
|
||||||
|
// マスクの制限数の警告を出す
|
||||||
|
CubismLogError(
|
||||||
|
'not supported mask count : {0}\n[Details] render texture count : {1}, mask count : {2}',
|
||||||
|
usingClipCount - useClippingMaskMaxCount,
|
||||||
|
this._renderTextureCount,
|
||||||
|
usingClipCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// この場合は一つのマスクターゲットを毎回クリアして使用する
|
||||||
|
for (
|
||||||
|
let index = 0;
|
||||||
|
index < this._clippingContextListForMask.getSize();
|
||||||
|
index++
|
||||||
|
) {
|
||||||
|
const clipContext: T_ClippingContext =
|
||||||
|
this._clippingContextListForMask.at(index);
|
||||||
|
clipContext._layoutChannelNo = 0; // どうせ毎回消すので固定
|
||||||
|
clipContext._layoutBounds.x = 0.0;
|
||||||
|
clipContext._layoutBounds.y = 0.0;
|
||||||
|
clipContext._layoutBounds.width = 1.0;
|
||||||
|
clipContext._layoutBounds.height = 1.0;
|
||||||
|
clipContext._bufferIndex = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// レンダーテクスチャが1枚なら9分割する(最大36枚)
|
||||||
|
const layoutCountMaxValue = this._renderTextureCount <= 1 ? 9 : 8;
|
||||||
|
|
||||||
|
// 指定された数のレンダーテクスチャを極力いっぱいに使ってマスクをレイアウトする(デフォルトなら1)
|
||||||
|
// マスクグループの数が4以下ならRGBA各チャンネルに1つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する
|
||||||
|
let countPerSheetDiv: number = usingClipCount / this._renderTextureCount; // レンダーテクスチャ1枚あたり何枚割り当てるか
|
||||||
|
let countPerSheetMod: number = usingClipCount % this._renderTextureCount; // この番号のレンダーテクスチャまでに一つずつ配分する
|
||||||
|
|
||||||
|
// 小数点は切り捨てる
|
||||||
|
countPerSheetDiv = ~~countPerSheetDiv;
|
||||||
|
countPerSheetMod = ~~countPerSheetMod;
|
||||||
|
|
||||||
|
// RGBAを順番に使っていく
|
||||||
|
let div: number = countPerSheetDiv / ColorChannelCount; // 1チャンネルに配置する基本のマスク
|
||||||
|
let mod: number = countPerSheetDiv % ColorChannelCount; // 余り、この番号のチャンネルまでに一つずつ配分する
|
||||||
|
|
||||||
|
// 小数点は切り捨てる
|
||||||
|
div = ~~div;
|
||||||
|
mod = ~~mod;
|
||||||
|
|
||||||
|
// RGBAそれぞれのチャンネルを用意していく(0:R, 1:G, 2:B, 3:A)
|
||||||
|
let curClipIndex = 0; // 順番に設定していく
|
||||||
|
|
||||||
|
for (
|
||||||
|
let renderTextureNo = 0;
|
||||||
|
renderTextureNo < this._renderTextureCount;
|
||||||
|
renderTextureNo++
|
||||||
|
) {
|
||||||
|
for (let channelNo = 0; channelNo < ColorChannelCount; channelNo++) {
|
||||||
|
// このチャンネルにレイアウトする数
|
||||||
|
let layoutCount: number = div + (channelNo < mod ? 1 : 0);
|
||||||
|
|
||||||
|
// このレンダーテクスチャにまだ割り当てられていなければ追加する
|
||||||
|
const checkChannelNo = mod + 1 >= ColorChannelCount ? 0 : mod + 1;
|
||||||
|
if (layoutCount < layoutCountMaxValue && channelNo == checkChannelNo) {
|
||||||
|
layoutCount += renderTextureNo < countPerSheetMod ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分割方法を決定する
|
||||||
|
if (layoutCount == 0) {
|
||||||
|
// 何もしない
|
||||||
|
} else if (layoutCount == 1) {
|
||||||
|
// 全てをそのまま使う
|
||||||
|
const clipContext: T_ClippingContext =
|
||||||
|
this._clippingContextListForMask.at(curClipIndex++);
|
||||||
|
clipContext._layoutChannelNo = channelNo;
|
||||||
|
clipContext._layoutBounds.x = 0.0;
|
||||||
|
clipContext._layoutBounds.y = 0.0;
|
||||||
|
clipContext._layoutBounds.width = 1.0;
|
||||||
|
clipContext._layoutBounds.height = 1.0;
|
||||||
|
clipContext._bufferIndex = renderTextureNo;
|
||||||
|
} else if (layoutCount == 2) {
|
||||||
|
for (let i = 0; i < layoutCount; i++) {
|
||||||
|
let xpos: number = i % 2;
|
||||||
|
|
||||||
|
// 小数点は切り捨てる
|
||||||
|
xpos = ~~xpos;
|
||||||
|
|
||||||
|
const cc: T_ClippingContext = this._clippingContextListForMask.at(
|
||||||
|
curClipIndex++
|
||||||
|
);
|
||||||
|
cc._layoutChannelNo = channelNo;
|
||||||
|
|
||||||
|
// UVを2つに分解して使う
|
||||||
|
cc._layoutBounds.x = xpos * 0.5;
|
||||||
|
cc._layoutBounds.y = 0.0;
|
||||||
|
cc._layoutBounds.width = 0.5;
|
||||||
|
cc._layoutBounds.height = 1.0;
|
||||||
|
cc._bufferIndex = renderTextureNo;
|
||||||
|
}
|
||||||
|
} else if (layoutCount <= 4) {
|
||||||
|
// 4分割して使う
|
||||||
|
for (let i = 0; i < layoutCount; i++) {
|
||||||
|
let xpos: number = i % 2;
|
||||||
|
let ypos: number = i / 2;
|
||||||
|
|
||||||
|
// 小数点は切り捨てる
|
||||||
|
xpos = ~~xpos;
|
||||||
|
ypos = ~~ypos;
|
||||||
|
|
||||||
|
const cc = this._clippingContextListForMask.at(curClipIndex++);
|
||||||
|
cc._layoutChannelNo = channelNo;
|
||||||
|
|
||||||
|
cc._layoutBounds.x = xpos * 0.5;
|
||||||
|
cc._layoutBounds.y = ypos * 0.5;
|
||||||
|
cc._layoutBounds.width = 0.5;
|
||||||
|
cc._layoutBounds.height = 0.5;
|
||||||
|
cc._bufferIndex = renderTextureNo;
|
||||||
|
}
|
||||||
|
} else if (layoutCount <= layoutCountMaxValue) {
|
||||||
|
// 9分割して使う
|
||||||
|
for (let i = 0; i < layoutCount; i++) {
|
||||||
|
let xpos = i % 3;
|
||||||
|
let ypos = i / 3;
|
||||||
|
|
||||||
|
// 小数点は切り捨てる
|
||||||
|
xpos = ~~xpos;
|
||||||
|
ypos = ~~ypos;
|
||||||
|
|
||||||
|
const cc: T_ClippingContext = this._clippingContextListForMask.at(
|
||||||
|
curClipIndex++
|
||||||
|
);
|
||||||
|
cc._layoutChannelNo = channelNo;
|
||||||
|
|
||||||
|
cc._layoutBounds.x = xpos / 3.0;
|
||||||
|
cc._layoutBounds.y = ypos / 3.0;
|
||||||
|
cc._layoutBounds.width = 1.0 / 3.0;
|
||||||
|
cc._layoutBounds.height = 1.0 / 3.0;
|
||||||
|
cc._bufferIndex = renderTextureNo;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// マスクの制限枚数を超えた場合の処理
|
||||||
|
CubismLogError(
|
||||||
|
'not supported mask count : {0}\n[Details] render texture count : {1}, mask count : {2}',
|
||||||
|
usingClipCount - useClippingMaskMaxCount,
|
||||||
|
this._renderTextureCount,
|
||||||
|
usingClipCount
|
||||||
|
);
|
||||||
|
|
||||||
|
// SetupShaderProgramでオーバーアクセスが発生するので仮で数値を入れる
|
||||||
|
// もちろん描画結果は正しいものではなくなる
|
||||||
|
for (let index = 0; index < layoutCount; index++) {
|
||||||
|
const cc: T_ClippingContext = this._clippingContextListForMask.at(
|
||||||
|
curClipIndex++
|
||||||
|
);
|
||||||
|
|
||||||
|
cc._layoutChannelNo = 0;
|
||||||
|
|
||||||
|
cc._layoutBounds.x = 0.0;
|
||||||
|
cc._layoutBounds.y = 0.0;
|
||||||
|
cc._layoutBounds.width = 1.0;
|
||||||
|
cc._layoutBounds.height = 1.0;
|
||||||
|
cc._bufferIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* マスクされる描画オブジェクト群全体を囲む矩形(モデル座標系)を計算する
|
||||||
|
* @param model モデルのインスタンス
|
||||||
|
* @param clippingContext クリッピングマスクのコンテキスト
|
||||||
|
*/
|
||||||
|
public calcClippedDrawTotalBounds(
|
||||||
|
model: CubismModel,
|
||||||
|
clippingContext: T_ClippingContext
|
||||||
|
): void {
|
||||||
|
// 被クリッピングマスク(マスクされる描画オブジェクト)の全体の矩形
|
||||||
|
let clippedDrawTotalMinX: number = Number.MAX_VALUE;
|
||||||
|
let clippedDrawTotalMinY: number = Number.MAX_VALUE;
|
||||||
|
let clippedDrawTotalMaxX: number = Number.MIN_VALUE;
|
||||||
|
let clippedDrawTotalMaxY: number = Number.MIN_VALUE;
|
||||||
|
|
||||||
|
// このマスクが実際に必要か判定する
|
||||||
|
// このクリッピングを利用する「描画オブジェクト」がひとつでも使用可能であればマスクを生成する必要がある
|
||||||
|
const clippedDrawCount: number =
|
||||||
|
clippingContext._clippedDrawableIndexList.length;
|
||||||
|
|
||||||
|
for (
|
||||||
|
let clippedDrawableIndex = 0;
|
||||||
|
clippedDrawableIndex < clippedDrawCount;
|
||||||
|
clippedDrawableIndex++
|
||||||
|
) {
|
||||||
|
// マスクを使用する描画オブジェクトの描画される矩形を求める
|
||||||
|
const drawableIndex: number =
|
||||||
|
clippingContext._clippedDrawableIndexList[clippedDrawableIndex];
|
||||||
|
|
||||||
|
const drawableVertexCount: number =
|
||||||
|
model.getDrawableVertexCount(drawableIndex);
|
||||||
|
const drawableVertexes: Float32Array =
|
||||||
|
model.getDrawableVertices(drawableIndex);
|
||||||
|
|
||||||
|
let minX: number = Number.MAX_VALUE;
|
||||||
|
let minY: number = Number.MAX_VALUE;
|
||||||
|
let maxX: number = -Number.MAX_VALUE;
|
||||||
|
let maxY: number = -Number.MAX_VALUE;
|
||||||
|
|
||||||
|
const loop: number = drawableVertexCount * Constant.vertexStep;
|
||||||
|
for (
|
||||||
|
let pi: number = Constant.vertexOffset;
|
||||||
|
pi < loop;
|
||||||
|
pi += Constant.vertexStep
|
||||||
|
) {
|
||||||
|
const x: number = drawableVertexes[pi];
|
||||||
|
const y: number = drawableVertexes[pi + 1];
|
||||||
|
|
||||||
|
if (x < minX) {
|
||||||
|
minX = x;
|
||||||
|
}
|
||||||
|
if (x > maxX) {
|
||||||
|
maxX = x;
|
||||||
|
}
|
||||||
|
if (y < minY) {
|
||||||
|
minY = y;
|
||||||
|
}
|
||||||
|
if (y > maxY) {
|
||||||
|
maxY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有効な点が一つも取れなかったのでスキップ
|
||||||
|
if (minX == Number.MAX_VALUE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全体の矩形に反映
|
||||||
|
if (minX < clippedDrawTotalMinX) {
|
||||||
|
clippedDrawTotalMinX = minX;
|
||||||
|
}
|
||||||
|
if (minY < clippedDrawTotalMinY) {
|
||||||
|
clippedDrawTotalMinY = minY;
|
||||||
|
}
|
||||||
|
if (maxX > clippedDrawTotalMaxX) {
|
||||||
|
clippedDrawTotalMaxX = maxX;
|
||||||
|
}
|
||||||
|
if (maxY > clippedDrawTotalMaxY) {
|
||||||
|
clippedDrawTotalMaxY = maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clippedDrawTotalMinX == Number.MAX_VALUE) {
|
||||||
|
clippingContext._allClippedDrawRect.x = 0.0;
|
||||||
|
clippingContext._allClippedDrawRect.y = 0.0;
|
||||||
|
clippingContext._allClippedDrawRect.width = 0.0;
|
||||||
|
clippingContext._allClippedDrawRect.height = 0.0;
|
||||||
|
clippingContext._isUsing = false;
|
||||||
|
} else {
|
||||||
|
clippingContext._isUsing = true;
|
||||||
|
const w: number = clippedDrawTotalMaxX - clippedDrawTotalMinX;
|
||||||
|
const h: number = clippedDrawTotalMaxY - clippedDrawTotalMinY;
|
||||||
|
clippingContext._allClippedDrawRect.x = clippedDrawTotalMinX;
|
||||||
|
clippingContext._allClippedDrawRect.y = clippedDrawTotalMinY;
|
||||||
|
clippingContext._allClippedDrawRect.width = w;
|
||||||
|
clippingContext._allClippedDrawRect.height = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 画面描画に使用するクリッピングマスクのリストを取得する
|
||||||
|
* @return 画面描画に使用するクリッピングマスクのリスト
|
||||||
|
*/
|
||||||
|
public getClippingContextListForDraw(): csmVector<T_ClippingContext> {
|
||||||
|
return this._clippingContextListForDraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* クリッピングマスクバッファのサイズを取得する
|
||||||
|
* @return クリッピングマスクバッファのサイズ
|
||||||
|
*/
|
||||||
|
public getClippingMaskBufferSize(): number {
|
||||||
|
return this._clippingMaskBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このバッファのレンダーテクスチャの枚数を取得する
|
||||||
|
* @return このバッファのレンダーテクスチャの枚数
|
||||||
|
*/
|
||||||
|
public getRenderTextureCount(): number {
|
||||||
|
return this._renderTextureCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* カラーチャンネル(RGBA)のフラグを取得する
|
||||||
|
* @param channelNo カラーチャンネル(RGBA)の番号(0:R, 1:G, 2:B, 3:A)
|
||||||
|
*/
|
||||||
|
public getChannelFlagAsColor(channelNo: number): CubismTextureColor {
|
||||||
|
return this._channelColors.at(channelNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* クリッピングマスクバッファのサイズを設定する
|
||||||
|
* @param size クリッピングマスクバッファのサイズ
|
||||||
|
*/
|
||||||
|
public setClippingMaskBufferSize(size: number): void {
|
||||||
|
this._clippingMaskBufferSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _clearedFrameBufferFlags: csmVector<boolean>; //マスクのクリアフラグの配列
|
||||||
|
|
||||||
|
protected _channelColors: csmVector<CubismTextureColor>;
|
||||||
|
protected _clippingContextListForMask: csmVector<T_ClippingContext>; // マスク用クリッピングコンテキストのリスト
|
||||||
|
protected _clippingContextListForDraw: csmVector<T_ClippingContext>; // 描画用クリッピングコンテキストのリスト
|
||||||
|
protected _clippingMaskBufferSize: number; // クリッピングマスクのバッファサイズ(初期値:256)
|
||||||
|
protected _renderTextureCount: number; // 生成するレンダーテクスチャの枚数
|
||||||
|
|
||||||
|
protected _tmpMatrix: CubismMatrix44; // マスク計算用の行列
|
||||||
|
protected _tmpMatrixForMask: CubismMatrix44; // マスク計算用の行列
|
||||||
|
protected _tmpMatrixForDraw: CubismMatrix44; // マスク計算用の行列
|
||||||
|
protected _tmpBoundsOnModel: csmRect; // マスク配置計算用の矩形
|
||||||
|
|
||||||
|
protected _clippingContexttConstructor: ClippingContextConstructor<T_ClippingContext>;
|
||||||
|
}
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
import { CubismMatrix44 } from '../math/cubismmatrix44';
|
import { CubismMatrix44 } from '../math/cubismmatrix44';
|
||||||
import { CubismModel } from '../model/cubismmodel';
|
import { CubismModel } from '../model/cubismmodel';
|
||||||
|
import { csmRect } from '../type/csmrectf';
|
||||||
|
import { ICubismClippingManager } from './cubismclippingmanager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* モデル描画を処理するレンダラ
|
* モデル描画を処理するレンダラ
|
||||||
|
@ -45,7 +47,11 @@ export abstract class CubismRenderer {
|
||||||
public drawModel(): void {
|
public drawModel(): void {
|
||||||
if (this.getModel() == null) return;
|
if (this.getModel() == null) return;
|
||||||
|
|
||||||
|
this.saveProfile();
|
||||||
|
|
||||||
this.doDrawModel();
|
this.doDrawModel();
|
||||||
|
|
||||||
|
this.restoreProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,6 +125,24 @@ export abstract class CubismRenderer {
|
||||||
return JSON.parse(JSON.stringify(this._modelColor));
|
return JSON.parse(JSON.stringify(this._modelColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 透明度を考慮したモデルの色を計算する。
|
||||||
|
*
|
||||||
|
* @param opacity 透明度
|
||||||
|
*
|
||||||
|
* @return RGBAのカラー情報
|
||||||
|
*/
|
||||||
|
getModelColorWithOpacity(opacity: number): CubismTextureColor {
|
||||||
|
const modelColorRGBA: CubismTextureColor = this.getModelColor();
|
||||||
|
modelColorRGBA.A *= opacity;
|
||||||
|
if (this.isPremultipliedAlpha()) {
|
||||||
|
modelColorRGBA.R *= modelColorRGBA.A;
|
||||||
|
modelColorRGBA.G *= modelColorRGBA.A;
|
||||||
|
modelColorRGBA.B *= modelColorRGBA.A;
|
||||||
|
}
|
||||||
|
return modelColorRGBA;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 乗算済みαの有効・無効をセットする
|
* 乗算済みαの有効・無効をセットする
|
||||||
* 有効にするならtrue、無効にするならfalseをセットする
|
* 有効にするならtrue、無効にするならfalseをセットする
|
||||||
|
@ -178,6 +202,27 @@ export abstract class CubismRenderer {
|
||||||
return this._model;
|
return this._model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* マスク描画の方式を変更する。
|
||||||
|
* falseの場合、マスクを1枚のテクスチャに分割してレンダリングする(デフォルト)
|
||||||
|
* 高速だが、マスク個数の上限が36に限定され、質も荒くなる
|
||||||
|
* trueの場合、パーツ描画の前にその都度必要なマスクを描き直す
|
||||||
|
* レンダリング品質は高いが描画処理負荷は増す
|
||||||
|
* @param high 高精細マスクに切り替えるか?
|
||||||
|
*/
|
||||||
|
public useHighPrecisionMask(high: boolean): void {
|
||||||
|
this._useHighPrecisionMask = high;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* マスクの描画方式を取得する
|
||||||
|
* @return true 高精細方式
|
||||||
|
* @return false デフォルト
|
||||||
|
*/
|
||||||
|
public isUsingHighPrecisionMask(): boolean {
|
||||||
|
return this._useHighPrecisionMask;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* コンストラクタ
|
* コンストラクタ
|
||||||
*/
|
*/
|
||||||
|
@ -187,6 +232,7 @@ export abstract class CubismRenderer {
|
||||||
this._anisotropy = 0.0;
|
this._anisotropy = 0.0;
|
||||||
this._model = null;
|
this._model = null;
|
||||||
this._modelColor = new CubismTextureColor();
|
this._modelColor = new CubismTextureColor();
|
||||||
|
this._useHighPrecisionMask = false;
|
||||||
|
|
||||||
// 単位行列に初期化
|
// 単位行列に初期化
|
||||||
this._mvpMatrix4x4 = new CubismMatrix44();
|
this._mvpMatrix4x4 = new CubismMatrix44();
|
||||||
|
@ -199,31 +245,14 @@ export abstract class CubismRenderer {
|
||||||
public abstract doDrawModel(): void;
|
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(
|
protected abstract saveProfile(): void;
|
||||||
textureNo: number,
|
|
||||||
indexCount: number,
|
/**
|
||||||
vertexCount: number,
|
* モデル描画直前のレンダラのステートを復帰する
|
||||||
indexArray: Uint16Array,
|
*/
|
||||||
vertexArray: Float32Array,
|
protected abstract restoreProfile(): void;
|
||||||
uvArray: Float32Array,
|
|
||||||
multiplyColor: CubismTextureColor,
|
|
||||||
screenColor: CubismTextureColor,
|
|
||||||
opacity: number,
|
|
||||||
colorBlendMode: CubismBlendMode,
|
|
||||||
invertedMask: boolean
|
|
||||||
): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* レンダラが保持する静的なリソースを開放する
|
* レンダラが保持する静的なリソースを開放する
|
||||||
|
@ -236,12 +265,13 @@ export abstract class CubismRenderer {
|
||||||
protected _isPremultipliedAlpha: boolean; // 乗算済みαならtrue
|
protected _isPremultipliedAlpha: boolean; // 乗算済みαならtrue
|
||||||
protected _anisotropy: any; // テクスチャの異方性フィルタリングのパラメータ
|
protected _anisotropy: any; // テクスチャの異方性フィルタリングのパラメータ
|
||||||
protected _model: CubismModel; // レンダリング対象のモデル
|
protected _model: CubismModel; // レンダリング対象のモデル
|
||||||
|
protected _useHighPrecisionMask: boolean; // falseの場合、マスクを纏めて描画する trueの場合、マスクはパーツ描画ごとに書き直す
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CubismBlendMode {
|
export enum CubismBlendMode {
|
||||||
CubismBlendMode_Normal = 0, // 通常
|
CubismBlendMode_Normal = 0, // 通常
|
||||||
CubismBlendMode_Additive = 1, // 加算
|
CubismBlendMode_Additive = 1, // 加算
|
||||||
CubismBlendMode_Multiplicative = 2, // 乗算
|
CubismBlendMode_Multiplicative = 2 // 乗算
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -251,11 +281,11 @@ export class CubismTextureColor {
|
||||||
/**
|
/**
|
||||||
* コンストラクタ
|
* コンストラクタ
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor(r = 1.0, g = 1.0, b = 1.0, a = 1.0) {
|
||||||
this.R = 1.0;
|
this.R = r;
|
||||||
this.G = 1.0;
|
this.G = g;
|
||||||
this.B = 1.0;
|
this.B = b;
|
||||||
this.A = 1.0;
|
this.A = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
R: number; // 赤チャンネル
|
R: number; // 赤チャンネル
|
||||||
|
@ -264,6 +294,75 @@ export class CubismTextureColor {
|
||||||
A: number; // αチャンネル
|
A: number; // αチャンネル
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* クリッピングマスクのコンテキスト
|
||||||
|
*/
|
||||||
|
export abstract class CubismClippingContext {
|
||||||
|
/**
|
||||||
|
* 引数付きコンストラクタ
|
||||||
|
*/
|
||||||
|
public constructor(clippingDrawableIndices: Int32Array, clipCount: number) {
|
||||||
|
// クリップしている(=マスク用の)Drawableのインデックスリスト
|
||||||
|
this._clippingIdList = clippingDrawableIndices;
|
||||||
|
|
||||||
|
// マスクの数
|
||||||
|
this._clippingIdCount = clipCount;
|
||||||
|
|
||||||
|
this._allClippedDrawRect = new csmRect();
|
||||||
|
this._layoutBounds = new csmRect();
|
||||||
|
|
||||||
|
this._clippedDrawableIndexList = [];
|
||||||
|
|
||||||
|
this._matrixForMask = new CubismMatrix44();
|
||||||
|
this._matrixForDraw = new CubismMatrix44();
|
||||||
|
|
||||||
|
this._bufferIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このマスクを管理するマネージャのインスタンスを取得する
|
||||||
|
* @return クリッピングマネージャのインスタンス
|
||||||
|
*/
|
||||||
|
public abstract getClippingManager(): ICubismClippingManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* デストラクタ相当の処理
|
||||||
|
*/
|
||||||
|
public release(): void {
|
||||||
|
if (this._layoutBounds != null) {
|
||||||
|
this._layoutBounds = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._allClippedDrawRect != null) {
|
||||||
|
this._allClippedDrawRect = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._clippedDrawableIndexList != null) {
|
||||||
|
this._clippedDrawableIndexList = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このマスクにクリップされる描画オブジェクトを追加する
|
||||||
|
*
|
||||||
|
* @param drawableIndex クリッピング対象に追加する描画オブジェクトのインデックス
|
||||||
|
*/
|
||||||
|
public addClippedDrawable(drawableIndex: number) {
|
||||||
|
this._clippedDrawableIndexList.push(drawableIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public _isUsing: boolean; // 現在の描画状態でマスクの準備が必要ならtrue
|
||||||
|
public readonly _clippingIdList: Int32Array; // クリッピングマスクのIDリスト
|
||||||
|
public _clippingIdCount: number; // クリッピングマスクの数
|
||||||
|
public _layoutChannelNo: number; // RGBAのいずれのチャンネルにこのクリップを配置するか(0:R, 1:G, 2:B, 3:A)
|
||||||
|
public _layoutBounds: csmRect; // マスク用チャンネルのどの領域にマスクを入れるか(View座標-1~1, UVは0~1に直す)
|
||||||
|
public _allClippedDrawRect: csmRect; // このクリッピングで、クリッピングされるすべての描画オブジェクトの囲み矩形(毎回更新)
|
||||||
|
public _matrixForMask: CubismMatrix44; // マスクの位置計算結果を保持する行列
|
||||||
|
public _matrixForDraw: CubismMatrix44; // 描画オブジェクトの位置計算結果を保持する行列
|
||||||
|
public _clippedDrawableIndexList: number[]; // このマスクにクリップされる描画オブジェクトのリスト
|
||||||
|
public _bufferIndex: number; // このマスクが割り当てられるレンダーテクスチャ(フレームバッファ)やカラーバッファのインデックス
|
||||||
|
}
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
import * as $ from './cubismrenderer';
|
import * as $ from './cubismrenderer';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,7 @@ import {
|
||||||
CSM_LOG_LEVEL_ERROR,
|
CSM_LOG_LEVEL_ERROR,
|
||||||
CSM_LOG_LEVEL_INFO,
|
CSM_LOG_LEVEL_INFO,
|
||||||
CSM_LOG_LEVEL_VERBOSE,
|
CSM_LOG_LEVEL_VERBOSE,
|
||||||
CSM_LOG_LEVEL_WARNING,
|
CSM_LOG_LEVEL_WARNING
|
||||||
} from '../cubismframeworkconfig';
|
} from '../cubismframeworkconfig';
|
||||||
import { CubismFramework, LogLevel } from '../live2dcubismframework';
|
import { CubismFramework, LogLevel } from '../live2dcubismframework';
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,8 @@ export abstract class Value {
|
||||||
|
|
||||||
public static errorValue: Value; // 一時的な返り値として返すエラー。 CubismFramework::Disposeするまではdeleteしない
|
public static errorValue: Value; // 一時的な返り値として返すエラー。 CubismFramework::Disposeするまではdeleteしない
|
||||||
public static nullValue: Value; // 一時的な返り値として返すNULL。 CubismFramework::Disposeするまではdeleteしない
|
public static nullValue: Value; // 一時的な返り値として返すNULL。 CubismFramework::Disposeするまではdeleteしない
|
||||||
|
|
||||||
|
[key: string]: any; // 明示的に連想配列をany型で指定
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,7 +237,7 @@ export class CubismJson {
|
||||||
this._root = null;
|
this._root = null;
|
||||||
|
|
||||||
if (buffer != undefined) {
|
if (buffer != undefined) {
|
||||||
this.parseBytes(buffer, length);
|
this.parseBytes(buffer, length, this._parseCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +250,11 @@ export class CubismJson {
|
||||||
*/
|
*/
|
||||||
public static create(buffer: ArrayBuffer, size: number) {
|
public static create(buffer: ArrayBuffer, size: number) {
|
||||||
const json = new CubismJson();
|
const json = new CubismJson();
|
||||||
const succeeded: boolean = json.parseBytes(buffer, size);
|
const succeeded: boolean = json.parseBytes(
|
||||||
|
buffer,
|
||||||
|
size,
|
||||||
|
json._parseCallback
|
||||||
|
);
|
||||||
|
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
CubismJson.delete(json);
|
CubismJson.delete(json);
|
||||||
|
@ -280,7 +286,7 @@ export class CubismJson {
|
||||||
* @param buffer 変換するバイナリデータ
|
* @param buffer 変換するバイナリデータ
|
||||||
* @return 変換後の文字列
|
* @return 変換後の文字列
|
||||||
*/
|
*/
|
||||||
public arrayBufferToString(buffer: ArrayBuffer): string {
|
public static arrayBufferToString(buffer: ArrayBuffer): string {
|
||||||
const uint8Array: Uint8Array = new Uint8Array(buffer);
|
const uint8Array: Uint8Array = new Uint8Array(buffer);
|
||||||
let str = '';
|
let str = '';
|
||||||
|
|
||||||
|
@ -295,7 +301,7 @@ export class CubismJson {
|
||||||
/**
|
/**
|
||||||
* エンコード、パディング
|
* エンコード、パディング
|
||||||
*/
|
*/
|
||||||
private pad(n: string): string {
|
private static pad(n: string): string {
|
||||||
return n.length < 2 ? '0' + n : n;
|
return n.length < 2 ? '0' + n : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,10 +312,20 @@ export class CubismJson {
|
||||||
* return true : 成功
|
* return true : 成功
|
||||||
* return false: 失敗
|
* return false: 失敗
|
||||||
*/
|
*/
|
||||||
public parseBytes(buffer: ArrayBuffer, size: number): boolean {
|
public parseBytes(
|
||||||
|
buffer: ArrayBuffer,
|
||||||
|
size: number,
|
||||||
|
parseCallback?: parseJsonObject
|
||||||
|
): boolean {
|
||||||
const endPos: number[] = new Array<number>(1); // 参照渡しにするため配列
|
const endPos: number[] = new Array<number>(1); // 参照渡しにするため配列
|
||||||
const decodeBuffer: string = this.arrayBufferToString(buffer);
|
const decodeBuffer: string = CubismJson.arrayBufferToString(buffer);
|
||||||
this._root = this.parseValue(decodeBuffer, size, 0, endPos);
|
|
||||||
|
if (parseCallback == undefined) {
|
||||||
|
this._root = this.parseValue(decodeBuffer, size, 0, endPos);
|
||||||
|
} else {
|
||||||
|
// TypeScript標準のJSONパーサを使う
|
||||||
|
this._root = parseCallback(JSON.parse(decodeBuffer), new JsonMap());
|
||||||
|
}
|
||||||
|
|
||||||
if (this._error) {
|
if (this._error) {
|
||||||
let strbuf = '\0';
|
let strbuf = '\0';
|
||||||
|
@ -704,11 +720,17 @@ export class CubismJson {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_parseCallback: parseJsonObject = CubismJsonExtension.parseJsonObject; // パース時に使う処理のコールバック関数
|
||||||
|
|
||||||
_error: string; // パース時のエラー
|
_error: string; // パース時のエラー
|
||||||
_lineCount: number; // エラー報告に用いる行数カウント
|
_lineCount: number; // エラー報告に用いる行数カウント
|
||||||
_root: Value; // パースされたルート要素
|
_root: Value; // パースされたルート要素
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface parseJsonObject {
|
||||||
|
(obj: Value, map: JsonMap): JsonMap;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* パースしたJSONの要素をfloat値として扱う
|
* パースしたJSONの要素をfloat値として扱う
|
||||||
*/
|
*/
|
||||||
|
@ -1230,6 +1252,7 @@ export class JsonMap extends Value {
|
||||||
|
|
||||||
// Namespace definition for compatibility.
|
// Namespace definition for compatibility.
|
||||||
import * as $ from './cubismjson';
|
import * as $ from './cubismjson';
|
||||||
|
import { CubismJsonExtension } from './cubismjsonextension';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
export namespace Live2DCubismFramework {
|
export namespace Live2DCubismFramework {
|
||||||
export const CubismJson = $.CubismJson;
|
export const CubismJson = $.CubismJson;
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
JsonArray,
|
||||||
|
JsonBoolean,
|
||||||
|
JsonFloat,
|
||||||
|
JsonMap,
|
||||||
|
JsonNullvalue,
|
||||||
|
JsonString,
|
||||||
|
Value
|
||||||
|
} from './cubismjson';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CubismJsonで実装されているJsonパーサを使用せず、
|
||||||
|
* TypeScript標準のJsonパーサなどを使用し出力された結果を
|
||||||
|
* Cubism SDKで定義されているJSONエレメントの要素に
|
||||||
|
* 置き換える処理をするクラス。
|
||||||
|
*/
|
||||||
|
export class CubismJsonExtension {
|
||||||
|
static parseJsonObject(obj: Value, map: JsonMap) {
|
||||||
|
Object.keys(obj).forEach((key) => {
|
||||||
|
if (typeof obj[key] == 'boolean') {
|
||||||
|
const convValue = Boolean(obj[key]);
|
||||||
|
map.put(key, new JsonBoolean(convValue));
|
||||||
|
} else if (typeof obj[key] == 'string') {
|
||||||
|
const convValue = String(obj[key]);
|
||||||
|
map.put(key, new JsonString(convValue));
|
||||||
|
} else if (typeof obj[key] == 'number') {
|
||||||
|
const convValue = Number(obj[key]);
|
||||||
|
map.put(key, new JsonFloat(convValue));
|
||||||
|
} else if (obj[key] instanceof Array) {
|
||||||
|
map.put(key, CubismJsonExtension.parseJsonArray(obj[key]));
|
||||||
|
} else if (obj[key] instanceof Object) {
|
||||||
|
map.put(
|
||||||
|
key,
|
||||||
|
CubismJsonExtension.parseJsonObject(obj[key], new JsonMap())
|
||||||
|
);
|
||||||
|
} else if (obj[key] == null) {
|
||||||
|
map.put(key, new JsonNullvalue());
|
||||||
|
} else {
|
||||||
|
// どれにも当てはまらない場合でも処理する
|
||||||
|
map.put(key, obj[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static parseJsonArray(obj: Value) {
|
||||||
|
const arr = new JsonArray();
|
||||||
|
Object.keys(obj).forEach((key) => {
|
||||||
|
const convKey = Number(key);
|
||||||
|
if (typeof convKey == 'number') {
|
||||||
|
if (typeof obj[key] == 'boolean') {
|
||||||
|
const convValue = Boolean(obj[key]);
|
||||||
|
arr.add(new JsonBoolean(convValue));
|
||||||
|
} else if (typeof obj[key] == 'string') {
|
||||||
|
const convValue = String(obj[key]);
|
||||||
|
arr.add(new JsonString(convValue));
|
||||||
|
} else if (typeof obj[key] == 'number') {
|
||||||
|
const convValue = Number(obj[key]);
|
||||||
|
arr.add(new JsonFloat(convValue));
|
||||||
|
} else if (obj[key] instanceof Array) {
|
||||||
|
arr.add(this.parseJsonArray(obj[key]));
|
||||||
|
} else if (obj[key] instanceof Object) {
|
||||||
|
arr.add(this.parseJsonObject(obj[key], new JsonMap()));
|
||||||
|
} else if (obj[key] == null) {
|
||||||
|
arr.add(new JsonNullvalue());
|
||||||
|
} else {
|
||||||
|
// どれにも当てはまらない場合でも処理する
|
||||||
|
arr.add(obj[key]);
|
||||||
|
}
|
||||||
|
} else if (obj[key] instanceof Array) {
|
||||||
|
arr.add(this.parseJsonArray(obj[key]));
|
||||||
|
} else if (obj[key] instanceof Object) {
|
||||||
|
arr.add(this.parseJsonObject(obj[key], new JsonMap()));
|
||||||
|
} else if (obj[key] == null) {
|
||||||
|
arr.add(new JsonNullvalue());
|
||||||
|
} else {
|
||||||
|
const convValue = Array(obj[key]);
|
||||||
|
// 配列ともObjectとも判定できなかった場合でも処理する
|
||||||
|
for (let i = 0; i < convValue.length; i++) {
|
||||||
|
arr.add(convValue[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,9 @@
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true
|
"emitDecoratorMetadata": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"useUnknownInCatchVariables": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
|
|
Loading…
Reference in New Issue