diff --git a/.editorconfig b/.editorconfig index 8b68d775..f5134ac2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -25,3 +25,6 @@ charset = unset [*.md] trim_trailing_whitespace = false + +[*.{cpp,hpp,h}] +charset = utf-8-bom diff --git a/.gitignore b/.gitignore index 2958703e..f0c2ad0a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ # Sample build directories /Samples/**/build/ +# HarmonyOS files +Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/rawfile/ # Sample third party files /Samples/**/thirdParty/* !/Samples/**/thirdParty/scripts/* diff --git a/CHANGELOG.md b/CHANGELOG.md index e82bc5fb..a0d5e426 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,59 @@ 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/). +## [5-r.2] - 2024-12-19 + +### Added + +* Add Vulkan support in Ubuntu 22.04 and AlmaLinux 9. +* Add a function to notify when motion playback starts. +* Add shader setup classes for D3D9, D3D11, OpenGL, Vulkan. +* Add the sample for OpenGL API in HarmonyOS. + +### Changed + +* Change to overwrite motion fade by the value specified in .model3.json on Framework. +* Change to use multi-buffering in Vulkan. +* Change the screen orientation and rotation direction to be unified across Android, iPhone, and iPad. +* Change specify the NDK version of the Android sample. +* Change to read shader source codes from files. +* Change the compile and target SDK version of Android OS to 15.0 (API 35). + * Upgrade the version of Android Gradle Plugin from 8.1.1 to 8.6.1. + * Upgrade the version of Gradle from 8.2 to 8.7. + * Upgrade the version of NDK from 25.2.9519653 to 26.3.11579264. + * Change the minimum version of Android Studio to Ladybug(2024.2.1 Patch 2). +* Change the minimum support version of Java to 8. +* Change the function for playing back expression motions from CubismExpressionMotionManager::StartMotionPriority() to CubismExpressionMotionManager::StartMotion(). +* Change to use GLSurfaceView event queues to handle touch events. + +### Fixed + +* Fix memory leak in Vulkan. +* Fixed drawing failure when enabling `USE_RENDER_TARGET` macros in Vulkan samples. +* Fix memory leak when exit in D3D9 and D3D11. +* Fix exit error in Vulkan. +* Fix the processing of anisotropy filtering in Vulkan to match that of other renderers. +* Fix an issue on Windows where an error would occur if the model name contained certain characters. +* Implement support for `MSVC19.40` in the VS2022 build. by [@tatsuya-shiozawa](https://github.com/Live2D/CubismNativeSamples/pull/46) +* Fix an issue where a compile error occurred due to missing includes in the OpenGL iOS minimum sample. +* Fix an issue in the Android sample where the model display would reset after performing certain operations. +* Fix a memory leak in the compilation process of shader strings in OpenGL. +* Fix an issue that could cause drawing errors when the application is restored from the background. +* Fix an issue in the OpenGL sample where the textures are not released. +* Fix a warning due to the initial value of programId being NULL. +* Fix an issue that caused white edge-like objects to be drawn when enabling the `USE_RENDER_TARGET` or `USE_MODEL_RENDER_TARGET` flag in `LAppLive2DManager`. +* Fix an issue causing a decrease in rendering resolution when using render targets in the Metal sample project. +* Fix an issue where rendering would break when using the iPad with `USE_RENDER_TARGET` or `USE_MODEL_RENDER_TARGET` defined in OpenGL samples. + +### Removed + +* Remove Visual Studio 2013 samples. +* Remove armeabi-v7a from architecture support. +* Remove the Cocos2d-x sample project. +* Remove the callback what motion playback finishes on the minimum sample. +* Remove unnecessary declarations in the OpenGL Android sample. + + ## [5-r.1] - 2024-03-26 ### Added @@ -17,6 +70,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * The log function was changed because it was ambiguous whether or not a newline was inserted. * Change so that `LAppSprite` is not depend on `LAppDelegate` in D3D11 and D3D9, Metal, Vulkan. * Some function arguments in `LAppSprite` are changed in D3D11 and D3D9, Metal, Vulkan. +* Change to read shader source codes from files. ### Fixed @@ -43,7 +97,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Change so that `LAppSprite` is not depend on `LAppDelegate` in Android. * Change so that `ViewController` is not include on `LAppSprite` in iOS. * Change the path acquisition process to a library function on OpenGL Mac and Linux. -* Change the compile and target SDK version of Android OS to 14.0 (API 34). +* Change the compile and target SDK version of Android OS to 14.0 (API 34). * Upgrade the version of Android Gradle Plugin from 8.0.2 to 8.1.1. * Upgrade the version of Gradle from 8.1.1 to 8.2. * Change the minimum version of Android Studio to Hedgehog(2023.1.1). @@ -407,6 +461,7 @@ See [Core Changelog] for details. * What was `Package.json` is currently being changed to`cubism-info.yml`. +[5-r.2]: https://github.com/Live2D/CubismNativeSamples/compare/5-r.1...5-r.2 [5-r.1]: https://github.com/Live2D/CubismNativeSamples/compare/5-r.1-beta.4...5-r.1 [5-r.1-beta.4]: https://github.com/Live2D/CubismNativeSamples/compare/5-r.1-beta.3...5-r.1-beta.4 [5-r.1-beta.3]: https://github.com/Live2D/CubismNativeSamples/compare/5-r.1-beta.2...5-r.1-beta.3 diff --git a/Core/CHANGELOG.md b/Core/CHANGELOG.md index afe4260c..04b3de48 100644 --- a/Core/CHANGELOG.md +++ b/Core/CHANGELOG.md @@ -5,6 +5,31 @@ 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/). +## 2024-12-19 + +### Removed + +* [Native] Remove Visual Studio 2013 (MSVC 120) static library. + + +## 2024-11-07 + +### Added + +* [Native] Add experimental support `arm64` library for linux. + +### Removed + +* [Unity,Native,Java] Remove Android ARM v7 library. + + +## 2024-04-04 + +### Added + +* [Unity] Add library(.so) for HarmonyOS build. + + ## 2024-03-26 ### Remove diff --git a/Core/README.ja.md b/Core/README.ja.md index 3898c395..92cd9654 100644 --- a/Core/README.ja.md +++ b/Core/README.ja.md @@ -29,12 +29,12 @@ Core | プラットフォーム | アーキテクチャ | dll | lib | パス | 注記 | | --- | --- | --- | --- | --- | --- | | Android | ARM64 | ✓ | ✓ | android/arm64-v8a | | -| Android | ARMv7 | ✓ | ✓ | android/armeabi-v7a | このライブラリは現在非推奨で、近日中に削除される予定です。 | | Android | x86 | ✓ | ✓ | android/x86 | | | Android | x86_64 | ✓ | ✓ | android/x86_64 | | | iOS | ARM64 | | ✓ | ios/xxx-iphoneos | iOSデバイス | | iOS | x86_64 | | ✓ | ios/xxx-iphonesimulator | iOS Simulator | | Linux | x86_64 | ✓ | ✓ | linux/x86_64 | | +| Linux | ARM64 | ✓ | ✓ | experimental/linux/ARM64 | | | macOS | ARM64 | ✓ | ✓ | macos/arm64 | | | macOS | x86_64 | ✓ | ✓ | macos/x86_64 | | | Mac Catalyst | ARM64 | | ✓ | experimental/catalyst | Universal Binary | @@ -59,7 +59,6 @@ Core | VC++バージョン | Visual Studioバージョン | | ---: | --- | -| 120 | Visual Studio 2013 | | 140 | Visual Studio 2015 | | 141 | Visual Studio 2017 | | 142 | Visual Studio 2019 | diff --git a/Core/README.md b/Core/README.md index 95b6f78a..e7832937 100644 --- a/Core/README.md +++ b/Core/README.md @@ -31,12 +31,12 @@ Core | Platform | Architecture | dll | lib | Path | Note | | --- | --- | --- | --- | --- | --- | | Android | ARM64 | ✓ | ✓ | android/arm64-v8a | | -| Android | ARMv7 | ✓ | ✓ | android/armeabi-v7a | This library is currently deprecated and will be removed in the near future. | | Android | x86 | ✓ | ✓ | android/x86 | | | Android | x86_64 | ✓ | ✓ | android/x86_64 | | | iOS | ARM64 | | ✓ | ios/xxx-iphoneos | iOS Devices | | iOS | x86_64 | | ✓ | ios/xxx-iphonesimulator | iOS Simulator | | Linux | x86_64 | ✓ | ✓ | linux/x86_64 | | +| Linux | ARM64 | ✓ | ✓ | experimental/linux/ARM64 | | | macOS | ARM64 | ✓ | ✓ | macos/arm64 | | | macOS | x86_64 | ✓ | ✓ | macos/x86_64 | | | Mac Catalyst | ARM64 | | ✓ | experimental/catalyst | Universal Binary | @@ -61,7 +61,6 @@ Below is the Visual Studio version for the VC++ version. | VC++ version | Visual Studio version | | ---: | --- | -| 120 | Visual Studio 2013 | | 140 | Visual Studio 2015 | | 141 | Visual Studio 2017 | | 142 | Visual Studio 2019 | diff --git a/Core/RedistributableFiles.txt b/Core/RedistributableFiles.txt index 6f02cc2d..c20397fb 100644 --- a/Core/RedistributableFiles.txt +++ b/Core/RedistributableFiles.txt @@ -2,7 +2,6 @@ The following is a list of files available for redistribution under the terms of the Live2D Proprietary Software License Agreement: - dll/android/arm64-v8a/libLive2DCubismCore.so -- dll/android/armeabi-v7a/libLive2DCubismCore.so - dll/android/x86/libLive2DCubismCore.so - dll/android/x86_64/libLive2DCubismCore.so - dll/experimental/rpi/libLive2DCubismCore.so @@ -11,6 +10,7 @@ under the terms of the Live2D Proprietary Software License Agreement: - dll/experimental/uwp/x64/Live2DCubismCore.dll - dll/experimental/uwp/x86/Live2DCubismCore.dll - dll/linux/x86_64/libLive2DCubismCore.so +- dll/experimental/linux/arm64/libLive2DCubismCore.so - dll/macos/Live2DCubismCore.bundle - dll/macos/libLive2DCubismCore.dylib - dll/windows/x86/Live2DCubismCore.dll @@ -18,7 +18,6 @@ under the terms of the Live2D Proprietary Software License Agreement: - dll/windows/x86_64/Live2DCubismCore.dll - dll/windows/x86_64/Live2DCubismCore.lib - lib/android/arm64-v8a/libLive2DCubismCore.a -- lib/android/armeabi-v7a/libLive2DCubismCore.a - lib/android/x86/libLive2DCubismCore.a - lib/android/x86_64/libLive2DCubismCore.so - lib/experimental/catalyst/libLive2DCubismCore.a @@ -28,12 +27,9 @@ under the terms of the Live2D Proprietary Software License Agreement: - lib/ios/Release-iphoneos/libLive2DCubismCore.a - lib/ios/Release-iphonesimulator/libLive2DCubismCore.a - lib/linux/x86_64/libLive2DCubismCore.a +- lib/experimental/linux/arm64/libLive2DCubismCore.a - lib/macos/arm64/libLive2DCubismCore.a - lib/macos/x86_64/libLive2DCubismCore.a -- lib/windows/x86/120/Live2DCubismCore_MD.lib -- lib/windows/x86/120/Live2DCubismCore_MDd.lib -- lib/windows/x86/120/Live2DCubismCore_MT.lib -- lib/windows/x86/120/Live2DCubismCore_MTd.lib - lib/windows/x86/140/Live2DCubismCore_MD.lib - lib/windows/x86/140/Live2DCubismCore_MDd.lib - lib/windows/x86/140/Live2DCubismCore_MT.lib @@ -50,10 +46,6 @@ under the terms of the Live2D Proprietary Software License Agreement: - lib/windows/x86/143/Live2DCubismCore_MDd.lib - lib/windows/x86/143/Live2DCubismCore_MT.lib - lib/windows/x86/143/Live2DCubismCore_MTd.lib -- lib/windows/x86_64/120/Live2DCubismCore_MD.lib -- lib/windows/x86_64/120/Live2DCubismCore_MDd.lib -- lib/windows/x86_64/120/Live2DCubismCore_MT.lib -- lib/windows/x86_64/120/Live2DCubismCore_MTd.lib - lib/windows/x86_64/140/Live2DCubismCore_MD.lib - lib/windows/x86_64/140/Live2DCubismCore_MDd.lib - lib/windows/x86_64/140/Live2DCubismCore_MT.lib diff --git a/Framework b/Framework index 3d9f82a4..5a5e4923 160000 --- a/Framework +++ b/Framework @@ -1 +1 @@ -Subproject commit 3d9f82a47f3f9c8c89ae692703f2dad79296b61a +Subproject commit 5a5e4923c245944d71fe93a875385bb15ba0e206 diff --git a/NOTICE.ja.md b/NOTICE.ja.md index 2bc598e6..7db61234 100644 --- a/NOTICE.ja.md +++ b/NOTICE.ja.md @@ -4,6 +4,12 @@ # お知らせ +## [注意事項] Cubism SDK for NativeのCocos2d-xサポートについて (2024-12-19) + +Cubism SDK for NativeのCocos2d-x対応につきまして、Cubism 5 SDK for Native R2でサポートを終了いたしました。 +本件のお問い合わせにつきましては、[お問合せフォーム]()からご連絡ください。  + + ## [注意事項] Apple社のPrivacy Manifest Policy対応について Apple社が対応を必要としているPrivacy Manifest Policyについて、本製品では指定されているAPI及びサードパーティ製品を使用しておりません。 @@ -36,26 +42,9 @@ MetalのMac Catalystのビルド時にエラーが発生する場合がござい * cmakeを3.27未満のバージョンで使用する -## [注意事項] Cocos2d-xセットアップのエラーについて (2022-03-15) - -Cocos2d-xサンプルプロジェクトのセットアップ時に実行するsetup-cocos2dバッチにおいてエラーが発生いたします。 -これはGitHubがGitプロトコルセキュリティを改善したことに起因し、GitにてCocos2d-xのsubmodule取得が失敗するためです。 -具体的には`git://`経由での接続ができなくなったためエラーが発生しています。 +## [注意事項] Metal の macOSサンプルビルドにおけるメモリリークについて (2021-12-09) -詳しくはGitHub公式ブログをご確認ください。 - -* [GitHub 公式ブログ](https://github.blog/2021-09-01-improving-git-protocol-security-github/) - -### 回避方法 - -* ターミナルもしくはコマンドプロンプトにて以下のコマンドを実行することで、`git://`を用いた接続を`https://`に置き換える - * `git config --global url."https://github.com/".insteadOf git://github.com/` - * このコマンドは実行端末の全ユーザのgitconfigに影響します。ご了承ください。 - - -## [注意事項] Metal及びCocos2d-x v4.0 の macOSサンプルビルドにおけるメモリリークについて (2021-12-09) - -Metal及びCocos2d-x v4.0 の macOSサンプルビルドにおいてメモリリークが発生いたします。 +Metal の macOSサンプルビルドにおいてメモリリークが発生いたします。 これはMetalフレームワーク内で発生するため、公式の対応をお待ち下さい。 本件のお問い合わせについて弊社ではお答えいたしかねますので、ご了承ください。 @@ -64,35 +53,6 @@ Metal及びCocos2d-x v4.0 の macOSサンプルビルドにおいてメモリリ * [Apple Developer Forums - Memory leak in MTLCommandBuffer?](https://developer.apple.com/forums/thread/120931) -## [制限事項] Cocos2d-x v4.0 の Linux(Ubuntu)サンプルビルドについて (2021-04-15) - -Cocos2d-x v4.0 は `Ubuntu 20.04` ビルドに対応しておりません。 -使用する際は以下の回避方法を確認し、いずれかを適用してご利用いただきますようお願いいたします。 - -### 回避方法 - -* `Ubuntu 16.04` または `Ubuntu 18.04` を使用する - -* 以下issueを確認し、`Cocos2d-x v4.0` で使用されている `libchipmunk` ライブラリを差し替える - * [cocos2d/cocos2d-x linking error when integrating with libchipmunk on linux#20471](https://github.com/cocos2d/cocos2d-x/issues/20471) - * WARNING: この回避方法を使用してビルドしたプロジェクトはいかなる場合でも保守いたしかねます - - -## [注意事項] Visual Studio 2013 ご利用時の OpenGL サンプルビルドについて (2021-02-17) - -`Visual Studio 2013` を使用した `OpenGL` サンプルビルドでは、`setup_glew_glfw.bat` をそのまま使用してビルドすると `GLEW` にてリンクエラーが発生します。 -以下回避方法を確認し、ご利用いただきますようお願いいたします。 - -### 回避方法 - -* `GLEW 2.2.0` を使用する場合 - * `glew` プロジェクトから `libvcruntime.lib` の参照を削除する - * `Visual Studio 2013` 以降の Visual Studio を使用する - -* `GLEW 2.1.0` を使用する場合 - * `setup_glew_glfw_vs2013.bat` を使用して `thirdParty` のセットアップを行う - - ## Cubism Core ### [注意事項] macOS Catalina 以降のバージョンでの `.bundle` と `.dylib` の利用について diff --git a/NOTICE.md b/NOTICE.md index 36f2b7e6..069c60c9 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -4,6 +4,12 @@ # Notices +## [Caution] Regarding Cubism SDK for Native Cocos2d-x Support (2024-12-19) + +Support for Cocos2d-x in the Cubism SDK for Native has been discontinued starting with Cubism 5 SDK for Native R2. +For any inquiries regarding this matter, please contact us through the [contact form]](). + + ## [Caution] Support for Apple's Privacy Manifest Policy This product does not use the APIs or third-party products specified in Apple's privacy manifest policy. @@ -36,26 +42,9 @@ We will continue to investigate the details. * Use cmake with versions less than 3.27 -## [Caution] About Cocos2d-x setup error (2022-03-15) - -An error occurs in the setup-cocos2d batch that is executed when setting up the Cocos2d-x sample project. -This is because GitHub has improved the security of the Git protocol, and Git fails to get the Cocos2d-x submodule. -Specifically, an error has occurred because the connection via `git://` is no longer possible. +## [Caution] Memory leak in macOS sample builds of Metal (2021-12-09) -Please check the official GitHub blog for details. - -* [GitHub Official Blog](https://github.blog/2021-09-01-improving-git-protocol-security-github/) - -### Workaround - -* Replace the connection using `git://` with `https://` by executing the following command in the terminal or command prompt. - * `git config --global url."https://github.com/".insteadOf git://github.com/` - * Please note that this command affects gitconfig for all users of the execution terminal. - - -## [Caution] Memory leak in macOS sample builds of Metal and Cocos2d-x v4.0 (2021-12-09) - -A memory leak occurs in the macOS sample builds of Metal and Cocos2d-x v4.0. +A memory leak occurs in the macOS sample builds of Metal. This happens within the Metal framework, so please wait for official support. Note that we cannot answer inquiries regarding this matter. @@ -64,35 +53,6 @@ Please check the Apple Developer Forums for more information. * [Apple Developer Forums - Memory leak in MTLCommandBuffer?](https://developer.apple.com/forums/thread/120931) -## [Limitation] About the Linux (Ubuntu) sample builds of Cocos2d-x v4.0 (2021-04-15) - -Cocos2d-x v4.0 does not support `Ubuntu 20.04` builds. -Please check and apply one of the following workarounds when using it. - -### Workaround - -* Use `Ubuntu 16.04` or `Ubuntu 18.04` - -* Check the following issue and replace the `libchipmunk` library used in `Cocos2d-x v4.0` - * [cocos2d/cocos2d-x linking error when integrating with libchipmunk on linux#20471](https://github.com/cocos2d/cocos2d-x/issues/20471) - * WARNING: Projects built using this workaround cannot be maintained under any circumstances. - - -## [Caution] About OpenGL sample builds when using Visual Studio 2013 (2021-02-17) - -In the `OpenGL` sample builds using `Visual Studio 2013`, a link error will occur in `GLEW` if you build using `setup_glew_glfw.bat` as is. -Please check and use the workaround below. - -### Workaround - -* When using `GLEW 2.2.0` - * Remove the reference to `libvcruntime.lib` from the `glew` project - * Use Visual Studio later than `Visual Studio 2013` - -* When using `GLEW 2.1.0` - * Use `setup_glew_glfw_vs2013.bat` to set up `thirdParty` - - ## Cubism Core ### [Caution] About using `.bundle` and `.dylib` on macOS Catalina or later diff --git a/README.ja.md b/README.ja.md index 0143fc25..0b105a06 100644 --- a/README.ja.md +++ b/README.ja.md @@ -35,7 +35,6 @@ Cubism 5 Editorに搭載された新機能のSDK対応については [こちら ├─ Core # Live2D Cubism Core が含まれるディレクトリ ├─ Framework # レンダリングやアニメーション機能などのソースコードが含まれるディレクトリ └─ Samples - ├─ Cocos2d-x # Cocos2d-x のサンプルプロジェクトが含まれるディレクトリ ├─ D3D9 # DirectX 9.0c のサンプルプロジェクトが含まれるディレクトリ ├─ D3D11 # DirectX 11 のサンプルプロジェクトが含まれるディレクトリ ├─ Metal # Metal のサンプルプロジェクトが含まれるディレクトリ @@ -111,36 +110,37 @@ Core : [CHANGELOG.md](Core/CHANGELOG.md) | 開発ツール | バージョン | | --- | --- | -| Android Studio | Iguana 2023.2.1 | -| CMake | 3.28.3 | -| Visual Studio 2013 | Update 5 | +| Android Studio | Ladybug 2024.2.1 Patch 3 | +| DevEco Studio | 5.0.5.306 | +| CMake | 3.31.2 | | Visual Studio 2015 | Update 3 | -| Visual Studio 2017 | 15.9.60 | -| Visual Studio 2019 | 16.11.34 | -| Visual Studio 2022 | 17.9.4 | -| Xcode | 15.3 | +| Visual Studio 2017 | 15.9.68 | +| Visual Studio 2019 | 16.11.42 | +| Visual Studio 2022 | 17.12.3 | +| Xcode | 16.2 | ### Android | Android SDK tools | バージョン | | --- | --- | -| Android NDK | 26.2.11394342 | -| Android SDK | 34.0.0 | +| Android NDK | 26.3.11579264 | +| Android SDK | 35.0.0 | | CMake | 3.22.1 | +### HarmonyOS + +| HarmonyOS SDK tools | バージョン | +| --- | --- | +| HarmonyOS SDK | 5.0.1.112 | + ### Linux | 系統 | ディストリビューション・バージョン | Docker イメージ | GCC | | --- | --- | --- | --- | | Red Hat | Amazon Linux 2 | `amazonlinux:2` | 7.3.1 | -| Red Hat | CentOS 7 | `centos:7` | 4.8.5 | -| Red Hat | CentOS Stream 8 *1 | `centos:latest` | 8.5.0 | -| Red Hat | CentOS Stream 9 | - | 12.2.1 | | Red Hat | AlmaLinux | `almalinux:latest` | 11.4.1 | -| Debian | Ubuntu 18.04 | `ubuntu:18.04` | 7.5.0 | | Debian | Ubuntu 22.04.4 | `ubuntu:22.04` | 11.4.0 | - -*1 CentOS 8はサポートしておりません +| Debian | Ubuntu 24.04.1 | `ubuntu:24.04` | 13.3.0 | #### Mesa ライブラリ @@ -156,25 +156,31 @@ Core : [CHANGELOG.md](Core/CHANGELOG.md) | プラットフォーム | バージョン | | --- | --- | -| iOS / iPadOS | 17.4 | -| macOS | 14.4 | -| Windows 10 | 22H2 | -| Windows 11 | 22H2 | +| iOS / iPadOS | 18.2 | +| macOS | 15.2 | +| Windows 10 | 23H2 | +| Windows 11 | 23H2 | ### Android | バージョン | デバイス | Tegra | | --- | --- | --- | -| 13 | Pixel 7a | | +| 15 | Pixel 7a | | | 7.1.1 | Nexus 9 | ✔︎ | +### HarmonyOS + +| バージョン | デバイス | +| --- | --- | +| NEXT.0.0.71 | HUAWEI Mate 60 Pro | + ### Linux | 系統 | ディストリビューション | バージョン | | --- | --- | --- | | Red Hat | Amazon Linux | 2 | | Red Hat | AlmaLinux | 9 | -| Debian | Ubuntu | 22.04.4 | +| Debian | Ubuntu | 24.04.1 | ## プロジェクトへの貢献 diff --git a/README.md b/README.md index f047544b..c277c656 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ For compatibility with previous versions of Cubism SDK, please refer to [here](h ├─ Core # Directory containing Live2D Cubism Core ├─ Framework # Directory containing source code for rendering and animation functions └─ Samples - ├─ Cocos2d-x # Directory containing the Cocos2d-x sample project ├─ D3D9 # Directory containing the DirectX 9.0c sample project ├─ D3D11 # Directory containing the DirectX 11 sample project ├─ Metal # Directory containing the Metal sample project @@ -110,36 +109,37 @@ Core : [CHANGELOG.md](Core/CHANGELOG.md) | Development Tool | Version | | --- | --- | -| Android Studio | Iguana 2023.2.1 | -| CMake | 3.28.3 | -| Visual Studio 2013 | Update 5 | +| Android Studio | Ladybug 2024.2.1 Patch 3 | +| DevEco Studio | 5.0.5.306 | +| CMake | 3.31.2 | | Visual Studio 2015 | Update 3 | -| Visual Studio 2017 | 15.9.60 | -| Visual Studio 2019 | 16.11.34 | -| Visual Studio 2022 | 17.9.4 | -| Xcode | 15.3 | +| Visual Studio 2017 | 15.9.68 | +| Visual Studio 2019 | 16.11.42 | +| Visual Studio 2022 | 17.12.3 | +| Xcode | 16.2 | ### Android | Android SDK tools | Version | | --- | --- | -| Android NDK | 26.2.11394342 | -| Android SDK | 34.0.0 | +| Android NDK | 26.3.11579264 | +| Android SDK | 35.0.0 | | CMake | 3.22.1 | +### HarmonyOS + +| HarmonyOS SDK tools | Version | +| --- | --- | +| HarmonyOS SDK | 5.0.1.112 | + ### Linux | System | Distribution version | Docker image | GCC | | --- | --- | --- | --- | | Red Hat | Amazon Linux 2 | `amazonlinux:2` | 7.3.1 | -| Red Hat | CentOS 7 | `centos:7` | 4.8.5 | -| Red Hat | CentOS Stream 8 *1 | `centos:latest` | 8.5.0 | -| Red Hat | CentOS Stream 9 | - | 12.2.1 | | Red Hat | AlmaLinux | `almalinux:latest` | 11.4.1 | -| Debian | Ubuntu 18.04 | `ubuntu:18.04` | 7.5.0 | | Debian | Ubuntu 22.04.4 | `ubuntu:22.04` | 11.4.0 | - -*1 CentOS 8 is not supported +| Debian | Ubuntu 24.04.1 | `ubuntu:24.04` | 13.3.0 | #### Mesa library @@ -155,25 +155,31 @@ Core : [CHANGELOG.md](Core/CHANGELOG.md) | Platform | Version | | --- | --- | -| iOS / iPadOS | 17.4 | -| macOS | 14.4 | -| Windows 10 | 22H2 | -| Windows 11 | 22H2 | +| iOS / iPadOS | 18.2 | +| macOS | 15.2 | +| Windows 10 | 23H2 | +| Windows 11 | 23H2 | ### Android | Version | Device | Tegra | | --- | --- | --- | -| 13 | Pixel 7a | | +| 15 | Pixel 7a | | | 7.1.1 | Nexus 9 | ✔︎ | +### HarmonyOS + +| Version | Device | +| --- | --- | +| NEXT.0.0.71 | HUAWEI Mate 60 Pro | + ### Linux | System | Distribution | Version | | --- | --- | --- | | Red Hat | Amazon Linux | 2 | | Red Hat | AlmaLinux | 9 | -| Debian | Ubuntu | 22.04.4 | +| Debian | Ubuntu | 24.04.1 | ## Contributing diff --git a/Samples/Cocos2d-x/.editorconfig b/Samples/Cocos2d-x/.editorconfig deleted file mode 100644 index 08ffcc45..00000000 --- a/Samples/Cocos2d-x/.editorconfig +++ /dev/null @@ -1,5 +0,0 @@ -[/Demo/Classes/**/*.{h,cpp,hpp}] -charset = utf-8-bom - -[/Demo/proj.win/src/**/*.{h,cpp}] -charset = utf-8-bom diff --git a/Samples/Cocos2d-x/Demo/CMakeLists.txt b/Samples/Cocos2d-x/Demo/CMakeLists.txt deleted file mode 100644 index 2152daae..00000000 --- a/Samples/Cocos2d-x/Demo/CMakeLists.txt +++ /dev/null @@ -1,306 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -option( - CORE_CRL_MD - "Use Cubism Core that is multithread-specific and DLL-specific version" - OFF -) - -# Set app name. -set(APP_NAME Demo) -# Set directory paths. -set(COCOS2DX_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../thirdParty/cocos2d) -set(CMAKE_MODULE_PATH ${COCOS2DX_ROOT_PATH}/cmake/Modules) -set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../..) -set(CORE_PATH ${SDK_ROOT_PATH}/Core) -set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) -set(CLASSES_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Classes) -set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) - -# Set project. -project(${APP_NAME}) - -# Set Visual Studio startup project. -set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT ${APP_NAME}) - -# Define output directory. -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/${APP_NAME}) -# Set configuration (Release and Debug only). -set(CMAKE_CONFIGURATION_TYPES Debug Release - CACHE STRING "Configurations" FORCE -) -# Suppress generation of ZERO_CHECK project. -set(CMAKE_SUPPRESS_REGENERATION ON) - -# Specify version of compiler. -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -# Add cocos libs. -include(CocosBuildSet) -add_subdirectory( - ${COCOS2DX_ROOT_PATH}/cocos - ${ENGINE_BINARY_PATH}/cocos/core -) - -# Record sources, headers, resources... -set(GAME_SOURCE) -set(GAME_HEADER) - -# Add resource directories. -set(GAME_RES_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/Resources ${RES_PATH}) -if(APPLE OR WINDOWS) - cocos_mark_multi_resources(common_res_files - RES_TO Resources FOLDERS ${GAME_RES_FOLDER} - ) -endif() - -# Add cross-platforms source files and header files. -list(APPEND GAME_SOURCE - ${CLASSES_PATH}/AppDelegate.cpp - ${CLASSES_PATH}/LAppAllocator.cpp - ${CLASSES_PATH}/LAppDefine.cpp - ${CLASSES_PATH}/LAppLive2DManager.cpp - ${CLASSES_PATH}/LAppModel.cpp - ${CLASSES_PATH}/LAppPal.cpp - ${CLASSES_PATH}/LAppSprite.cpp - ${CLASSES_PATH}/LAppView.cpp - ${CLASSES_PATH}/SampleScene.cpp - ${CLASSES_PATH}/TouchManager.cpp - ${CLASSES_PATH}/LAppLive2DManagerInternal.cpp -) - -list(APPEND GAME_HEADER - ${CLASSES_PATH}/AppDelegate.h - ${CLASSES_PATH}/AppMacros.h - ${CLASSES_PATH}/LAppAllocator.hpp - ${CLASSES_PATH}/LAppDefine.hpp - ${CLASSES_PATH}/LAppLive2DManager.hpp - ${CLASSES_PATH}/LAppModel.hpp - ${CLASSES_PATH}/LAppPal.hpp - ${CLASSES_PATH}/LAppSprite.hpp - ${CLASSES_PATH}/LAppView.hpp - ${CLASSES_PATH}/SampleScene.h - ${CLASSES_PATH}/TouchManager.h - ${CLASSES_PATH}/LAppLive2DManagerInternal.h -) - -# Add Cubism Core as static library. -add_library(Live2DCubismCore STATIC IMPORTED) -# Specify Cubism Core library path for each platform and add source files. -if(ANDROID) - list(APPEND GAME_SOURCE - proj.android/app/jni/demo/main.cpp - ) - set_target_properties(Live2DCubismCore - PROPERTIES - IMPORTED_LOCATION - ${CORE_PATH}/lib/android/${ANDROID_ABI}/libLive2DCubismCore.a - ) - -elseif(LINUX) - list(APPEND GAME_SOURCE - proj.linux/src/main.cpp) - set_target_properties(Live2DCubismCore - PROPERTIES - IMPORTED_LOCATION - ${CORE_PATH}/lib/linux/x86_64/libLive2DCubismCore.a - ) - -elseif(WINDOWS) - list(APPEND GAME_HEADER - proj.win/src/main.h - proj.win/src/resource.h - ) - list(APPEND GAME_SOURCE - proj.win/src/main.cpp - proj.win/src/game.rc - ${common_res_files} - ) - - # Detect compiler. - if(MSVC_VERSION MATCHES 1900) - # Visual Studio 2015 - set(MSVC_NUM 140) - elseif(MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) - # Visual Studio 2017 - set(MSVC_NUM 141) - elseif(MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) - # Visual Studio 2019 - set(MSVC_NUM 142) - elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) - # Visual Studio 2022 - set(MSVC_NUM 143) - elseif(MSVC) - message(FATAL_ERROR "[${APP_NAME}] Unsupported Visual C++ compiler used.") - else() - message(FATAL_ERROR "[${APP_NAME}] Unsupported compiler used.") - endif() - - # Detect core crt. - if(CORE_CRL_MD) - set(CRT MD) - else() - set(CRT MT) - endif() - - set_target_properties(Live2DCubismCore - PROPERTIES - IMPORTED_LOCATION_DEBUG - ${CORE_PATH}/lib/windows/x86/${MSVC_NUM}/Live2DCubismCore_${CRT}d.lib - IMPORTED_LOCATION_RELEASE - ${CORE_PATH}/lib/windows/x86/${MSVC_NUM}/Live2DCubismCore_${CRT}.lib - ) - -elseif(APPLE) - if(IOS) - list(APPEND GAME_HEADER - proj.ios/src/AppController.h - proj.ios/src/RootViewController.h - ) - set(APP_UI_RES - proj.ios/src/LaunchScreen.storyboard - proj.ios/src/LaunchScreenBackground.png - proj.ios/src/Images.xcassets - ) - list(APPEND GAME_SOURCE - proj.ios/src/main.m - proj.ios/src/AppController.mm - proj.ios/src/RootViewController.mm - proj.ios/src/Prefix.pch - ${APP_UI_RES} - ) - - # iPhone Simulator (i386) is not support on Cubism Core. - if(IOS_PLATFORM STREQUAL "SIMULATOR") - message(FATAL_ERROR - "[CubismNativeSamples] Cubism Core does not support i386 iOS architecture." - ) - endif() - - set_target_properties(Live2DCubismCore - PROPERTIES - IMPORTED_LOCATION_DEBUG - ${CORE_PATH}/lib/ios/Debug-iphoneos/libLive2DCubismCore.a - IMPORTED_LOCATION_RELEASE - ${CORE_PATH}/lib/ios/Release-iphoneos/libLive2DCubismCore.a - ) - - elseif(MACOSX) - set(APP_UI_RES - proj.mac/src/Icon.icns - proj.mac/src/Info.plist - ) - list(APPEND GAME_SOURCE - proj.mac/src/main.cpp - proj.mac/src/Prefix.pch - ${APP_UI_RES} - ) - EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE ) - set_target_properties(Live2DCubismCore - PROPERTIES - IMPORTED_LOCATION - ${CORE_PATH}/lib/macos/${ARCHITECTURE}/libLive2DCubismCore.a - ) - - endif() - list(APPEND GAME_SOURCE ${common_res_files}) -endif() -# Set core include directory. -set_target_properties(Live2DCubismCore - PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES ${CORE_PATH}/include -) - -# Specify Cubism Framework rendering. -set(FRAMEWORK_SOURCE Cocos2d) -# Add Cubism Framework. -add_subdirectory(${FRAMEWORK_PATH} ${CMAKE_CURRENT_BINARY_DIR}/Framework) -# Add definitions for Cubism Framework. -target_compile_definitions(Framework PUBLIC CSM_TARGET_COCOS) -use_cocos2dx_compile_define(Framework) -use_cocos2dx_compile_options(Framework) - -# Mark app complie info and libs info. -set(all_code_files ${GAME_HEADER} ${GAME_SOURCE}) -if(NOT ANDROID) - add_executable(${APP_NAME} ${all_code_files}) -else() - add_library(${APP_NAME} SHARED ${all_code_files}) - add_subdirectory( - ${COCOS2DX_ROOT_PATH}/cocos/platform/android - ${ENGINE_BINARY_PATH}/cocos/platform - ) - target_link_libraries(${APP_NAME} - -Wl,--whole-archive - cpp_android_spec - -Wl,--no-whole-archive - ) -endif() - -# Link libraries. -target_link_libraries(${APP_NAME} Framework Live2DCubismCore cocos2d) -# Specify include directories. -target_include_directories(${APP_NAME} PRIVATE ${CLASSES_PATH}) - -# Mark app resources and add definitions for Cubism Framework. -setup_cocos_app_config(${APP_NAME}) -if(APPLE) - set_target_properties(${APP_NAME} PROPERTIES RESOURCE "${APP_UI_RES}") - if(MACOSX) - set_xcode_property(${APP_NAME} INFOPLIST_FILE "${COCOS2DX_ROOT_PATH}/templates/cpp-template-default/proj.ios_mac/mac/Info.plist") - target_compile_definitions(${APP_NAME} PRIVATE CSM_TARGET_MACOSX) - target_compile_definitions(Framework PUBLIC CSM_TARGET_MAC_GL) - set(COCOS_GLFW3 ${COCOS2DX_ROOT_PATH}/external/glfw3) - target_include_directories(Framework PUBLIC ${COCOS_GLFW3}/include/Mac) - target_include_directories(Framework PUBLIC ${COCOS2DX_ROOT_PATH}/cocos) - elseif(IOS) - # Add information aboud XCode project. - set_xcode_property(${APP_NAME} INFOPLIST_FILE "${COCOS2DX_ROOT_PATH}/templates/cpp-template-default/proj.ios_mac/ios/Info.plist") - set_xcode_property(${APP_NAME} ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon") - set_xcode_property(${APP_NAME} DEVELOPMENT_TEAM "") - set_xcode_property(${APP_NAME} CODE_SIGN_IDENTITY "iPhone Developer") - set_xcode_property(${APP_NAME} PRODUCT_BUNDLE_IDENTIFIER "com.live2d.demo-4-r7-cocos2dx") - set_xcode_property(${APP_NAME} TARGETED_DEVICE_FAMILY "1,2") - set_xcode_property(${APP_NAME} ONLY_ACTIVE_ARCH "NO") - set_xcode_property(${APP_NAME} ARCHS "arm64") - target_compile_definitions(${APP_NAME} PRIVATE CSM_TARGET_IOS) - target_compile_definitions(Framework PUBLIC CSM_TARGET_IPHONE_ES2) - target_include_directories(Framework PUBLIC ${COCOS2DX_ROOT_PATH}/cocos) - endif() -elseif(WINDOWS) - cocos_copy_target_dll(${APP_NAME}) - target_compile_definitions(Framework PUBLIC CSM_TARGET_WIN_GL) - # Specify glew directories for Cubism Framework. - set(COCOS_GLEW ${COCOS2DX_ROOT_PATH}/external/win32-specific/gles) - set(COCOS_GLFW3 ${COCOS2DX_ROOT_PATH}/external/glfw3) - target_include_directories(Framework PUBLIC ${COCOS_GLEW}/include/OGLES) - target_include_directories(Framework PUBLIC ${COCOS_GLFW3}/include/win32) - target_include_directories(Framework PUBLIC ${COCOS2DX_ROOT_PATH}/cocos) -elseif(ANDROID) - target_compile_definitions(Framework PUBLIC CSM_TARGET_ANDROID_ES2) - target_include_directories(Framework PUBLIC ${COCOS2DX_ROOT_PATH}/cocos) -elseif(LINUX) - set(COCOS_GLFW3 ${COCOS2DX_ROOT_PATH}/external/glfw3) - target_include_directories(Framework PUBLIC ${COCOS_GLFW3}/include/linux) - target_compile_definitions(Framework PUBLIC CSM_TARGET_LINUX_GL) - target_include_directories(Framework PUBLIC ${COCOS2DX_ROOT_PATH}/cocos) -endif() - -# Copy resources. -if(LINUX OR WINDOWS) - cocos_get_resource_path(APP_RES_DIR ${APP_NAME}) - cocos_copy_target_res(${APP_NAME} - LINK_TO ${APP_RES_DIR} FOLDERS ${GAME_RES_FOLDER} - ) -endif() - -# When this flag is turned on, the renderer will draw for each texture that has LAppModel. -# Otherwise, will draw to the main framebuffer. -# target_compile_definitions(${APP_NAME} PRIVATE USE_MODEL_RENDER_TARGET) - -# When this flag is turned on, the renderer will draw to the texture. -# The texture only has LAppView. -# This flag has higher priority than USE_MODEL_RENDER_TARGET. -# target_compile_definitions(${APP_NAME} PRIVATE USE_RENDER_TARGET) diff --git a/Samples/Cocos2d-x/Demo/Classes/AppDelegate.cpp b/Samples/Cocos2d-x/Demo/Classes/AppDelegate.cpp deleted file mode 100644 index 175b72c1..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/AppDelegate.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "AppDelegate.h" -#include "SampleScene.h" -#include "LAppLive2DManager.hpp" -#include "LAppDefine.hpp" -#include "LAppPal.hpp" - -#if USE_AUDIO_ENGINE && USE_SIMPLE_AUDIO_ENGINE -#error "Don't use AudioEngine and SimpleAudioEngine at the same time. Please just select one in your game!" -#endif - -#if USE_AUDIO_ENGINE -#include "audio/include/AudioEngine.h" -using namespace cocos2d::experimental; -#elif USE_SIMPLE_AUDIO_ENGINE -#include "audio/include/SimpleAudioEngine.h" -using namespace CocosDenshion; -#endif - -USING_NS_CC; - -static cocos2d::Size designResolutionSize = cocos2d::Size(LAppDefine::RenderTargetWidth, LAppDefine::RenderTargetHeight); -static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 320); -static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768); -static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536); - -AppDelegate::AppDelegate() -{ -} - -AppDelegate::~AppDelegate() -{ - Director::getInstance()->getEventDispatcher()->removeEventListener(_recreatedEventlistener); - - LAppLive2DManager::ReleaseInstance(); - -#if USE_AUDIO_ENGINE - AudioEngine::end(); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::end(); -#endif -} - -// if you want a different context, modify the value of glContextAttrs -// it will affect all platforms -void AppDelegate::initGLContextAttrs() -{ - // set OpenGL context attributes: red,green,blue,alpha,depth,stencil,multisamplesCount - GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8, 0}; - - GLView::setGLContextAttrs(glContextAttrs); -} - -// if you want to use the package manager to install more packages, -// don't modify or remove this function -static int register_all_packages() -{ - return 0; //flag for packages manager -} - -bool AppDelegate::applicationDidFinishLaunching() -{ - // initialize director - auto director = Director::getInstance(); - auto glview = director->getOpenGLView(); - if(!glview) - { -#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX) - glview = GLViewImpl::createWithRect("Demo", cocos2d::Rect(0, 0, designResolutionSize.width, designResolutionSize.height)); -#else - glview = GLViewImpl::create("Demo"); -#endif - director->setOpenGLView(glview); - } - - // turn on display FPS - director->setDisplayStats(true); - - // set FPS. the default value is 1.0/60 if you don't call this - director->setAnimationInterval(1.0f / 60); - - // Set the design resolution - glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER); - auto frameSize = glview->getFrameSize(); - // if the frame's height is larger than the height of medium size. - if (frameSize.height > mediumResolutionSize.height) - { - director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width)); - } - // if the frame's height is larger than the height of small size. - else if (frameSize.height > smallResolutionSize.height) - { - director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width)); - } - // if the frame's height is smaller than the height of medium size. - else - { - director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width)); - } - - register_all_packages(); - - // prepare for Cubism Framework API. - _cubismOption.LogFunction = LAppPal::PrintMessageLn; - _cubismOption.LoggingLevel = LAppDefine::CubismLoggingLevel; - Csm::CubismFramework::StartUp(&_cubismAllocator, &_cubismOption); - - _recreatedEventlistener = cocos2d::EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*) - { - LAppLive2DManager::GetInstance()->RecreateRenderer(); - }); - director->getEventDispatcher()->addEventListenerWithFixedPriority(_recreatedEventlistener, -1); - - // create a scene. it's an autorelease object - auto scene = SampleScene::createScene(); - - // run - director->runWithScene(scene); - - return true; -} - -// This function will be called when the app is inactive. Note, when receiving a phone call it is invoked. -void AppDelegate::applicationDidEnterBackground() -{ - Director::getInstance()->stopAnimation(); - -#if USE_AUDIO_ENGINE - AudioEngine::pauseAll(); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::getInstance()->pauseBackgroundMusic(); - SimpleAudioEngine::getInstance()->pauseAllEffects(); -#endif -} - -// this function will be called when the app is active again -void AppDelegate::applicationWillEnterForeground() -{ - Director::getInstance()->startAnimation(); - -#if USE_AUDIO_ENGINE - AudioEngine::resumeAll(); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::getInstance()->resumeBackgroundMusic(); - SimpleAudioEngine::getInstance()->resumeAllEffects(); -#endif - // Director::getInstance()->startAnimation(); -} diff --git a/Samples/Cocos2d-x/Demo/Classes/AppDelegate.h b/Samples/Cocos2d-x/Demo/Classes/AppDelegate.h deleted file mode 100644 index 2cc1cfb4..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/AppDelegate.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#ifndef _APP_DELEGATE_H_ -#define _APP_DELEGATE_H_ - -#include "cocos2d.h" -#include "LAppAllocator.hpp" -#include - -// #define USE_AUDIO_ENGINE 1 -// #define USE_SIMPLE_AUDIO_ENGINE 1 - -/** -@brief The cocos2d Application. - -Private inheritance here hides part of interface from Director. -*/ -class AppDelegate : private cocos2d::Application -{ -public: - AppDelegate(); - virtual ~AppDelegate(); - - virtual void initGLContextAttrs(); - - /** - @brief Implement Director and Scene init code here. - @return true Initialize success, app continue. - @return false Initialize failed, app terminate. - */ - virtual bool applicationDidFinishLaunching(); - - /** - @brief Called when the application moves to the background - @param the pointer of the application - */ - virtual void applicationDidEnterBackground(); - - /** - @brief Called when the application reenters the foreground - @param the pointer of the application - */ - virtual void applicationWillEnterForeground(); - -private: - cocos2d::EventListenerCustom* _recreatedEventlistener; - - LAppAllocator _cubismAllocator; - Csm::CubismFramework::Option _cubismOption; -}; - -#endif // _APP_DELEGATE_H_ - diff --git a/Samples/Cocos2d-x/Demo/Classes/AppMacros.h b/Samples/Cocos2d-x/Demo/Classes/AppMacros.h deleted file mode 100644 index 5a75936c..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/AppMacros.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __APPMACROS_H__ -#define __APPMACROS_H__ - -#include "cocos2d.h" - -/* For demonstrating using one design resolution to match different resources, - or one resource to match different design resolutions. - - [Situation 1] Using one design resolution to match different resources. - Please look into Appdelegate::applicationDidFinishLaunching. - We check current device frame size to decide which resource need to be selected. - So if you want to test this situation which said in title '[Situation 1]', - you should change ios simulator to different device(e.g. iphone, iphone-retina3.5, iphone-retina4.0, ipad, ipad-retina), - or change the window size in "proj.XXX/main.cpp" by "CCEGLView::setFrameSize" if you are using win32 or linux plaform - and modify "proj.mac/AppController.mm" by changing the window rectangle. - - [Situation 2] Using one resource to match different design resolutions. - The coordinates in your codes is based on your current design resolution rather than resource size. - Therefore, your design resolution could be very large and your resource size could be small. - To test this, just define the marco 'TARGET_DESIGN_RESOLUTION_SIZE' to 'DESIGN_RESOLUTION_2048X1536' - and open iphone simulator or create a window of 480x320 size. - - [Note] Normally, developer just need to define one design resolution(e.g. 960x640) with one or more resources. - */ - -#define DESIGN_RESOLUTION_480X320 0 -#define DESIGN_RESOLUTION_1024X768 1 -#define DESIGN_RESOLUTION_2048X1536 2 - -/* If you want to switch design resolution, change next line */ -#define TARGET_DESIGN_RESOLUTION_SIZE DESIGN_RESOLUTION_480X320 - -typedef struct tagResource -{ - cocos2d::CCSize size; - char directory[100]; -} Resource; - -static Resource smallResource = {cocos2d::CCSizeMake(480, 320), "iphone"}; -static Resource mediumResource = {cocos2d::CCSizeMake(1024, 768), "ipad"}; -static Resource largeResource = {cocos2d::CCSizeMake(2048, 1536), "ipadhd"}; - -#if (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_480X320) -static cocos2d::CCSize designResolutionSize = cocos2d::CCSizeMake(480, 320); -#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_1024X768) -static cocos2d::CCSize designResolutionSize = cocos2d::CCSizeMake(1024, 768); -#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_2048X1536) -static cocos2d::CCSize designResolutionSize = cocos2d::CCSizeMake(2048, 1536); -#else -#error unknown target design resolution! -#endif - -// The font size 24 is designed for small resolution, so we should change it to fit for current design resolution -#define TITLE_FONT_SIZE (cocos2d::CCEGLView::sharedOpenGLView()->getDesignResolutionSize().width / smallResource.size.width * 24) - -#endif /* __APPMACROS_H__ */ diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppAllocator.hpp b/Samples/Cocos2d-x/Demo/Classes/LAppAllocator.hpp deleted file mode 100644 index 7be4d006..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppAllocator.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#pragma once - -#include -#include - -/** - * @brief メモリアロケーションを実装するクラス。 - * - * メモリ確保・解放処理のインターフェースの実装。 - * フレームワークから呼び出される。 - * - */ -class LAppAllocator : public Csm::ICubismAllocator -{ - void* Allocate(const Csm::csmSizeType size); - - void Deallocate(void* memory); - - void* AllocateAligned(const Csm::csmSizeType size, const Csm::csmUint32 alignment); - - void DeallocateAligned(void* alignedMemory); -}; diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManager.cpp b/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManager.cpp deleted file mode 100644 index c2d0f9db..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManager.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "SampleScene.h" -#include - -//cocos2d-x -#include "base/CCDirector.h" -#include "renderer/backend/Device.h" - -//Cubism -#include "LAppLive2DManager.hpp" -#include "LAppPal.hpp" -#include "LAppDefine.hpp" -#include "LAppView.hpp" -#include "LAppSprite.hpp" - -#if defined(_WIN32) -#include -#elif defined(CSM_TARGET_IOS) || defined(CSM_TARGET_MACOSX) || defined(__ANDROID__) -#include "LAppLive2DManagerInternal.h" -#else -#include -#endif - -#ifdef CSM_TARGET_ANDROID_ES2 -#include -#endif - -using namespace Csm; -using namespace LAppDefine; - -USING_NS_CC; - -namespace { - LAppLive2DManager* s_instance = NULL; - - void FinishedMotion(ACubismMotion* self) - { - LAppPal::PrintLogLn("Motion Finished: %x", self); - } - - int CompareCsmString(const void* a, const void* b) - { - return strcmp(reinterpret_cast(a)->GetRawString(), - reinterpret_cast(b)->GetRawString()); - } -} - -LAppLive2DManager* LAppLive2DManager::GetInstance() -{ - if (s_instance == NULL) - { - s_instance = new LAppLive2DManager(); - } - - return s_instance; -} - -void LAppLive2DManager::ReleaseInstance() -{ - if (s_instance != NULL) - { - delete s_instance; - } - - s_instance = NULL; -} - -LAppLive2DManager::LAppLive2DManager() - : _sceneIndex(0) - , _viewMatrix(NULL) - , _renderTarget(SelectTarget_None) - , _program(NULL) - , _sprite(NULL) - , _renderBuffer(NULL) -{ - assert(CubismFramework::IsStarted()); - - CubismFramework::Initialize(); - - CreateShader(); - SetUpModel(); - - int width = static_cast(cocos2d::Director::getInstance()->getOpenGLView()->getFrameSize().width); - int height = static_cast(cocos2d::Director::getInstance()->getOpenGLView()->getFrameSize().height); - - // 画面全体を覆うサイズ - _sprite = new LAppSprite(_program); - - _viewMatrix = new CubismMatrix44(); - - // 使用するターゲット - _renderBuffer = new Csm::Rendering::CubismOffscreenSurface_Cocos2dx; - if (_renderBuffer) - {// 描画ターゲット作成 - -#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) - // Retina対策でこっちからとる - GLViewImpl *glimpl = (GLViewImpl *)Director::getInstance()->getOpenGLView(); - glfwGetFramebufferSize(glimpl->getWindow(), &width, &height); -#endif - - // モデル描画キャンバス - _renderBuffer->CreateOffscreenSurface(static_cast(width), static_cast(height)); - } - -#ifdef CSM_TARGET_ANDROID_ES2 - char *exts = (char*)backend::Device::getInstance()->getDeviceInfo()->getExtension(); - if(strstr(exts, "GL_NV_shader_framebuffer_fetch ")){ - Rendering::CubismRenderer_Cocos2dx::SetExtShaderMode( true , true ); - } -#endif - - ChangeScene(_sceneIndex); -} - -LAppLive2DManager::~LAppLive2DManager() -{ - if (_renderBuffer) - { - _renderBuffer->DestroyOffscreenSurface(); - delete _renderBuffer; - _renderBuffer = NULL; - } - delete _sprite; - _sprite = NULL; - - ReleaseAllModel(); - - CubismFramework::Dispose(); -} - -void LAppLive2DManager::ReleaseAllModel() -{ - for (csmUint32 i = 0; i < _models.GetSize(); i++) - { - delete _models[i]; - } - - _models.Clear(); -} - -LAppModel* LAppLive2DManager::GetModel(csmUint32 no) const -{ - if(no < _models.GetSize()) - { - return _models[no]; - } - - return NULL; -} - -csmUint32 LAppLive2DManager::GetModelCount() const -{ - return _models.GetSize(); -} - -void LAppLive2DManager::RecreateRenderer() const -{ - Rendering::CubismRenderer::StaticRelease(); - - for (csmUint32 i = 0; i < _models.GetSize(); i++) - { - LAppModel* model = GetModel(i); - model->ReloadRnederer(); - } -} - -void LAppLive2DManager::SetViewMatrix(Csm::CubismMatrix44* matrix) -{ - _viewMatrix = matrix; -} - -void LAppLive2DManager::OnDrag(csmFloat32 x, csmFloat32 y) const -{ - for (csmUint32 i = 0; i < _models.GetSize(); i++) - { - LAppModel* model = GetModel(i); - - model->SetDragging(x, y); - } -} - -void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) -{ - if (DebugLogEnable) LAppPal::PrintLogLn("[APP]tap point: {x:%.2f y:%.2f}", x, y); - - for (csmUint32 i = 0; i < _models.GetSize(); i++) - { - if (_models[i]->HitTest(HitAreaNameHead, x, y)) - { - if (DebugLogEnable) LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameHead); - _models[i]->SetRandomExpression(); - } - else if (_models[i]->HitTest(HitAreaNameBody, x, y)) - { - if (DebugLogEnable) LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); - } - } -} - -void LAppLive2DManager::OnUpdate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer) const -{ - Director* director = Director::getInstance(); - Size window = director->getWinSize(); - - Csm::Rendering::CubismRenderer_Cocos2dx::StartFrame(commandBuffer); - - for (csmUint32 i = 0; i < _models.GetSize(); ++i) - { - CubismMatrix44 projection; - LAppModel* model = GetModel(i); - - if (model->GetModel() == NULL) - { - LAppPal::PrintLogLn("Failed to model->GetModel()."); - continue; - } - - if (model->GetModel()->GetCanvasWidth() > 1.0f && window.width < window.height) - { - // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する - model->GetModelMatrix()->SetWidth(2.0f); - projection.Scale(1.0f, static_cast(window.width) / static_cast(window.height)); - } - else - { - projection.Scale(static_cast(window.height) / static_cast(window.width), 1.0f); - } - - // 必要があればここで乗算 - if (_viewMatrix != NULL) - { - projection.MultiplyByMatrix(_viewMatrix); - } - - if (_renderTarget == SelectTarget_ViewFrameBuffer && _renderBuffer && _sprite) - {// レンダリングターゲット使いまわしの場合 - // レンダリング開始 - _renderBuffer->BeginDraw(commandBuffer, NULL); - _renderBuffer->Clear(commandBuffer, _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]); // 背景クリアカラー - } - - model->Update(); - model->Draw(commandBuffer, projection);///< 参照渡しなのでprojectionは変質する - - // 各モデルが持つ描画ターゲットをテクスチャとする場合 - if (_renderTarget == SelectTarget_ModelFrameBuffer) - { - // レンダリング先とスプライトを作成 - model->MakeRenderingTarget(); - // αを付ける - float alpha = i < 1 ? 1.0f : model->GetOpacity(); // 片方のみ不透明度を取得できるようにする - model->SetSpriteColor(1.0f, 1.0f, 1.0f, alpha); - } - - if (_renderTarget == SelectTarget_ViewFrameBuffer && _renderBuffer && _sprite) - {// レンダリングターゲット使いまわしの場合 - // レンダリング終了 - _renderBuffer->EndDraw(commandBuffer); - - float uvVertex[] = - { - 1.0f, 1.0f, - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 0.0f, - }; - - // program退避 - Csm::Rendering::CubismCommandBuffer_Cocos2dx* lastCommandBuffer = commandBuffer; - - _sprite->SetColor(1.0f, 1.0f, 1.0f, 0.25f + (float)i * 0.5f); - _sprite->RenderImmidiate(commandBuffer, _renderBuffer->GetColorBuffer(), uvVertex); - - // 元に戻す - commandBuffer = lastCommandBuffer; - } - } -} - -void LAppLive2DManager::NextScene() -{ - csmInt32 no = (_sceneIndex + 1) % GetModelDirSize(); - ChangeScene(no); -} - -void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) -{ - _sceneIndex = index; - if (DebugLogEnable) LAppPal::PrintLogLn("[APP]model index: %d", _sceneIndex); - - // ModelDir[]に保持したディレクトリ名から - // model3.jsonのパスを決定する. - // ディレクトリ名とmodel3.jsonの名前を一致させておくこと. - const csmString& model = _modelDir[index]; - - csmString dir(model);; - dir.Append(1, '/'); - - csmString modelJsonName(model); - modelJsonName += ".model3.json"; - - ReleaseAllModel(); - _models.PushBack(new LAppModel()); - _models[0]->LoadAssets(dir.GetRawString(), modelJsonName.GetRawString()); - - /* - * モデル半透明表示を行うサンプルを提示する。 - * ここでUSE_RENDER_TARGET、USE_MODEL_RENDER_TARGETが定義されている場合 - * 別のレンダリングターゲットにモデルを描画し、描画結果をテクスチャとして別のスプライトに張り付ける。 - */ - { -#if defined(USE_RENDER_TARGET) - // Live2DManagerの持つターゲットに描画を行う場合、こちらを選択 - _renderTarget = SelectTarget_ViewFrameBuffer; -#elif defined(USE_MODEL_RENDER_TARGET) - // 各LAppModelの持つターゲットに描画を行う場合、こちらを選択 - _renderTarget = SelectTarget_ModelFrameBuffer; -#else - // デフォルトのメインフレームバッファへレンダリングする(通常) - _renderTarget = SelectTarget_None; -#endif - -#if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET) - // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす - _models.PushBack(new LAppModel()); - _models[1]->LoadAssets(dir.GetRawString(), modelJsonName.GetRawString()); - _models[1]->GetModelMatrix()->TranslateX(0.2f); -#endif - - if(_renderTarget == SelectTarget_ModelFrameBuffer) - { - for(Csm::csmUint32 i=0;i<_models.GetSize(); i++) - { - // レンダリング先とスプライトを作成 - _models[i]->MakeRenderingTarget(); - // αを付ける - LAppModel* model = _models[i]; - float alpha = i < 1 ? 1.0f : model->GetOpacity(); // 片方のみ不透明度を取得できるようにする - _models[i]->SetSpriteColor(1.0f, 1.0f, 1.0f, alpha); - } - } - } -} - -void LAppLive2DManager::CreateShader() -{ - const char* vertexShader = - "attribute vec3 position;" - "attribute vec2 uv;" - "varying vec2 vuv;" - "void main(void){" -#if defined(CC_USE_METAL) - " gl_Position = vec4(position.x, -position.y, position.z, 1.0);" -#else - " gl_Position = vec4(position, 1.0);" -#endif - " vuv = uv;" - "}"; - - const char* fragmentShader = -#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) - "precision mediump float;" -#endif - "varying vec2 vuv;" - "uniform sampler2D texture;" - "uniform vec4 baseColor;" - "void main(void){" - " gl_FragColor = texture2D(texture, vuv) * baseColor;" - " gl_FragColor = vec4(gl_FragColor.rgb * gl_FragColor.a, gl_FragColor.a);" - "}"; - - auto program = cocos2d::backend::Device::getInstance()->newProgram(vertexShader, fragmentShader); - _program = program; - -} - -void LAppLive2DManager::SetUpModel() -{ - _modelDir.Clear(); - - // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 - // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 -#if defined(CSM_TARGET_IOS) || defined(CSM_TARGET_MACOSX) || defined(__ANDROID__) - LAppLive2DManagerInternal::SetUpModel(_modelDir); -#else - const csmString resourcePath(FileUtils::getInstance()->getDefaultResourceRootPath().c_str()); -#if defined(_WIN32) - struct _finddata_t fdata; - csmString crawlPath(resourcePath); - crawlPath += "*.*"; - - intptr_t fh = _findfirst(crawlPath.GetRawString(), &fdata); - if (fh == -1) return; - - while (_findnext(fh, &fdata) == 0) - { - if ((fdata.attrib & _A_SUBDIR) && strcmp(fdata.name, "..") != 0) - { - // フォルダと同名の.model3.jsonがあるか探索する - csmString modelName(fdata.name); - csmString model3jsonPath(resourcePath); - model3jsonPath += modelName; - model3jsonPath.Append(1, '/'); - model3jsonPath += modelName; - model3jsonPath += ".model3.json"; - - struct _finddata_t fdata2; - if (_findfirst(model3jsonPath.GetRawString(), &fdata2) != -1) - { - _modelDir.PushBack(csmString(fdata.name)); - } - } - } -#else - DIR* pDir = opendir(resourcePath.GetRawString()); - if (pDir == NULL) return; - - struct dirent* dirent; - while ((dirent = readdir(pDir)) != NULL) - { - if ((dirent->d_type & DT_DIR) && strcmp(dirent->d_name, "..") != 0) - { - // フォルダと同名の.model3.jsonがあるか探索する - csmString modelName(dirent->d_name); - csmString modelPath(resourcePath); - modelPath += modelName; - modelPath.Append(1, '/'); - - csmString model3jsonName(modelName); - model3jsonName += ".model3.json"; - - DIR* pDir2 = opendir(modelPath.GetRawString()); - - struct dirent* dirent2; - while ((dirent2 = readdir(pDir2)) != NULL) - { - if (strcmp(dirent2->d_name, model3jsonName.GetRawString()) == 0) - { - _modelDir.PushBack(csmString(dirent->d_name)); - } - } - closedir(pDir2); - } - } - closedir(pDir); -#endif -#endif - qsort(_modelDir.GetPtr(), _modelDir.GetSize(), sizeof(csmString), CompareCsmString); -} - -Csm::csmVector LAppLive2DManager::GetModelDir() const -{ - return _modelDir; -} - -Csm::csmInt32 LAppLive2DManager::GetModelDirSize() const -{ - return _modelDir.GetSize(); -} - -void LAppLive2DManager::SetRenderTargetClearColor(float r, float g, float b) -{ - _clearColor[0] = r; - _clearColor[1] = g; - _clearColor[2] = b; -} diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManager.hpp b/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManager.hpp deleted file mode 100644 index 754ae7de..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManager.hpp +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#pragma once - -#include -#include -#include -#include "LAppModel.hpp" - -class LAppSprite; - -/** - * @brief サンプルアプリケーションにおいてCubismModelを管理するクラス
- * モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。 - * - */ -class LAppLive2DManager -{ - -public: - - /** - * @brief LAppModelのレンダリング先 - */ - enum SelectTarget - { - SelectTarget_None, ///< デフォルトのフレームバッファにレンダリング - SelectTarget_ModelFrameBuffer, ///< LAppModelが各自持つフレームバッファにレンダリング - SelectTarget_ViewFrameBuffer, ///< LAppViewの持つフレームバッファにレンダリング - }; - - /** - * @brief クラスのインスタンス(シングルトン)を返す。
- * インスタンスが生成されていない場合は内部でインスタンを生成する。 - * - * @return クラスのインスタンス - */ - static LAppLive2DManager* GetInstance(); - - /** - * @brief クラスのインスタンス(シングルトン)を解放する。 - * - */ - static void ReleaseInstance(); - - /** - * @brief 現在のシーンで保持しているモデルを返す - * - * @param[in] no モデルリストのインデックス値 - * @return モデルのインスタンスを返す。インデックス値が範囲外の場合はNULLを返す。 - */ - LAppModel* GetModel(Csm::csmUint32 no) const; - - /** - * @brief 現在のシーンで保持しているモデルの数を返す - * - * @return モデルリストの数 - */ - Csm::csmUint32 GetModelCount() const; - - /** - * @brief 現在のシーンで保持しているすべてのモデルを解放する - * - */ - void ReleaseAllModel(); - - /** - * @brief モデル描画用のレンダラを再構築する。 - * - */ - void RecreateRenderer() const; - - /** - * @brief モデル描画用のView行列をセットする。 - * - * @param[in] matrix View行列 - * - */ - void SetViewMatrix(Csm::CubismMatrix44* matrix); - - /** - * @brief 画面をドラッグしたときの処理 - * - * @param[in] x 画面のX座標 - * @param[in] y 画面のY座標 - */ - void OnDrag(Csm::csmFloat32 x, Csm::csmFloat32 y) const; - - /** - * @brief 画面をタップしたときの処理 - * - * @param[in] x 画面のX座標 - * @param[in] y 画面のY座標 - */ - void OnTap(Csm::csmFloat32 x, Csm::csmFloat32 y); - - /** - * @brief 画面を更新するときの処理 - * モデルの更新処理および描画処理を行う - */ - void OnUpdate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer) const; - - /** - * @brief 次のシーンに切り替える
- * サンプルアプリケーションではモデルセットの切り替えを行う。 - */ - void NextScene(); - - /** - * @brief シーンを切り替える
- * サンプルアプリケーションではモデルセットの切り替えを行う。 - */ - void ChangeScene(Csm::csmInt32 index); - - /** - * @brief レンダリング先をデフォルト以外に切り替えた際の背景クリア色設定 - * @param[in] r 赤(0.0~1.0) - * @param[in] g 緑(0.0~1.0) - * @param[in] b 青(0.0~1.0) - */ - void SetRenderTargetClearColor(float r, float g, float b); - -private: - /** - * @brief コンストラクタ - */ - LAppLive2DManager(); - - /** - * @brief デストラクタ - */ - virtual ~LAppLive2DManager(); - - /** - * @brief シェーダーを登録する。 - */ - void CreateShader(); - - /** - * @brief Resources フォルダにあるモデルフォルダ名をセットする - */ - void SetUpModel(); - - /** - * @brief Resources フォルダにあるモデルフォルダ名を取得する - */ - Csm::csmVector GetModelDir() const; - - /** - * @brief Resources フォルダにあるモデルフォルダのサイズを取得する - */ - Csm::csmInt32 GetModelDirSize() const; - - Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列 - Csm::csmVector _models; ///< モデルインスタンスのコンテナ - Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値 - - // レンダリング先を別ターゲットにする方式の場合に使用 - SelectTarget _renderTarget; ///< レンダリング先の選択肢 - LAppSprite* _sprite; ///< テクスチャの単純描画クラス - Csm::Rendering::CubismOffscreenSurface_Cocos2dx* _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング - float _clearColor[4]; ///< レンダリングターゲットのクリアカラー - cocos2d::backend::Program* _program; - - Csm::csmVector _modelDir; ///< モデルディレクトリ名のコンテナ -}; diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManagerInternal.cpp b/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManagerInternal.cpp deleted file mode 100644 index 24524235..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManagerInternal.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "LAppLive2DManagerInternal.h" -#if defined(CSM_TARGET_IOS) || defined(CSM_TARGET_MACOSX) -#include -#elif defined(__ANDROID__) -#include -#include -#include "platform/android/jni/JniHelper.h" -#endif - - -namespace -{ -#if defined(CSM_TARGET_IOS) || defined(CSM_TARGET_MACOSX) -inline Csm::csmString GetPath(CFURLRef url) -{ - CFStringRef cfstr = CFURLCopyFileSystemPath(url, CFURLPathStyle::kCFURLPOSIXPathStyle); - CFIndex size = CFStringGetLength(cfstr) * 4 + 1; // Length * UTF-16 Max Character size + null-terminated-byte - char* buf = new char[size]; - CFStringGetCString(cfstr, buf, size, CFStringBuiltInEncodings::kCFStringEncodingUTF8); - Csm::csmString result(buf); - delete[] buf; - return result; -} -#elif defined(__ANDROID__) -// jobject, jstring -template -class ScopedJObject { -public: - ScopedJObject(JNIEnv* env, T ptr); - ScopedJObject(const ScopedJObject&) = delete; - ScopedJObject(ScopedJObject&& move) = default; - ScopedJObject& operator= (const ScopedJObject&) = delete; - ScopedJObject& operator= (ScopedJObject&&) = default; - ~ScopedJObject(); - inline JNIEnv* env() - { - return _env; - } - inline const T& get() - { - return _ptr; - } - inline void reset(T ptr = nullptr) - { - if (_ptr != nullptr) - { - _env->DeleteLocalRef(_ptr); - } - _ptr = ptr; - } -private: - JNIEnv* _env; - T _ptr = nullptr; -}; - -class JniContext; -class JniAssetManager; - -template -ScopedJObject::ScopedJObject(JNIEnv* env, T ptr) - : _env(env) - , _ptr(ptr) -{ -} -template -ScopedJObject::~ScopedJObject() -{ - if (_ptr != nullptr) - { - _env->DeleteLocalRef(_ptr); - } -} - -class JniContext -{ -public: - JniContext() = delete; - JniContext(const JniContext&) = delete; - JniContext(JniContext&&) = default; - JniContext& operator= (const JniContext&) = delete; - JniContext& operator= (JniContext&&) = default; - JniAssetManager getAssets(); - static JniContext GetContext(JNIEnv* env); - -private: - JniContext(JNIEnv* env, jobject obj); - - ScopedJObject obj; - jmethodID method_getAssets; -}; - -class JniAssetManager -{ -public: - JniAssetManager() = delete; - JniAssetManager(JNIEnv* env, jobject assetManager); - JniAssetManager(const JniAssetManager&) = delete; - JniAssetManager(JniAssetManager&&) = default; - JniAssetManager& operator= (const JniAssetManager&) = delete; - JniAssetManager& operator= (JniAssetManager&&) = default; - - jobjectArray list(jstring path); - Csm::csmVector list(const char* path); - -private: - ScopedJObject obj; - jmethodID method_list; -}; - -JniContext::JniContext(JNIEnv* env, jobject context) - : obj(env, context) - , method_getAssets(env->GetMethodID(env->GetObjectClass(context), "getAssets", "()Landroid/content/res/AssetManager;")) -{ -} - -JniAssetManager JniContext::getAssets() -{ - return JniAssetManager(obj.env(), obj.env()->CallObjectMethod(obj.get(), method_getAssets)); -} - -JniContext JniContext::GetContext(JNIEnv* env) -{ - cocos2d::JniMethodInfo getContext; - cocos2d::JniHelper::getStaticMethodInfo(getContext, "org/cocos2dx/lib/Cocos2dxActivity", "getContext", "()Landroid/content/Context;"); - return JniContext(env, env->CallStaticObjectMethod(getContext.classID, getContext.methodID)); -} - -JniAssetManager::JniAssetManager(JNIEnv* env, jobject assetManager) - : obj(env, assetManager) - , method_list(env->GetMethodID(env->GetObjectClass(assetManager), u8"list", u8"(Ljava/lang/String;)[Ljava/lang/String;")) -{ -} - -Csm::csmVector JniAssetManager::list(const char* path) -{ - JNIEnv* env = obj.env(); - ScopedJObject jstr(env, env->NewStringUTF(path)); - jobjectArray files = (jobjectArray)env->CallObjectMethod(obj.get(), method_list, jstr.get()); - int length = env->GetArrayLength(files); - Csm::csmVector list(length); - for (int i = 0; i < length; i++) - { - ScopedJObject jstr(env, reinterpret_cast(env->GetObjectArrayElement(files, i))); - const char* jchars = env->GetStringUTFChars(jstr.get(), nullptr); - list.PushBack(Csm::csmString(jchars)); - env->ReleaseStringUTFChars(jstr.get(), jchars); - } - return list; -} -#endif -} -namespace LAppLive2DManagerInternal { -#if defined(CSM_TARGET_IOS) || defined(CSM_TARGET_MACOSX) -void SetUpModel(Csm::csmVector& dst) -{ - CFBundleRef mainBundle = CFBundleGetMainBundle(); - CFURLRef rootUrl = CFBundleCopyResourcesDirectoryURL(mainBundle); -#if defined(CSM_TARGET_MACOSX) - rootUrl = CFURLCopyAbsoluteURL(rootUrl); -#endif - Csm::csmString rootPath(GetPath(rootUrl)); - rootPath.Append(1, '/'); - { - CFArrayRef arr = CFBundleCreateBundlesFromDirectory(NULL, rootUrl, NULL); - CFIndex count = CFArrayGetCount(arr); - for (CFIndex i = 0; i < count; i++) - { - CFBundleRef item = (CFBundleRef)CFArrayGetValueAtIndex(arr, i); - CFURLRef itemDirUrl = CFBundleCopyResourcesDirectoryURL(item); - CFArrayRef model3json = CFBundleCopyResourceURLsOfType(item, CFSTR(".model3.json"), NULL); - if (CFArrayGetCount(model3json) == 1) - { - Csm::csmString itemDirPath(GetPath(itemDirUrl)); - dst.PushBack(Csm::csmString(itemDirPath.GetRawString() + rootPath.GetLength())); - } - } - } -} -#elif defined(__ANDROID__) -void SetUpModel(Csm::csmVector& dst) -{ - JniContext cxtObj = JniContext::GetContext(cocos2d::JniHelper::getEnv()); - JniAssetManager assetManager = cxtObj.getAssets(); - Csm::csmVector root = assetManager.list(""); - for (int i = 0; i < root.GetSize(); i++) - { - Csm::csmVector files = assetManager.list(root[i].GetRawString()); - Csm::csmString target(root[i]); - target += ".model3.json"; - for (int j = 0; j < files.GetSize(); j++) - { - if (target == files[j]) - { - dst.PushBack(root[i]); - break; - } - } - } -} -#endif -} diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManagerInternal.h b/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManagerInternal.h deleted file mode 100644 index 4287f4d1..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppLive2DManagerInternal.h +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#pragma once -#if defined(CSM_TARGET_IOS) || defined(CSM_TARGET_MACOSX) || defined(__ANDROID__) -#include -#include -namespace LAppLive2DManagerInternal -{ - void SetUpModel(Csm::csmVector& dst); -} -#endif diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppPal.cpp b/Samples/Cocos2d-x/Demo/Classes/LAppPal.cpp deleted file mode 100644 index 00d466b4..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppPal.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "LAppPal.hpp" -#include -#include "cocos2d.h" -#include "LAppDefine.hpp" - -using namespace Csm; -USING_NS_CC; - -csmByte* LAppPal::LoadFileAsBytes(const csmChar* filePath, csmSizeInt* outSize) -{ - ssize_t size = 0; - csmByte* buf = FileUtils::getInstance()->getDataFromFile(filePath).takeBuffer(&size); - - if (buf == NULL) - { - if (LAppDefine::DebugLogEnable) - { - PrintLogLn("File load failed : %s", filePath); - } - return NULL; - } - - *outSize = static_cast(size); - return buf; -} - -void LAppPal::ReleaseBytes(csmByte* byteData) -{ - free(byteData); -} - -csmFloat32 LAppPal::GetDeltaTime() -{ - if(Director::getInstance() != NULL) - { - return Director::getInstance()->getDeltaTime(); - } - return 0.0f; -} - -void LAppPal::PrintLogLn(const csmChar* format, ...) -{ - va_list args; - csmChar buf[256]; - va_start(args, format); - vsnprintf(buf, sizeof(buf), format, args); // 標準出力でレンダリング - cocos2d::log("%s", buf); // cocos2dのログ関数で出力(関数で改行される) - va_end(args); -} - -void LAppPal::PrintMessageLn(const csmChar* message) -{ - PrintLogLn("%s", message); -} diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppPal.hpp b/Samples/Cocos2d-x/Demo/Classes/LAppPal.hpp deleted file mode 100644 index bbf793d5..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppPal.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#pragma once - -#include - -/** - * @brief プラットフォーム依存機能を抽象化する Cubism Platform Abstraction Layer. - * - * ファイル読み込みや時刻取得等のプラットフォームに依存する関数をまとめる - * - */ -class LAppPal -{ -public: - /** - * @brief ファイルをバイトデータとして読み込む - * - * ファイルをバイトデータとして読み込む - * - * @param[in] filePath 読み込み対象ファイルのパス - * @param[out] outSize ファイルサイズ - * @return バイトデータ - */ - static Csm::csmByte* LoadFileAsBytes(const Csm::csmChar* filePath,Csm::csmSizeInt* outSize); - - - /** - * @brief バイトデータを解放する - * - * バイトデータを解放する - * - * @param[in] byteData 解放したいバイトデータ - */ - static void ReleaseBytes(Csm::csmByte* byteData); - - /** - * @biref デルタ時間(前回フレームとの差分)を取得する - * - * @return デルタ時間[ms] - * - */ - static Csm::csmFloat32 GetDeltaTime(); - - /** - * @brief ログを出力し最後に改行する - * - * ログを出力し最後に改行する - * - * @param[in] format 書式付文字列 - * @param[in] ... (可変長引数)文字列 - * - */ - static void PrintLogLn(const Csm::csmChar* format, ...); - - /** - * @brief メッセージを出力し最後に改行する - * - * メッセージを出力し最後に改行する - * - * @param[in] message 文字列 - * - */ - static void PrintMessageLn(const Csm::csmChar* message); - -private: - LAppPal(); - -}; - diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppSprite.cpp b/Samples/Cocos2d-x/Demo/Classes/LAppSprite.cpp deleted file mode 100644 index 47d98567..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppSprite.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "LAppSprite.hpp" -#include "base/CCDirector.h" -#include "LAppPal.hpp" - -LAppSprite::LAppSprite(backend::Program* program) -{ - _program = program; - _drawCommandBuffer = NULL; -} - -LAppSprite::~LAppSprite() -{ - if (_drawCommandBuffer != NULL) - { - CSM_FREE(_drawCommandBuffer); - } -} - -void LAppSprite::RenderImmidiate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer, Texture2D* texture, float uvVertex[8]) -{ - if (_drawCommandBuffer == NULL) - { - _drawCommandBuffer = CSM_NEW Csm::Rendering::CubismCommandBuffer_Cocos2dx::DrawCommandBuffer(); - } - - PipelineDescriptor* pipelineDescriptor = _drawCommandBuffer->GetCommandDraw()->GetPipelineDescriptor(); - backend::BlendDescriptor* blendDescriptor = _drawCommandBuffer->GetCommandDraw()->GetBlendDescriptor(); - backend::ProgramState* programState = pipelineDescriptor->programState; - - _drawCommandBuffer->GetCommandDraw()->GetCommand()->setDrawType(cocos2d::CustomCommand::DrawType::ELEMENT); - _drawCommandBuffer->GetCommandDraw()->GetCommand()->setPrimitiveType(cocos2d::backend::PrimitiveType::TRIANGLE); - _drawCommandBuffer->CreateVertexBuffer(sizeof(float) * 2, 4 * 2); - _drawCommandBuffer->CreateIndexBuffer(6); - - // 画面サイズを取得する - cocos2d::Size visibleSize = cocos2d::Director::getInstance()->getVisibleSize(); - cocos2d::Size winSize = cocos2d::Director::getInstance()->getWinSize(); - - // 頂点データ - float positionVertex[] = - { - visibleSize.width / winSize.width, visibleSize.height / winSize.height, - -visibleSize.width / winSize.width, visibleSize.height / winSize.height, - -visibleSize.width / winSize.width,-visibleSize.height / winSize.height, - visibleSize.width / winSize.width,-visibleSize.height / winSize.height, - }; - - short positionIndex[] = - { - 0,1,2, - 0,2,3 - }; - - _drawCommandBuffer->UpdateVertexBuffer(positionVertex, uvVertex, 4); - _drawCommandBuffer->UpdateIndexBuffer(positionIndex, 6); - _drawCommandBuffer->CommitVertexBuffer(); - - if (!programState) - { - programState = new cocos2d::backend::ProgramState(_program); - } - - // attribute属性を登録 - programState->getVertexLayout()->setAttribute("position", _program->getAttributeLocation("position"), backend::VertexFormat::FLOAT2, 0, false); - programState->getVertexLayout()->setAttribute("uv", _program->getAttributeLocation("uv"), backend::VertexFormat::FLOAT2, sizeof(float) * 2, false); - - // uniform属性の登録 - programState->setTexture(_program->getUniformLocation("texture"), 0, texture->getBackendTexture()); - - programState->setUniform(_program->getUniformLocation("baseColor"), _spriteColor, sizeof(float) * 4); - - programState->getVertexLayout()->setLayout(sizeof(float) * 4); - - blendDescriptor->sourceRGBBlendFactor = cocos2d::backend::BlendFactor::ONE; - blendDescriptor->destinationRGBBlendFactor = cocos2d::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor->sourceAlphaBlendFactor = cocos2d::backend::BlendFactor::ONE; - blendDescriptor->destinationAlphaBlendFactor = cocos2d::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor->blendEnabled = true; - - pipelineDescriptor->programState = programState; - - // モデルの描画 - commandBuffer->AddDrawCommand(_drawCommandBuffer->GetCommandDraw()); - -} - -void LAppSprite::SetColor(float r, float g, float b, float a) -{ - _spriteColor[0] = r; - _spriteColor[1] = g; - _spriteColor[2] = b; - _spriteColor[3] = a; -} diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppSprite.hpp b/Samples/Cocos2d-x/Demo/Classes/LAppSprite.hpp deleted file mode 100644 index 9ccc1e4a..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppSprite.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#pragma once - -#include "Rendering/Cocos2d/CubismRenderer_Cocos2dx.hpp" -#include "Rendering/Cocos2d/CubismCommandBuffer_Cocos2dx.hpp" -#include "cocos2d.h" - -USING_NS_CC; - -/** -* @brief スプライトを実装するクラス。 -* -* テクスチャID、Rectの管理。 -* -*/ -class LAppSprite -{ -public: - /** - * @brief Rect 構造体。 - */ - struct Rect - { - public: - float left; ///< 左辺 - float right; ///< 右辺 - float up; ///< 上辺 - float down; ///< 下辺 - }; - - /** - * @brief コンストラクタ - * - * @param[in] x x座標 - * @param[in] y y座標 - * @param[in] width 横幅 - * @param[in] height 高さ - * @param[in] textureId テクスチャID - * @param[in] programId シェーダID - */ - LAppSprite(backend::Program* program); - - /** - * @brief デストラクタ - */ - ~LAppSprite(); - - /** - * @brief テクスチャIDを指定して描画する - * - */ - void RenderImmidiate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer, Texture2D* texture, float uvVertex[8]); - - /** - * @brief 色設定 - * - * @param[in] r (0.0~1.0) - * @param[in] g (0.0~1.0) - * @param[in] b (0.0~1.0) - * @param[in] a (0.0~1.0) - */ - void SetColor(float r, float g, float b, float a); - -private: - - float _spriteColor[4]; ///< 表示カラー - - cocos2d::backend::Program* _program; - Csm::Rendering::CubismCommandBuffer_Cocos2dx::DrawCommandBuffer* _drawCommandBuffer; -}; - diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppView.cpp b/Samples/Cocos2d-x/Demo/Classes/LAppView.cpp deleted file mode 100644 index 2d29192e..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppView.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "LAppView.hpp" -#include "LAppLive2DManager.hpp" -#include "LAppDefine.hpp" -#include "LAppPal.hpp" -#include "LAppModel.hpp" - -using namespace Csm; -using namespace LAppDefine; - -USING_NS_CC; - -LAppView::LAppView(): DrawNode() - , _debugRects(NULL) -{ -} - -void LAppView::onEnter() -{ - DrawNode::onEnter(); - - // タッチ関係のイベント管理 - touchMgr = new TouchManager(); - - // デバイス座標からスクリーン座標に変換するための - deviceToScreen = new CubismMatrix44(); - - // 画面の表示の拡大縮小や移動の変換を行う行列 - viewMatrix = new CubismViewMatrix(); - - Size size = Director::getInstance()->getWinSize(); - - float width = size.width; - float height = size.height; - // 縦サイズを基準とする - float ratio = width / height; - float left = -ratio; - float right = ratio; - float bottom = ViewLogicalLeft; - float top = ViewLogicalRight; - - viewMatrix->SetScreenRect(left, right, bottom, top); // デバイスに対応する画面の範囲。 Xの左端, Xの右端, Yの下端, Yの上端 - viewMatrix->Scale(ViewScale, ViewScale); - - deviceToScreen->LoadIdentity(); // サイズが変わった際などリセット必須 - if (width > height) - { - float screenW = fabsf(right - left); - deviceToScreen->ScaleRelative(screenW / width, -screenW / width); - } - else - { - float screenH = fabsf(top - bottom); - deviceToScreen->ScaleRelative(screenH / height, -screenH / height); - } - deviceToScreen->TranslateRelative(-width / 2.0f, -height / 2.0f); - - // 表示範囲の設定 - viewMatrix->SetMaxScale(ViewMaxScale); // 限界拡大率 - viewMatrix->SetMinScale(ViewMinScale); // 限界縮小率 - - // 表示できる最大範囲 - viewMatrix->SetMaxScreenRect( - ViewLogicalMaxLeft, - ViewLogicalMaxRight, - ViewLogicalMaxBottom, - ViewLogicalMaxTop - ); - - // イベントリスナー作成 - EventListenerTouchAllAtOnce* listener = EventListenerTouchAllAtOnce::create(); - - // タッチメソッド設定 - listener->onTouchesBegan = CC_CALLBACK_2(LAppView::onTouchesBegan, this); - listener->onTouchesMoved = CC_CALLBACK_2(LAppView::onTouchesMoved, this); - listener->onTouchesEnded = CC_CALLBACK_2(LAppView::onTouchesEnded, this); - - // 優先度100でディスパッチャーに登録 - this->getEventDispatcher()->addEventListenerWithFixedPriority(listener, 100); -} - -void LAppView::onExit() -{ - DrawNode::onExit(); - - delete touchMgr; - delete deviceToScreen; - delete viewMatrix; -} - -void LAppView::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) -{ - DrawNode::draw(renderer, transform, flags); - onDraw(transform, flags); -} - -void LAppView::onDraw(const cocos2d::Mat4& transform, uint32_t flags) -{ - _commandBuffer.PushCommandGroup(); - - Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); - Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform); - - LAppLive2DManager* Live2DMgr = LAppLive2DManager::GetInstance(); - - Live2DMgr->SetViewMatrix(viewMatrix); - - // Cubism更新・描画 - Live2DMgr->OnUpdate(&_commandBuffer); - - if (_debugRects) - { - drawDebugRects(Live2DMgr); - } - - Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); - - _commandBuffer.PopCommandGroup(); -} - -void LAppView::onTouchesBegan(const std::vector& touches, Event* event) -{ - // タッチ開始 - size_t touchNum = touches.size(); - - if (touchNum == 1) - { - Point pt = touches[0]->getLocationInView(); - if (DebugTouchLogEnable)LAppPal::PrintLogLn("[APP]touchesBegan x:%.0f y:%.0f", pt.x, pt.y); - touchMgr->touchesBegan(pt.x, pt.y); - } -} - -void LAppView::onTouchesMoved(const std::vector& touches, Event* event) -{ - // タッチ中 - size_t touchNum = touches.size(); - - float screenX = this->transformScreenX(touchMgr->getX()); - float screenY = this->transformScreenY(touchMgr->getY()); - float viewX = this->transformViewX(touchMgr->getX()); - float viewY = this->transformViewY(touchMgr->getY()); - - if (touchNum == 1) - { - Point pt = touches[0]->getLocationInView(); - - if (DebugTouchLogEnable) - LAppPal::PrintLogLn("[APP]touchesMoved device{x:%.0f y:%.0f} screen{x:%.2f y:%.2f} view{x:%.2f y:%.2f}", pt.x, pt.y, screenX, screenY, viewX, viewY); - - touchMgr->touchesMoved(pt.x, pt.y); - } - LAppLive2DManager* live2DMgr = LAppLive2DManager::GetInstance(); - live2DMgr->OnDrag(viewX, viewY); -} - -void LAppView::onTouchesEnded(const std::vector& touches, cocos2d::Event* event) -{ - // タッチ終了 - LAppLive2DManager* live2DMgr = LAppLive2DManager::GetInstance(); - live2DMgr->OnDrag(0, 0); - - if (touches.size() == 1) - { - // シングルタップ - float x = deviceToScreen->TransformX(touchMgr->getX()); // 論理座標変換した座標を取得。 - float y = deviceToScreen->TransformY(touchMgr->getY()); // 論理座標変換した座標を取得。 - if (DebugTouchLogEnable) LAppPal::PrintLogLn("[APP]touchesEnded x:%.2f y:%.2f", x, y); - live2DMgr->OnTap(x, y); - } -} - -void LAppView::updateViewMatrix(float dx, float dy, float cx, float cy, float scale) -{ - LAppLive2DManager* live2DMgr = LAppLive2DManager::GetInstance(); - - // 拡大縮小 - viewMatrix->AdjustScale(cx, cy, scale); - - // 移動 - viewMatrix->AdjustTranslate(dx, dy); - - live2DMgr->SetViewMatrix(viewMatrix); -} - -float LAppView::transformViewX(float deviceX) -{ - float screenX = deviceToScreen->TransformX(deviceX); // 論理座標変換した座標を取得。 - return viewMatrix->InvertTransformX(screenX); // 拡大、縮小、移動後の値。 -} - -float LAppView::transformViewY(float deviceY) -{ - float screenY = deviceToScreen->TransformY(deviceY); // 論理座標変換した座標を取得。 - return viewMatrix->InvertTransformY(screenY); // 拡大、縮小、移動後の値。 -} - -float LAppView::transformScreenX(float deviceX) -{ - return deviceToScreen->TransformX(deviceX); -} - -float LAppView::transformScreenY(float deviceY) -{ - return deviceToScreen->TransformY(deviceY); -} - -void LAppView::setDebugRectsNode(DrawNode* debugRects) -{ - _debugRects = debugRects; -} - -void LAppView::drawDebugRects(LAppLive2DManager* manager) const -{ - const Color4F hitAreaColor = Color4F(1.0f, 0, 0, 0.2f); - const Color4F userDataAreaColor = Color4F(0, 0, 1.0f, 0.2f); - - CubismMatrix44 projection; - const Size window = Director::getInstance()->getWinSize(); - const CubismVector2 windowSize = CubismVector2(window.width, window.height); - projection.Scale(1, window.width / window.height); - - if (viewMatrix != NULL) - { - projection.MultiplyByMatrix(viewMatrix); - } - - for (csmUint32 i = 0; i < manager->GetModelCount(); ++i) - { - _debugRects->clear(); - LAppModel* model = manager->GetModel(i); - const Csm::csmVector& userDataAreas = model->GetUserDataAreas(projection, windowSize); - for (csmUint32 j = 0; j < userDataAreas.GetSize(); ++j) - { - _debugRects->drawSolidRect(Vec2(userDataAreas[j].X, userDataAreas[j].Y) - , Vec2(userDataAreas[j].GetRight(), userDataAreas[j].GetBottom()) - , userDataAreaColor); - } - - const Csm::csmVector& hitAreas = model->GetHitAreas(projection, windowSize); - for (csmUint32 j = 0; j < hitAreas.GetSize(); ++j) - { - _debugRects->drawSolidRect(Vec2(hitAreas[j].X, hitAreas[j].Y) - , Vec2(hitAreas[j].GetRight(), hitAreas[j].GetBottom()) - , hitAreaColor); - } - } -} - -LAppView* LAppView::createDrawNode() -{ - LAppView* ret = new(std::nothrow) LAppView(); - if (ret && ret->init()) - { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; -} diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppView.hpp b/Samples/Cocos2d-x/Demo/Classes/LAppView.hpp deleted file mode 100644 index a33ad1fe..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/LAppView.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#pragma once - -#include -#include -#include -#include "TouchManager.h" -#include "2d/CCSprite.h" -#include "cocos2d.h" -#include -#include "LAppLive2DManager.hpp" - -class LAppView : public cocos2d::DrawNode -{ -public: - LAppView(); - virtual ~LAppView() {} - - virtual void onEnter(); - virtual void onExit(); - - virtual void draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags); - void onDraw(const cocos2d::Mat4& transform, uint32_t flags); - - void onTouchesBegan(const std::vector& touches, cocos2d::Event* event); - void onTouchesMoved(const std::vector& touches, cocos2d::Event* event); - void onTouchesEnded(const std::vector& touches, cocos2d::Event* event); - - void updateViewMatrix(float dx, float dy, float cx, float cy, float scale); - float transformViewX(float deviceX); - float transformViewY(float deviceY); - float transformScreenX(float deviceX); - float transformScreenY(float deviceY); - - void setDebugRectsNode(DrawNode* debugRects); - void drawDebugRects(LAppLive2DManager* manager) const; - - static LAppView* createDrawNode(); - -private: - TouchManager* touchMgr; - Csm::CubismMatrix44* deviceToScreen; - Csm::CubismViewMatrix* viewMatrix; - Csm::Rendering::CubismCommandBuffer_Cocos2dx _commandBuffer; - DrawNode* _debugRects; -}; diff --git a/Samples/Cocos2d-x/Demo/Classes/SampleScene.cpp b/Samples/Cocos2d-x/Demo/Classes/SampleScene.cpp deleted file mode 100644 index 76468a38..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/SampleScene.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "SampleScene.h" -#include "LAppView.hpp" -#include "LAppLive2DManager.hpp" -#include "LAppDefine.hpp" -#include "LAppPal.hpp" - -USING_NS_CC; - -namespace -{ - SampleScene* instance = NULL; -} - -SampleScene::SampleScene() - : _pView(NULL) - , _changeItem(NULL) - , _closeItem(NULL) -{ -} - -Scene* SampleScene::createScene() -{ - return SampleScene::create(); -} - -SampleScene * SampleScene::getInstance() -{ - return instance; -} - -// Print useful error message instead of segfaulting when files are not there. -static void problemLoading(const char* filename) -{ - printf("Error while loading: %s\n", filename); - printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in SampleSceneScene.cpp\n"); -} - -// on "init" you need to initialize your instance -bool SampleScene::init() -{ - ////////////////////////////// - // 1. super init first - if (!Scene::init()) - { - return false; - } - - // Live2DManager実体化の前に必要となる - instance = this; - - auto winSize = Director::getInstance()->getWinSize(); - auto visibleSize = Director::getInstance()->getVisibleSize(); - Vec2 origin = Director::getInstance()->getVisibleOrigin(); - - ///////////////////////////// - // 2. add a menu item with "X" image, which is clicked to quit the program - // you may modify it. - - // add a "close" icon to exit the progress. it's an autorelease object - _closeItem = MenuItemImage::create( - "CloseNormal.png", - "CloseSelected.png", - CC_CALLBACK_1(SampleScene::menuCloseCallback, this) - ); - - if (_closeItem == nullptr || - _closeItem->getContentSize().width <= 0 || - _closeItem->getContentSize().height <= 0) - { - problemLoading("'CloseNormal.png' and 'CloseSelected.png'"); - } - - // create menu, it's an autorelease object - auto closeMenu = Menu::create(_closeItem, NULL); - closeMenu->setScale(0.9f); - closeMenu->setPosition(Vec2::ZERO); - this->addChild(closeMenu, 1); - - _changeItem = MenuItemImage::create( - "icon_gear.png", - "icon_gear.png", - CC_CALLBACK_1(SampleScene::menuChangeCallback, this) - ); - - if (_changeItem == nullptr || - _changeItem->getContentSize().width <= 0 || - _changeItem->getContentSize().height <= 0) - { - problemLoading("'icon_gear.png'"); - } - - // create menu, it's an autorelease object - auto changeMenu = Menu::create(_changeItem, NULL); - changeMenu->setScale(0.9f); - changeMenu->setPosition(Point::ZERO); - this->addChild(changeMenu, 1); - - ///////////////////////////// - // 3. add your codes below... - - // add "SampleScene" splash screen" - - auto sprite = Sprite::create(LAppDefine::BackImageName); - if (sprite == nullptr) - { - problemLoading(LAppDefine::BackImageName); - } - else - { - // position the sprite on the center of the screen - sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); - sprite->setScale(2); - - // add the sprite as a child to this layer - this->addChild(sprite, 0); - } - - // add "Live2DModel" - _pView = LAppView::createDrawNode(); - this->addChild(_pView); - - // Live2DManager実体化 - LAppLive2DManager::GetInstance(); - - if (LAppDefine::DebugLogEnable) - { - LAppPal::PrintLogLn("=============================================="); - LAppPal::PrintLogLn(" Live2D SDK Sample App "); - LAppPal::PrintLogLn("=============================================="); - } - - if (LAppDefine::DebugDrawRectEnable) - { - auto* pDebugRects = DrawNode::create(); - this->addChild(pDebugRects); - _pView->setDebugRectsNode(pDebugRects); - } - - // update有効 - this->scheduleUpdate(); - - return true; -} - -void SampleScene::update(float delta) -{ - Node::update(delta); - - { - auto winSize = Director::getInstance()->getWinSize(); - auto visibleSize = Director::getInstance()->getVisibleSize(); - Vec2 origin = Director::getInstance()->getVisibleOrigin(); - // 端に隙間なく位置すると端末によっては描画されないことがあるのでマージンを設ける - Vec2 margin = Vec2(20, 20); - - if (_changeItem) - { - float x = origin.x + visibleSize.width - _changeItem->getContentSize().width / 2 - margin.x; - float y = getContentSize().height - _changeItem->getContentSize().height / 2 - margin.y; - _changeItem->setPosition(Vec2(x,y)); - } - - if (_closeItem) - { - float x = origin.x + visibleSize.width - _closeItem->getContentSize().width / 2 - margin.x; - float y = origin.y + _closeItem->getContentSize().height / 2 + margin.y; - _closeItem->setPosition(Vec2(x,y)); - } - } -} - -void SampleScene::onExit() -{ - Node::onExit(); - - // LAppModelがRenderingSpriteを使用していることがある。これはCocosのExit以降に開放することが出来ないので、 - // モデルはここですべて消えてもらう - LAppLive2DManager::GetInstance()->ReleaseAllModel(); -} - -void SampleScene::menuCloseCallback(Ref* pSender) -{ - LAppLive2DManager::ReleaseInstance(); - - Director::getInstance()->end(); - -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) - exit(0); -#endif -} - -void SampleScene::menuChangeCallback(Ref* pSender) -{ - LAppLive2DManager::GetInstance()->NextScene(); -} diff --git a/Samples/Cocos2d-x/Demo/Classes/SampleScene.h b/Samples/Cocos2d-x/Demo/Classes/SampleScene.h deleted file mode 100644 index c81ff64a..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/SampleScene.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#ifndef __SAMPLE_SCENE_H__ -#define __SAMPLE_SCENE_H__ - -#include "cocos2d.h" -#include - -class LAppView; - -class SampleScene : public cocos2d::Scene -{ -public: - static cocos2d::Scene* createScene(); - - static SampleScene* getInstance(); - - virtual bool init() override; - - virtual void update(float delta) override; - - virtual void onExit() override; - - // a selector callback - void menuCloseCallback(cocos2d::Ref* pSender); - void menuChangeCallback(cocos2d::Ref* pSender); - - // implement the "static create()" method manually - CREATE_FUNC(SampleScene); - - // constructor - SampleScene(); - -private: - LAppView* _pView; - - cocos2d::MenuItemImage* _changeItem; - cocos2d::MenuItemImage* _closeItem; -}; - -#endif // __SAMPLE_SCENE_H__ diff --git a/Samples/Cocos2d-x/Demo/Classes/TouchManager.cpp b/Samples/Cocos2d-x/Demo/Classes/TouchManager.cpp deleted file mode 100644 index 474d88e6..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/TouchManager.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#include "TouchManager.h" - -TouchManager::TouchManager() - : lastX(0) - , lastY(0) - , lastX1(0) - , lastY1(0) - , lastX2(0) - , lastY2(0) - , lastTouchDist(0) - , deltaX(0) - , deltaY(0) - , scale(1) -{ } - -/* - * タッチ開始時イベント - * @param x - * @param deviceY - */ -void TouchManager::touchesBegan(float x, float y) -{ - lastX = x; - lastY = y; - startX = x; - startY = y; - lastTouchDist = -1; - flipAvailable = true; - touchSingle = true; -} - -/* - * タッチ開始時イベント。 - * @param x1 - * @param y1 - * @param x2 - * @param y2 - */ -void TouchManager::touchesBegan(float x1, float y1, float x2, float y2) -{ - float dist = distance(x1, y1, x2, y2); - float centerX = (x1 + x2) * 0.5f; - float centerY = (y1 + y2) * 0.5f; - - lastX1 = x1; - lastY1 = y1; - lastX2 = x2; - lastY2 = y2; - - lastX = centerX; - lastY = centerY; - startX = centerX; - startY = centerY; - lastTouchDist = dist; - flipAvailable = true; - touchSingle = false; -} - -void TouchManager::touchesMoved(cocos2d::Point touches[], int num) -{ - // 前回のクリック位置に最も近いものを選びだす - // pt1、pt2の両点への距離の和が最小となる点の組み合わせを総当たりで探す - int index1, index2, minDist2 = 999999999; - index1 = 0; - index2 = 1; - for (int i1 = 0; i1 < num; i1 ++) - { - cocos2d::Point pp1 = touches[i1]; - - for (int i2 = 0; i2 < num; i2++) - { - if (i1 == i2) continue ; - - cocos2d::Point pp2 = touches[i2]; - - int distTotal = ((lastX1 - pp1.x) * (lastX1 - pp1.x) + (lastY1 - pp1.y) * (lastY1 - pp1.y)) - + ((lastX2 - pp2.x) * (lastX2 - pp2.x) + (lastY2 - pp2.y) * (lastY2 - pp2.y)); - - if (distTotal < minDist2) - { - minDist2 = distTotal; - index1 = i1; - index2 = i2; - } - } - } - - if (minDist2 > 70 * 70 * 2 && num > 2) return; // 処理しない - // pt2に一番近い点 - cocos2d::Point pt1 = touches[index1]; - cocos2d::Point pt2 = touches[index2]; - - touchesMoved(pt1.x, pt1.y, pt2.x, pt2.y); -} - -/* - * ドラッグ時のイベント - * @param deviceX - * @param deviceY - */ -void TouchManager::touchesMoved(float deviceX, float deviceY) -{ - lastX = deviceX; - lastY = deviceY; - lastTouchDist = -1; - touchSingle = true; -} - -/* - * ドラッグ時のイベント - * @param x1 - * @param y1 - * @param x2 - * @param y2 - */ -void TouchManager::touchesMoved(float x1, float y1, float x2, float y2) -{ - float dist = distance(x1, y1, x2, y2); - float centerX = (x1 + x2) * 0.5f; - float centerY = (y1 + y2) * 0.5f; - - if (lastTouchDist > 0) - { - scale = (float)pow(dist / lastTouchDist, 0.75); - deltaX = calcShift(x1 - lastX1, x2 - lastX2); - deltaY = calcShift(y1 - lastY1, y2 - lastY2); - } - else - { - scale = 1; - deltaX = 0; - deltaY = 0; - } - - lastX = centerX; - lastY = centerY; - lastX1 = x1; - lastY1 = y1; - lastX2 = x2; - lastY2 = y2; - lastTouchDist = dist; - touchSingle = false; -} - -/* - * フリックした距離 - * @return - */ -float TouchManager::getFlickDistance() -{ - return distance(startX, startY, lastX, lastY); -} - -/* - * 点1から点2への距離を求める - * @param p1x - * @param p1y - * @param p2x - * @param p2y - * @return - */ -float TouchManager::distance(float x1, float y1, float x2, float y2) -{ - return (float)sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); -} - -/* - * 二つの値から、移動量を求める。 - * 違う方向の場合は移動量0。同じ方向の場合は、絶対値が小さい方の値を参照する - */ -float TouchManager::calcShift(float v1, float v2) -{ - if ((v1 > 0) != (v2 > 0)) return 0; - - float fugou = v1 > 0 ? 1 : -1; - float a1 = abs(v1); - float a2 = abs(v2); - return fugou * ((a1 < a2) ? a1 : a2); -} diff --git a/Samples/Cocos2d-x/Demo/Classes/TouchManager.h b/Samples/Cocos2d-x/Demo/Classes/TouchManager.h deleted file mode 100644 index a3b81771..00000000 --- a/Samples/Cocos2d-x/Demo/Classes/TouchManager.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright(c) Live2D Inc. All rights reserved. - * - * Use of this source code is governed by the Live2D Open Software license - * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. - */ - -#pragma once - -#include "cocos2d.h" - -class TouchManager -{ -private: - float startY; // タッチを開始した位置 - float startX; - - float lastX; // シングルタッチ時のxの値 - float lastY; // シングルタッチ時のyの値 - float lastX1; // ダブルタッチ時の一つ目のxの値 - float lastY1; // ダブルタッチ時の一つ目のyの値 - float lastX2; // ダブルタッチ時の二つ目のxの値 - float lastY2; // ダブルタッチ時の二つ目のyの値 - - float lastTouchDist; // 2本以上でタッチしたときの指の距離 - - float deltaX; // 前回の値から今回の値へのxの移動距離。 - float deltaY; // 前回の値から今回の値へのyの移動距離。 - - float scale; // このフレームで掛け合わせる拡大率。拡大操作中以外は1。 - - bool touchSingle; // シングルタッチ時はtrue - bool flipAvailable; // フリップが有効かどうか - -public: - TouchManager(); - float getCenterX() { return lastX; } - float getCenterY() { return lastY; } - float getDeltaX() { return deltaX; } - float getDeltaY() { return deltaY; } - float getStartX() { return startX; } - float getStartY() { return startY; } - float getScale() { return scale; } - float getX() { return lastX; } - float getY() { return lastY; } - float getX1() { return lastX1; } - float getY1() { return lastY1; } - float getX2() { return lastX2; } - float getY2() { return lastY2; } - bool isSingleTouch() { return touchSingle; } - bool isFlickAvailable() { return flipAvailable; } - void disableFlick() { flipAvailable = false; } - - void touchesBegan(float deviceX, float deviceY); - void touchesBegan(float deviceX1, float deviceY1, float deviceX2, float deviceY2); - void touchesMoved(cocos2d::Point touches[], int num); - void touchesMoved(float deviceX, float deviceY); - void touchesMoved(float deviceX1, float deviceY1, float deviceX2, float deviceY2); - float getFlickDistance(); - -private: - float distance(float x1, float y1, float x2, float y2); - float calcShift(float v1, float v2); -}; diff --git a/Samples/Cocos2d-x/Demo/Resources/CloseNormal.png b/Samples/Cocos2d-x/Demo/Resources/CloseNormal.png deleted file mode 100644 index b65498c9..00000000 Binary files a/Samples/Cocos2d-x/Demo/Resources/CloseNormal.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/Resources/CloseSelected.png b/Samples/Cocos2d-x/Demo/Resources/CloseSelected.png deleted file mode 100644 index 306749ec..00000000 Binary files a/Samples/Cocos2d-x/Demo/Resources/CloseSelected.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/Resources/HelloWorld.png b/Samples/Cocos2d-x/Demo/Resources/HelloWorld.png deleted file mode 100644 index 21d43268..00000000 Binary files a/Samples/Cocos2d-x/Demo/Resources/HelloWorld.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/Resources/fonts/Marker Felt.ttf b/Samples/Cocos2d-x/Demo/Resources/fonts/Marker Felt.ttf deleted file mode 100644 index 3752ef31..00000000 Binary files a/Samples/Cocos2d-x/Demo/Resources/fonts/Marker Felt.ttf and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/Resources/fonts/arial.ttf b/Samples/Cocos2d-x/Demo/Resources/fonts/arial.ttf deleted file mode 100644 index abc899cd..00000000 Binary files a/Samples/Cocos2d-x/Demo/Resources/fonts/arial.ttf and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/Resources/res/.gitkeep b/Samples/Cocos2d-x/Demo/Resources/res/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Samples/Cocos2d-x/Demo/proj.android/.gitignore b/Samples/Cocos2d-x/Demo/proj.android/.gitignore deleted file mode 100644 index 7f96cabb..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.gradle/ -.cxx/ -build/ -/local.properties diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/AndroidManifest.xml b/Samples/Cocos2d-x/Demo/proj.android/app/AndroidManifest.xml deleted file mode 100644 index 08df45c8..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/app/AndroidManifest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/build.gradle b/Samples/Cocos2d-x/Demo/proj.android/app/build.gradle deleted file mode 100644 index 21cd4649..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/app/build.gradle +++ /dev/null @@ -1,102 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger() - - defaultConfig { - applicationId "com.live2d.demo" - minSdkVersion PROP_MIN_SDK_VERSION - targetSdkVersion PROP_TARGET_SDK_VERSION - versionCode 1 - versionName "1.0" - - externalNativeBuild { - cmake { - targets 'Demo' - arguments "-DCMAKE_FIND_ROOT_PATH=", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE" - cppFlags "-frtti -fexceptions -fsigned-char" - } - } - - ndk { - abiFilters = [] - abiFilters.addAll(PROP_APP_ABI.split(':').collect{it as String}) - } - } - - sourceSets.main { - java.srcDir "src" - res.srcDir "res" - manifest.srcFile "AndroidManifest.xml" - assets.srcDirs "../../../../Resources", "../../Resources" - } - - externalNativeBuild { - cmake { - path "../../CMakeLists.txt" - version "3.10.2" - } - } - - signingConfigs { - - release { - if (project.hasProperty("RELEASE_STORE_FILE")) { - storeFile file(RELEASE_STORE_FILE) - storePassword RELEASE_STORE_PASSWORD - keyAlias RELEASE_KEY_ALIAS - keyPassword RELEASE_KEY_PASSWORD - } - } - - debug { - storeFile file("debug.keystore") - storePassword "android" - keyAlias "androiddebugkey" - keyPassword "android" - } - } - - buildTypes { - release { - debuggable false - jniDebuggable false - renderscriptDebuggable false - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - if (project.hasProperty("RELEASE_STORE_FILE")) { - signingConfig signingConfigs.release - } - } - - debug { - debuggable true - jniDebuggable true - renderscriptDebuggable true - } - } -} - -android.applicationVariants.all { variant -> - def dest_assets_folder = "${projectDir}/assets" - - // delete previous files first - delete dest_assets_folder - def targetName = variant.name.capitalize() - def copyTaskName = "copy${targetName}ResourcesToAssets" - - tasks.register(copyTaskName) { - copy { - from "${buildDir}/../../../Resources", "${buildDir}/../../../../../Res" - into "${buildDir}/intermediates/assets/${variant.dirName}" - exclude "**/*.gz" - } - } - tasks.getByName("pre${targetName}Build").dependsOn copyTaskName -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation project(':libcocos2dx') -} diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/debug.keystore b/Samples/Cocos2d-x/Demo/proj.android/app/debug.keystore deleted file mode 100644 index 9746acf8..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.android/app/debug.keystore and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/jni/demo/main.cpp b/Samples/Cocos2d-x/Demo/proj.android/app/jni/demo/main.cpp deleted file mode 100644 index 6cab47cb..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/app/jni/demo/main.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include - -#include -#include - -#include "AppDelegate.h" - -#define LOG_TAG "main" -#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) - -namespace { -std::unique_ptr appDelegate; -} - -void cocos_android_app_init(JNIEnv* env) { - LOGD("cocos_android_app_init"); - appDelegate.reset(new AppDelegate()); -} diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/proguard-rules.pro b/Samples/Cocos2d-x/Demo/proj.android/app/proguard-rules.pro deleted file mode 100644 index 9f6d4ff6..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/app/proguard-rules.pro +++ /dev/null @@ -1,39 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Proguard Cocos2d-x for release --keep public class org.cocos2dx.** { *; } --dontwarn org.cocos2dx.** --keep public class com.chukong.** { *; } --dontwarn com.chukong.** --keep public class com.huawei.android.** { *; } --dontwarn com.huawei.android.** --keep public class com.oppo.oiface.engine.** { *; } --dontwarn com.oppo.oiface.engine.** - -# Proguard Apache HTTP for release --keep class org.apache.http.** { *; } --dontwarn org.apache.http.** - -# Proguard Android Webivew for release. uncomment if you are using a webview in cocos2d-x -#-keep public class android.net.http.SslError -#-keep public class android.webkit.WebViewClient - -#-dontwarn android.webkit.WebView -#-dontwarn android.net.http.SslError -#-dontwarn android.webkit.WebViewClient \ No newline at end of file diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-hdpi/ic_launcher.png b/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 45ee51d1..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-mdpi/ic_launcher.png b/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 0dd2a608..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-xhdpi/ic_launcher.png b/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index a32f16f9..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-xxhdpi/ic_launcher.png b/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 332f268e..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.android/app/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/res/values/strings.xml b/Samples/Cocos2d-x/Demo/proj.android/app/res/values/strings.xml deleted file mode 100644 index b2250a86..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/app/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Demo - diff --git a/Samples/Cocos2d-x/Demo/proj.android/app/src/org/cocos2dx/cpp/AppActivity.java b/Samples/Cocos2d-x/Demo/proj.android/app/src/org/cocos2dx/cpp/AppActivity.java deleted file mode 100644 index 661fe75f..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/app/src/org/cocos2dx/cpp/AppActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -Copyright (c) 2015-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -http://www.cocos2d-x.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ -package org.cocos2dx.cpp; - -import android.os.Bundle; -import org.cocos2dx.lib.Cocos2dxActivity; -import android.os.Build; -import android.view.WindowManager; -import android.view.WindowManager.LayoutParams; - -public class AppActivity extends Cocos2dxActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.setEnableVirtualButton(false); - super.onCreate(savedInstanceState); - // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508 - if (!isTaskRoot()) { - // Android launched another instance of the root activity into an existing task - // so just quietly finish and go away, dropping the user back into the activity - // at the top of the stack (ie: the last state of this task) - // Don't need to finish it again since it's finished in super.onCreate . - return; - } - // Make sure we're running on Pie or higher to change cutout mode - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - // Enable rendering into the cutout area - WindowManager.LayoutParams lp = getWindow().getAttributes(); - lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; - getWindow().setAttributes(lp); - } - // DO OTHER INITIALIZATION BELOW - - } - -} diff --git a/Samples/Cocos2d-x/Demo/proj.android/build.gradle b/Samples/Cocos2d-x/Demo/proj.android/build.gradle deleted file mode 100644 index ff9d35c6..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/build.gradle +++ /dev/null @@ -1,26 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/Samples/Cocos2d-x/Demo/proj.android/gradle.properties b/Samples/Cocos2d-x/Demo/proj.android/gradle.properties deleted file mode 100644 index 21b0b5c9..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/gradle.properties +++ /dev/null @@ -1,42 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -# Android SDK version that will be used as the compile project -PROP_COMPILE_SDK_VERSION=30 - -# Android SDK version that will be used as the earliest version of android this application can run on -PROP_MIN_SDK_VERSION=16 - -# Android SDK version that will be used as the latest version of android this application has been tested on -PROP_TARGET_SDK_VERSION=30 - - -# List of CPU Archtexture to build that application with -# Available architextures (armeabi-v7a | arm64-v8a | x86) -# To build for multiple architexture, use the `:` between them -# Example - PROP_APP_ABI=armeabi-v7a:arm64-v8a:x86 -PROP_APP_ABI=armeabi-v7a:arm64-v8a:x86 - -# uncomment it and fill in sign information for release mode -#RELEASE_STORE_FILE=file path of keystore -#RELEASE_STORE_PASSWORD=password of keystore -#RELEASE_KEY_ALIAS=alias of key -#RELEASE_KEY_PASSWORD=password of key - -android.injected.testOnly=false diff --git a/Samples/Cocos2d-x/Demo/proj.android/gradle/wrapper/gradle-wrapper.jar b/Samples/Cocos2d-x/Demo/proj.android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.android/gradle/wrapper/gradle-wrapper.properties b/Samples/Cocos2d-x/Demo/proj.android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index ad03d966..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Jan 04 17:56:17 JST 2022 -distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip -distributionPath=wrapper/dists -zipStorePath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME diff --git a/Samples/Cocos2d-x/Demo/proj.android/gradlew b/Samples/Cocos2d-x/Demo/proj.android/gradlew deleted file mode 100644 index 91a7e269..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/Samples/Cocos2d-x/Demo/proj.android/gradlew.bat b/Samples/Cocos2d-x/Demo/proj.android/gradlew.bat deleted file mode 100644 index 8a0b282a..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/Samples/Cocos2d-x/Demo/proj.android/settings.gradle b/Samples/Cocos2d-x/Demo/proj.android/settings.gradle deleted file mode 100644 index 38016e10..00000000 --- a/Samples/Cocos2d-x/Demo/proj.android/settings.gradle +++ /dev/null @@ -1,4 +0,0 @@ -include ':libcocos2dx' -project(':libcocos2dx').projectDir = new File(settingsDir, '../../thirdParty/cocos2d/cocos/platform/android/libcocos2dx') -include ':Demo' -project(':Demo').projectDir = new File(settingsDir, 'app') diff --git a/Samples/Cocos2d-x/Demo/proj.ios/scripts/proj_xcode b/Samples/Cocos2d-x/Demo/proj.ios/scripts/proj_xcode deleted file mode 100644 index adb231cf..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/scripts/proj_xcode +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env sh - -set -ue - -SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) -CMAKE_PATH=$SCRIPT_PATH/../.. -BUILD_PATH=$SCRIPT_PATH/../build/proj_xcode -THIRD_PARTY_DIR=$SCRIPT_PATH/../../../thirdParty - -# Run CMake. -cmake -S "$CMAKE_PATH" \ - -B "${BUILD_PATH}_iphoneos" \ - -G Xcode \ - -D CMAKE_SYSTEM_NAME=iOS \ - -D CMAKE_OSX_SYSROOT=iphoneos diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/AppController.h b/Samples/Cocos2d-x/Demo/proj.ios/src/AppController.h deleted file mode 100644 index f0e78b77..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/AppController.h +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** - Copyright (c) 2010-2013 cocos2d-x.org - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#import - -@class RootViewController; - -@interface AppController : NSObject { - -} - -@property(nonatomic, readonly) RootViewController* viewController; - -@end - diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/AppController.mm b/Samples/Cocos2d-x/Demo/proj.ios/src/AppController.mm deleted file mode 100644 index 18c90ebb..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/AppController.mm +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** - Copyright (c) 2010-2013 cocos2d-x.org - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#import "AppController.h" -#import "cocos2d.h" -#import "AppDelegate.h" -#import "RootViewController.h" - -@implementation AppController - -@synthesize window; - -#pragma mark - -#pragma mark Application lifecycle - -// cocos2d application instance -static AppDelegate s_sharedApplication; - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - - cocos2d::Application *app = cocos2d::Application::getInstance(); - - // Initialize the GLView attributes - app->initGLContextAttrs(); - cocos2d::GLViewImpl::convertAttrs(); - - // Override point for customization after application launch. - - // Add the view controller's view to the window and display. - window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; - - // Use RootViewController to manage CCEAGLView - _viewController = [[RootViewController alloc]init]; - _viewController.wantsFullScreenLayout = YES; - - - // Set RootViewController to window - if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0) - { - // warning: addSubView doesn't work on iOS6 - [window addSubview: _viewController.view]; - } - else - { - // use this method on ios6 - [window setRootViewController:_viewController]; - } - - [window makeKeyAndVisible]; - - [[UIApplication sharedApplication] setStatusBarHidden:true]; - - // IMPORTANT: Setting the GLView should be done after creating the RootViewController - cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)_viewController.view); - cocos2d::Director::getInstance()->setOpenGLView(glview); - - //run the cocos2d-x game scene - app->run(); - - return YES; -} - - -- (void)applicationWillResignActive:(UIApplication *)application { - /* - Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - */ - // We don't need to call this method any more. It will interrupt user defined game pause&resume logic - /* cocos2d::Director::getInstance()->pause(); */ -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - /* - Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - */ - // We don't need to call this method any more. It will interrupt user defined game pause&resume logic - /* cocos2d::Director::getInstance()->resume(); */ -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - /* - Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - If your application supports background execution, called instead of applicationWillTerminate: when the user quits. - */ - cocos2d::Application::getInstance()->applicationDidEnterBackground(); -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - /* - Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. - */ - cocos2d::Application::getInstance()->applicationWillEnterForeground(); -} - -- (void)applicationWillTerminate:(UIApplication *)application { - /* - Called when the application is about to terminate. - See also applicationDidEnterBackground:. - */ -} - - -#pragma mark - -#pragma mark Memory management - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - /* - Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. - */ -} - - -#if __has_feature(objc_arc) -#else -- (void)dealloc { - [window release]; - [_viewController release]; - [super dealloc]; -} -#endif - - -@end diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Contents.json b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 51cbd32f..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-29.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-40@3x.png", - "scale" : "3x" - }, - { - "size" : "57x57", - "idiom" : "iphone", - "filename" : "Icon-57.png", - "scale" : "1x" - }, - { - "size" : "57x57", - "idiom" : "iphone", - "filename" : "Icon-57@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-20.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-29.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-40.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-40@2x.png", - "scale" : "2x" - }, - { - "size" : "50x50", - "idiom" : "ipad", - "filename" : "Icon-50.png", - "scale" : "1x" - }, - { - "size" : "50x50", - "idiom" : "ipad", - "filename" : "Icon-50@2x.png", - "scale" : "2x" - }, - { - "size" : "72x72", - "idiom" : "ipad", - "filename" : "Icon-72.png", - "scale" : "1x" - }, - { - "size" : "72x72", - "idiom" : "ipad", - "filename" : "Icon-72@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-76.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-83.5@2x.png", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20.png deleted file mode 100644 index 8ead23e3..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20@2x.png deleted file mode 100644 index 775685da..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20@3x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20@3x.png deleted file mode 100644 index a5b49ccb..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-20@3x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29.png deleted file mode 100644 index 0500184c..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png deleted file mode 100644 index f0f8b7fe..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png deleted file mode 100644 index 5287e50a..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40.png deleted file mode 100644 index 775685da..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png deleted file mode 100644 index d9c7ab44..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png deleted file mode 100644 index a5b49ccb..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-50.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-50.png deleted file mode 100644 index ac381bc2..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-50.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-50@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-50@2x.png deleted file mode 100644 index ef38d450..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-50@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-57.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-57.png deleted file mode 100644 index 4fcc6fdd..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-57.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-57@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-57@2x.png deleted file mode 100644 index c3807861..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-57@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png deleted file mode 100644 index a5b49ccb..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png deleted file mode 100644 index d4bc5313..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-72.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-72.png deleted file mode 100644 index 2c573c8d..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-72.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png deleted file mode 100644 index 1526615c..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-76.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-76.png deleted file mode 100644 index 8a1fa185..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-76.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png deleted file mode 100644 index 8aa82506..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png deleted file mode 100644 index 6bf801d1..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/Contents.json b/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/Contents.json deleted file mode 100644 index da4a164c..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/Images.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Info.plist b/Samples/Cocos2d-x/Demo/proj.ios/src/Info.plist deleted file mode 100644 index 94a00802..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/Info.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - Icon-57.png - CFBundleIdentifier - com.live2d.demo - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - UIAppFonts - - UILaunchStoryboardName - LaunchScreen - UIPrerenderedIcon - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationLandscapeLeft - - - diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/LaunchScreen.storyboard b/Samples/Cocos2d-x/Demo/proj.ios/src/LaunchScreen.storyboard deleted file mode 100644 index 068bbaa8..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/LaunchScreen.storyboard +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/LaunchScreenBackground.png b/Samples/Cocos2d-x/Demo/proj.ios/src/LaunchScreenBackground.png deleted file mode 100644 index dadccee6..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.ios/src/LaunchScreenBackground.png and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/Prefix.pch b/Samples/Cocos2d-x/Demo/proj.ios/src/Prefix.pch deleted file mode 100644 index ce1833f9..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/Prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -// -// Prefix header for all source files of the 'iphone' target in the 'iphone' project -// - -#ifdef __OBJC__ - #import - #import -#endif - -#ifdef __cplusplus - #include "cocos2d.h" -#endif diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/RootViewController.h b/Samples/Cocos2d-x/Demo/proj.ios/src/RootViewController.h deleted file mode 100644 index ed4046d6..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/RootViewController.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - Copyright (c) 2013 cocos2d-x.org - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#import - - -@interface RootViewController : UIViewController { - -} -- (BOOL) prefersStatusBarHidden; - -@end diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/RootViewController.mm b/Samples/Cocos2d-x/Demo/proj.ios/src/RootViewController.mm deleted file mode 100644 index 7f5ca28f..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/RootViewController.mm +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** - Copyright (c) 2013 cocos2d-x.org - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#import "RootViewController.h" -#import "cocos2d.h" -#import "platform/ios/CCEAGLView-ios.h" - - -@implementation RootViewController - -/* - // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { - // Custom initialization - } - return self; -} -*/ - -// Implement loadView to create a view hierarchy programmatically, without using a nib. -- (void)loadView { - // Initialize the CCEAGLView - CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [UIScreen mainScreen].bounds - pixelFormat: (__bridge NSString *)cocos2d::GLViewImpl::_pixelFormat - depthFormat: cocos2d::GLViewImpl::_depthFormat - preserveBackbuffer: NO - sharegroup: nil - multiSampling: cocos2d::GLViewImpl::_multisamplingCount > 0 ? YES : NO - numberOfSamples: cocos2d::GLViewImpl::_multisamplingCount ]; - - // Enable or disable multiple touches - [eaglView setMultipleTouchEnabled:NO]; - - // Set EAGLView as view of RootViewController - self.view = eaglView; -} - -// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. -- (void)viewDidLoad { - [super viewDidLoad]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; -} - -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; -} - - -// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead -#ifdef __IPHONE_6_0 -- (NSUInteger) supportedInterfaceOrientations{ - return UIInterfaceOrientationMaskAllButUpsideDown; -} -#endif - -- (BOOL) shouldAutorotate { - return YES; -} - -- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { - [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; - - auto glview = cocos2d::Director::getInstance()->getOpenGLView(); - - if (glview) - { - CCEAGLView *eaglview = (__bridge CCEAGLView *)glview->getEAGLView(); - - if (eaglview) - { - CGSize s = CGSizeMake([eaglview getWidth], [eaglview getHeight]); - cocos2d::Application::getInstance()->applicationScreenSizeChanged((int) s.width, (int) s.height); - } - } -} - -//fix not hide status on ios7 -- (BOOL)prefersStatusBarHidden { - return YES; -} - -// Controls the application's preferred home indicator auto-hiding when this view controller is shown. -// (better use preferredScreenEdgesDeferringSystemGestures for controlling the home indicator) -- (BOOL)prefersHomeIndicatorAutoHidden { - return NO; -} - -// HOME Indicator need to be tapped twice --(UIRectEdge)preferredScreenEdgesDeferringSystemGestures -{ - return UIRectEdgeBottom; -} - -- (void)didReceiveMemoryWarning { - // Releases the view if it doesn't have a superview. - [super didReceiveMemoryWarning]; - - // Release any cached data, images, etc that aren't in use. -} - - -@end diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/exportoptions.plist b/Samples/Cocos2d-x/Demo/proj.ios/src/exportoptions.plist deleted file mode 100644 index 14a6dc5c..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/exportoptions.plist +++ /dev/null @@ -1,15 +0,0 @@ - - - - - compileBitcode - - method - development - provisioningProfiles - - Bundle Identifier - Provision Prifile Name - - - diff --git a/Samples/Cocos2d-x/Demo/proj.ios/src/main.m b/Samples/Cocos2d-x/Demo/proj.ios/src/main.m deleted file mode 100644 index 62178533..00000000 --- a/Samples/Cocos2d-x/Demo/proj.ios/src/main.m +++ /dev/null @@ -1,7 +0,0 @@ -#import - -int main(int argc, char *argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, @"AppController"); - } -} diff --git a/Samples/Cocos2d-x/Demo/proj.linux/scripts/fix_libs b/Samples/Cocos2d-x/Demo/proj.linux/scripts/fix_libs deleted file mode 100644 index 7a1c33fa..00000000 --- a/Samples/Cocos2d-x/Demo/proj.linux/scripts/fix_libs +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env sh - -set -ue - -SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) -COCOS2D_DIR=$SCRIPT_PATH/../../../thirdParty/cocos2d - -cd $SCRIPT_PATH -curl -fsSL -o cocos-3rd.zip \ - https://github.com/cocos2d/cocos2d-x-3rd-party-libs-src/archive/v3.zip -unzip -oq cocos-3rd.zip -cd cocos2d-*/build/ -./build.sh -p=linux --libs=freetype --arch=x86_64 --mode=release -mv linux/freetype/prebuilt/x86_64/libfreetype.a \ - $COCOS2D_DIR/external/freetype2/prebuilt/linux/64-bit/libfreetype.a -cd $SCRIPT_PATH -rm -rf cocos* - -cd $COCOS2D_DIR/external/linux-specific/fmod/prebuilt/64-bit/ -ln -sf libfmod.so libfmod.so.6 diff --git a/Samples/Cocos2d-x/Demo/proj.linux/scripts/make_gcc b/Samples/Cocos2d-x/Demo/proj.linux/scripts/make_gcc deleted file mode 100644 index 184dafe4..00000000 --- a/Samples/Cocos2d-x/Demo/proj.linux/scripts/make_gcc +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env sh - -set -ue - -SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) -CMAKE_PATH=$SCRIPT_PATH/../.. -BUILD_PATH=$SCRIPT_PATH/../build/make_gcc - -# Run CMake. -mkdir -p "$BUILD_PATH" -cd "$BUILD_PATH" -cmake \ - -DCMAKE_BUILD_TYPE=Release "$CMAKE_PATH" \ - -DCMAKE_SYSTEM_NAME=Linux -make diff --git a/Samples/Cocos2d-x/Demo/proj.linux/src/main.cpp b/Samples/Cocos2d-x/Demo/proj.linux/src/main.cpp deleted file mode 100644 index 2bd3032f..00000000 --- a/Samples/Cocos2d-x/Demo/proj.linux/src/main.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "../Classes/AppDelegate.h" - -#include -#include -#include -#include - -USING_NS_CC; - -int main(int argc, char **argv) -{ - // create the application instance - AppDelegate app; - return Application::getInstance()->run(); -} diff --git a/Samples/Cocos2d-x/Demo/proj.mac/scripts/make_xcode b/Samples/Cocos2d-x/Demo/proj.mac/scripts/make_xcode deleted file mode 100644 index 96cef9ec..00000000 --- a/Samples/Cocos2d-x/Demo/proj.mac/scripts/make_xcode +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env sh - -set -ue - -SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) -CMAKE_PATH=$SCRIPT_PATH/../.. -BUILD_PATH=$SCRIPT_PATH/../build/make_xcode - -# Run CMake. -cmake \ - -S "$CMAKE_PATH" \ - -B "$BUILD_PATH" \ - -D CMAKE_BUILD_TYPE=Release -cd "$BUILD_PATH" && make diff --git a/Samples/Cocos2d-x/Demo/proj.mac/scripts/proj_xcode b/Samples/Cocos2d-x/Demo/proj.mac/scripts/proj_xcode deleted file mode 100644 index b00671d9..00000000 --- a/Samples/Cocos2d-x/Demo/proj.mac/scripts/proj_xcode +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env sh - -set -ue - -SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) -CMAKE_PATH=$SCRIPT_PATH/../.. -BUILD_PATH=$SCRIPT_PATH/../build/proj_xcode - -# Run CMake. -cmake -S "$CMAKE_PATH" \ - -B "$BUILD_PATH" \ - -G Xcode diff --git a/Samples/Cocos2d-x/Demo/proj.mac/src/Icon.icns b/Samples/Cocos2d-x/Demo/proj.mac/src/Icon.icns deleted file mode 100644 index 2040fc6f..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.mac/src/Icon.icns and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.mac/src/Info.plist b/Samples/Cocos2d-x/Demo/proj.mac/src/Info.plist deleted file mode 100644 index e4be49d4..00000000 --- a/Samples/Cocos2d-x/Demo/proj.mac/src/Info.plist +++ /dev/null @@ -1,36 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - Icon - CFBundleIdentifier - com.live2d.demo - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSApplicationCategoryType - public.app-category.games - LSMinimumSystemVersion - ${MACOSX_DEPLOYMENT_TARGET} - NSHumanReadableCopyright - Copyright © 2013. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Samples/Cocos2d-x/Demo/proj.mac/src/Prefix.pch b/Samples/Cocos2d-x/Demo/proj.mac/src/Prefix.pch deleted file mode 100644 index dde8bdc6..00000000 --- a/Samples/Cocos2d-x/Demo/proj.mac/src/Prefix.pch +++ /dev/null @@ -1,11 +0,0 @@ -// -// Prefix header for all source files of the 'Paralaxer' target in the 'Paralaxer' project -// - -#ifdef __OBJC__ - #import -#endif - -#ifdef __cplusplus - #include "cocos2d.h" -#endif diff --git a/Samples/Cocos2d-x/Demo/proj.mac/src/main.cpp b/Samples/Cocos2d-x/Demo/proj.mac/src/main.cpp deleted file mode 100644 index ed8ee7c1..00000000 --- a/Samples/Cocos2d-x/Demo/proj.mac/src/main.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - Copyright (c) 2010 cocos2d-x.org - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "AppDelegate.h" -#include "cocos2d.h" - -USING_NS_CC; - -int main(int argc, char *argv[]) -{ - AppDelegate app; - return Application::getInstance()->run(); -} diff --git a/Samples/Cocos2d-x/Demo/proj.win/scripts/_msvc_common.bat b/Samples/Cocos2d-x/Demo/proj.win/scripts/_msvc_common.bat deleted file mode 100644 index 053bf13d..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/scripts/_msvc_common.bat +++ /dev/null @@ -1,74 +0,0 @@ -@echo off - -setlocal -set VARIABLE_EXISTS=TRUE -if "%MSVC_VERSION%" equ "" set VARIABLE_EXISTS=FALSE -if "%MSVC_NUMBER%" equ "" set VARIABLE_EXISTS=FALSE -if "%VCVARSALL%" equ "" set VARIABLE_EXISTS=FALSE -if "%VARIABLE_EXISTS%" equ "FALSE" ( - echo [CubismNativeSamples] Invalid batch call. - exit /b 1 -) -endlocal - -cd %~dp0 - -rem ============== -rem Dialog Options -rem ============== - -rem Core C Runtime selection -echo. -echo Select which cubism core c runtime library to use -echo ************************************************** -echo 1. use the multithread-specific and DLL-specific version of the run-time library (MD) -echo 2. use the multithread, static version of the run-time library (MT) -echo. -choice /c:12 /n /m ">" -set SELECTED=%errorlevel% -if "%SELECTED%" equ "1" ( - set CORE_CRL_MD=ON -) else if "%SELECTED%" equ "2" ( - set CORE_CRL_MD=OFF -) else ( - echo [CubismNativeSamples] Invalid option. - exit /b 1 -) - -rem ======== -rem Validate -rem ======== - -rem Make sure toolchain exists. -if not exist "%VCVARSALL%" ( - echo [CubismNativeSamples] Visual C++ Compiler %MSVC_VERSION% not found. - exit /b 1 -) - -rem ===== -rem Build -rem ===== - -rem Execute build. -echo Building x86 with Visual C++ Compiler %MSVC_VERSION%... - -rem Initialize Visual Studio toolchain. -call "%VCVARSALL%" x86 -if %errorlevel% neq 0 exit /b %errorlevel% - -rem Build for native development. -if "%CORE_CRL_MD%" equ "ON" ( - set CORE_CRL=md -) else ( - set CORE_CRL=mt -) - -set BUILD_PATH=..\build\proj_msvc%MSVC_VERSION%_x86_%CORE_CRL% - -cmake -S ..\.. -B "%BUILD_PATH%" ^ - -G "Visual Studio %MSVC_NUMBER% %MSVC_VERSION%" ^ - -A Win32 ^ - -D CORE_CRL_MD=%CORE_CRL_MD% -if %errorlevel% neq 0 exit /b %errorlevel% - -exit /b 0 diff --git a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2015.bat b/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2015.bat deleted file mode 100644 index b6c7a378..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2015.bat +++ /dev/null @@ -1,13 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2015 -set MSVC_NUMBER=14 -set VCVARSALL=%VS140COMNTOOLS%..\..\VC\vcvarsall.bat - -call %SCRIPT_PATH%_msvc_common.bat -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2017.bat b/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2017.bat deleted file mode 100644 index 9efbe7f5..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2017.bat +++ /dev/null @@ -1,18 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2017 -set MSVC_NUMBER=15 -set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe -set /a _MSVC_RANGE_S=MSVC_NUMBER -set /a _MSVC_RANGE_E=MSVC_NUMBER+1 -for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( - set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat -) - -call %SCRIPT_PATH%_msvc_common.bat -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2019.bat b/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2019.bat deleted file mode 100644 index 1a574553..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2019.bat +++ /dev/null @@ -1,18 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2019 -set MSVC_NUMBER=16 -set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe -set /a _MSVC_RANGE_S=MSVC_NUMBER -set /a _MSVC_RANGE_E=MSVC_NUMBER+1 -for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( - set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat -) - -call %SCRIPT_PATH%_msvc_common.bat -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2022.bat b/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2022.bat deleted file mode 100644 index ecfbf93a..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/scripts/proj_msvc2022.bat +++ /dev/null @@ -1,18 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2022 -set MSVC_NUMBER=17 -set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe -set /a _MSVC_RANGE_S=MSVC_NUMBER -set /a _MSVC_RANGE_E=MSVC_NUMBER+1 -for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -legacy -version [%_MSVC_RANGE_S%^,%_MSVC_RANGE_E%^) -property installationPath`) do ( - set VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat -) - -call %SCRIPT_PATH%_msvc_common.bat -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/Cocos2d-x/Demo/proj.win/src/game.rc b/Samples/Cocos2d-x/Demo/proj.win/src/game.rc deleted file mode 100644 index 338b8f96..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/src/game.rc +++ /dev/null @@ -1,86 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -#endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -GLFW_ICON ICON "res\\game.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "game Module\0" - VALUE "FileVersion", "1, 0, 0, 1\0" - VALUE "InternalName", "game\0" - VALUE "LegalCopyright", "Copyright \0" - VALUE "OriginalFilename", "game.exe\0" - VALUE "ProductName", "game Module\0" - VALUE "ProductVersion", "1, 0, 0, 1\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 0x04B0 - END -END - -///////////////////////////////////////////////////////////////////////////// -#endif // !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) diff --git a/Samples/Cocos2d-x/Demo/proj.win/src/main.cpp b/Samples/Cocos2d-x/Demo/proj.win/src/main.cpp deleted file mode 100644 index 9a39bdde..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/src/main.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "main.h" -#include "AppDelegate.h" -#include "cocos2d.h" - -USING_NS_CC; - -int WINAPI _tWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPTSTR lpCmdLine, - int nCmdShow) -{ - UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(lpCmdLine); - - // create the application instance - AppDelegate app; - return Application::getInstance()->run(); -} diff --git a/Samples/Cocos2d-x/Demo/proj.win/src/main.h b/Samples/Cocos2d-x/Demo/proj.win/src/main.h deleted file mode 100644 index dba8f53b..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/src/main.h +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#ifndef __MAIN_H__ -#define __MAIN_H__ - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - -// Windows Header Files: -#include -#include - -// C RunTime Header Files -#include "platform/CCStdC.h" - -#endif // __MAIN_H__ diff --git a/Samples/Cocos2d-x/Demo/proj.win/src/res/game.ico b/Samples/Cocos2d-x/Demo/proj.win/src/res/game.ico deleted file mode 100644 index feaf932a..00000000 Binary files a/Samples/Cocos2d-x/Demo/proj.win/src/res/game.ico and /dev/null differ diff --git a/Samples/Cocos2d-x/Demo/proj.win/src/resource.h b/Samples/Cocos2d-x/Demo/proj.win/src/resource.h deleted file mode 100644 index 2268ba81..00000000 --- a/Samples/Cocos2d-x/Demo/proj.win/src/resource.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by game.RC -// - -#define IDS_PROJNAME 100 -#define IDR_TESTJS 100 - -#define ID_FILE_NEW_WINDOW 32771 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 201 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 32775 -#endif -#endif diff --git a/Samples/Cocos2d-x/README.ja.md b/Samples/Cocos2d-x/README.ja.md deleted file mode 100644 index 4be2d613..00000000 --- a/Samples/Cocos2d-x/README.ja.md +++ /dev/null @@ -1,206 +0,0 @@ -[English](README.md) / [日本語](README.ja.md) - ---- - -# Cubism Native Samples for Cocos2d-x - -Cocos2d-xで実装したアプリケーションのサンプル実装です。 - - -## 開発環境 - -| フレームワーク | バージョン | -| --- | --- | -| [Xcode] | 15.1 | -| [Cocos2d-x] | 4.0 (`95e5d868ce5958c0dadfc485bdda52f1bc404fe0`) | - -その他の開発環境・動作確認環境はトップディレクトリにある [README.md](../../README.ja.md) を参照してください。 - -また、[Cocos2d-x ドキュメントの前提条件]も確認してください。 - -[Cocos2d-x ドキュメントの前提条件]: https://docs.cocos2d-x.org/cocos2d-x/v3/en/installation/prerequisites.html - -### Cocos2d-x v4.x に関して - -Cocos2d-x v4.0 から Metal API の対応に伴い、Renderer の構成が変更され、OpenGLES の API を直接使用することが出来なくなりました。 -詳しくは [Cocos2d-x のドキュメント](https://docs.cocos2d-x.org/cocos2d-x/v4/en/upgradeGuide/) を参照してください。 - -この変更に伴い Cocos2d-x v4.x 系では Cubism Framework の Renderer に Cocos2d-x 専用の物を用意いたしました。現在は、各プラットフォームで共通の Renderer を使用しており、 macOS, Windows, Linux, iOS, Android と横断的にクロスコンパイルを通すことが可能です。 - - -## ディレクトリ構造 - -``` -. -├─ Demo -│ ├─ Classes # Sources for sample projects -│ ├─ proj.android # Android Studio project -│ ├─ proj.ios # Additional files and build scripts for iOS -│ ├─ proj.linux # Additional files and build scripts for Linux -│ ├─ proj.mac # Additional files and build scripts for macOS -│ ├─ proj.win # Additional files and build scripts for Windows -│ └─ Resources # Resources of cocos2d-x template project -└─ thirdParty # Third party libraries and scripts -``` - - -## Demo - -[Cubism Native Framework] の各機能を一通り利用したサンプルです。 -モーションの再生、表情の設定、ポーズの切り替え、物理演算の設定などを行います。 -メニューボタンからモデルを切り替えることができます。 - -[Cubism Native Framework]: https://github.com/Live2D/CubismNativeFramework - -このディレクトリ内に含まれるものは以下の通りです。 - -### Classes - -サンプルプロジェクトで使用するソースコードが含まれます。 - -### proj.android - -Android 用の Android Studio プロジェクトが含まれます。 - -NOTE: 事前に下記の SDK のダウンロードが必要です - -* Android SDK Build-Tools -* NDK -* CMake - -ビルド時に下記の手順を行なってください。 - -1. Android Studio の `File - Build, Execution, Deployment - Build Tools - Gradle - Gradle JDK` を `1.8` に設定してください - -### proj.ios - -iOS 用の CMake プロジェクトです。 - -`script` ディレクトリのスクリプトを実行すると `build` ディレクトリに CMake 成果物が生成されます - -| スクリプト名 | 生成物 | -| --- | --- | -| `proj_xcode` | Xcode プロジェクト | - -ビルド時に下記の手順を行なってください。 - -1. Xcode の `Project設定 - TARGETS - Demo - Packaging - Info.plist File` に記載されている `Info.plist` 内の `Executable file` を `$(EXECUTABLE_NAME)` または`Demo`(アプリ名)に書き換えてください - -1. `cocos2d/cocos/2d/CCFontAtlas.h` に以下の修正を加えてください -```CCFontAtlas.h -@@ -30,6 +30,7 @@ - - #include - #include -+#include - - #include "platform/CCPlatformMacros.h" - #include "base/CCRef.h" -@@ -129,7 +130,7 @@ protected: - float _lineHeight; - Font* _font; - FontFreeType* _fontFreeType; -- void* _iconv; -+ iconv_t _iconv; -``` - -NOTICE: Cubism Core は i386 アーキテクチャをサポートしていないため、**iPhone Simulator 向けのビルドは行えません。** - -### proj.linux - -Linux 用の CMake プロジェクトです。 - -`script` ディレクトリのスクリプトを実行すると `build` ディレクトリに CMake 成果物が生成されます - -| スクリプト名 | 生成物 | -| --- | --- | -| `make_gcc` | 実行可能なアプリケーション | - -ビルド前に下記の手順を行なってください。 - -1. [Dependencies that you need] ドキュメントを参照して必要なパッケージをダウンロードします - -[Dependencies that you need]: https://docs.cocos2d-x.org/cocos2d-x/v4/en/installation/Linux.html#dependencies-that-you-need - -NOTICE: Linuxビルドには制限があります。使用する際は必ずトップディレクトリにある[NOTICE.md](../../NOTICE.md)をご確認ください。 - -### proj.mac - -macOS 用の CMake プロジェクトです。 - -`script` ディレクトリのスクリプトを実行すると `build` ディレクトリに CMake 成果物が生成されます - -| スクリプト名 | 生成物 | -| --- | --- | -| `make_xcode` | 実行可能なアプリケーション | -| `proj_xcode` | Xcode プロジェクト | - -WARNING: macOSビルドにつきまして、`Cocos2d-x V4.0` に起因する不具合のために正常にビルドができない状態となっております。対処方法につきましては、以下の Issue をご確認ください。 - -* [cocos2d/cocos2d-x error: Objective-C was disabled in PCH file but is currently enabled -#20607 -](https://github.com/cocos2d/cocos2d-x/issues/20607#issuecomment-780266298) - -ビルド時に下記の手順を行なってください。 - -1. `cocos2d/cocos/2d/CCFontAtlas.h` に以下の修正を加えてください -```CCFontAtlas.h -@@ -30,6 +30,7 @@ - - #include - #include -+#include - - #include "platform/CCPlatformMacros.h" - #include "base/CCRef.h" -@@ -129,7 +130,7 @@ protected: - float _lineHeight; - Font* _font; - FontFreeType* _fontFreeType; -- void* _iconv; -+ iconv_t _iconv; -``` - -### proj.win - -Windows 用の CMake プロジェクトです。 - -`script` ディレクトリのスクリプトを実行すると `build` ディレクトリに CMake 成果物が生成されます - -| スクリプト名 | 生成物 | -| --- | --- | -| `proj_msvcXXXX.bat` | Visual Studio プロジェクト | - -NOTICE: nmake を使用したビルドは Cocos2d-x のエラーが発生するため対応していません。 - -### Resources - -Cocos2d-xのテンプレートプロジェクトで参照しているリソースが含まれます。 - -### CMakeLists.txt - -CMake 用の設定ファイルです。 - -各プラットフォームのビルド設定が記載されています。 - - -## thirdParty - -サンプルプロジェクトで利用するサードパーティライブラリとビルドスクリプトが含まれます。 - -### Cocos2d-x のセットアップ - -`script` ディレクトリ内のスクリプトを実行することで Cocos2d-x のダウンロードを行います。 - -| プラットフォーム | スクリプト名 | -| --- | --- | -| Linux / macOS | `setup_cocos2d` | -| Windows | `setup_cocos2d.bat` | - -スクリプト内の `COCOS_COMMIT_HASH` を変更することで、使用する Cocos2d-x の SCM 上のバージョンをコミットハッシュで指定することが出来ます。 - -ダウンロード後は `thirdParty/cocos2d` というディレクトリ名で展開されます。 - -[Cocos2d-x]: https://cocos2d-x.org/ - -NOTICE: MacOSにて thirdParty/cocos2d 内のスクリプト download-deps.py で一部URLの解決が出来ずエラーとなる問題を確認しております。 diff --git a/Samples/Cocos2d-x/README.md b/Samples/Cocos2d-x/README.md deleted file mode 100644 index fba210c5..00000000 --- a/Samples/Cocos2d-x/README.md +++ /dev/null @@ -1,202 +0,0 @@ -[English](README.md) / [日本語](README.ja.md) - ---- - -# Cubism Native Samples for Cocos2d-x - -This is a sample implementation of an application implemented with Cocos2d-x. - - -## Development environment - -| Framework | Version | -| --- | --- | -| [Xcode] | 15.1 | -| [Cocos2d-x] | 4.0 (`95e5d868ce5958c0dadfc485bdda52f1bc404fe0`) | - -For other development environments and operation environments, see [README.md](../../README.md) in the top directory. - -Please also check the [Cocos2d-x Documentation Prerequisites]. - -[Cocos2d-x Documentation Prerequisites]: https://docs.cocos2d-x.org/cocos2d-x/v3/en/installation/prerequisites.html - -### Regarding Cocos2d-x v4.x - -With support for the Metal API since Cocos2d-x v4.0, the configuration of the Renderer has changed to make it impossible to use the OpenGLES API directly. -Please check the [Cocos2d-x Documentation](https://docs.cocos2d-x.org/cocos2d-x/v4/en/upgradeGuide/) for more information. - -Along with this change, we have prepared a dedicated Cocos2d-x Renderer for the Cubism Framework in the Cocos2d-x v4.x series. Currently, each platform uses a common Renderer, and it is possible to cross-compile across macOS, Windows, Linux, iOS, and Android. - - -## Directory structure - -``` -. -├─ Demo -│ ├─ Classes # Sources for sample projects -│ ├─ proj.android # Android Studio project -│ ├─ proj.ios # Additional files and build scripts for iOS -│ ├─ proj.linux # Additional files and build scripts for Linux -│ ├─ proj.mac # Additional files and build scripts for macOS -│ ├─ proj.win # Additional files and build scripts for Windows -│ └─ Resources # Resources of cocos2d-x template project -└─ thirdParty # Third party libraries and scripts -``` - - -## Demo - -A sample that uses each function of [Cubism Native Framework]. You can play motions, set facial expressions, switch poses, set physics, etc. You can switch models from the menu button. - -[Cubism Native Framework]: https://github.com/Live2D/CubismNativeFramework - -The items contained in this directory are as follows. - -### Classes - -Contains the source code used in the sample project. - -### proj.android - -Contains Android Studio projects for Android. - -NOTE: You need to download the following SDKs in advance. - -* Android SDK Build-Tools -* NDK -* CMake - -Follow the steps below before building. - -1. set `File - Build, Execution, Deployment - Build Tools - Gradle - Gradle JDK` to `1.8` in Android Studio - -### proj.ios - -CMake project for iOS. - -Running the script in the `script` directory will generate a CMake deliverable in the `build` directory. - -| Script name | Product | -| --- | --- | -| `proj_xcode` | Xcode project | - -Follow the steps below when building. - -1. Rewrite the `Executable file` in `Info.plist` stated in Xcode's `Project Settings - TARGETS - Demo - Packaging - Info.plist File` to `$(EXECUTABLE_NAME)` or `Demo` (app name). - -1. make the following modifications to `cocos2d/cocos/2d/CCFontAtlas.h`. -```CCFontAtlas.h -@@ -30,6 +30,7 @@ - - #include - #include -+#include - - #include "platform/CCPlatformMacros.h" - #include "base/CCRef.h" -@@ -129,7 +130,7 @@ protected: - float _lineHeight; - Font* _font; - FontFreeType* _fontFreeType; -- void* _iconv; -+ iconv_t _iconv; -``` - -NOTICE: Cubism Core does not support the i386 architecture, so **it is not possible to build for iPhone Simulator.** - -### proj.linux - -CMake project for Linux. - -Running the script in the `script` directory will generate a CMake deliverable in the `build` directory. - -| Script name | Product | -| --- | --- | -| `make_gcc` | Executable application | - -Follow the steps below before building. - -1. Refer to the [Dependencies that you need] documentation to download the required packages. - -[Dependencies that you need]: https://docs.cocos2d-x.org/cocos2d-x/v4/en/installation/Linux.html#dependencies-that-you-need - -NOTICE: Linux builds have restrictions. Please be sure to check [NOTICE.md](../../NOTICE.md) in the top directory when using it. - -### proj.mac - -CMake project for macOS. - -Running the script in the `script` directory will generate a CMake deliverable in the `build` directory. - -| Script name | Product | -| --- | --- | -| `make_xcode` | Executable application | -| `proj_xcode` | Xcode project | - -WARNING: Regarding macOS build, it is not possible to build normally due to a problem caused by `Cocos2d-x V4.0`. Please check the following Issue for the workaround. - -* [cocos2d/cocos2d-x error: Objective-C was disabled in PCH file but is currently enabled#20607](https://github.com/cocos2d/cocos2d-x/issues/20607#issuecomment-780266298) - -Follow the steps below when building. - -1. make the following modifications to `cocos2d/cocos/2d/CCFontAtlas.h` -```CCFontAtlas.h -@@ -30,6 +30,7 @@ - - #include - #include -+#include - - #include "platform/CCPlatformMacros.h" - #include "base/CCRef.h" -@@ -129,7 +130,7 @@ protected: - float _lineHeight; - Font* _font; - FontFreeType* _fontFreeType; -- void* _iconv; -+ iconv_t _iconv; -``` - -### proj.win - -CMake project for Windows. - -Running the script in the `script` directory will generate a CMake deliverable in the `build` directory. - -| Script name | Product | -| --- | --- | -| `proj_msvcXXXX.bat` | Visual Studio project | - -NOTICE: Builds using nmake are not supported due to Cocos2d-x errors. - -### Resources - -Contains the resources referenced in the Cocos2d-x template project. - -### CMakeLists.txt - -Configuration file for CMake. - -The build settings for each platform are listed. - - -## thirdParty - -Contains third-party libraries and build scripts used in the sample project. - -### Cocos2d-x setup - -Download Cocos2d-x by running the script in the `script` directory. - -| Platform | Script name | -| --- | --- | -| Linux / macOS | `setup_cocos2d` | -| Windows | `setup_cocos2d.bat` | - -You can specify the version of Cocos2d-x on the SCM to be used with a commit hash by changing `COCOS_COMMIT_HASH` in the script. - -After downloading, it will be expanded with the directory name `thirdParty/cocos2d`. - -[Cocos2d-x]: https://cocos2d-x.org/ - -NOTICE: Setting up a Cocos-2dx environment on macOS using `download-deps.py` in `thirdParty/cocos2d` fails to resolve certain URLs and causes an error. diff --git a/Samples/Cocos2d-x/thirdParty/scripts/setup_cocos2d b/Samples/Cocos2d-x/thirdParty/scripts/setup_cocos2d deleted file mode 100644 index 95aa53f6..00000000 --- a/Samples/Cocos2d-x/thirdParty/scripts/setup_cocos2d +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env sh - -set -ue - -COCOS_COMMIT_HASH=95e5d868ce5958c0dadfc485bdda52f1bc404fe0 - -SCRIPT_PATH=$(cd $(dirname $0) && pwd) - -cd $SCRIPT_PATH/.. - -################# -# Setup Cocos2d # -################# - -# Download and extract the archive. -echo - Setup Cocos2D -mkdir cocos2d -cd cocos2d -git init -git remote add origin https://github.com/cocos2d/cocos2d-x.git -git fetch --depth 1 origin ${COCOS_COMMIT_HASH} -git reset --hard FETCH_HEAD -python download-deps.py --remove-download yes -git submodule update --init -rm -rf .git/ -cd .. diff --git a/Samples/Cocos2d-x/thirdParty/scripts/setup_cocos2d.bat b/Samples/Cocos2d-x/thirdParty/scripts/setup_cocos2d.bat deleted file mode 100644 index 0431670d..00000000 --- a/Samples/Cocos2d-x/thirdParty/scripts/setup_cocos2d.bat +++ /dev/null @@ -1,30 +0,0 @@ -@echo off - -set COCOS_COMMIT_HASH=95e5d868ce5958c0dadfc485bdda52f1bc404fe0 - -set SCRIPT_PATH=%~dp0 - -::::::::::::::::::: -:: Setup Cocos2d :: -::::::::::::::::::: - -cd %SCRIPT_PATH%\.. - -:: Download and extract the archive. -echo - Setup Cocos2d -cd ..\..\..\ -mkdir _l2d_tmp -cd _l2d_tmp -git init -git remote add origin https://github.com/cocos2d/cocos2d-x.git -git fetch --depth 1 origin %COCOS_COMMIT_HASH% -git reset --hard FETCH_HEAD -python "download-deps.py" "--remove-download" "yes" -git submodule update --init -rmdir /s /q .git -cd .. -robocopy _l2d_tmp %SCRIPT_PATH%\..\cocos2d /MIR -rmdir /s /q _l2d_tmp - -echo. -pause diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/CMakeLists.txt b/Samples/D3D11/Demo/proj.d3d11.cmake/CMakeLists.txt index 70373d2c..572069e7 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/CMakeLists.txt +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/CMakeLists.txt @@ -15,6 +15,7 @@ set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) set(THIRD_PARTY_PATH ${SDK_ROOT_PATH}/Samples/D3D11/thirdParty) set(DX_PATH ${THIRD_PARTY_PATH}/DirectXTK) set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SAMPLE_SHADER_PATH ${SDK_ROOT_PATH}/Samples/D3D11/Shaders) # Set project. project(${APP_NAME}) @@ -47,11 +48,7 @@ else() message(FATAL_ERROR "[${APP_NAME}] Invalid linker flag ${CMAKE_EXE_LINKER_FLAGS}.") endif() # Detect compiler. -if(MSVC_VERSION MATCHES 1800) - # Visual Studio 2013 - set(COMPILER 120) - set(MSVC_YEAR 2013) -elseif(MSVC_VERSION MATCHES 1900) +if(MSVC_VERSION MATCHES 1900) # Visual Studio 2015 set(COMPILER 140) set(MSVC_YEAR 2015) @@ -63,7 +60,7 @@ elseif(MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) # Visual Studio 2019 set(COMPILER 142) set(MSVC_YEAR 2019) -elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) +elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1950) # Visual Studio 2022 set(COMPILER 143) set(MSVC_YEAR 2022) @@ -114,6 +111,7 @@ find_package(OpenGL REQUIRED) add_executable(${APP_NAME} WIN32) # Add source files. add_subdirectory(src) + # Link libraries to app. target_link_libraries(${APP_NAME} Framework @@ -131,6 +129,9 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy_directory ${RES_PATH} $/Resources + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${SAMPLE_SHADER_PATH} $/SampleShaders ) # Set project properties. diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/scripts/nmake_msvc2013.bat b/Samples/D3D11/Demo/proj.d3d11.cmake/scripts/nmake_msvc2013.bat deleted file mode 100644 index 50de20fd..00000000 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/scripts/nmake_msvc2013.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2013 -set MSVC_NUMBER=12 -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat -set GENERATOR=nmake - -call "%SCRIPT_PATH%_msvc_common.bat" -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/scripts/proj_msvc2013.bat b/Samples/D3D11/Demo/proj.d3d11.cmake/scripts/proj_msvc2013.bat deleted file mode 100644 index d11674f6..00000000 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/scripts/proj_msvc2013.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2013 -set MSVC_NUMBER=12 -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat -set GENERATOR=proj - -call "%SCRIPT_PATH%_msvc_common.bat" -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CMakeLists.txt b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CMakeLists.txt index c0db52af..17317305 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CMakeLists.txt +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CMakeLists.txt @@ -12,6 +12,8 @@ if (CSM_MINIMUM_DEMO) ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismUserModelExtend.cpp @@ -44,6 +46,8 @@ else () ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.cpp index d3628ae4..b5b001a6 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.cpp @@ -40,12 +40,6 @@ CubismDirectXRenderer::CubismDirectXRenderer() , _depthTexture(nullptr) , _depthStencilView(nullptr) , _depthState(nullptr) - , _rasterizer(nullptr) - , _samplerState(nullptr) - , _vertexShader(nullptr) - , _pixelShader(nullptr) - , _blendState(nullptr) - , _vertexFormat(nullptr) { } @@ -56,27 +50,11 @@ CubismDirectXRenderer::~CubismDirectXRenderer() void CubismDirectXRenderer::Release() { - if (_samplerState) - { - _samplerState->Release(); - _samplerState = nullptr; - } - if (_rasterizer) - { - _rasterizer->Release(); - _rasterizer = nullptr; - } - if (_renderTargetView) { _renderTargetView->Release(); _renderTargetView = nullptr; } - if (_depthState) - { - _depthState->Release(); - _depthState = nullptr; - } if (_depthStencilView) { _depthStencilView->Release(); @@ -213,231 +191,6 @@ bool CubismDirectXRenderer::CreateRenderTarget(UINT width, UINT height) return true; } -bool CubismDirectXRenderer::CreateShader() -{ - // 一旦削除する - ReleaseShader(); - - // スプライト描画用シェーダ - static const csmChar* SpriteShaderEffectSrc = - "cbuffer ConstantBuffer {"\ - "float4x4 projectMatrix;"\ - "float4x4 clipMatrix;"\ - "float4 baseColor;"\ - "float4 channelFlag;"\ - "}"\ - \ - "Texture2D mainTexture : register(t0);"\ - "SamplerState mainSampler : register(s0);"\ - "struct VS_IN {"\ - "float2 pos : POSITION0;"\ - "float2 uv : TEXCOORD0;"\ - "};"\ - "struct VS_OUT {"\ - "float4 Position : SV_POSITION;"\ - "float2 uv : TEXCOORD0;"\ - "float4 clipPosition : TEXCOORD1;"\ - "};"\ - \ - "/* Vertex Shader */"\ - "/* normal */"\ - "VS_OUT VertNormal(VS_IN In) {"\ - "VS_OUT Out = (VS_OUT)0;"\ - "Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ - "Out.uv.x = In.uv.x;"\ - "Out.uv.y = 1.0 - +In.uv.y;"\ - "return Out;"\ - "}"\ - \ - "/* Pixel Shader */"\ - "/* normal */"\ - "float4 PixelNormal(VS_OUT In) : SV_Target {"\ - "float4 color = mainTexture.Sample(mainSampler, In.uv) * baseColor;"\ - "return color;"\ - "}"; - - ID3DBlob* vertexError = nullptr; - ID3DBlob* pixelError = nullptr; - - ID3DBlob* vertexBlob = nullptr; ///< スプライト描画用シェーダ - ID3DBlob* pixelBlob = nullptr; ///< スプライト描画用シェーダ - - HRESULT hr = S_OK; - do - { - UINT compileFlag = 0; - - hr = D3DCompile( - SpriteShaderEffectSrc, // メモリー内のシェーダーへのポインターです - strlen(SpriteShaderEffectSrc), // メモリー内のシェーダーのサイズです - nullptr, // シェーダー コードが格納されているファイルの名前 - nullptr, // マクロ定義の配列へのポインター - nullptr, // インクルード ファイルを扱うインターフェイスへのポインター - "VertNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 - "vs_4_0", // シェーダー モデルを指定する文字列。 - compileFlag, // シェーダーコンパイルフラグ - 0, // シェーダーコンパイルフラグ - &vertexBlob, - &vertexError); // エラーが出る場合はここで - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Compile Vertex Shader"); - break; - } - hr = _device->CreateVertexShader(vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), nullptr, &_vertexShader); - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Create Vertex Shader"); - break; - } - - hr = D3DCompile( - SpriteShaderEffectSrc, // メモリー内のシェーダーへのポインターです - strlen(SpriteShaderEffectSrc), // メモリー内のシェーダーのサイズです - nullptr, // シェーダー コードが格納されているファイルの名前 - nullptr, // マクロ定義の配列へのポインター - nullptr, // インクルード ファイルを扱うインターフェイスへのポインター - "PixelNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 - "ps_4_0", // シェーダー モデルを指定する文字列 - compileFlag, // シェーダーコンパイルフラグ - 0, // シェーダーコンパイルフラグ - &pixelBlob, - &pixelError); // エラーが出る場合はここで - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Compile Pixel Shader"); - break; - } - - hr = _device->CreatePixelShader(pixelBlob->GetBufferPointer(), pixelBlob->GetBufferSize(), NULL, &_pixelShader); - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Create Pixel Shader"); - break; - } - - // この描画で使用する頂点フォーマット - D3D11_INPUT_ELEMENT_DESC elems[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - hr = _device->CreateInputLayout(elems, ARRAYSIZE(elems), vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), &_vertexFormat); - - if (FAILED(hr)) - { - LAppPal::PrintLogLn("CreateVertexDeclaration failed"); - break; - } - - } while (0); - - if (pixelError) - { - pixelError->Release(); - pixelError = nullptr; - } - if (vertexError) - { - vertexError->Release(); - vertexError = nullptr; - } - - // blobはもうここで不要 - if (pixelBlob) - { - pixelBlob->Release(); - pixelBlob = nullptr; - } - if (vertexBlob) - { - vertexBlob->Release(); - vertexBlob = nullptr; - } - - if (FAILED(hr)) - { - return false; - } - - // レンダリングステートオブジェクト - D3D11_BLEND_DESC blendDesc; - memset(&blendDesc, 0, sizeof(blendDesc)); - blendDesc.AlphaToCoverageEnable = FALSE; - blendDesc.IndependentBlendEnable = FALSE; // falseの場合はRenderTarget[0]しか使用しなくなる - blendDesc.RenderTarget[0].BlendEnable = TRUE; - blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; - blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - - _device->CreateBlendState(&blendDesc, &_blendState); - - return true; -} - -void CubismDirectXRenderer::SetupShader() -{ - if (!_device || !_vertexFormat || !_vertexShader || !_pixelShader) - { - return; - } - - // 現在のウィンドウサイズ - int windowWidth, windowHeight; - GetClientSize(windowWidth, windowHeight); - - // スプライト描画用の設定をし、シェーダセット - float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - _deviceContext->OMSetBlendState(_blendState, blendFactor, 0xffffffff); - - _deviceContext->IASetInputLayout(_vertexFormat); - _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - _deviceContext->IASetInputLayout(_vertexFormat); - - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = static_cast(windowWidth); - viewport.Height = static_cast(windowHeight); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - - _deviceContext->RSSetViewports(1, &viewport); - _deviceContext->RSSetState(_rasterizer); - - _deviceContext->VSSetShader(_vertexShader, nullptr, 0); - - _deviceContext->PSSetShader(_pixelShader, nullptr, 0); - _deviceContext->PSSetSamplers(0, 1, &_samplerState); -} - -void CubismDirectXRenderer::ReleaseShader() -{ - if (_blendState) - { - _blendState->Release(); - _blendState = nullptr; - } - if (_vertexFormat) - { - _vertexFormat->Release(); - _vertexFormat = nullptr; - } - if (_pixelShader) - { - _pixelShader->Release(); - _pixelShader = nullptr; - } - if (_vertexShader) - { - _vertexShader->Release(); - _vertexShader = nullptr; - } -} - void CubismDirectXRenderer::ResizeDevice(CubismUserModel* userModel) { // 今のクライアント領域の大きさに合わせます diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.hpp index eb6fc065..a2ee9bed 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXRenderer.hpp @@ -61,26 +61,11 @@ class CubismDirectXRenderer */ void ReleaseInstance(); - /** - * @brief スプライト描画用シェーダの作成と頂点宣言の作成を行う - */ - bool CreateShader(); - /** * @brief レンダーターゲット作成内部関数 */ bool CreateRenderTarget(UINT width, UINT height); - /** - * @brief シェーダをコンテキストにセット - */ - void SetupShader(); - - /** - * @brief CreateShaderで確保したオブジェクトの開放 - */ - void ReleaseShader(); - /** * @brief アプリケーションを終了するかどうか。 */ @@ -120,15 +105,7 @@ class CubismDirectXRenderer ID3D11RenderTargetView* _renderTargetView; ///< 描画ターゲットビュー ID3D11Texture2D* _depthTexture; ///< Zバッファ ID3D11DepthStencilView* _depthStencilView; ///< Zバッファビュー - ID3D11DepthStencilState* _depthState; ///< スプライト描画用深度オブジェクト - - ID3D11RasterizerState* _rasterizer; ///< スプライト描画用ラスタライザ - ID3D11SamplerState* _samplerState; ///< スプライト描画用サンプラーステート - - ID3D11VertexShader* _vertexShader; ///< スプライト描画シェーダ - ID3D11PixelShader* _pixelShader; ///< スプライト描画シェーダ - ID3D11BlendState* _blendState; ///< スプライト描画用ブレンドステート - ID3D11InputLayout* _vertexFormat; ///< スプライト描画用型宣言 + ID3D11DepthStencilState* _depthState; ///< 描画用深度オブジェクト CubismTextureManager* _textureManager; ///< テクスチャマネージャー diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.cpp index cc8690ee..e7f08f0e 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.cpp @@ -9,6 +9,7 @@ #include "CubismDirectXRenderer.hpp" #include "CubismSampleViewMatrix.hpp" +#include "CubismSpriteShader.hpp" namespace { CubismDirectXView* _instance = nullptr; @@ -25,7 +26,7 @@ CubismDirectXView* CubismDirectXView::GetInstance() } CubismDirectXView::CubismDirectXView() - :_windowWidth(0), _windowHeight(0), _renderSprite(nullptr), _renderTarget(SelectTarget_None) + :_windowWidth(0), _windowHeight(0), _renderSprite(nullptr), _renderTarget(SelectTarget_None), _shader(NULL) { _clearColor[0] = 1.0f; _clearColor[1] = 1.0f; @@ -37,6 +38,9 @@ CubismDirectXView::CubismDirectXView() // デバイス座標からスクリーン座標に変換するための行列 _deviceToScreen = new CubismMatrix44(); + // スプライト用シェーダー + _shader = new CubismSpriteShader(); + Initialize(); } @@ -44,6 +48,9 @@ CubismDirectXView::~CubismDirectXView() { _renderBuffer.DestroyOffscreenSurface(); + _shader->ReleaseShader(); + + delete _shader; delete _renderSprite; delete _deviceToScreen; @@ -54,6 +61,9 @@ void CubismDirectXView::Initialize() { CubismDirectXRenderer::GetInstance()->GetClientSize(_windowWidth, _windowHeight); + // シェーダー作成 + _shader->CreateShader(); + InitializeSprite(); } @@ -94,7 +104,7 @@ void CubismDirectXView::InitializeSprite() CubismDirectXRenderer::GetInstance()->GetClientSize(_windowWidth, _windowHeight); float x = _windowWidth * 0.5f; float y = _windowHeight * 0.5f; - _renderSprite = new CubismSprite(x, y, static_cast(_windowWidth), static_cast(_windowHeight), 0); + _renderSprite = new CubismSprite(x, y, static_cast(_windowWidth), static_cast(_windowHeight), 0, _shader); } void CubismDirectXView::ReleaseSprite() diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.hpp index 5c1db4a7..6e0bc339 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismDirectXView.hpp @@ -15,6 +15,8 @@ #include "CubismUserModelExtend.hpp" #include "CubismSprite.hpp" +class CubismSpriteShader; + class CubismDirectXView { public: @@ -144,4 +146,6 @@ class CubismDirectXView Csm::Rendering::CubismOffscreenSurface_D3D11 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + CubismSpriteShader* _shader; ///< スプライト用のシェーダー準備クラス }; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.cpp index 140e8194..3dd01072 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.cpp @@ -13,18 +13,20 @@ #include "LAppDefine.hpp" #include "LAppPal.hpp" #include "Rendering/D3D11/CubismType_D3D11.hpp" +#include "CubismSpriteShader.hpp" CubismSprite::CubismSprite() - : _rect(),_vertexBuffer(nullptr),_indexBuffer(nullptr),_constantBuffer(nullptr) + : _rect(),_vertexBuffer(nullptr),_indexBuffer(nullptr),_constantBuffer(nullptr),_shader(NULL) { _color = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); } -CubismSprite::CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId) +CubismSprite::CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, CubismSpriteShader* shader) : _rect(), _vertexBuffer(NULL), _indexBuffer(NULL), - _constantBuffer(NULL) + _constantBuffer(NULL), + _shader(shader) { _color = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); @@ -130,6 +132,8 @@ CubismSprite::~CubismSprite() { CubismDirectXRenderer::GetInstance()->_textureManager->ReleaseTexture(_textureId); + _shader = NULL; + if (_constantBuffer) { _constantBuffer->Release(); @@ -203,7 +207,7 @@ void CubismSprite::Render(int width, int height) const renderContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 描画用設定 - cubismDirectXRenderer->SetupShader(); + _shader->SetupShader(); // テクスチャセット ID3D11ShaderResourceView* textureView = nullptr; @@ -275,7 +279,7 @@ void CubismSprite::RenderImmidiate(int width, int height, ID3D11ShaderResourceVi renderContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 描画用設定 - cubismDirectXRenderer->SetupShader(); + _shader->SetupShader(); // テクスチャセット { diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.hpp index 546c9092..de05addb 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSprite.hpp @@ -12,6 +12,8 @@ #include #include +class CubismSpriteShader; + /** * @brief スプライトを実装するクラス。 * @@ -52,8 +54,9 @@ class CubismSprite * @param[in] width 横幅 * @param[in] height 高さ * @param[in] textureId テクスチャID + * @param[in] shader シェーダー設定 */ - CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId); + CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, CubismSpriteShader* shader); /** * @brief デストラクタ @@ -106,7 +109,6 @@ class CubismSprite static const int INDEX_NUM = 6; private: - Csm::csmUint64 _textureId; ///< テクスチャID Rect _rect; ///< 矩形 @@ -115,5 +117,6 @@ class CubismSprite ID3D11Buffer* _constantBuffer; ///< 定数バッファ DirectX::XMFLOAT4 _color; ///< スプライトカラー -}; + CubismSpriteShader* _shader; ///< スプライト用のシェーダー準備クラス +}; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSpriteShader.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSpriteShader.cpp new file mode 100644 index 00000000..040aeb65 --- /dev/null +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSpriteShader.cpp @@ -0,0 +1,280 @@ +/** + * 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. + */ + +#include "CubismSpriteShader.hpp" + +#include +#include +#include "CubismDirectXRenderer.hpp" +#include "LAppDefine.hpp" +#include "LAppPal.hpp" + +CubismSpriteShader::CubismSpriteShader() + : _rasterizer(NULL) + , _samplerState(NULL) + , _vertexShader(NULL) + , _pixelShader(NULL) + , _blendState(NULL) + , _vertexFormat(NULL) +{ +} + +CubismSpriteShader::~CubismSpriteShader() +{ +} + +bool CubismSpriteShader::CreateShader() +{ + ReleaseShader(); + + ID3D11Device* device = CubismDirectXRenderer::GetInstance()->GetD3dDevice(); + HRESULT result = S_OK; + + ID3DBlob* vertexError = NULL; + ID3DBlob* pixelError = NULL; + + ID3DBlob* vertexBlob = NULL; + ID3DBlob* pixelBlob = NULL; + + // ファイル読み込み + const char* shaderCode; + Csm::csmSizeInt shaderSize; + { + // シェーダーのパスの作成 + Csm::csmString shaderFileName(LAppDefine::ShaderPath); + shaderFileName += LAppDefine::ShaderName; + + // ファイル読み込み + shaderCode = reinterpret_cast(LAppPal::LoadFileAsBytes(shaderFileName.GetRawString(), &shaderSize)); + } + + do + { + // ラスタライザ + D3D11_RASTERIZER_DESC rasterDesc; + memset(&rasterDesc, 0, sizeof(rasterDesc)); + rasterDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_BACK; // 裏面を切る + rasterDesc.FrontCounterClockwise = TRUE; // CCWを表面にする + rasterDesc.DepthClipEnable = FALSE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.DepthBiasClamp = 0; + rasterDesc.SlopeScaledDepthBias = 0; + result = device->CreateRasterizerState(&rasterDesc, &_rasterizer); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Rasterizer 0x%x", result); + break; + } + + // テクスチャサンプラーステート + D3D11_SAMPLER_DESC samplerDesc; + memset(&samplerDesc, 0, sizeof(D3D11_SAMPLER_DESC)); + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.MinLOD = -D3D11_FLOAT32_MAX; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + result = device->CreateSamplerState(&samplerDesc, &_samplerState); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Sampler 0x%x", result); + break; + } + + // ブレンドステートオブジェクト + D3D11_BLEND_DESC blendDesc; + memset(&blendDesc, 0, sizeof(blendDesc)); + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = FALSE; // falseの場合はRenderTarget[0]しか使用しなくなる + blendDesc.RenderTarget[0].BlendEnable = TRUE; + blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + result = device->CreateBlendState(&blendDesc, &_blendState); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create BlendState 0x%x", result); + break; + } + + UINT compileFlag = 0; + + result = D3DCompile( + shaderCode, // メモリー内のシェーダーへのポインターです + shaderSize, // メモリー内のシェーダーのサイズです + NULL, // シェーダー コードが格納されているファイルの名前 + NULL, // マクロ定義の配列へのポインター + NULL, // インクルード ファイルを扱うインターフェイスへのポインター + "VertNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 + "vs_4_0", // シェーダー モデルを指定する文字列。 + compileFlag, // シェーダーコンパイルフラグ + 0, // シェーダーコンパイルフラグ + &vertexBlob, + &vertexError); // エラーが出る場合はここで + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Compile Vertex Shader"); + break; + } + result = device->CreateVertexShader(vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), NULL, &_vertexShader); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Vertex Shader"); + break; + } + + result = D3DCompile( + shaderCode, // メモリー内のシェーダーへのポインターです + shaderSize, // メモリー内のシェーダーのサイズです + NULL, // シェーダー コードが格納されているファイルの名前 + NULL, // マクロ定義の配列へのポインター + NULL, // インクルード ファイルを扱うインターフェイスへのポインター + "PixelNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 + "ps_4_0", // シェーダー モデルを指定する文字列 + compileFlag, // シェーダーコンパイルフラグ + 0, // シェーダーコンパイルフラグ + &pixelBlob, + &pixelError); // エラーが出る場合はここで + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Compile Pixel Shader"); + break; + } + + result = device->CreatePixelShader(pixelBlob->GetBufferPointer(), pixelBlob->GetBufferSize(), NULL, &_pixelShader); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Pixel Shader"); + break; + } + + // この描画で使用する頂点フォーマット + D3D11_INPUT_ELEMENT_DESC elems[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + result = device->CreateInputLayout(elems, ARRAYSIZE(elems), vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), &_vertexFormat); + + if (FAILED(result)) + { + LAppPal::PrintLog("CreateVertexDeclaration failed"); + break; + } + + } while (0); + + if(pixelError) + { + pixelError->Release(); + pixelError = NULL; + } + if (vertexError) + { + vertexError->Release(); + vertexError = NULL; + } + + // blobはもうここで不要 + if (pixelBlob) + { + pixelBlob->Release(); + pixelBlob = NULL; + } + if (vertexBlob) + { + vertexBlob->Release(); + vertexBlob = NULL; + } + + if (FAILED(result)) + { + return false; + } + + return true; +} + +void CubismSpriteShader::SetupShader() +{ + ID3D11DeviceContext* deviceContext = CubismDirectXRenderer::GetInstance()->GetD3dContext(); + + if (_rasterizer == NULL || _samplerState == NULL || _blendState == NULL || + _vertexShader == NULL || _pixelShader == NULL || _vertexFormat == NULL) + { + return; + } + + // 現在のウィンドウサイズの取得 + int windowWidth, windowHeight; + CubismDirectXRenderer::GetInstance()->GetClientSize(windowWidth, windowHeight); + + // スプライト描画用の設定をし、シェーダーセット + deviceContext->IASetInputLayout(_vertexFormat); + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + deviceContext->IASetInputLayout(_vertexFormat); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(windowWidth); + viewport.Height = static_cast(windowHeight); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + deviceContext->RSSetViewports(1, &viewport); + deviceContext->RSSetState(_rasterizer); + + deviceContext->VSSetShader(_vertexShader, NULL, 0); + + deviceContext->PSSetShader(_pixelShader, NULL, 0); + deviceContext->PSSetSamplers(0, 1, &_samplerState); + + float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + deviceContext->OMSetBlendState(_blendState, blendFactor, 0xffffffff); +} + +void CubismSpriteShader::ReleaseShader() +{ + if (_rasterizer) + { + _rasterizer->Release(); + _rasterizer = NULL; + } + if(_samplerState) + { + _samplerState->Release(); + _samplerState = NULL; + } + if(_blendState) + { + _blendState->Release(); + _blendState = NULL; + } + if (_vertexShader) + { + _vertexShader->Release(); + _vertexShader = NULL; + } + if (_pixelShader) + { + _pixelShader->Release(); + _pixelShader = NULL; + } + if(_vertexFormat) + { + _vertexFormat->Release(); + _vertexFormat = NULL; + } +} diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSpriteShader.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSpriteShader.hpp new file mode 100644 index 00000000..4441410c --- /dev/null +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismSpriteShader.hpp @@ -0,0 +1,53 @@ +/** + * 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. + */ + +#pragma once + +#include + +/** + * @brief スプライト用のシェーダー設定を保持するクラス。 + */ +class CubismSpriteShader +{ +public: + + /** + * @brief コンストラクタ + */ + CubismSpriteShader(); + + /** + * @brief デストラクタ + */ + ~CubismSpriteShader(); + + /** + * @brief シェーダーの作成を行う + */ + bool CreateShader(); + + /** + * @brief スプライトの描画直前に呼び出される + * シェーダーのセットを行う + */ + void SetupShader(); + + /** + * @brief シェーダーの解放を行う + */ + void ReleaseShader(); + +private: + + ID3D11RasterizerState* _rasterizer; ///< ラスタライザ + ID3D11SamplerState* _samplerState; ///< サンプラーステート + ID3D11BlendState* _blendState; ///< ブレンドステート + ID3D11VertexShader* _vertexShader; ///< 頂点シェーダ + ID3D11PixelShader* _pixelShader; ///< ピクセルシェーダ + ID3D11InputLayout* _vertexFormat; ///< 頂点フォーマット +}; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismTextureManager.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismTextureManager.cpp index 0f2a95d8..2be19978 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismTextureManager.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismTextureManager.cpp @@ -35,7 +35,7 @@ CubismTextureManager::TextureInfo* CubismTextureManager::CreateTextureFromPngFil // wcharに変換 const int WCHAR_LENGTH = 512; wchar_t wchrStr[WCHAR_LENGTH] = L""; - LAppPal::MbcToWchar(fileName.c_str(), fileName.length(), wchrStr, sizeof(wchrStr)); + LAppPal::ConvertMultiByteToWide(fileName.c_str(), wchrStr, sizeof(wchrStr)); ID3D11Resource* texture = NULL; ID3D11ShaderResourceView* textureView = NULL; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.cpp index 6b605a96..83de0912 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.cpp @@ -204,24 +204,10 @@ void CubismUserModelExtend::PreloadMotionGroup(const csmChar* group) csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // モーションデータの読み込み - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelJson, group, i)); if (tmpMotion) { - // フェードインの時間を取得 - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - // フェードアウトの時間を取得 - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } - if (_motions[name]) { // インスタンスを破棄 @@ -261,10 +247,9 @@ void CubismUserModelExtend::ReleaseModelSetting() * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 -* @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ -Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority) { // モーション数が取得出来なかった、もしくは0の時 if (!(_modelJson->GetMotionCount(group))) @@ -300,33 +285,16 @@ Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm:: csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // 一番先頭のモーションを読み込む - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, NULL, NULL, _modelJson, group, no)); if (motion) { - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } - // 終了時にメモリから削除 autoDelete = true; } DeleteBuffer(buffer, path.GetRawString()); } - else - { - // モーションの再生終了コールバックを登録 - motion->SetFinishedMotionHandler(onFinishedMotionHandler); - } // 優先度を設定してモーションを始める return _motionManager->StartMotionPriority(motion, autoDelete, priority); diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.hpp index 8a64d9b6..595d9ee0 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/CubismUserModelExtend.hpp @@ -82,10 +82,9 @@ class CubismUserModelExtend : * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 - * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority); /** * @brief 解放 diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.cpp index 2ca324cc..3b3c147c 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.cpp @@ -37,6 +37,11 @@ namespace LAppDefine { // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = "SampleShaders/"; + // シェーダー本体 + const csmChar* ShaderName = "SpriteEffect.fx"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.hpp index 63740b16..6b1ae66f 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDefine.hpp @@ -35,6 +35,9 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* ShaderName; ///< シェーダー本体 + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.cpp index a4c14ee1..46d29e7f 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.cpp @@ -144,44 +144,6 @@ bool LAppDelegate::Initialize() return false; } - // ラスタライザ - D3D11_RASTERIZER_DESC rasterDesc; - memset(&rasterDesc, 0, sizeof(rasterDesc)); - rasterDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID; - rasterDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_BACK; // 裏面を切る - rasterDesc.FrontCounterClockwise = TRUE; // CCWを表面にする - rasterDesc.DepthClipEnable = FALSE; - rasterDesc.MultisampleEnable = FALSE; - rasterDesc.DepthBiasClamp = 0; - rasterDesc.SlopeScaledDepthBias = 0; - result = _device->CreateRasterizerState(&rasterDesc, &_rasterizer); - if (FAILED(result)) - { - LAppPal::PrintLogLn("Fail Create Rasterizer 0x%x", result); - return false; - } - - // テクスチャサンプラーステート - D3D11_SAMPLER_DESC samplerDesc; - memset(&samplerDesc, 0, sizeof(D3D11_SAMPLER_DESC)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MaxAnisotropy = 1; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = -D3D11_FLOAT32_MAX; - samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; - _device->CreateSamplerState(&samplerDesc, &_samplerState); - if (FAILED(result)) - { - LAppPal::PrintLogLn("Fail Create Sampler 0x%x", result); - return false; - } - - // スプライト用シェーダ作成 - CreateShader(); - // デバイス作成の後 _textureManager = new LAppTextureManager(); @@ -262,25 +224,11 @@ void LAppDelegate::Release() // リソースを解放 LAppLive2DManager::ReleaseInstance(); - // シェーダ類の開放 - ReleaseShader(); - delete _view; delete _textureManager; _view = NULL; _textureManager = NULL; - if(_samplerState) - { - _samplerState->Release(); - _samplerState = NULL; - } - if (_rasterizer) - { - _rasterizer->Release(); - _rasterizer = NULL; - } - if (_renderTargetView) { _renderTargetView->Release(); @@ -378,12 +326,6 @@ LAppDelegate::LAppDelegate() , _depthTexture(NULL) , _depthStencilView(NULL) , _depthState(NULL) - , _rasterizer(NULL) - , _samplerState(NULL) - , _vertexShader(NULL) - , _pixelShader(NULL) - , _blendState(NULL) - , _vertexFormat(NULL) { _view = new LAppView(); } @@ -413,231 +355,6 @@ void LAppDelegate::InitializeCubism() _view->InitializeSprite(); } -bool LAppDelegate::CreateShader() -{ - // 一旦削除する - ReleaseShader(); - -// スプライト描画用シェーダ - static const csmChar* SpriteShaderEffectSrc = - "cbuffer ConstantBuffer {"\ - "float4x4 projectMatrix;"\ - "float4x4 clipMatrix;"\ - "float4 baseColor;"\ - "float4 channelFlag;"\ - "}"\ - \ - "Texture2D mainTexture : register(t0);"\ - "SamplerState mainSampler : register(s0);"\ - "struct VS_IN {"\ - "float2 pos : POSITION0;"\ - "float2 uv : TEXCOORD0;"\ - "};"\ - "struct VS_OUT {"\ - "float4 Position : SV_POSITION;"\ - "float2 uv : TEXCOORD0;"\ - "float4 clipPosition : TEXCOORD1;"\ - "};"\ - \ - "/* Vertex Shader */"\ - "/* normal */"\ - "VS_OUT VertNormal(VS_IN In) {"\ - "VS_OUT Out = (VS_OUT)0;"\ - "Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ - "Out.uv.x = In.uv.x;"\ - "Out.uv.y = 1.0 - +In.uv.y;"\ - "return Out;"\ - "}"\ - \ - "/* Pixel Shader */"\ - "/* normal */"\ - "float4 PixelNormal(VS_OUT In) : SV_Target {"\ - "float4 color = mainTexture.Sample(mainSampler, In.uv) * baseColor;"\ - "return color;"\ - "}"; - - ID3DBlob* vertexError = NULL; - ID3DBlob* pixelError = NULL; - - ID3DBlob* vertexBlob = NULL; ///< スプライト描画用シェーダ - ID3DBlob* pixelBlob = NULL; ///< スプライト描画用シェーダ - - HRESULT hr = S_OK; - do - { - UINT compileFlag = 0; - - hr = D3DCompile( - SpriteShaderEffectSrc, // メモリー内のシェーダーへのポインターです - strlen(SpriteShaderEffectSrc), // メモリー内のシェーダーのサイズです - NULL, // シェーダー コードが格納されているファイルの名前 - NULL, // マクロ定義の配列へのポインター - NULL, // インクルード ファイルを扱うインターフェイスへのポインター - "VertNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 - "vs_4_0", // シェーダー モデルを指定する文字列。 - compileFlag, // シェーダーコンパイルフラグ - 0, // シェーダーコンパイルフラグ - &vertexBlob, - &vertexError); // エラーが出る場合はここで - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Compile Vertex Shader"); - break; - } - hr = _device->CreateVertexShader(vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), NULL, &_vertexShader); - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Create Vertex Shader"); - break; - } - - hr = D3DCompile( - SpriteShaderEffectSrc, // メモリー内のシェーダーへのポインターです - strlen(SpriteShaderEffectSrc), // メモリー内のシェーダーのサイズです - NULL, // シェーダー コードが格納されているファイルの名前 - NULL, // マクロ定義の配列へのポインター - NULL, // インクルード ファイルを扱うインターフェイスへのポインター - "PixelNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 - "ps_4_0", // シェーダー モデルを指定する文字列 - compileFlag, // シェーダーコンパイルフラグ - 0, // シェーダーコンパイルフラグ - &pixelBlob, - &pixelError); // エラーが出る場合はここで - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Compile Pixel Shader"); - break; - } - - hr = _device->CreatePixelShader(pixelBlob->GetBufferPointer(), pixelBlob->GetBufferSize(), NULL, &_pixelShader); - if (FAILED(hr)) - { - LAppPal::PrintLogLn("Fail Create Pixel Shader"); - break; - } - - // この描画で使用する頂点フォーマット - D3D11_INPUT_ELEMENT_DESC elems[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - hr = _device->CreateInputLayout(elems, ARRAYSIZE(elems), vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), &_vertexFormat); - - if (FAILED(hr)) - { - LAppPal::PrintLogLn("CreateVertexDeclaration failed"); - break; - } - - } while (0); - - if(pixelError) - { - pixelError->Release(); - pixelError = NULL; - } - if (vertexError) - { - vertexError->Release(); - vertexError = NULL; - } - - // blobはもうここで不要 - if (pixelBlob) - { - pixelBlob->Release(); - pixelBlob = NULL; - } - if (vertexBlob) - { - vertexBlob->Release(); - vertexBlob = NULL; - } - - if (FAILED(hr)) - { - return false; - } - - // レンダリングステートオブジェクト - D3D11_BLEND_DESC blendDesc; - memset(&blendDesc, 0, sizeof(blendDesc)); - blendDesc.AlphaToCoverageEnable = FALSE; - blendDesc.IndependentBlendEnable = FALSE; // falseの場合はRenderTarget[0]しか使用しなくなる - blendDesc.RenderTarget[0].BlendEnable = TRUE; - blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; - blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - - _device->CreateBlendState(&blendDesc, &_blendState); - - return true; -} - -void LAppDelegate::SetupShader() -{ - if(_device==NULL || _vertexFormat==NULL || _vertexShader==NULL || _pixelShader==NULL) - { - return; - } - - // 現在のウィンドウサイズ - int windowWidth, windowHeight; - GetClientSize(windowWidth, windowHeight); - - // スプライト描画用の設定をし、シェーダセット - float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - _deviceContext->OMSetBlendState(_blendState, blendFactor, 0xffffffff); - - _deviceContext->IASetInputLayout(_vertexFormat); - _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - _deviceContext->IASetInputLayout(_vertexFormat); - - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = static_cast(windowWidth); - viewport.Height = static_cast(windowHeight); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - - _deviceContext->RSSetViewports(1, &viewport); - _deviceContext->RSSetState(_rasterizer); - - _deviceContext->VSSetShader(_vertexShader, NULL, 0); - - _deviceContext->PSSetShader(_pixelShader, NULL, 0); - _deviceContext->PSSetSamplers(0, 1, &_samplerState); -} - -void LAppDelegate::ReleaseShader() -{ - if(_blendState) - { - _blendState->Release(); - _blendState = NULL; - } - if(_vertexFormat) - { - _vertexFormat->Release(); - _vertexFormat = NULL; - } - if (_pixelShader) - { - _pixelShader->Release(); - _pixelShader = NULL; - } - if (_vertexShader) - { - _vertexShader->Release(); - _vertexShader = NULL; - } -} - void LAppDelegate::StartFrame() { /* diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.hpp index e0735149..309fdef4 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppDelegate.hpp @@ -60,7 +60,6 @@ class LAppDelegate */ static void GetClientSize(int& rWidth, int& rHeight); - /** * @brief APPに必要なものを初期化する。 */ @@ -103,21 +102,6 @@ class LAppDelegate */ void EndFrame(); - /** - * @brief スプライト描画用シェーダの作成と頂点宣言の作成を行う - */ - bool CreateShader(); - - /** - * @brief シェーダをコンテキストにセット - */ - void SetupShader(); - - /** - * @brief CreateShaderで確保したオブジェクトの開放 - */ - void ReleaseShader(); - private: enum DeviceStep @@ -179,12 +163,4 @@ class LAppDelegate ID3D11Texture2D* _depthTexture; ///< Zバッファ ID3D11DepthStencilView* _depthStencilView; ///< Zバッファビュー ID3D11DepthStencilState* _depthState; ///< スプライト描画用深度オブジェクト - - ID3D11RasterizerState* _rasterizer; ///< スプライト描画用ラスタライザ - ID3D11SamplerState* _samplerState; ///< スプライト描画用サンプラーステート - - ID3D11VertexShader* _vertexShader; ///< スプライト描画シェーダ - ID3D11PixelShader* _pixelShader; ///< スプライト描画シェーダ - ID3D11BlendState* _blendState; ///< スプライト描画用ブレンドステート - ID3D11InputLayout* _vertexFormat; ///< スプライト描画用型宣言 }; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppLive2DManager.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppLive2DManager.cpp index 1e1bf39d..c25c4efc 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppLive2DManager.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppLive2DManager.cpp @@ -7,6 +7,7 @@ #include "LAppLive2DManager.hpp" +#include #include #include #include @@ -24,6 +25,11 @@ using namespace LAppDefine; namespace { LAppLive2DManager* s_instance = NULL; + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion Began: %x", self); + } + void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -78,6 +84,7 @@ LAppLive2DManager::~LAppLive2DManager() } } _releaseModel.Clear(); + _modelDir.Clear(); delete _viewMatrix; CubismFramework::Dispose(); @@ -106,30 +113,43 @@ void LAppLive2DManager::SetUpModel() { // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 + // 一部文字が受け取れないためワイド文字で受け取ってUTF8に変換し格納する。 + csmString crawlPath(ResourcesPath); crawlPath += "*.*"; - struct _finddata_t fdata; - intptr_t fh = _findfirst(crawlPath.GetRawString(), &fdata); - if (fh == -1) return; + wchar_t wideStr[MAX_PATH]; + csmChar name[MAX_PATH]; + LAppPal::ConvertMultiByteToWide(crawlPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata; + intptr_t fh = _wfindfirst(wideStr, &fdata); + if (fh == -1) + { + return; + } _modelDir.Clear(); - while (_findnext(fh, &fdata) == 0) + while (_wfindnext(fh, &fdata) == 0) { - if ((fdata.attrib & _A_SUBDIR) && strcmp(fdata.name, "..") != 0) + if ((fdata.attrib & _A_SUBDIR) && wcscmp(fdata.name, L"..") != 0) { + LAppPal::ConvertWideToMultiByte(fdata.name, name, MAX_PATH); + // フォルダと同名の.model3.jsonがあるか探索する csmString model3jsonPath(ResourcesPath); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath.Append(1, '/'); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath += ".model3.json"; - struct _finddata_t fdata2; - if (_findfirst(model3jsonPath.GetRawString(), &fdata2) != -1) + LAppPal::ConvertMultiByteToWide(model3jsonPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata2; + if (_wfindfirst(wideStr, &fdata2) != -1) { - _modelDir.PushBack(csmString(fdata.name)); + _modelDir.PushBack(csmString(name)); } } } @@ -189,7 +209,7 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) { LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); } - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -305,7 +325,7 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); // 別レンダリング先を選択した際の背景クリア色 - float clearColor[3] = { 1.0f, 1.0f, 1.0f }; + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]); } } diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.cpp index dc54d053..8afacb54 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.cpp @@ -290,21 +290,10 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -447,7 +436,8 @@ void LAppModel::Update() } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, + ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -477,21 +467,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -500,6 +479,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -519,7 +499,8 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, + ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -528,7 +509,7 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -582,7 +563,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.hpp index e366d78e..18b17695 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppModel.hpp @@ -67,9 +67,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -77,9 +78,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.cpp index d64781ad..63c283d1 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.cpp @@ -20,6 +20,7 @@ namespace { LARGE_INTEGER s_frequency; LARGE_INTEGER s_lastFrame; double s_deltaTime = 0.0; + const csmUint32 LogMessageLength = 256; } void LAppPal::StartTimer() @@ -29,12 +30,12 @@ void LAppPal::StartTimer() csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { - //filePath;// - const char* path = filePath.c_str(); + wchar_t wideStr[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0U, filePath.c_str(), -1, wideStr, MAX_PATH); int size = 0; - struct stat statBuf; - if (stat(path, &statBuf) == 0) + struct _stat statBuf; + if (_wstat(wideStr, &statBuf) == 0) { size = statBuf.st_size; @@ -42,7 +43,7 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat succeeded but file size is zero. path:%s", path); + PrintLogLn("Stat succeeded but file size is zero. path:%s", filePath.c_str()); } return NULL; } @@ -51,27 +52,33 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat failed. errno:%d path:%s", errno, path); + PrintLogLn("Stat failed. errno:%d path:%s", errno, filePath.c_str()); } return NULL; } - std::fstream file; - file.open(path, std::ios::in | std::ios::binary); + std::wfstream file; + file.open(wideStr, std::ios::in | std::ios::binary); if (!file.is_open()) { if (DebugLogEnable) { - PrintLogLn("File open failed. path:%s", path); + PrintLogLn("File open failed. path:%s", filePath.c_str()); } return NULL; } - char* buf = new char[size]; - file.read(buf, size); - file.close(); + // ファイル名はワイド文字で探しているがファイルの中身はutf-8なので、1バイトずつ取得する。 *outSize = size; + csmChar* buf = new char[*outSize]; + std::wfilebuf* fileBuf = file.rdbuf(); + for (csmUint32 i = 0; i < *outSize; i++) + { + buf[i] = fileBuf->sbumpc(); + } + file.close(); + return reinterpret_cast(buf); } @@ -107,42 +114,25 @@ void LAppPal::UpdateTime() void LAppPal::PrintLog(const char* format, ...) { va_list args; - char buf[256]; + char multiByteBuf[LogMessageLength]; + wchar_t wideBuf[LogMessageLength]; va_start(args, format); - _vsnprintf_s(buf, sizeof(buf), format, args); - OutputDebugStringA((LPCSTR)buf); + _vsnprintf_s(multiByteBuf, sizeof(multiByteBuf), format, args); + ConvertMultiByteToWide(multiByteBuf, wideBuf, sizeof(wideBuf)); + OutputDebugStringW(wideBuf); va_end(args); } void LAppPal::PrintLogLn(const char* format, ...) { va_list args; - char buf[256]; + char multiByteBuf[LogMessageLength]; + wchar_t wideBuf[LogMessageLength]; va_start(args, format); - _vsnprintf_s(buf, sizeof(buf), format, args); - OutputDebugStringA((LPCSTR)buf); - OutputDebugStringA("\n"); // 改行を別途付与します - va_end(args); -} - -void LAppPal::PrintLogW(const wchar_t* format, ...) -{ - va_list args; - wchar_t buf[256]; - va_start(args, format); - _vsnwprintf_s(buf, sizeof(buf), format, args); - OutputDebugString((LPCSTR)buf); - va_end(args); -} - -void LAppPal::PrintLogLnW(const wchar_t* format, ...) -{ - va_list args; - wchar_t buf[256]; - va_start(args, format); - _vsnwprintf_s(buf, sizeof(buf), format, args); - OutputDebugString((LPCSTR)buf); - OutputDebugString("\n"); // 改行を別途付与します + _vsnprintf_s(multiByteBuf, sizeof(multiByteBuf), format, args); + ConvertMultiByteToWide(multiByteBuf, wideBuf, sizeof(wideBuf)); + OutputDebugStringW(wideBuf); + OutputDebugStringW(L"\n"); // 改行を別途付与します va_end(args); } @@ -163,7 +153,10 @@ void LAppPal::CoordinateFullScreenToWindow(float clientWidth, float clientHeight const float width = static_cast(clientWidth); const float height = static_cast(clientHeight); - if (width == 0.0f || height == 0.0f) return; + if (width == 0.0f || height == 0.0f) + { + return; + } retWindowX = (fullScreenX + width) * 0.5f; retWindowY = (-fullScreenY + height) * 0.5f; @@ -176,16 +169,21 @@ void LAppPal::CoordinateWindowToFullScreen(float clientWidth, float clientHeight const float width = static_cast(clientWidth); const float height = static_cast(clientHeight); - if (width == 0.0f || height == 0.0f) return; + if (width == 0.0f || height == 0.0f) + { + return; + } retFullScreenX = 2.0f * windowX - width; retFullScreenY = (2.0f * windowY - height) * -1.0f; } -void LAppPal::MbcToWchar(const char* src, size_t srcLength, wchar_t* dest, size_t destLength) +bool LAppPal::ConvertMultiByteToWide(const csmChar* multiByte, wchar_t* wide, int wideSize) { - if (srcLength<1 || destLength<2) return; + return MultiByteToWideChar(CP_UTF8, 0U, multiByte, -1, wide, wideSize) != 0; +} - memset(dest, 0, destLength); - MultiByteToWideChar(CP_ACP, 0, src, static_cast(srcLength), dest, static_cast(destLength)); +bool LAppPal::ConvertWideToMultiByte(const wchar_t* wide, csmChar* multiByte, int multiByteSize) +{ + return WideCharToMultiByte(CP_UTF8, 0U, wide, -1, multiByte, multiByteSize, NULL, NULL) != 0; } diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.hpp index 8eee246a..47d94ebd 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppPal.hpp @@ -85,28 +85,6 @@ class LAppPal */ static void PrintLogLn(const char*, ...); - /** - * @brief ログを出力する wchar版 - * - * ログを出力する - * - * @param[in] format 書式付文字列 - * @param[in] ... (可変長引数)文字列 - * - */ - static void PrintLogW(const wchar_t*, ...); - - /** - * @brief ログを出力し最後に改行する wchar版 - * - * ログを出力し最後に改行する - * - * @param[in] format 書式付文字列 - * @param[in] ... (可変長引数)文字列 - * - */ - static void PrintLogLnW(const wchar_t*, ...); - /** * @brief メッセージを出力する * @@ -140,8 +118,21 @@ class LAppPal static void CoordinateWindowToFullScreen(float clientWidth, float clientHeight, float windowX, float windowY, float& retFullScreenX, float& retFullScreenY); /** - * @brief MbcからWcharに変換 + * @brief マルチバイト文字からワイド文字に変換する + * + * @param[in] multiByte 変換元 + * @param[in] wide 格納先 + * @param[in] wideSize 格納先の大きさ + */ + static bool ConvertMultiByteToWide(const Csm::csmChar* multiByte, wchar_t* wide, int wideSize); + + /** + * @brief ワイド文字からマルチバイト文字に変換する + * + * @param[in] wide 変換元 + * @param[in] multiByte 格納先 + * @param[in] multiByteSize 格納先の大きさ */ - static void MbcToWchar(const char* src, size_t srcLength, wchar_t* dest, size_t destLength); + static bool ConvertWideToMultiByte(const wchar_t* wide, Csm::csmChar* multiByte, int multiByteSize); }; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.cpp index a97ef437..aae37655 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.cpp @@ -10,6 +10,7 @@ #include "LAppPal.hpp" #include "LAppDefine.hpp" #include "LAppTextureManager.hpp" +#include "LAppSpriteShader.hpp" #include "Rendering/D3D11/CubismType_D3D11.hpp" using namespace LAppDefine; @@ -19,16 +20,18 @@ LAppSprite::LAppSprite() : _rect(), _vertexBuffer(NULL), _indexBuffer(NULL), - _constantBuffer(NULL) + _constantBuffer(NULL), + _shader(NULL) { _color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); } -LAppSprite::LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, ID3D11Device* device) +LAppSprite::LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, LAppSpriteShader* shader, ID3D11Device* device) : _rect(), _vertexBuffer(NULL), _indexBuffer(NULL), - _constantBuffer(NULL) + _constantBuffer(NULL), + _shader(shader) { _color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); @@ -130,6 +133,8 @@ LAppSprite::LAppSprite(float x, float y, float width, float height, Csm::csmUint LAppSprite::~LAppSprite() { + _shader = NULL; + if(_constantBuffer) { _constantBuffer->Release(); @@ -201,6 +206,9 @@ void LAppSprite::RenderImmidiate(int width, int height, ID3D11ShaderResourceView renderContext->IASetIndexBuffer(_indexBuffer, DXGI_FORMAT_R16_UINT, 0); renderContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + // シェーダーセット + _shader->SetupShader(); + // テクスチャセット { renderContext->PSSetShaderResources(0, 1, &resourceView); diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.hpp index 9f882a69..79a9021b 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSprite.hpp @@ -12,7 +12,7 @@ #include #include - +class LAppSpriteShader; /** * @brief スプライトを実装するクラス。 @@ -51,9 +51,10 @@ class LAppSprite * @param[in] width 横幅 * @param[in] height 高さ * @param[in] textureId テクスチャID + * @param[in] shader シェーダー設定 * @param[in] device D3Dデバイス */ - LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, ID3D11Device* device); + LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, LAppSpriteShader* shader, ID3D11Device* device); /** * @brief デストラクタ @@ -119,4 +120,6 @@ class LAppSprite ID3D11Buffer* _constantBuffer; ///< 定数バッファ DirectX::XMFLOAT4 _color; ///< スプライトカラー + + LAppSpriteShader* _shader; }; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSpriteShader.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSpriteShader.cpp new file mode 100644 index 00000000..3b04e19f --- /dev/null +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSpriteShader.cpp @@ -0,0 +1,280 @@ +/** + * 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. + */ + +#include "LAppSpriteShader.hpp" + +#include +#include +#include "LAppDefine.hpp" +#include "LAppDelegate.hpp" +#include "LAppPal.hpp" + +LAppSpriteShader::LAppSpriteShader() + : _rasterizer(NULL) + , _samplerState(NULL) + , _vertexShader(NULL) + , _pixelShader(NULL) + , _blendState(NULL) + , _vertexFormat(NULL) +{ +} + +LAppSpriteShader::~LAppSpriteShader() +{ +} + +bool LAppSpriteShader::CreateShader() +{ + ReleaseShader(); + + ID3D11Device* device = LAppDelegate::GetD3dDevice(); + HRESULT result = S_OK; + + ID3DBlob* vertexError = NULL; + ID3DBlob* pixelError = NULL; + + ID3DBlob* vertexBlob = NULL; + ID3DBlob* pixelBlob = NULL; + + // ファイル読み込み + const char* shaderCode; + Csm::csmSizeInt shaderSize; + { + // シェーダーのパスの作成 + Csm::csmString shaderFileName(LAppDefine::ShaderPath); + shaderFileName += LAppDefine::ShaderName; + + // ファイル読み込み + shaderCode = reinterpret_cast(LAppPal::LoadFileAsBytes(shaderFileName.GetRawString(), &shaderSize)); + } + + do + { + // ラスタライザ + D3D11_RASTERIZER_DESC rasterDesc; + memset(&rasterDesc, 0, sizeof(rasterDesc)); + rasterDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_BACK; // 裏面を切る + rasterDesc.FrontCounterClockwise = TRUE; // CCWを表面にする + rasterDesc.DepthClipEnable = FALSE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.DepthBiasClamp = 0; + rasterDesc.SlopeScaledDepthBias = 0; + result = device->CreateRasterizerState(&rasterDesc, &_rasterizer); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Rasterizer 0x%x", result); + break; + } + + // テクスチャサンプラーステート + D3D11_SAMPLER_DESC samplerDesc; + memset(&samplerDesc, 0, sizeof(D3D11_SAMPLER_DESC)); + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.MinLOD = -D3D11_FLOAT32_MAX; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + result = device->CreateSamplerState(&samplerDesc, &_samplerState); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Sampler 0x%x", result); + break; + } + + // レンダリングステートオブジェクト + D3D11_BLEND_DESC blendDesc; + memset(&blendDesc, 0, sizeof(blendDesc)); + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = FALSE; // falseの場合はRenderTarget[0]しか使用しなくなる + blendDesc.RenderTarget[0].BlendEnable = TRUE; + blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + result = device->CreateBlendState(&blendDesc, &_blendState); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create BlendState 0x%x", result); + break; + } + + UINT compileFlag = 0; + + result = D3DCompile( + shaderCode, // メモリー内のシェーダーへのポインターです + shaderSize, // メモリー内のシェーダーのサイズです + NULL, // シェーダー コードが格納されているファイルの名前 + NULL, // マクロ定義の配列へのポインター + NULL, // インクルード ファイルを扱うインターフェイスへのポインター + "VertNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 + "vs_4_0", // シェーダー モデルを指定する文字列。 + compileFlag, // シェーダーコンパイルフラグ + 0, // シェーダーコンパイルフラグ + &vertexBlob, + &vertexError); // エラーが出る場合はここで + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Compile Vertex Shader"); + break; + } + result = device->CreateVertexShader(vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), NULL, &_vertexShader); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Vertex Shader"); + break; + } + + result = D3DCompile( + shaderCode, // メモリー内のシェーダーへのポインターです + shaderSize, // メモリー内のシェーダーのサイズです + NULL, // シェーダー コードが格納されているファイルの名前 + NULL, // マクロ定義の配列へのポインター + NULL, // インクルード ファイルを扱うインターフェイスへのポインター + "PixelNormal", // シェーダーの実行が開始されるシェーダー エントリポイント関数の名前 + "ps_4_0", // シェーダー モデルを指定する文字列 + compileFlag, // シェーダーコンパイルフラグ + 0, // シェーダーコンパイルフラグ + &pixelBlob, + &pixelError); // エラーが出る場合はここで + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Compile Pixel Shader"); + break; + } + + result = device->CreatePixelShader(pixelBlob->GetBufferPointer(), pixelBlob->GetBufferSize(), NULL, &_pixelShader); + if (FAILED(result)) + { + LAppPal::PrintLog("Fail Create Pixel Shader"); + break; + } + + // この描画で使用する頂点フォーマット + D3D11_INPUT_ELEMENT_DESC elems[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + result = device->CreateInputLayout(elems, ARRAYSIZE(elems), vertexBlob->GetBufferPointer(), vertexBlob->GetBufferSize(), &_vertexFormat); + + if (FAILED(result)) + { + LAppPal::PrintLog("CreateVertexDeclaration failed"); + break; + } + + } while (0); + + if (pixelError) + { + pixelError->Release(); + pixelError = NULL; + } + if (vertexError) + { + vertexError->Release(); + vertexError = NULL; + } + + // blobはもうここで不要 + if (pixelBlob) + { + pixelBlob->Release(); + pixelBlob = NULL; + } + if (vertexBlob) + { + vertexBlob->Release(); + vertexBlob = NULL; + } + + if (FAILED(result)) + { + return false; + } + + return true; +} + +void LAppSpriteShader::SetupShader() +{ + ID3D11DeviceContext* deviceContext = LAppDelegate::GetD3dContext(); + + if (_rasterizer == NULL || _samplerState == NULL || _blendState == NULL || + _vertexShader == NULL || _pixelShader == NULL || _vertexFormat == NULL) + { + return; + } + + // 現在のウィンドウサイズの取得 + int windowWidth, windowHeight; + LAppDelegate::GetClientSize(windowWidth, windowHeight); + + // スプライト描画用の設定をし、シェーダーセット + deviceContext->IASetInputLayout(_vertexFormat); + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + deviceContext->IASetInputLayout(_vertexFormat); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(windowWidth); + viewport.Height = static_cast(windowHeight); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + deviceContext->RSSetViewports(1, &viewport); + deviceContext->RSSetState(_rasterizer); + + deviceContext->VSSetShader(_vertexShader, NULL, 0); + + deviceContext->PSSetShader(_pixelShader, NULL, 0); + deviceContext->PSSetSamplers(0, 1, &_samplerState); + + float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + deviceContext->OMSetBlendState(_blendState, blendFactor, 0xffffffff); +} + +void LAppSpriteShader::ReleaseShader() +{ + if (_rasterizer) + { + _rasterizer->Release(); + _rasterizer = NULL; + } + if (_samplerState) + { + _samplerState->Release(); + _samplerState = NULL; + } + if (_blendState) + { + _blendState->Release(); + _blendState = NULL; + } + if (_vertexShader) + { + _vertexShader->Release(); + _vertexShader = NULL; + } + if (_pixelShader) + { + _pixelShader->Release(); + _pixelShader = NULL; + } + if (_vertexFormat) + { + _vertexFormat->Release(); + _vertexFormat = NULL; + } +} diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSpriteShader.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSpriteShader.hpp new file mode 100644 index 00000000..257f8447 --- /dev/null +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppSpriteShader.hpp @@ -0,0 +1,53 @@ +/** + * 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. + */ + +#pragma once + +#include + +/** + * @brief スプライト用のシェーダー設定を保持するクラス。 + */ +class LAppSpriteShader +{ +public: + + /** + * @brief コンストラクタ + */ + LAppSpriteShader(); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーの作成を行う + */ + bool CreateShader(); + + /** + * @brief スプライトの描画直前に呼び出される + * シェーダーのセットを行う + */ + void SetupShader(); + + /** + * @brief シェーダーの解放を行う + */ + void ReleaseShader(); + +private: + + ID3D11RasterizerState* _rasterizer; ///< ラスタライザ + ID3D11SamplerState* _samplerState; ///< サンプラーステート + ID3D11BlendState* _blendState; ///< ブレンドステート + ID3D11VertexShader* _vertexShader; ///< 頂点シェーダ + ID3D11PixelShader* _pixelShader; ///< ピクセルシェーダ + ID3D11InputLayout* _vertexFormat; ///< 頂点フォーマット +}; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppTextureManager.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppTextureManager.cpp index a3327511..978eada0 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppTextureManager.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppTextureManager.cpp @@ -31,7 +31,7 @@ LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile(st // wcharに変換 const int WCHAR_LENGTH = 512; wchar_t wchrStr[WCHAR_LENGTH] = L""; - LAppPal::MbcToWchar(fileName.c_str(), fileName.length(), wchrStr, sizeof(wchrStr)); + LAppPal::ConvertMultiByteToWide(fileName.c_str(), wchrStr, sizeof(wchrStr)); ID3D11Resource* texture = NULL; ID3D11ShaderResourceView* textureView = NULL; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.cpp index 9769c511..50862ba3 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.cpp @@ -15,6 +15,7 @@ #include "LAppDefine.hpp" #include "TouchManager.hpp" #include "LAppSprite.hpp" +#include "LAppSpriteShader.hpp" #include "LAppModel.hpp" using namespace std; @@ -25,7 +26,8 @@ LAppView::LAppView(): _gear(NULL), _power(NULL), _renderSprite(NULL), - _renderTarget(SelectTarget_None) + _renderTarget(SelectTarget_None), + _shader(NULL) { _clearColor[0] = 1.0f; _clearColor[1] = 1.0f; @@ -40,6 +42,9 @@ LAppView::LAppView(): // 画面の表示の拡大縮小や移動の変換を行う行列 _viewMatrix = new CubismViewMatrix(); + + // スプライト用シェーダー + _shader = new LAppSpriteShader(); } LAppView::~LAppView() @@ -47,7 +52,9 @@ LAppView::~LAppView() _renderBuffer.DestroyOffscreenSurface(); ReleaseSprite(); + _shader->ReleaseShader(); + delete _shader; delete _viewMatrix; delete _deviceToScreen; delete _touchManager; @@ -97,6 +104,9 @@ void LAppView::Initialize() ViewLogicalMaxBottom, ViewLogicalMaxTop ); + + // シェーダー作成 + _shader->CreateShader(); } void LAppView::Render() @@ -107,9 +117,6 @@ void LAppView::Render() return; } - // シェーダー設定 - LAppDelegate::GetInstance()->SetupShader(); - // スプライト描画 int width, height; LAppDelegate::GetInstance()->GetClientSize(width, height); @@ -180,7 +187,7 @@ void LAppView::InitializeSprite() y = height * 0.5f; fWidth = static_cast(backgroundTexture->width * 2); fHeight = static_cast(height) * 0.95f; - _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, device); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _shader, device); imageName = resourcesPath + GearImageName; LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(imageName, false); @@ -188,7 +195,7 @@ void LAppView::InitializeSprite() y = static_cast(height - gearTexture->height * 0.5f); fWidth = static_cast(gearTexture->width); fHeight = static_cast(gearTexture->height); - _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, device); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _shader, device); imageName = resourcesPath + PowerImageName; LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(imageName, false); @@ -196,11 +203,11 @@ void LAppView::InitializeSprite() y = static_cast(powerTexture->height * 0.5f); fWidth = static_cast(powerTexture->width); fHeight = static_cast(powerTexture->height); - _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, device); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _shader, device); x = width * 0.5f; y = height * 0.5f; - _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, device); + _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, _shader, device); } void LAppView::ReleaseSprite() @@ -420,9 +427,6 @@ void LAppView::PostModelDraw(LAppModel& refModel) // LAppViewの持つフレームバッファを使うなら、スプライトへの描画はここ if (_renderTarget == SelectTarget_ViewFrameBuffer && _renderSprite) { - // シェーダー設定 - LAppDelegate::GetInstance()->SetupShader(); - // スプライト描画 int width, height; LAppDelegate::GetInstance()->GetClientSize(width, height); diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.hpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.hpp index 553e46e4..033f04fd 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.hpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/LAppView.hpp @@ -16,6 +16,7 @@ class TouchManager; class LAppSprite; +class LAppSpriteShader; class LAppModel; /** @@ -170,4 +171,6 @@ class LAppView Csm::Rendering::CubismOffscreenSurface_D3D11 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + LAppSpriteShader* _shader; ///< スプライト用のシェーダー準備クラス }; diff --git a/Samples/D3D11/Demo/proj.d3d11.cmake/src/mainMinimum.cpp b/Samples/D3D11/Demo/proj.d3d11.cmake/src/mainMinimum.cpp index eae63a43..a7777005 100644 --- a/Samples/D3D11/Demo/proj.d3d11.cmake/src/mainMinimum.cpp +++ b/Samples/D3D11/Demo/proj.d3d11.cmake/src/mainMinimum.cpp @@ -268,44 +268,6 @@ static bool InitializeSystem() return false; } - // ラスタライザ - D3D11_RASTERIZER_DESC rasterDesc; - memset(&rasterDesc, 0, sizeof(rasterDesc)); - rasterDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID; - rasterDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_BACK; // 裏面を切る - rasterDesc.FrontCounterClockwise = TRUE; // CCWを表面にする - rasterDesc.DepthClipEnable = FALSE; - rasterDesc.MultisampleEnable = FALSE; - rasterDesc.DepthBiasClamp = 0; - rasterDesc.SlopeScaledDepthBias = 0; - result = directXRenderer->_device->CreateRasterizerState(&rasterDesc, &directXRenderer->_rasterizer); - if (FAILED(result)) - { - LAppPal::PrintLogLn("Fail Create Rasterizer 0x%x", result); - return false; - } - - // テクスチャサンプラーステート - D3D11_SAMPLER_DESC samplerDesc; - memset(&samplerDesc, 0, sizeof(D3D11_SAMPLER_DESC)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MaxAnisotropy = 1; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = -D3D11_FLOAT32_MAX; - samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; - directXRenderer->_device->CreateSamplerState(&samplerDesc, &directXRenderer->_samplerState); - if (FAILED(result)) - { - LAppPal::PrintLogLn("Fail Create Sampler 0x%x", result); - return false; - } - - // スプライト用シェーダ作成 - directXRenderer->CreateShader(); - // デバイス作成の後 _textureManager = new CubismTextureManager(); diff --git a/Samples/D3D11/README.ja.md b/Samples/D3D11/README.ja.md index e3707408..238dae21 100644 --- a/Samples/D3D11/README.ja.md +++ b/Samples/D3D11/README.ja.md @@ -11,7 +11,6 @@ DirectX 11 で実装したアプリケーションのサンプル実装です。 | 開発キット | Visual Studio | バージョン | | --- | --- | --- | -| [DirectXTK] | 2013 | April 23, 2018 | | [DirectXTK] | 2015 | December 17, 2019 | | [DirectXTK] | 2017 | March 24, 2022 | | [DirectXTK] | 2019 / 2022 | December 31, 2023 | @@ -72,7 +71,6 @@ CMake プロジェクトです。 | Visual Studio | スクリプト名 | | --- | --- | -| 2013 | `setup_msvc2013.bat` | | 2015 | `setup_msvc2015.bat` | | 2017 | `setup_msvc2017.bat` | | 2019 | `setup_msvc2019.bat` | diff --git a/Samples/D3D11/README.md b/Samples/D3D11/README.md index ff3bff8a..768609d5 100644 --- a/Samples/D3D11/README.md +++ b/Samples/D3D11/README.md @@ -11,7 +11,6 @@ This is a sample implementation of an application implemented with DirectX 11. | Development Kit | Visual Studio | Version | | --- | --- | --- | -| [DirectXTK] | 2013 | April 23, 2018 | | [DirectXTK] | 2015 | December 17, 2019 | | [DirectXTK] | 2017 | March 24, 2022 | | [DirectXTK] | 2019 / 2022 | December 31, 2023 | @@ -72,7 +71,6 @@ Download DirectXTK and build the library by running the script in the `script` d | Visual Studio | Script Name | | --- | --- | -| 2013 | `setup_msvc2013.bat` | | 2015 | `setup_msvc2015.bat` | | 2017 | `setup_msvc2017.bat` | | 2019 | `setup_msvc2019.bat` | diff --git a/Samples/D3D11/Shaders/SpriteEffect.fx b/Samples/D3D11/Shaders/SpriteEffect.fx new file mode 100644 index 00000000..cba1ca5e --- /dev/null +++ b/Samples/D3D11/Shaders/SpriteEffect.fx @@ -0,0 +1,46 @@ +/** + * 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. + */ + +// 定数バッファ +cbuffer ConstantBuffer { + float4x4 projectMatrix; + float4x4 clipMatrix; + float4 baseColor; + float4 channelFlag; +} + +// テクスチャとサンプラー設定 +Texture2D mainTexture : register(t0); +SamplerState mainSampler : register(s0); + +// 頂点シェーダーの入力定義 +struct VS_IN { + float2 pos : POSITION0; + float2 uv : TEXCOORD0; +}; + +// 頂点シェーダーの出力定義 +struct VS_OUT { + float4 Position : SV_POSITION; + float2 uv : TEXCOORD0; + float4 clipPosition : TEXCOORD1; +}; + +// 頂点シェーダー +VS_OUT VertNormal(VS_IN In) { + VS_OUT Out = (VS_OUT)0; + Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix); + Out.uv.x = In.uv.x; + Out.uv.y = 1.0 - +In.uv.y; + return Out; +} + +// ピクセルシェーダー +float4 PixelNormal(VS_OUT In) : SV_Target { + float4 color = mainTexture.Sample(mainSampler, In.uv) * baseColor; + return color; +} diff --git a/Samples/D3D11/thirdParty/scripts/setup_msvc2013.bat b/Samples/D3D11/thirdParty/scripts/setup_msvc2013.bat deleted file mode 100644 index c1666d9f..00000000 --- a/Samples/D3D11/thirdParty/scripts/setup_msvc2013.bat +++ /dev/null @@ -1,21 +0,0 @@ -@echo off - -setlocal - -set XTK_VERSION=apr2018 - -set SCRIPT_PATH=%~dp0 - -:: Download and archive XTK. -call "%SCRIPT_PATH%_setup_common.bat" -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2013 -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat - -:: Build XTK project. -call "%SCRIPT_PATH%_msvc_common.bat" %XTK_VERSION% -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/CMakeLists.txt b/Samples/D3D9/Demo/proj.d3d9.cmake/CMakeLists.txt index 33ae1142..f35f191a 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/CMakeLists.txt +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/CMakeLists.txt @@ -13,6 +13,7 @@ set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) set(CORE_PATH ${SDK_ROOT_PATH}/Core) set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SAMPLE_SHADER_PATH ${SDK_ROOT_PATH}/Samples/D3D9/Shaders) # Set project. project(${APP_NAME}) @@ -45,10 +46,7 @@ else() message(FATAL_ERROR "[${APP_NAME}] Invalid linker flag ${CMAKE_EXE_LINKER_FLAGS}.") endif() # Detect compiler. -if(MSVC_VERSION MATCHES 1800) - # Visual Studio 2013 - set(COMPILER 120) -elseif(MSVC_VERSION MATCHES 1900) +if(MSVC_VERSION MATCHES 1900) # Visual Studio 2015 set(COMPILER 140) elseif(MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) @@ -57,7 +55,7 @@ elseif(MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) elseif(MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) # Visual Studio 2019 set(COMPILER 142) -elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) +elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1950) # Visual Studio 2022 set(COMPILER 143) elseif(MSVC) @@ -103,6 +101,7 @@ target_link_libraries(Framework add_executable(${APP_NAME} WIN32) # Add source files. add_subdirectory(src) + # Link libraries to app. target_link_libraries(${APP_NAME} Framework @@ -120,6 +119,9 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy_directory ${RES_PATH} $/Resources + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${SAMPLE_SHADER_PATH} $/SampleShaders ) # Set project properties. diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/scripts/nmake_msvc2013.bat b/Samples/D3D9/Demo/proj.d3d9.cmake/scripts/nmake_msvc2013.bat deleted file mode 100644 index 50de20fd..00000000 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/scripts/nmake_msvc2013.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2013 -set MSVC_NUMBER=12 -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat -set GENERATOR=nmake - -call "%SCRIPT_PATH%_msvc_common.bat" -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/scripts/proj_msvc2013.bat b/Samples/D3D9/Demo/proj.d3d9.cmake/scripts/proj_msvc2013.bat deleted file mode 100644 index d11674f6..00000000 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/scripts/proj_msvc2013.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2013 -set MSVC_NUMBER=12 -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat -set GENERATOR=proj - -call "%SCRIPT_PATH%_msvc_common.bat" -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CMakeLists.txt b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CMakeLists.txt index c0db52af..17317305 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CMakeLists.txt +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CMakeLists.txt @@ -12,6 +12,8 @@ if (CSM_MINIMUM_DEMO) ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/CubismUserModelExtend.cpp @@ -44,6 +46,8 @@ else () ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.cpp index 6ad81dc5..da250b0e 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.cpp @@ -7,9 +7,6 @@ #include "LAppPal.hpp" -#include -#include - #include "CubismDirectXRenderer.hpp" #include "CubismDirectXView.hpp" #include "CubismTextureManager.hpp" @@ -38,8 +35,6 @@ CubismDirectXRenderer::CubismDirectXRenderer() , _deviceLostStep(LostStep::LostStep_None) , _lostCounter(0) , _isFullScreen(false) - , _shaderEffect(nullptr) - , _vertexFormat(nullptr) , _model(nullptr) { _textureManager = new CubismTextureManager(); @@ -102,102 +97,6 @@ void CubismDirectXRenderer::GetClientSize(int& rWidth, int& rHeight) rHeight = (clientRect.bottom - clientRect.top); } -bool CubismDirectXRenderer::CreateShader() -{ - // 一旦削除する - ReleaseShader(); - - static const csmChar* SpriteShaderEffectSrc = - "float4x4 projectMatrix;"\ - "float4 baseColor;"\ - "texture mainTexture;"\ - \ - "sampler mainSampler = sampler_state{"\ - "texture = ;"\ - "};"\ - \ - "struct VS_IN {"\ - "float2 pos : POSITION;"\ - "float2 uv : TEXCOORD0;"\ - "};"\ - "struct VS_OUT {"\ - "float4 Position : POSITION0;"\ - "float2 uv : TEXCOORD0;"\ - "float4 clipPosition : TEXCOORD1;"\ - "};"\ - \ - "/* Vertex Shader */"\ - "/* normal */"\ - "VS_OUT VertNormal(VS_IN In) {"\ - "VS_OUT Out = (VS_OUT)0;"\ - "Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ - "Out.uv.x = In.uv.x;"\ - "Out.uv.y = 1.0 - +In.uv.y;"\ - "return Out;"\ - "}"\ - \ - "/* Pixel Shader */"\ - "/* normal */"\ - "float4 PixelNormal(VS_OUT In) : COLOR0{"\ - "float4 color = tex2D(mainSampler, In.uv) * baseColor;"\ - "return color;"\ - "}"\ - \ - "/* Technique */"\ - "technique ShaderNames_Normal {"\ - "pass p0{"\ - "VertexShader = compile vs_2_0 VertNormal();"\ - "PixelShader = compile ps_2_0 PixelNormal();"\ - "}"\ - "}"; - - ID3DXBuffer* error = 0; - if (FAILED(D3DXCreateEffect(_device, SpriteShaderEffectSrc, static_cast(strlen(SpriteShaderEffectSrc)), 0, 0, 0, 0, &_shaderEffect, &error))) - { - LAppPal::PrintLogLn("Cannot load the shaders"); - return false; - } - - // この描画で使用する頂点フォーマット - D3DVERTEXELEMENT9 elems[] = { - { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - { 0, sizeof(float) * 2, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, - D3DDECL_END() - }; - if (_device->CreateVertexDeclaration(elems, &_vertexFormat)) - { - LAppPal::PrintLogLn("CreateVertexDeclaration failed"); - CSM_ASSERT(0); - } - - return true; -} - -ID3DXEffect* CubismDirectXRenderer::SetupShader() -{ - if (_device == nullptr || _vertexFormat == nullptr || _shaderEffect == nullptr) - { - return nullptr; - } - - _device->SetVertexDeclaration(_vertexFormat); - return _shaderEffect; -} - -void CubismDirectXRenderer::ReleaseShader() -{ - if (_vertexFormat) - { - _vertexFormat->Release(); - _vertexFormat = nullptr; - } - if (_shaderEffect) - { - _shaderEffect->Release(); - _shaderEffect = nullptr; - } -} - void CubismDirectXRenderer::RecreateDevice() { // Viewロスト処理 @@ -251,13 +150,6 @@ void CubismDirectXRenderer::StartFrame() const void CubismDirectXRenderer::EndFrame(CubismUserModel* userModel) { - // テクスチャの参照を外しておく - if (_shaderEffect) - { - _shaderEffect->SetTexture("mainTexture", NULL); - _shaderEffect->CommitChanges(); - } - if (_device) { //シーンの終了 diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.hpp index 0ce11aa9..b197ccd2 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXRenderer.hpp @@ -52,21 +52,6 @@ class CubismDirectXRenderer */ void ReleaseInstance(); - /** - * @brief スプライト描画用シェーダの作成と頂点宣言の作成を行う - */ - bool CreateShader(); - - /** - * @brief シェーダをコンテキストにセット - */ - ID3DXEffect* SetupShader(); - - /** - * @brief CreateShaderで確保したオブジェクトの開放 - */ - void ReleaseShader(); - /** * @brief デバイス再作成 ウィンドウサイズ変更の時など * ロスト対応の+α処理を行う @@ -116,9 +101,6 @@ class CubismDirectXRenderer D3DPRESENT_PARAMETERS _presentParameters; ///< プレゼントパラメータ D3DPRESENT_PARAMETERS _presentParametersFull; ///< プレゼントパラメータ フルスクリーン - ID3DXEffect* _shaderEffect; ///< スプライト描画用シェーダ - IDirect3DVertexDeclaration9* _vertexFormat; ///< スプライト描画用型宣言 - CubismTextureManager* _textureManager; ///< テクスチャマネージャー CubismUserModelExtend* _model; ///< モデルデータ diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.cpp index c9551b86..45e48809 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.cpp @@ -7,8 +7,11 @@ #include "CubismDirectXView.hpp" +#include + #include "CubismDirectXRenderer.hpp" #include "CubismSampleViewMatrix.hpp" +#include "LAppPal.hpp" namespace { CubismDirectXView* _instance = nullptr; @@ -25,7 +28,11 @@ CubismDirectXView* CubismDirectXView::GetInstance() } CubismDirectXView::CubismDirectXView() - :_windowWidth(0), _windowHeight(0), _renderSprite(nullptr), _renderTarget(SelectTarget_None) + :_windowWidth(0), + _windowHeight(0), + _renderSprite(nullptr), + _renderTarget(SelectTarget_None), + _shader(nullptr) { _clearColor[0] = 1.0f; _clearColor[1] = 1.0f; @@ -91,13 +98,13 @@ void CubismDirectXView::Render(CubismUserModel* userModel) void CubismDirectXView::InitializeSprite() { + // シェーダ作成 + _shader = new CubismSpriteShader(); + CubismDirectXRenderer::GetInstance()->GetClientSize(_windowWidth, _windowHeight); float x = _windowWidth * 0.5f; float y = _windowHeight * 0.5f; - _renderSprite = new CubismSprite(x, y, static_cast(_windowWidth), static_cast(_windowHeight), 0); - - // シェーダ作成 - CubismDirectXRenderer::GetInstance()->CreateShader(); + _renderSprite = new CubismSprite(x, y, static_cast(_windowWidth), static_cast(_windowHeight), 0, _shader); } void CubismDirectXView::ReleaseSprite() @@ -106,7 +113,8 @@ void CubismDirectXView::ReleaseSprite() _renderSprite = nullptr; // スプライト用のシェーダ・頂点宣言も開放 - CubismDirectXRenderer::GetInstance()->ReleaseShader(); + delete _shader; + _shader = nullptr; } void CubismDirectXView::ResizeSprite() diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.hpp index 8d32c5b1..358c7db3 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismDirectXView.hpp @@ -14,6 +14,7 @@ #include "MouseActionManager.hpp" #include "CubismUserModelExtend.hpp" #include "CubismSprite.hpp" +#include "CubismSpriteShader.hpp" class CubismDirectXView { @@ -149,4 +150,6 @@ class CubismDirectXView Csm::Rendering::CubismOffscreenSurface_D3D9 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + CubismSpriteShader* _shader; ///< スプライト用のシェーダー準備クラス }; diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.cpp index dbce4e78..81b49f19 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.cpp @@ -10,6 +10,7 @@ #include "CubismDirectXRenderer.hpp" +#include "CubismDirectXView.hpp" #include "LAppDefine.hpp" #include "LAppPal.hpp" #include "Rendering/D3D9/CubismType_D3D9.hpp" @@ -22,10 +23,11 @@ CubismSprite::CubismSprite() _color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); } -CubismSprite::CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId) +CubismSprite::CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, CubismSpriteShader* shader) : _rect(), _vertexStore(nullptr), - _indexStore(nullptr) + _indexStore(nullptr), + _shader(shader) { _color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); @@ -79,6 +81,7 @@ CubismSprite::~CubismSprite() } _indexStore = nullptr; _vertexStore = nullptr; + _shader = nullptr; } void CubismSprite::Render(LPDIRECT3DDEVICE9 device, int maxWidth, int maxHeight) const @@ -93,6 +96,11 @@ void CubismSprite::Render(LPDIRECT3DDEVICE9 device, int maxWidth, int maxHeight) return; // この際は描画できず } + if (device == nullptr || _shader == nullptr) + { + return; + } + // 頂点設定 _vertexStore[0].x = (_rect.left - maxWidth * 0.5f) / (maxWidth * 0.5f); _vertexStore[0].y = (_rect.down - maxHeight * 0.5f) / (maxHeight * 0.5f); _vertexStore[0].u = 0.0f; _vertexStore[0].v = 0.0f; _vertexStore[1].x = (_rect.right - maxWidth * 0.5f) / (maxWidth * 0.5f); _vertexStore[1].y = (_rect.down - maxHeight * 0.5f) / (maxHeight * 0.5f); _vertexStore[1].u = 1.0f; _vertexStore[1].v = 0.0f; @@ -100,53 +108,23 @@ void CubismSprite::Render(LPDIRECT3DDEVICE9 device, int maxWidth, int maxHeight) _vertexStore[3].x = (_rect.right - maxWidth * 0.5f) / (maxWidth * 0.5f); _vertexStore[3].y = (_rect.up - maxHeight * 0.5f) / (maxHeight * 0.5f); _vertexStore[3].u = 1.0f; _vertexStore[3].v = 1.0f; { - D3DXMATRIX proj( - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); - - // このエフェクトで描画 - ID3DXEffect* shaderEffect = CubismDirectXRenderer::GetInstance()->SetupShader(); - if (shaderEffect) - { - // レンダーステート - device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - - device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, false); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - - - UINT numPass = 0; - shaderEffect->SetTechnique("ShaderNames_Normal"); - - // numPassには指定のtechnique内に含まれるpassの数が返る - shaderEffect->Begin(&numPass, 0); - shaderEffect->BeginPass(0); - - shaderEffect->SetMatrix("projectMatrix", &proj); - - shaderEffect->SetVector("baseColor", &_color); - - IDirect3DTexture9* texture = NULL; - if (CubismDirectXRenderer::GetInstance()->_textureManager->GetTexture(_textureId, texture)) - { - shaderEffect->SetTexture("mainTexture", texture); - } - shaderEffect->CommitChanges(); - - - { - // 描画 - device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, VERTEX_NUM, 2, _indexStore, D3DFMT_INDEX16, _vertexStore, sizeof(SpriteVertex)); - } - - shaderEffect->EndPass(); - shaderEffect->End(); - } + // レンダーステート + device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, false); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); + + // シェーダー準備 + IDirect3DTexture9* texture = NULL; + CubismDirectXRenderer::GetInstance()->_textureManager->GetTexture(_textureId, texture); + _shader->SetShader(device, texture, _color); + + // 描画 + device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, VERTEX_NUM, 2, _indexStore, D3DFMT_INDEX16, _vertexStore, sizeof(SpriteVertex)); + + // シェーダー後処理 + _shader->UnsetShader(); } } @@ -162,6 +140,11 @@ void CubismSprite::RenderImmidiate(LPDIRECT3DDEVICE9 device, int maxWidth, int m return; // この際は描画できず } + if (device == nullptr || _shader == nullptr) + { + return; + } + // 頂点設定 _vertexStore[0].x = (_rect.left - maxWidth * 0.5f) / (maxWidth * 0.5f); _vertexStore[0].y = (_rect.down - maxHeight * 0.5f) / (maxHeight * 0.5f); _vertexStore[0].u = 0.0f; _vertexStore[0].v = 0.0f; _vertexStore[1].x = (_rect.right - maxWidth * 0.5f) / (maxWidth * 0.5f); _vertexStore[1].y = (_rect.down - maxHeight * 0.5f) / (maxHeight * 0.5f); _vertexStore[1].u = 1.0f; _vertexStore[1].v = 0.0f; @@ -169,51 +152,21 @@ void CubismSprite::RenderImmidiate(LPDIRECT3DDEVICE9 device, int maxWidth, int m _vertexStore[3].x = (_rect.right - maxWidth * 0.5f) / (maxWidth * 0.5f); _vertexStore[3].y = (_rect.up - maxHeight * 0.5f) / (maxHeight * 0.5f); _vertexStore[3].u = 1.0f; _vertexStore[3].v = 1.0f; { - D3DXMATRIX proj( - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); - - // このエフェクトで描画 - ID3DXEffect* shaderEffect = CubismDirectXRenderer::GetInstance()->SetupShader(); - if (shaderEffect) - { - // レンダーステート - device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - - device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, false); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - - - UINT numPass = 0; - shaderEffect->SetTechnique("ShaderNames_Normal"); - - // numPassには指定のtechnique内に含まれるpassの数が返る - shaderEffect->Begin(&numPass, 0); - shaderEffect->BeginPass(0); - - shaderEffect->SetMatrix("projectMatrix", &proj); - - shaderEffect->SetVector("baseColor", &_color); - - { - shaderEffect->SetTexture("mainTexture", texture); - } - shaderEffect->CommitChanges(); + // レンダーステート + device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, false); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); + // シェーダー準備 + _shader->SetShader(device, texture, _color); - { - // 描画 - device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, VERTEX_NUM, 2, _indexStore, D3DFMT_INDEX16, _vertexStore, sizeof(SpriteVertex)); - } + // 描画 + device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, VERTEX_NUM, 2, _indexStore, D3DFMT_INDEX16, _vertexStore, sizeof(SpriteVertex)); - shaderEffect->EndPass(); - shaderEffect->End(); - } + // シェーダー後処理 + _shader->UnsetShader(); } } diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.hpp index 64cebac3..462d888b 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSprite.hpp @@ -12,6 +12,8 @@ #include #include +#include "CubismSpriteShader.hpp" + /** * @brief スプライトを実装するクラス。 * @@ -52,8 +54,9 @@ class CubismSprite * @param[in] width 横幅 * @param[in] height 高さ * @param[in] textureId テクスチャID + * @param[in] shader シェーダー操作クラス */ - CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId); + CubismSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, CubismSpriteShader* shader); /** * @brief デストラクタ @@ -114,5 +117,6 @@ class CubismSprite SpriteVertex* _vertexStore; ///< 頂点をストアしておく領域 Live2D::Cubism::Framework::csmUint16* _indexStore; ///< インデックスをストアしておく領域 D3DXVECTOR4 _color; ///< スプライトカラー -}; + CubismSpriteShader* _shader; ///< シェーダー +}; diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSpriteShader.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSpriteShader.cpp new file mode 100644 index 00000000..fe875a16 --- /dev/null +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSpriteShader.cpp @@ -0,0 +1,126 @@ +/** + * 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. + */ + +#include "CubismSpriteShader.hpp" + +#include +#include +#include "CubismDirectXRenderer.hpp" +#include "LAppDefine.hpp" +#include "LAppPal.hpp" + +CubismSpriteShader::CubismSpriteShader() + : _shaderEffect(NULL) + , _vertexFormat(NULL) +{ + CreateShader(); +} + +CubismSpriteShader::~CubismSpriteShader() +{ + ReleaseShader(); +} + +bool CubismSpriteShader::CreateShader() +{ + LPDIRECT3DDEVICE9 device = CubismDirectXRenderer::GetInstance()->_device; + ReleaseShader(); + + // ファイル読み込み + const char* shaderCode; + Csm::csmSizeInt shaderSize; + { + // シェーダーのパスの作成 + Csm::csmString shaderFileName(LAppDefine::ShaderPath); + shaderFileName += LAppDefine::ShaderName; + + // ファイル読み込み + shaderCode = reinterpret_cast(LAppPal::LoadFileAsBytes(shaderFileName.GetRawString(), &shaderSize)); + } + + ID3DXBuffer* error = 0; + HRESULT result = S_OK; + do + { + // シェーダーエフェクト作成 + if (FAILED(result = D3DXCreateEffect(device, shaderCode, shaderSize, 0, 0, 0, 0, &_shaderEffect, &error))) + { + LAppPal::PrintLog("Cannot load the shaders"); + break; + } + + // この描画で使用する頂点フォーマット + D3DVERTEXELEMENT9 elems[] = { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, sizeof(float) * 2, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + D3DDECL_END() + }; + if (FAILED(result = device->CreateVertexDeclaration(elems, &_vertexFormat))) + { + LAppPal::PrintLog("CreateVertexDeclaration failed"); + break; + } + } while(0); + + if (FAILED(result)) { + return false; + } + + return true; +} + +void CubismSpriteShader::ReleaseShader() +{ + if (_vertexFormat) + { + _vertexFormat->Release(); + _vertexFormat = nullptr; + } + if (_shaderEffect) + { + _shaderEffect->Release(); + _shaderEffect = nullptr; + } +} + +void CubismSpriteShader::SetShader(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 texture, D3DXVECTOR4 color) +{ + D3DXMATRIX proj( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 頂点フォーマット + device->SetVertexDeclaration(_vertexFormat); + + _shaderEffect->SetTechnique("ShaderNames_Normal"); + + // numPassには指定のtechnique内に含まれるpassの数が返る + UINT numPass = 0; + _shaderEffect->Begin(&numPass, 0); + _shaderEffect->BeginPass(0); + + _shaderEffect->SetMatrix("projectMatrix", &proj); + + _shaderEffect->SetVector("baseColor", &color); + + _shaderEffect->SetTexture("mainTexture", texture); + + _shaderEffect->CommitChanges(); +} + +void CubismSpriteShader::UnsetShader() +{ + _shaderEffect->EndPass(); + + _shaderEffect->SetTexture("mainTexture", NULL); + _shaderEffect->CommitChanges(); + + _shaderEffect->End(); +} diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSpriteShader.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSpriteShader.hpp new file mode 100644 index 00000000..8ec730c5 --- /dev/null +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismSpriteShader.hpp @@ -0,0 +1,56 @@ +/** + * 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. + */ + +#pragma once + +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用のシェーダー設定を保持するクラス。 +*/ +class CubismSpriteShader +{ +public: + + /** + * @brief コンストラクタ + */ + CubismSpriteShader(); + + /** + * @brief デストラクタ + */ + ~CubismSpriteShader(); + + /** + * @brief シェーダーの作成を行う + */ + bool CreateShader(); + + /** + * @brief シェーダーの解放を行う + */ + void ReleaseShader(); + + /** + * @brief スプライトの描画直前に呼び出される + * シェーダーのセットを行う + */ + void SetShader(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 texture, D3DXVECTOR4 color); + + /** + * @brief スプライトの描画後に呼び出される + * シェーダーの後処理を行う + */ + void UnsetShader(); + +private: + + ID3DXEffect* _shaderEffect; ///< スプライト描画用シェーダ + IDirect3DVertexDeclaration9* _vertexFormat; ///< スプライト描画用型宣言 +}; diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.cpp index cf8c371d..e1298f75 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.cpp @@ -200,24 +200,10 @@ void CubismUserModelExtend::PreloadMotionGroup(const csmChar* group) csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // モーションデータの読み込み - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelJson, group, i)); if (tmpMotion) { - // フェードインの時間を取得 - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - // フェードアウトの時間を取得 - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } - if (_motions[name]) { // インスタンスを破棄 @@ -257,10 +243,9 @@ void CubismUserModelExtend::ReleaseModelSetting() * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 -* @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ -Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority) { // モーション数が取得出来なかった、もしくは0の時 if (!(_modelJson->GetMotionCount(group))) @@ -296,33 +281,16 @@ Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm:: csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // 一番先頭のモーションを読み込む - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, NULL, NULL, _modelJson, group, no)); if (motion) { - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } - // 終了時にメモリから削除 autoDelete = true; } DeleteBuffer(buffer, path.GetRawString()); } - else - { - // モーションの再生終了コールバックを登録 - motion->SetFinishedMotionHandler(onFinishedMotionHandler); - } // 優先度を設定してモーションを始める return _motionManager->StartMotionPriority(motion, autoDelete, priority); diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.hpp index 92da8c7a..32310ce6 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/CubismUserModelExtend.hpp @@ -93,10 +93,9 @@ class CubismUserModelExtend : * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 - * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority); /** * @brief 解放 diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.cpp index 2ca324cc..3b3c147c 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.cpp @@ -37,6 +37,11 @@ namespace LAppDefine { // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = "SampleShaders/"; + // シェーダー本体 + const csmChar* ShaderName = "SpriteEffect.fx"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.hpp index 6bf1bb8f..ed50fc41 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDefine.hpp @@ -35,6 +35,9 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* ShaderName; ///< シェーダー本体 + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.cpp index 0860c4f4..7c611e2e 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.cpp @@ -207,8 +207,6 @@ LAppDelegate::LAppDelegate() , _deviceLostStep(LostStep::LostStep_None) , _lostCounter(0) , _isFullScreen(false) - , _shaderEffect(NULL) - , _vertexFormat(NULL) { _textureManager = new LAppTextureManager(); _view = new LAppView(); @@ -240,102 +238,6 @@ void LAppDelegate::InitializeCubism() _view->InitializeSprite(); } -bool LAppDelegate::CreateShader() -{ - ReleaseShader(); - - static const csmChar* SpriteShaderEffectSrc = - "float4x4 projectMatrix;"\ - "float4 baseColor;"\ - "texture mainTexture;"\ - \ - "sampler mainSampler = sampler_state{"\ - "texture = ;"\ - "};"\ - \ - "struct VS_IN {"\ - "float2 pos : POSITION;"\ - "float2 uv : TEXCOORD0;"\ - "};"\ - "struct VS_OUT {"\ - "float4 Position : POSITION0;"\ - "float2 uv : TEXCOORD0;"\ - "float4 clipPosition : TEXCOORD1;"\ - "};"\ - \ - "/* Vertex Shader */"\ - "/* normal */"\ - "VS_OUT VertNormal(VS_IN In) {"\ - "VS_OUT Out = (VS_OUT)0;"\ - "Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ - "Out.uv.x = In.uv.x;"\ - "Out.uv.y = 1.0 - +In.uv.y;"\ - "return Out;"\ - "}"\ - \ - "/* Pixel Shader */"\ - "/* normal */"\ - "float4 PixelNormal(VS_OUT In) : COLOR0{"\ - "float4 color = tex2D(mainSampler, In.uv) * baseColor;"\ - "return color;"\ - "}"\ - \ - "/* Technique */"\ - "technique ShaderNames_Normal {"\ - "pass p0{"\ - "VertexShader = compile vs_2_0 VertNormal();"\ - "PixelShader = compile ps_2_0 PixelNormal();"\ - "}"\ - "}"; - - ID3DXBuffer* error = 0; - if (FAILED(D3DXCreateEffect(_device, SpriteShaderEffectSrc, static_cast(strlen(SpriteShaderEffectSrc)), 0, 0, 0, 0, &_shaderEffect, &error))) - { - LAppPal::PrintLogLn("Cannot load the shaders"); - return false; - } - - // この描画で使用する頂点フォーマット - D3DVERTEXELEMENT9 elems[] = { - { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - { 0, sizeof(float) * 2, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, - D3DDECL_END() - }; - if (_device->CreateVertexDeclaration(elems, &_vertexFormat)) - { - LAppPal::PrintLogLn("CreateVertexDeclaration failed"); - CSM_ASSERT(0); - } - - return true; -} - -ID3DXEffect* LAppDelegate::SetupShader() -{ - if(_device==NULL || _vertexFormat==NULL || _shaderEffect==NULL) - { - return NULL; - } - - _device->SetVertexDeclaration(_vertexFormat); - return _shaderEffect; -} - -void LAppDelegate::ReleaseShader() -{ - if(_vertexFormat) - { - _vertexFormat->Release(); - _vertexFormat = NULL; - } - if(_shaderEffect) - { - _shaderEffect->Release(); - _shaderEffect = NULL; - } -} - - void LAppDelegate::StartFrame() { /* @@ -368,13 +270,6 @@ void LAppDelegate::StartFrame() void LAppDelegate::EndFrame() { - // テクスチャの参照を外しておく - if (_shaderEffect) - { - _shaderEffect->SetTexture("mainTexture", NULL); - _shaderEffect->CommitChanges(); - } - if (_device) { //シーンの終了 diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.hpp index c6ed3c9e..25640fca 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppDelegate.hpp @@ -103,22 +103,6 @@ class LAppDelegate */ void EndFrame(); - /** - * @brief スプライト描画用シェーダの作成と頂点宣言の作成を行う - */ - bool CreateShader(); - - /** - * @brief スプライト描画時、頂点宣言をセットするとともにシェーダエフェクトを返す - */ - ID3DXEffect* SetupShader(); - - /** - * @brief CreateShaderで確保したオブジェクトの開放 - */ - void ReleaseShader(); - - private: enum LostStep @@ -173,7 +157,4 @@ class LAppDelegate bool _isFullScreen; ///< フルスクリーン中か D3DPRESENT_PARAMETERS _presentParameters; ///< プレゼントパラメータ D3DPRESENT_PARAMETERS _presentParametersFull; ///< プレゼントパラメータ フルスクリーン - - ID3DXEffect* _shaderEffect; ///< スプライト描画用シェーダ - IDirect3DVertexDeclaration9* _vertexFormat; ///< スプライト描画用型宣言 }; diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppLive2DManager.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppLive2DManager.cpp index 81df6e49..52c806ce 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppLive2DManager.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppLive2DManager.cpp @@ -24,6 +24,11 @@ using namespace LAppDefine; namespace { LAppLive2DManager* s_instance = NULL; + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion began: %x", self); + } + void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -78,6 +83,7 @@ LAppLive2DManager::~LAppLive2DManager() } } _releaseModel.Clear(); + _modelDir.Clear(); delete _viewMatrix; CubismFramework::Dispose(); @@ -106,30 +112,43 @@ void LAppLive2DManager::SetUpModel() { // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 + // 一部文字が受け取れないためワイド文字で受け取ってUTF8に変換し格納する。 + csmString crawlPath(ResourcesPath); crawlPath += "*.*"; - struct _finddata_t fdata; - intptr_t fh = _findfirst(crawlPath.GetRawString(), &fdata); - if (fh == -1) return; + wchar_t wideStr[MAX_PATH]; + csmChar name[MAX_PATH]; + LAppPal::ConvertMultiByteToWide(crawlPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata; + intptr_t fh = _wfindfirst(wideStr, &fdata); + if (fh == -1) + { + return; + } _modelDir.Clear(); - while (_findnext(fh, &fdata) == 0) + while (_wfindnext(fh, &fdata) == 0) { - if ((fdata.attrib & _A_SUBDIR) && strcmp(fdata.name, "..") != 0) + if ((fdata.attrib & _A_SUBDIR) && wcscmp(fdata.name, L"..") != 0) { + LAppPal::ConvertWideToMultiByte(fdata.name, name, MAX_PATH); + // フォルダと同名の.model3.jsonがあるか探索する csmString model3jsonPath(ResourcesPath); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath.Append(1, '/'); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath += ".model3.json"; - struct _finddata_t fdata2; - if (_findfirst(model3jsonPath.GetRawString(), &fdata2) != -1) + LAppPal::ConvertMultiByteToWide(model3jsonPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata2; + if (_wfindfirst(wideStr, &fdata2) != -1) { - _modelDir.PushBack(csmString(fdata.name)); + _modelDir.PushBack(csmString(name)); } } } @@ -189,7 +208,7 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) { LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); } - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -304,7 +323,7 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); // 別レンダリング先を選択した際の背景クリア色 - float clearColor[3] = { 1.0f, 1.0f, 1.0f }; + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]); } } diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.cpp index ea840395..b47e37ad 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.cpp @@ -290,21 +290,10 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -457,7 +446,7 @@ void LAppModel::Update() } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -487,21 +476,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -510,6 +488,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -529,7 +508,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -538,7 +517,7 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -595,7 +574,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.hpp index 24e969c9..8ef42dbd 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppModel.hpp @@ -67,9 +67,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -77,9 +78,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.cpp index ab9dc715..c60bf1de 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.cpp @@ -20,6 +20,7 @@ namespace { LARGE_INTEGER s_frequency; LARGE_INTEGER s_lastFrame; double s_deltaTime = 0.0; + const csmUint32 LogMessageLength = 256; } void LAppPal::StartTimer() @@ -29,12 +30,12 @@ void LAppPal::StartTimer() csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { - //filePath;// - const char* path = filePath.c_str(); + wchar_t wideStr[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0U, filePath.c_str(), -1, wideStr, MAX_PATH); int size = 0; - struct stat statBuf; - if (stat(path, &statBuf) == 0) + struct _stat statBuf; + if (_wstat(wideStr, &statBuf) == 0) { size = statBuf.st_size; @@ -42,7 +43,7 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat succeeded but file size is zero. path:%s", path); + PrintLogLn("Stat succeeded but file size is zero. path:%s", filePath.c_str()); } return NULL; } @@ -51,27 +52,33 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat failed. errno:%d path:%s", errno, path); + PrintLogLn("Stat failed. errno:%d path:%s", errno, filePath.c_str()); } return NULL; } - std::fstream file; - file.open(path, std::ios::in | std::ios::binary); + std::wfstream file; + file.open(wideStr, std::ios::in | std::ios::binary); if (!file.is_open()) { if (DebugLogEnable) { - PrintLogLn("File open failed. path:%s", path); + PrintLogLn("File open failed. path:%s", filePath.c_str()); } return NULL; } - char* buf = new char[size]; - file.read(buf, size); - file.close(); + // ファイル名はワイド文字で探しているがファイルの中身はutf-8なので、1バイトずつ取得する。 *outSize = size; + csmChar* buf = new char[*outSize]; + std::wfilebuf* fileBuf = file.rdbuf(); + for (csmUint32 i = 0; i < *outSize; i++) + { + buf[i] = fileBuf->sbumpc(); + } + file.close(); + return reinterpret_cast(buf); } @@ -107,53 +114,46 @@ void LAppPal::UpdateTime() void LAppPal::PrintLog(const char* format, ...) { va_list args; - char buf[256]; + char multiByteBuf[LogMessageLength]; + wchar_t wideBuf[LogMessageLength]; va_start(args, format); - _vsnprintf_s(buf, sizeof(buf), format, args); - OutputDebugStringA((LPCSTR)buf); + _vsnprintf_s(multiByteBuf, sizeof(multiByteBuf), format, args); + ConvertMultiByteToWide(multiByteBuf, wideBuf, sizeof(wideBuf)); + OutputDebugStringW(wideBuf); va_end(args); } void LAppPal::PrintLogLn(const char* format, ...) { va_list args; - char buf[256]; + char multiByteBuf[LogMessageLength]; + wchar_t wideBuf[LogMessageLength]; va_start(args, format); - _vsnprintf_s(buf, sizeof(buf), format, args); - OutputDebugStringA((LPCSTR)buf); - OutputDebugStringA("\n"); // 改行を別途付与します + _vsnprintf_s(multiByteBuf, sizeof(multiByteBuf), format, args); + ConvertMultiByteToWide(multiByteBuf, wideBuf, sizeof(wideBuf)); + OutputDebugStringW(wideBuf); + OutputDebugStringW(L"\n"); // 改行を別途付与します va_end(args); } -void LAppPal::PrintLogW(const wchar_t* format, ...) +void LAppPal::PrintMessage(const csmChar* message) { - va_list args; - wchar_t buf[256]; - va_start(args, format); - _vsnwprintf_s(buf, sizeof(buf), format, args); - OutputDebugString((LPCSTR)buf); - va_end(args); + PrintLog("%s", message); } -void LAppPal::PrintLogLnW(const wchar_t* format, ...) +void LAppPal::PrintMessageLn(const csmChar* message) { - va_list args; - wchar_t buf[256]; - va_start(args, format); - _vsnwprintf_s(buf, sizeof(buf), format, args); - OutputDebugString((LPCSTR)buf); - OutputDebugString("\n"); // 改行を別途付与します - va_end(args); + PrintLogLn("%s", message); } -void LAppPal::PrintMessage(const csmChar* message) +bool LAppPal::ConvertMultiByteToWide(const csmChar* multiByte, wchar_t* wide, int wideSize) { - PrintLog("%s", message); + return MultiByteToWideChar(CP_UTF8, 0U, multiByte, -1, wide, wideSize) != 0; } -void LAppPal::PrintMessageLn(const csmChar* message) +bool LAppPal::ConvertWideToMultiByte(const wchar_t* wide, csmChar* multiByte, int multiByteSize) { - PrintLogLn("%s", message); + return WideCharToMultiByte(CP_UTF8, 0U, wide, -1, multiByte, multiByteSize, NULL, NULL) != 0; } void LAppPal::CoordinateFullScreenToWindow(float clientWidth, float clientHeight, float fullScreenX, float fullScreenY, float& retWindowX, float& retWindowY) diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.hpp index 9afa6915..7e436b7f 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppPal.hpp @@ -85,28 +85,6 @@ class LAppPal */ static void PrintLogLn(const char*, ...); - /** - * @brief ログを出力する wchar版 - * - * ログを出力する - * - * @param[in] format 書式付文字列 - * @param[in] ... (可変長引数)文字列 - * - */ - static void PrintLogW(const wchar_t*, ...); - - /** - * @brief ログを出力し最後に改行する wchar版 - * - * ログを出力し最後に改行する - * - * @param[in] format 書式付文字列 - * @param[in] ... (可変長引数)文字列 - * - */ - static void PrintLogLnW(const wchar_t*, ...); - /** * @brief メッセージを出力する * @@ -127,6 +105,24 @@ class LAppPal */ static void PrintMessageLn(const Csm::csmChar* message); + /** + * @brief マルチバイト文字からワイド文字に変換する + * + * @param[in] multiByte 変換元 + * @param[in] wide 格納先 + * @param[in] wideSize 格納先の大きさ + */ + static bool ConvertMultiByteToWide(const Csm::csmChar* multiByte, wchar_t* wide, int wideSize); + + /** + * @brief ワイド文字からマルチバイト文字に変換する + * + * @param[in] wide 変換元 + * @param[in] multiByte 格納先 + * @param[in] multiByteSize 格納先の大きさ + */ + static bool ConvertWideToMultiByte(const wchar_t* wide, Csm::csmChar* multiByte, int multiByteSize); + /** * @brief 座標変換 * フルスクリーン LT(-bufferX, bufferY) RB(bufferX, -bufferY) → ウィンドウ・マウス LT(0, 0) RB(bufferX, bufferY) diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.cpp index 7ea9c1f8..b83f65ab 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.cpp @@ -16,15 +16,17 @@ using namespace LAppDefine; LAppSprite::LAppSprite() : _rect(), _vertexStore(NULL), - _indexStore(NULL) + _indexStore(NULL), + _shader(NULL) { _color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); } -LAppSprite::LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId) +LAppSprite::LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, LAppSpriteShader* shader) : _rect(), _vertexStore(NULL), - _indexStore(NULL) + _indexStore(NULL), + _shader(shader) { _rect.left = (x - width * 0.5f); _rect.right = (x + width * 0.5f); @@ -71,9 +73,10 @@ LAppSprite::~LAppSprite() } _indexStore = NULL; _vertexStore = NULL; + _shader = NULL; } -void LAppSprite::RenderImmidiate(LPDIRECT3DDEVICE9 device, ID3DXEffect* shaderEffect, int maxWidth, int maxHeight, LPDIRECT3DTEXTURE9 texture) const +void LAppSprite::RenderImmidiate(LPDIRECT3DDEVICE9 device, int maxWidth, int maxHeight, LPDIRECT3DTEXTURE9 texture) const { if (!_vertexStore) { @@ -85,7 +88,7 @@ void LAppSprite::RenderImmidiate(LPDIRECT3DDEVICE9 device, ID3DXEffect* shaderEf return; // この際は描画できず } - if (shaderEffect == NULL) + if (device == NULL || _shader == NULL) { return; } @@ -97,13 +100,6 @@ void LAppSprite::RenderImmidiate(LPDIRECT3DDEVICE9 device, ID3DXEffect* shaderEf _vertexStore[3].x = (_rect.right - maxWidth * 0.5f) / (maxWidth * 0.5f); _vertexStore[3].y = (_rect.up - maxHeight * 0.5f) / (maxHeight * 0.5f); _vertexStore[3].u = 1.0f; _vertexStore[3].v = 1.0f; { - D3DXMATRIX proj( - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); - // レンダーステート device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); @@ -112,27 +108,14 @@ void LAppSprite::RenderImmidiate(LPDIRECT3DDEVICE9 device, ID3DXEffect* shaderEf device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, false); device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - - UINT numPass = 0; - shaderEffect->SetTechnique("ShaderNames_Normal"); - - // numPassには指定のtechnique内に含まれるpassの数が返る - shaderEffect->Begin(&numPass, 0); - shaderEffect->BeginPass(0); - - shaderEffect->SetMatrix("projectMatrix", &proj); - - shaderEffect->SetVector("baseColor", &_color); - - shaderEffect->SetTexture("mainTexture", texture); - - shaderEffect->CommitChanges(); + // シェーダー準備 + _shader->SetShader(device, texture, _color); // 描画 device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, VERTEX_NUM, 2, _indexStore, D3DFMT_INDEX16, _vertexStore, sizeof(SpriteVertex)); - shaderEffect->EndPass(); - shaderEffect->End(); + // シェーダー後処理 + _shader->UnsetShader(); } } diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.hpp index 63e3d40c..58314fcd 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSprite.hpp @@ -12,6 +12,8 @@ #include #include +#include "LAppSpriteShader.hpp" + /** * @brief スプライトを実装するクラス。 * @@ -53,8 +55,9 @@ class LAppSprite * @param[in] width 横幅 * @param[in] height 高さ * @param[in] textureId テクスチャID + * @param[in] shader シェーダー操作クラス */ - LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId); + LAppSprite(float x, float y, float width, float height, Csm::csmUint64 textureId, LAppSpriteShader* shader); /** * @brief デストラクタ @@ -70,12 +73,11 @@ class LAppSprite /** * @brief テクスチャを指定しての描画 * @param[in] device D3D9デバイス - * @param[in] shaderEffect シェーダーエフェクト * @param[in] width 幅 * @param[in] height 高さ * @param[in] texture 使用テクスチャ */ - void RenderImmidiate(LPDIRECT3DDEVICE9 device, ID3DXEffect* shaderEffect, int maxWidth, int maxHeight, LPDIRECT3DTEXTURE9 texture) const; + void RenderImmidiate(LPDIRECT3DDEVICE9 device, int maxWidth, int maxHeight, LPDIRECT3DTEXTURE9 texture) const; /** * @brief ヒットチェック @@ -109,4 +111,6 @@ class LAppSprite SpriteVertex* _vertexStore; ///< 頂点をストアしておく領域 Live2D::Cubism::Framework::csmUint16* _indexStore; ///< インデックスをストアしておく領域 D3DXVECTOR4 _color; ///< 描画色 + + LAppSpriteShader* _shader; ///< シェーダー }; diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSpriteShader.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSpriteShader.cpp new file mode 100644 index 00000000..80ec16a5 --- /dev/null +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSpriteShader.cpp @@ -0,0 +1,128 @@ +/** + * 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. + */ + +#include "LAppSpriteShader.hpp" + +#include +#include +#include "LAppDefine.hpp" +#include "LAppDelegate.hpp" +#include "LAppPal.hpp" + +LAppSpriteShader::LAppSpriteShader() + : _shaderEffect(nullptr) + , _vertexFormat(nullptr) +{ + CreateShader(); +} + +LAppSpriteShader::~LAppSpriteShader() +{ + ReleaseShader(); +} + +bool LAppSpriteShader::CreateShader() +{ + LPDIRECT3DDEVICE9 device = LAppDelegate::GetInstance()->GetD3dDevice(); + ReleaseShader(); + + // ファイル読み込み + const char* shaderCode; + Csm::csmSizeInt shaderSize; + { + // シェーダーのパスの作成 + Csm::csmString shaderFileName(LAppDefine::ShaderPath); + shaderFileName += LAppDefine::ShaderName; + + // ファイル読み込み + shaderCode = reinterpret_cast(LAppPal::LoadFileAsBytes(shaderFileName.GetRawString(), &shaderSize)); + } + + // シェーダー作成 + ID3DXBuffer* error = 0; + HRESULT result = S_OK; + do + { + // エフェクト作成 + if (FAILED(result = D3DXCreateEffect(device, shaderCode, shaderSize, 0, 0, 0, 0, &_shaderEffect, &error))) + { + LAppPal::PrintLog("Cannot load the shaders"); + break; + } + + // この描画で使用する頂点フォーマット + D3DVERTEXELEMENT9 elems[] = { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, sizeof(float) * 2, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + D3DDECL_END() + }; + if (FAILED(result = device->CreateVertexDeclaration(elems, &_vertexFormat))) + { + LAppPal::PrintLog("CreateVertexDeclaration failed"); + break; + } + } while(0); + + if (FAILED(result)) { + return false; + } + + return true; +} + +void LAppSpriteShader::ReleaseShader() +{ + if (_vertexFormat) + { + _vertexFormat->Release(); + _vertexFormat = nullptr; + } + + if (_shaderEffect) + { + _shaderEffect->Release(); + _shaderEffect = nullptr; + } +} + +void LAppSpriteShader::SetShader(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 texture, D3DXVECTOR4 color) +{ + D3DXMATRIX proj( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 頂点フォーマット + device->SetVertexDeclaration(_vertexFormat); + + _shaderEffect->SetTechnique("ShaderNames_Normal"); + + // numPassには指定のtechnique内に含まれるpassの数が返る + UINT numPass = 0; + _shaderEffect->Begin(&numPass, 0); + _shaderEffect->BeginPass(0); + + _shaderEffect->SetMatrix("projectMatrix", &proj); + + _shaderEffect->SetVector("baseColor", &color); + + _shaderEffect->SetTexture("mainTexture", texture); + + _shaderEffect->CommitChanges(); +} + +void LAppSpriteShader::UnsetShader() +{ + _shaderEffect->EndPass(); + + _shaderEffect->SetTexture("mainTexture", NULL); + _shaderEffect->CommitChanges(); + + _shaderEffect->End(); +} diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSpriteShader.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSpriteShader.hpp new file mode 100644 index 00000000..f305024a --- /dev/null +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppSpriteShader.hpp @@ -0,0 +1,56 @@ +/** + * 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. + */ + +#pragma once + +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用のシェーダー設定を保持するクラス。 +*/ +class LAppSpriteShader +{ +public: + + /** + * @brief コンストラクタ + */ + LAppSpriteShader(); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーの作成を行う + */ + bool CreateShader(); + + /** + * @brief シェーダーの解放を行う + */ + void ReleaseShader(); + + /** + * @brief スプライトの描画直前に呼び出される + * シェーダーのセットを行う + */ + void SetShader(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 texture, D3DXVECTOR4 color); + + /** + * @brief スプライトの描画後に呼び出される + * シェーダーの後処理を行う + */ + void UnsetShader(); + +private: + + ID3DXEffect* _shaderEffect; ///< スプライト描画用シェーダ + IDirect3DVertexDeclaration9* _vertexFormat; ///< スプライト描画用型宣言 +}; diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppTextureManager.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppTextureManager.cpp index eb096515..a628440a 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppTextureManager.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppTextureManager.cpp @@ -29,6 +29,11 @@ LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile(st { LPDIRECT3DDEVICE9 device = LAppDelegate::GetD3dDevice(); + // wcharに変換 + const int WCHAR_LENGTH = 512; + wchar_t wchrStr[WCHAR_LENGTH] = L""; + LAppPal::ConvertMultiByteToWide(fileName.c_str(), wchrStr, sizeof(wchrStr)); + IDirect3DTexture9* texture = NULL; LAppTextureManager::TextureInfo* textureInfo = NULL; @@ -43,7 +48,7 @@ LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile(st // Lockする場合は立てる DWORD usage = isPreMult ? D3DUSAGE_DYNAMIC : 0; - if (SUCCEEDED(D3DXCreateTextureFromFileExA(device, fileName.c_str(), width, height, + if (SUCCEEDED(D3DXCreateTextureFromFileExW(device, wchrStr, width, height, mipLevel, // 「この値が 0 または D3DX_DEFAULT の場合は、完全なミップマップ チェーンが作成される。」 usage, D3DFMT_A8R8G8B8, diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.cpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.cpp index c8148b5c..a7c5d2e2 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.cpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.cpp @@ -8,6 +8,7 @@ #include "LAppView.hpp" #include #include +#include #include "LAppPal.hpp" #include "LAppDelegate.hpp" #include "LAppLive2DManager.hpp" @@ -25,7 +26,8 @@ LAppView::LAppView(): _gear(NULL), _power(NULL), _renderSprite(NULL), - _renderTarget(SelectTarget_None) + _renderTarget(SelectTarget_None), + _shader(NULL) { _clearColor[0] = 1.0f; _clearColor[1] = 1.0f; @@ -119,12 +121,6 @@ void LAppView::Render() return; } - ID3DXEffect* shaderEffect = LAppDelegate::GetInstance()->SetupShader(); - if (!shaderEffect) - { - return; - } - // スプライト描画 int width, height; LAppDelegate::GetInstance()->GetClientSize(width, height); @@ -134,17 +130,17 @@ void LAppView::Render() if (_back) { textureManager->GetTexture(_back->GetTextureId(), texture); - _back->RenderImmidiate(device, shaderEffect, width, height, texture); + _back->RenderImmidiate(device, width, height, texture); } if (_gear) { textureManager->GetTexture(_gear->GetTextureId(), texture); - _gear->RenderImmidiate(device, shaderEffect, width, height, texture); + _gear->RenderImmidiate(device, width, height, texture); } if (_power) { textureManager->GetTexture(_power->GetTextureId(), texture); - _power->RenderImmidiate(device, shaderEffect, width, height, texture); + _power->RenderImmidiate(device, width, height, texture); } } @@ -164,7 +160,7 @@ void LAppView::Render() if (model) { - _renderSprite->RenderImmidiate(device, shaderEffect, width, height, model->GetRenderBuffer().GetTexture()); + _renderSprite->RenderImmidiate(device, width, height, model->GetRenderBuffer().GetTexture()); } } } @@ -172,6 +168,9 @@ void LAppView::Render() void LAppView::InitializeSprite() { + // シェーダ作成 + _shader = new LAppSpriteShader(); + int width, height; LAppDelegate::GetInstance()->GetClientSize(width, height); @@ -186,7 +185,7 @@ void LAppView::InitializeSprite() float y = height * 0.5f; float fWidth = static_cast(backgroundTexture->width * 2.0f); float fHeight = static_cast(height * 0.95f); - _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _shader); imageName = GearImageName; LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName, false, @@ -196,7 +195,7 @@ void LAppView::InitializeSprite() y = static_cast(height - gearTexture->height * 0.5f); fWidth = static_cast(gearTexture->width); fHeight = static_cast(gearTexture->height); - _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _shader); imageName = PowerImageName; LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName, false, @@ -206,15 +205,12 @@ void LAppView::InitializeSprite() y = static_cast(powerTexture->height * 0.5f); fWidth = static_cast(powerTexture->width); fHeight = static_cast(powerTexture->height); - _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _shader); // 画面全体を覆うサイズ x = width * 0.5f; y = height * 0.5f; - _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0); - - // シェーダ作成 - LAppDelegate::GetInstance()->CreateShader(); + _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, _shader); } void LAppView::ReleaseSprite() @@ -228,13 +224,6 @@ void LAppView::ReleaseSprite() delete _renderSprite; _renderSprite = NULL; - if (_power) - { - textureManager->ReleaseTexture(_power->GetTextureId()); - } - delete _power; - _power = NULL; - if (_gear) { textureManager->ReleaseTexture(_gear->GetTextureId()); @@ -242,6 +231,13 @@ void LAppView::ReleaseSprite() delete _gear; _gear = NULL; + if (_power) + { + textureManager->ReleaseTexture(_power->GetTextureId()); + } + delete _power; + _power = NULL; + if (_back) { textureManager->ReleaseTexture(_back->GetTextureId()); @@ -250,7 +246,12 @@ void LAppView::ReleaseSprite() _back = NULL; // スプライト用のシェーダ・頂点宣言も開放 - LAppDelegate::GetInstance()->ReleaseShader(); + if (_shader) + { + _shader->ReleaseShader(); + } + delete _shader; + _shader = NULL; } void LAppView::OnDeviceLost() @@ -379,15 +380,13 @@ void LAppView::PostModelDraw(LAppModel &refModel) // LAppViewの持つフレームバッファを使うなら、スプライトへの描画はここ if (_renderTarget == SelectTarget_ViewFrameBuffer && _renderSprite) { - ID3DXEffect* shaderEffect = LAppDelegate::GetInstance()->SetupShader(); - // スプライト描画 int width, height; LAppDelegate::GetInstance()->GetClientSize(width, height); _renderSprite->SetColor(1.0f, 1.0f, 1.0f, GetSpriteAlpha(0)); _renderSprite->RenderImmidiate(LAppDelegate::GetInstance()->GetD3dDevice(), - shaderEffect, width, height, useTarget->GetTexture()); + width, height, useTarget->GetTexture()); } } } diff --git a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.hpp b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.hpp index 360d2453..88b67b21 100644 --- a/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.hpp +++ b/Samples/D3D9/Demo/proj.d3d9.cmake/src/LAppView.hpp @@ -11,6 +11,7 @@ #include #include #include "CubismFramework.hpp" +#include "LAppSpriteShader.hpp" class TouchManager; class LAppSprite; @@ -186,4 +187,5 @@ class LAppView SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + LAppSpriteShader* _shader; ///< スプライト用のシェーダー準備クラス }; diff --git a/Samples/D3D9/Shaders/SpriteEffect.fx b/Samples/D3D9/Shaders/SpriteEffect.fx new file mode 100644 index 00000000..919e6610 --- /dev/null +++ b/Samples/D3D9/Shaders/SpriteEffect.fx @@ -0,0 +1,51 @@ +/** + * 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. + */ + +float4x4 projectMatrix; +float4 baseColor; +texture mainTexture; + +// サンプリング +sampler mainSampler = sampler_state{ + texture = ; +}; + +// 頂点シェーダーの入力定義 +struct VS_IN { + float2 pos : POSITION; + float2 uv : TEXCOORD0; +}; + +// 頂点シェーダーの出力定義 +struct VS_OUT { + float4 Position : POSITION0; + float2 uv : TEXCOORD0; + float4 clipPosition : TEXCOORD1; +}; + +// 頂点シェーダー +VS_OUT VertNormal(VS_IN In) { + VS_OUT Out = (VS_OUT)0; + Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix); + Out.uv.x = In.uv.x; + Out.uv.y = 1.0 - +In.uv.y; + return Out; +} + +// ピクセルシェーダー +float4 PixelNormal(VS_OUT In) : COLOR0{ + float4 color = tex2D(mainSampler, In.uv) * baseColor; + return color; +} + +// テクニックとパス +technique ShaderNames_Normal { + pass p0{ + VertexShader = compile vs_2_0 VertNormal(); + PixelShader = compile ps_2_0 PixelNormal(); + } +} diff --git a/Samples/Metal/Demo/proj.ios.cmake/CMakeLists.txt b/Samples/Metal/Demo/proj.ios.cmake/CMakeLists.txt index dcb7c70a..78d3b2c6 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/CMakeLists.txt +++ b/Samples/Metal/Demo/proj.ios.cmake/CMakeLists.txt @@ -9,6 +9,7 @@ set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) set(THIRD_PARTY_PATH ${SDK_ROOT_PATH}/Samples/Metal/thirdParty) set(STB_PATH ${THIRD_PARTY_PATH}/stb) set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SHADER_PATH ${SDK_ROOT_PATH}/Samples/Metal/Shaders) # Set project. project(${APP_NAME}) @@ -135,7 +136,7 @@ if(CSM_MAC_CATALYST) ) else() set_xcode_property(${APP_NAME} - PRODUCT_BUNDLE_IDENTIFIER "com.live2d.demo-4-r7" "All" + PRODUCT_BUNDLE_IDENTIFIER "com.live2d.demo-5-r.2" "All" ) endif() set_xcode_property(${APP_NAME} TARGETED_DEVICE_FAMILY "1,2" "All") diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/CMakeLists.txt b/Samples/Metal/Demo/proj.ios.cmake/src/CMakeLists.txt index c59c775f..e7877127 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/CMakeLists.txt +++ b/Samples/Metal/Demo/proj.ios.cmake/src/CMakeLists.txt @@ -25,11 +25,18 @@ target_sources(${APP_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/MetalUIView.m ${CMAKE_CURRENT_SOURCE_DIR}/MetalView.h ${CMAKE_CURRENT_SOURCE_DIR}/MetalView.m + ${CMAKE_CURRENT_SOURCE_DIR}/Shaders ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../Framework/src/Rendering/Metal/MetalShaders.metal ) +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/Shaders PROPERTIES MACOSX_PACKAGE_LOCATION Shaders) + +set(RESOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/Shaders + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../Framework/src/Rendering/Metal/MetalShaders.metal) + set_target_properties(${APP_NAME} PROPERTIES MACOSX_BUNDLE TRUE MACOSX_FRAMEWORK_IDENTIFIER org.cmake.ExecutableTarget - RESOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../Framework/src/Rendering/Metal/MetalShaders.metal + RESOURCE "${RESOURCE_FILES}" ) diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/Info.plist b/Samples/Metal/Demo/proj.ios.cmake/src/Info.plist index 1e49ff2b..d5aa643b 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/Info.plist +++ b/Samples/Metal/Demo/proj.ios.cmake/src/Info.plist @@ -35,12 +35,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationLandscapeLeft - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.h b/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.h index ceef8019..c8c1fccc 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.h +++ b/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.h @@ -38,6 +38,9 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* ShaderName; ///< シェーダー本体 + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.mm b/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.mm index 5cb2a2a1..ee190e4f 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.mm +++ b/Samples/Metal/Demo/proj.ios.cmake/src/LAppDefine.mm @@ -41,6 +41,11 @@ // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = "Shaders/"; + // シェーダー本体 + const csmChar* ShaderName = "SpriteEffect.metal"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/LAppLive2DManager.mm b/Samples/Metal/Demo/proj.ios.cmake/src/LAppLive2DManager.mm index 656333a4..b2f992cc 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/LAppLive2DManager.mm +++ b/Samples/Metal/Demo/proj.ios.cmake/src/LAppLive2DManager.mm @@ -27,6 +27,11 @@ @implementation LAppLive2DManager static LAppLive2DManager* s_instance = nil; +void BeganMotion(Csm::ACubismMotion* self) +{ + LAppPal::PrintLogLn("Motion began: %x", self); +} + void FinishedMotion(Csm::ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -198,7 +203,7 @@ - (void)onTap:(Csm::csmFloat32)x floatY:(Csm::csmFloat32)y; { LAppPal::PrintLogLn("[APP]hit area: [%s]", LAppDefine::HitAreaNameBody); } - _models[i]->StartRandomMotion(LAppDefine::MotionGroupTapBody, LAppDefine::PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(LAppDefine::MotionGroupTapBody, LAppDefine::PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -207,8 +212,11 @@ - (void)onUpdate:(id )commandBuffer currentDrawable:(id)commandBuffer currentDrawable:(idSetMTLPixelFormat(MTLPixelFormatBGRA8Unorm); _renderBuffer->SetClearColor(0.0, 0.0, 0.0, 0.0); - _renderBuffer->CreateOffscreenSurface(width, height, nil); + _renderBuffer->CreateOffscreenSurface(static_cast(width), static_cast(height), nil); if (_renderTarget == SelectTarget_ViewFrameBuffer) { @@ -388,9 +396,9 @@ - (void)changeScene:(Csm::csmInt32)index; _models[1]->GetModelMatrix()->TranslateX(0.2f); #endif - float clearColorR = 1.0f; - float clearColorG = 1.0f; - float clearColorB = 1.0f; + float clearColorR = 0.0f; + float clearColorG = 0.0f; + float clearColorB = 0.0f; AppDelegate* delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate]; ViewController* view = [delegate viewController]; diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.h b/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.h index d698e90d..89ba6e64 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.h +++ b/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.h @@ -65,9 +65,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -75,9 +76,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.mm b/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.mm index 702278af..20a1d6e3 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.mm +++ b/Samples/Metal/Demo/proj.ios.cmake/src/LAppModel.mm @@ -300,21 +300,10 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -452,7 +441,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -482,21 +471,10 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, NULL, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -505,6 +483,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -523,7 +502,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -532,7 +511,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -588,7 +567,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/LAppSprite.mm b/Samples/Metal/Demo/proj.ios.cmake/src/LAppSprite.mm index 0684703c..141220fd 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/LAppSprite.mm +++ b/Samples/Metal/Demo/proj.ios.cmake/src/LAppSprite.mm @@ -7,6 +7,8 @@ #import "LAppSprite.h" #import +#import "LAppDefine.h" +#import "LAppPal.h" #import #import #import "Rendering/Metal/CubismRenderingInstanceSingleton_Metal.h" @@ -138,43 +140,6 @@ - (void)SetColor:(float)r g:(float)g b:(float)b a:(float)a _spriteColorA = a; } -- (NSString*)GetMetalShader { - NSString *string = - @"#include \n" - "using namespace metal;\n" - "\n" - "struct ColorInOut\n" - "{\n" - " float4 position [[ position ]];\n" - " float2 texCoords;\n" - "};\n" - "\n" - "struct BaseColor\n" - "{\n" - " float4 color;\n" - "};\n" - "\n" - "vertex ColorInOut vertexShader(constant float4 *positions [[ buffer(0) ]],\n" - " constant float2 *texCoords [[ buffer(1) ]],\n" - " uint vid [[ vertex_id ]])\n" - "{\n" - " ColorInOut out;\n" - " out.position = positions[vid];\n" - " out.texCoords = texCoords[vid];\n" - " return out;\n" - "}\n" - "\n" - "fragment float4 fragmentShader(ColorInOut in [[ stage_in ]],\n" - " texture2d texture [[ texture(0) ]],\n" - " constant BaseColor &uniform [[ buffer(2) ]])\n" - "{\n" - " constexpr sampler colorSampler;\n" - " float4 color = texture.sample(colorSampler, in.texCoords) * uniform.color;\n" - " return color;\n" - "}\n"; - return string; -} - - (void)SetMTLBuffer:(id )device MaxWidth:(float)maxWidth MaxHeight:(float)maxHeight { vector_float4 positionVertex[] = @@ -205,7 +170,14 @@ - (void)SetMTLFunction:(id )device { MTLCompileOptions* compileOptions = [MTLCompileOptions new]; compileOptions.languageVersion = MTLLanguageVersion2_1; - NSString* shader = [self GetMetalShader]; + + // シェーダをファイルから読みこみ + unsigned int size; + Csm::csmString shaderFilePath(LAppDefine::ShaderPath); + shaderFilePath += LAppDefine::ShaderName; + unsigned char* shaderRawString = LAppPal::LoadFileAsBytes(shaderFilePath.GetRawString(), &size); + NSString* shader = [NSString stringWithUTF8String:(char *)shaderRawString]; + NSError* compileError; id shaderLib = [device newLibraryWithSource:shader options:compileOptions error:&compileError]; if (!shaderLib) diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/LAppTextureManager.mm b/Samples/Metal/Demo/proj.ios.cmake/src/LAppTextureManager.mm index 5bda0d97..213949ec 100644 --- a/Samples/Metal/Demo/proj.ios.cmake/src/LAppTextureManager.mm +++ b/Samples/Metal/Demo/proj.ios.cmake/src/LAppTextureManager.mm @@ -96,7 +96,6 @@ - (TextureInfo*) createTextureFromPngFile:(std::string)fileName int widthLevels = ceil(log2(width)); int heightLevels = ceil(log2(height)); int mipCount = (heightLevels > widthLevels) ? heightLevels : widthLevels; - textureDescriptor.mipmapLevelCount = mipCount; CubismRenderingInstanceSingleton_Metal *single = [CubismRenderingInstanceSingleton_Metal sharedManager]; diff --git a/Samples/Metal/Demo/proj.ios.cmake/src/Shaders/SpriteEffect.metal b/Samples/Metal/Demo/proj.ios.cmake/src/Shaders/SpriteEffect.metal new file mode 100644 index 00000000..30489f00 --- /dev/null +++ b/Samples/Metal/Demo/proj.ios.cmake/src/Shaders/SpriteEffect.metal @@ -0,0 +1,33 @@ +#include + +using namespace metal; + +struct ColorInOut +{ +float4 position [[ position ]]; +float2 texCoords; +}; + +struct BaseColor +{ + float4 color; +}; + +vertex ColorInOut vertexShader(constant float4 *positions [[ buffer(0) ]], + constant float2 *texCoords [[ buffer(1) ]], + uint vid [[ vertex_id ]]) +{ + ColorInOut out; + out.position = positions[vid]; + out.texCoords = texCoords[vid]; + return out; +} + +fragment float4 fragmentShader(ColorInOut in [[ stage_in ]], + texture2d texture [[ texture(0) ]], + constant BaseColor &uniform [[ buffer(2) ]]) +{ + constexpr sampler colorSampler; + float4 color = texture.sample(colorSampler, in.texCoords) * uniform.color; + return color; +} diff --git a/Samples/Metal/README.ja.md b/Samples/Metal/README.ja.md index 30fccce0..911e04b3 100644 --- a/Samples/Metal/README.ja.md +++ b/Samples/Metal/README.ja.md @@ -12,8 +12,8 @@ Metal で実装したアプリケーションのサンプル実装です。 | サードパーティ | バージョン | | --- | --- | -| [ios-cmake] | 4.4.1 | -| [stb_image.h] | 2.29 | +| [ios-cmake] | 4.5.0 | +| [stb_image.h] | 2.30 | その他の開発環境・動作確認環境はトップディレクトリにある [README.md](/README.ja.md) を参照してください。 diff --git a/Samples/Metal/README.md b/Samples/Metal/README.md index 76b394f3..0b343ddb 100644 --- a/Samples/Metal/README.md +++ b/Samples/Metal/README.md @@ -12,8 +12,8 @@ There are restrictions. Please check [NOTICE.md](/NOTICE.md) in the top director | Third Party | Version | | --- | --- | -| [ios-cmake] | 4.4.1 | -| [stb_image.h] | 2.29 | +| [ios-cmake] | 4.5.0 | +| [stb_image.h] | 2.30 | For other development environments and operation environments, see [README.md](/README.md) in the top directory. diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/build.gradle b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/build.gradle index 23752cd3..0b3e87c3 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/build.gradle +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/build.gradle @@ -19,6 +19,7 @@ android { abiFilters.addAll(PROP_APP_ABI.split(':').collect{ it as String }) } } + ndkVersion "26.3.11579264" } signingConfigs { debug { @@ -29,8 +30,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } buildTypes { release { @@ -46,6 +47,7 @@ android { } sourceSets.main { assets.srcDir "../../../../../Resources" + assets.srcDir "../../../../Shaders/StandardES" } } diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/AndroidManifest.xml b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/AndroidManifest.xml index 820452eb..6a16cdb9 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/AndroidManifest.xml +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/AndroidManifest.xml @@ -13,7 +13,7 @@ diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/CMakeLists.txt b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/CMakeLists.txt index 727a91bb..3b88c5cb 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${APP_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.cpp index ac352ea6..1dba01dd 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.cpp @@ -37,6 +37,13 @@ namespace LAppDefine { // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = ""; + // 頂点シェーダー + const csmChar* VertShaderName = "VertSprite.vert"; + // フラグメントシェーダー + const csmChar* FragShaderName = "FragSprite.frag"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.hpp index c8b7eb61..6beb3072 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDefine.hpp @@ -36,6 +36,10 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* VertShaderName; ///< 頂点シェーダー + extern const csmChar* FragShaderName; ///< フラグメントシェーダー + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.cpp index 77327f09..78811d55 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.cpp @@ -13,8 +13,11 @@ #include "LAppDefine.hpp" #include "LAppLive2DManager.hpp" #include "LAppTextureManager.hpp" +#include "LAppModel.hpp" #include "JniBridgeC.hpp" +#include + using namespace Csm; using namespace std; using namespace LAppDefine; @@ -46,14 +49,11 @@ void LAppDelegate::ReleaseInstance() void LAppDelegate::OnStart() { - _textureManager = new LAppTextureManager(); - _view = new LAppView(); - LAppPal::UpdateTime(); + _isActive = true; } void LAppDelegate::OnPause() { - _SceneIndex = LAppLive2DManager::GetInstance()->GetSceneIndex(); } void LAppDelegate::OnStop() @@ -112,10 +112,36 @@ void LAppDelegate::OnSurfaceCreate() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (_textureManager == nullptr) + { + _textureManager = new LAppTextureManager(); + } + else + { + // 無効になっているOpenGLリソースを破棄 + _textureManager->ReleaseInvalidTextures(); + } + if (_view != NULL) + { + delete _view; + } + _view = new LAppView(); + LAppPal::UpdateTime(); + //Initialize cubism - CubismFramework::Initialize(); + if (!CubismFramework::IsInitialized()) + { + CubismFramework::Initialize(); + } - _view->InitializeShader(); + // 無効になっているOpenGLリソースを破棄 + Live2D::Cubism::Framework::Rendering::CubismShader_OpenGLES2::GetInstance()->ReleaseInvalidShaderProgram(); + + LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance(); + for (Csm::csmUint32 i = 0; i < live2DManager->GetModelNum(); i++) + { + live2DManager->GetModel(i)->ReloadRenderer(); + } } void LAppDelegate::OnSurfaceChanged(float width, float height) @@ -124,17 +150,15 @@ void LAppDelegate::OnSurfaceChanged(float width, float height) _width = width; _height = height; - //AppViewの初期化 + // AppViewの初期化 _view->Initialize(); + // Spriteの初期化 _view->InitializeSprite(); +} - //load model - if (LAppLive2DManager::GetInstance()->GetSceneIndex() != _SceneIndex) - { - LAppLive2DManager::GetInstance()->ChangeScene(_SceneIndex); - } - - _isActive = true; +void LAppDelegate::SetSceneIndex(int index) +{ + _SceneIndex = index; } LAppDelegate::LAppDelegate(): @@ -192,46 +216,3 @@ void LAppDelegate::OnTouchMoved(double x, double y) _view->OnTouchesMoved(_mouseX, _mouseY); } } - -GLuint LAppDelegate::CreateShader() -{ - //バーテックスシェーダのコンパイル - GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - const char* vertexShader = - "#version 100\n" - "attribute vec3 position;" - "attribute vec2 uv;" - "varying vec2 vuv;" - "void main(void){" - " gl_Position = vec4(position, 1.0);" - " vuv = uv;" - "}"; - glShaderSource(vertexShaderId, 1, &vertexShader, NULL); - glCompileShader(vertexShaderId); - - //フラグメントシェーダのコンパイル - GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragmentShader = - "#version 100\n" - "precision mediump float;" - "varying vec2 vuv;" - "uniform sampler2D texture;" - "uniform vec4 baseColor;" - "void main(void){" - " gl_FragColor = texture2D(texture, vuv) * baseColor;" - "}"; - glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL); - glCompileShader(fragmentShaderId); - - //プログラムオブジェクトの作成 - GLuint programId = glCreateProgram(); - glAttachShader(programId, vertexShaderId); - glAttachShader(programId, fragmentShaderId); - - // リンク - glLinkProgram(programId); - - glUseProgram(programId); - - return programId; -} diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.hpp index 5bd4aa46..5f3469e0 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppDelegate.hpp @@ -96,11 +96,6 @@ class LAppDelegate */ void OnTouchMoved(double x, double y); - /** - * @brief シェーダーを登録する。 - */ - GLuint CreateShader(); - /** * @brief テクスチャマネージャーの取得 */ @@ -126,6 +121,16 @@ class LAppDelegate */ LAppView* GetView() { return _view; } + /** + * @brief シーンインデックスを設定する + */ + void SetSceneIndex(int index); + + /** + * @brief シーンインデックスを取得する + */ + int GetSceneIndex() { return _SceneIndex; }; + private: /** * @brief コンストラクタ @@ -137,11 +142,6 @@ class LAppDelegate */ ~LAppDelegate(); - /** - * @brief Cubism SDK の初期化 - */ - void InitializeCubism(); - LAppAllocator _cubismAllocator; ///< Cubism SDK Allocator Csm::CubismFramework::Option _cubismOption; ///< Cubism SDK Option LAppTextureManager* _textureManager; ///< テクスチャマネージャー diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.cpp index 429f4f1e..cc6d3f14 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.cpp @@ -23,6 +23,11 @@ using namespace LAppDefine; namespace { LAppLive2DManager* s_instance = NULL; + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion Began: %x", self); + } + void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -57,12 +62,11 @@ void LAppLive2DManager::ReleaseInstance() LAppLive2DManager::LAppLive2DManager() : _viewMatrix(NULL) - , _sceneIndex(0) { _viewMatrix = new CubismMatrix44(); SetUpModel(); - ChangeScene(_sceneIndex); + ChangeScene(LAppDelegate::GetInstance()->GetSceneIndex()); } LAppLive2DManager::~LAppLive2DManager() @@ -146,7 +150,7 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) { LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); } - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -198,16 +202,16 @@ void LAppLive2DManager::OnUpdate() const void LAppLive2DManager::NextScene() { - csmInt32 no = (_sceneIndex + 1) % _modelDir.GetSize(); + csmInt32 no = (LAppDelegate::GetInstance()->GetSceneIndex() + 1) % _modelDir.GetSize(); ChangeScene(no); } void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) { - _sceneIndex = index; + LAppDelegate::GetInstance()->SetSceneIndex(index); if (DebugLogEnable) { - LAppPal::PrintLogLn("[APP]model index: %d", _sceneIndex); + LAppPal::PrintLogLn("[APP]model index: %d", index); } // model3.jsonのパスを決定する. @@ -248,7 +252,7 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); // 別レンダリング先を選択した際の背景クリア色 - float clearColor[3] = { 1.0f, 1.0f, 1.0f }; + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]); } } diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.hpp index b6921446..58e3b0f0 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppLive2DManager.hpp @@ -91,12 +91,6 @@ class LAppLive2DManager */ void ChangeScene(Csm::csmInt32 index); - /** - * @brief シーンインデックスの取得 - * @return シーンインデックスを返す - */ - Csm::csmInt32 GetSceneIndex() { return _sceneIndex; } - /** * @brief モデル個数を得る * @return 所持モデル個数 @@ -121,7 +115,6 @@ class LAppLive2DManager Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列 Csm::csmVector _models; ///< モデルインスタンスのコンテナ - Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値 Csm::csmVector _modelDir; ///< モデルディレクトリ名のコンテナ }; diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.cpp index ab659ba6..442bd6dd 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.cpp @@ -276,21 +276,10 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -438,7 +427,7 @@ void LAppModel::Update() } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -468,21 +457,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -491,6 +469,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -509,7 +488,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -518,7 +497,7 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -574,7 +553,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.hpp index 036cf30a..01809a5e 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppModel.hpp @@ -64,9 +64,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -74,9 +75,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppSpriteShader.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppSpriteShader.cpp new file mode 100644 index 00000000..d0ed5c40 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppSpriteShader.cpp @@ -0,0 +1,106 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppSpriteShader.hpp" +#include +#include "LAppDefine.hpp" +#include "LAppPal.hpp" + +LAppSpriteShader::LAppSpriteShader() +{ + _programId = CreateShader(); +} + +LAppSpriteShader::~LAppSpriteShader() +{ + glDeleteShader(_programId); +} + +GLuint LAppSpriteShader::GetShaderId() const +{ + return _programId; +} + +GLuint LAppSpriteShader::CreateShader() +{ + // シェーダーのパスの作成 + Csm::csmString vertShaderFile(LAppDefine::ShaderPath); + vertShaderFile += LAppDefine::VertShaderName; + Csm::csmString fragShaderFile(LAppDefine::ShaderPath); + fragShaderFile += LAppDefine::FragShaderName; + + // シェーダーのコンパイル + GLuint vertexShaderId = CompileShader(vertShaderFile, GL_VERTEX_SHADER); + GLuint fragmentShaderId = CompileShader(fragShaderFile, GL_FRAGMENT_SHADER); + + if (!vertexShaderId || !fragmentShaderId) + { + return 0; + } + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + // 不要になったシェーダーオブジェクトの削除 + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); + + return programId; +} + +bool LAppSpriteShader::CheckShader(GLuint shaderId) +{ + GLint status; + GLint logLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) + { + GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); + glGetShaderInfoLog(shaderId, logLength, &logLength, log); + CubismLogError("Shader compile log: %s", log); + CSM_FREE(log); + } + + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + glDeleteShader(shaderId); + return false; + } + + return true; +} + +GLuint LAppSpriteShader::CompileShader(Csm::csmString filename, GLenum shaderType) +{ + // ファイル読み込み + Csm::csmSizeInt bufferSize = 0; + const char* shaderString = reinterpret_cast(LAppPal::LoadFileAsBytes(filename.GetRawString(), &bufferSize)); + const GLint glSize = (GLint)bufferSize; + + // コンパイル + GLuint shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, 1, &shaderString, &glSize); + glCompileShader(shaderId); + + // 読み込んだシェーダー文字列の開放 + LAppPal::ReleaseBytes(reinterpret_cast(const_cast(shaderString))); + + if (!CheckShader(shaderId)) + { + return 0; + } + + return shaderId; +} diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppSpriteShader.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppSpriteShader.hpp new file mode 100644 index 00000000..8c229efd --- /dev/null +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppSpriteShader.hpp @@ -0,0 +1,57 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用のシェーダー設定を保持するクラス +*/ +class LAppSpriteShader +{ +public: + /** + * @brief コンストラクタ + */ + LAppSpriteShader(); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーIDを取得する + */ + GLuint GetShaderId() const; + +private: + /** + * @brief シェーダーを作成する。 + */ + GLuint CreateShader(); + + /** + * @brief CreateShader内部関数 エラーチェック + */ + bool CheckShader(GLuint shaderId); + + /** + * @brief シェーダーをコンパイルする + * コンパイルに失敗した場合には 0 が戻る。 + * + * @param[in] filename シェーダーファイル名 + * @param[in] shaderType 作成するシェーダーの種類 + */ + GLuint CompileShader(Csm::csmString filename, GLenum shaderType); + + GLuint _programId; ///< シェーダID +}; diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.cpp index edd758c8..5a12855c 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.cpp @@ -89,6 +89,17 @@ LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile(st } void LAppTextureManager::ReleaseTextures() +{ + for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) + { + glDeleteTextures(1, &(_textures[i]->id)); + delete _textures[i]; + } + + _textures.Clear(); +} + +void LAppTextureManager::ReleaseInvalidTextures() { for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) { @@ -106,6 +117,7 @@ void LAppTextureManager::ReleaseTexture(Csm::csmUint32 textureId) { continue; } + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; @@ -118,6 +130,7 @@ void LAppTextureManager::ReleaseTexture(std::string fileName) { if (_textures[i]->fileName == fileName) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.hpp index 1f86f055..38d1c5a3 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppTextureManager.hpp @@ -79,6 +79,12 @@ class LAppTextureManager */ void ReleaseTextures(); + /** + * @brief 一部の環境でこのインスタンスが管理するリソースが破棄される場合があります。 + * このような場合に二重解放を避け無効になったリソースを破棄します。 + */ + void ReleaseInvalidTextures(); + /** * @brief 画像の解放 * diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.cpp index 9e8bcac8..767c4f9f 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.cpp @@ -15,6 +15,7 @@ #include "LAppDefine.hpp" #include "TouchManager.hpp" #include "LAppSprite.hpp" +#include "LAppSpriteShader.hpp" #include "LAppModel.hpp" #include @@ -26,11 +27,11 @@ using namespace std; using namespace LAppDefine; LAppView::LAppView(): - _programId(0), _back(NULL), _gear(NULL), _power(NULL), _changeModel(false), + _spriteShader(NULL), _renderSprite(NULL), _renderTarget(SelectTarget_None) { @@ -52,14 +53,38 @@ LAppView::LAppView(): LAppView::~LAppView() { _renderBuffer.DestroyOffscreenSurface(); - delete _renderSprite; - - delete _viewMatrix; - delete _deviceToScreen; - delete _touchManager; - delete _back; - delete _gear; - delete _power; + if (_renderSprite) + { + delete _renderSprite; + } + if (_spriteShader) + { + delete _spriteShader; + } + if (_viewMatrix) + { + delete _viewMatrix; + } + if (_deviceToScreen) + { + delete _deviceToScreen; + } + if (_touchManager) + { + delete _touchManager; + } + if (_back) + { + delete _back; + } + if (_gear) + { + delete _gear; + } + if (_power) + { + delete _power; + } } void LAppView::Initialize() @@ -101,15 +126,14 @@ void LAppView::Initialize() ViewLogicalMaxBottom, ViewLogicalMaxTop ); -} -void LAppView::InitializeShader() -{ - _programId = LAppDelegate::GetInstance()->CreateShader(); + _spriteShader = new LAppSpriteShader(); } void LAppView::InitializeSprite() { + GLuint programId = _spriteShader->GetShaderId(); + int width = LAppDelegate::GetInstance()->GetWindowWidth(); int height = LAppDelegate::GetInstance()->GetWindowHeight(); @@ -126,7 +150,7 @@ void LAppView::InitializeSprite() if(_back == NULL) { - _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _programId); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId); } else { @@ -144,7 +168,7 @@ void LAppView::InitializeSprite() if(_gear == NULL) { - _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _programId); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId); } else { @@ -161,7 +185,7 @@ void LAppView::InitializeSprite() if(_power == NULL) { - _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _programId); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId); } else { @@ -174,7 +198,7 @@ void LAppView::InitializeSprite() if (_renderSprite == NULL) { - _renderSprite = new LAppSprite(x, y, width, height, 0, _programId); + _renderSprite = new LAppSprite(x, y, width, height, 0, programId); } else { diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.hpp index db0f8abd..e239e7fb 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/cpp/LAppView.hpp @@ -16,6 +16,7 @@ class TouchManager; class LAppSprite; +class LAppSpriteShader; class LAppModel; /** @@ -55,11 +56,6 @@ class LAppView */ void Render(); - /** - * @brief シェーダーの初期化を行う。 - */ - void InitializeShader(); - /** * @brief 画像の初期化を行う。 */ @@ -150,7 +146,6 @@ class LAppView TouchManager* _touchManager; ///< タッチマネージャー Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix - GLuint _programId; ///< シェーダID LAppSprite* _back; ///< 背景画像 LAppSprite* _gear; ///< ギア画像 LAppSprite* _power; ///< 電源画像 @@ -161,4 +156,6 @@ class LAppView Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + LAppSpriteShader* _spriteShader; ///< シェーダー作成委譲クラス }; diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/java/com/live2d/demo/MainActivity.java b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/java/com/live2d/demo/MainActivity.java index 6b4210be..5aa12baa 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/java/com/live2d/demo/MainActivity.java +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/app/src/main/java/com/live2d/demo/MainActivity.java @@ -18,20 +18,29 @@ public class MainActivity extends Activity { @Override - public boolean onTouchEvent(MotionEvent event) { - float pointX = event.getX(); - float pointY = event.getY(); - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - JniBridgeJava.nativeOnTouchesBegan(pointX, pointY); - break; - case MotionEvent.ACTION_UP: - JniBridgeJava.nativeOnTouchesEnded(pointX, pointY); - break; - case MotionEvent.ACTION_MOVE: - JniBridgeJava.nativeOnTouchesMoved(pointX, pointY); - break; - } + public boolean onTouchEvent(final MotionEvent event) { + final float pointX = event.getX(); + final float pointY = event.getY(); + + // GLSurfaceViewのイベント処理キューにタッチイベントを追加する。 + glSurfaceView.queueEvent( + new Runnable() { + @Override + public void run() { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + JniBridgeJava.nativeOnTouchesBegan(pointX, pointY); + break; + case MotionEvent.ACTION_UP: + JniBridgeJava.nativeOnTouchesEnded(pointX, pointY); + break; + case MotionEvent.ACTION_MOVE: + JniBridgeJava.nativeOnTouchesMoved(pointX, pointY); + break; + } + } + } + ); return super.onTouchEvent(event); } diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/build.gradle b/Samples/OpenGL/Demo/proj.android.cmake/Full/build.gradle index eaafae84..7faf18cb 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/build.gradle +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.1.1' + classpath 'com.android.tools.build:gradle:8.6.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle.properties b/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle.properties index 90aa5318..11e79526 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle.properties +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle.properties @@ -19,17 +19,17 @@ android.useAndroidX=true android.enableJetifier=true # Android SDK version that will be used as the compile project -PROP_COMPILE_SDK_VERSION=34 +PROP_COMPILE_SDK_VERSION=35 # Android SDK version that will be used as the earliest version of android this application can run on PROP_MIN_SDK_VERSION=21 # Android SDK version that will be used as the latest version of android this application has been tested on -PROP_TARGET_SDK_VERSION=34 +PROP_TARGET_SDK_VERSION=35 # List of CPU Archtexture to build that application with -# Available architextures (armeabi-v7a | arm64-v8a | x86 | x86_64) +# Available architextures (arm64-v8a | x86 | x86_64) # To build for multiple architexture, use the `:` between them -# Example - PROP_APP_ABI=armeabi-v7a:arm64-v8a:x86:x86_64 -PROP_APP_ABI=armeabi-v7a:arm64-v8a:x86:x86_64 +# Example - PROP_APP_ABI=arm64-v8a:x86:x86_64 +PROP_APP_ABI=arm64-v8a:x86:x86_64 diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle/wrapper/gradle-wrapper.properties b/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle/wrapper/gradle-wrapper.properties index 316ef137..a986c5d0 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle/wrapper/gradle-wrapper.properties +++ b/Samples/OpenGL/Demo/proj.android.cmake/Full/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Jul 11 17:01:27 JST 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/build.gradle b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/build.gradle index b5d25161..af10e795 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/build.gradle +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/build.gradle @@ -18,6 +18,7 @@ android { abiFilters.addAll(PROP_APP_ABI.split(':').collect{ it as String }) } } + ndkVersion "26.3.11579264" } signingConfigs { debug { @@ -28,8 +29,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } buildTypes { release { @@ -45,6 +46,7 @@ android { } sourceSets.main { assets.srcDir "../../../../../Resources" + assets.srcDir "../../../../Shaders/StandardES" } } diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/AndroidManifest.xml b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/AndroidManifest.xml index f80b7661..9fc7ded9 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/AndroidManifest.xml +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/AndroidManifest.xml @@ -13,7 +13,7 @@ diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/CMakeLists.txt b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/CMakeLists.txt index 97df1e5d..1c616897 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${APP_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppMinimumView.cpp diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.cpp index 9fad5af1..559a32c5 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.cpp @@ -37,6 +37,13 @@ namespace LAppDefine { // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = ""; + // 頂点シェーダー + const csmChar* VertShaderName = "VertSprite.vert"; + // フラグメントシェーダー + const csmChar* FragShaderName = "FragSprite.frag"; + // モデル定義------------------------------------------ // モデルを配置したディレクトリ名の配列 // ディレクトリ名とmodel3.jsonの名前を一致させておくこと diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.hpp index cfc214c6..0605e5bb 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppDefine.hpp @@ -36,6 +36,10 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* VertShaderName; ///< 頂点シェーダー + extern const csmChar* FragShaderName; ///< フラグメントシェーダー + // モデル定義-------------------------------------------- extern const csmChar* ModelDir[]; ///< モデルを配置したディレクトリ名の配列. ディレクトリ名とmodel3.jsonの名前を一致させておく. extern const csmInt32 ModelDirSize; ///< モデルディレクトリ配列のサイズ diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.cpp index 0e40270f..d4b36c78 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.cpp @@ -114,8 +114,6 @@ void LAppMinimumDelegate::OnSurfaceCreate() //Initialize cubism CubismFramework::Initialize(); - - _view->InitializeShader(); } void LAppMinimumDelegate::OnSurfaceChanged(float width, float height) @@ -191,46 +189,3 @@ void LAppMinimumDelegate::OnTouchMoved(double x, double y) _view->OnTouchesMoved(_mouseX, _mouseY); } } - -GLuint LAppMinimumDelegate::CreateShader() -{ - //バーテックスシェーダのコンパイル - GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - const char* vertexShader = - "#version 100\n" - "attribute vec3 position;" - "attribute vec2 uv;" - "varying vec2 vuv;" - "void main(void){" - " gl_Position = vec4(position, 1.0);" - " vuv = uv;" - "}"; - glShaderSource(vertexShaderId, 1, &vertexShader, nullptr); - glCompileShader(vertexShaderId); - - //フラグメントシェーダのコンパイル - GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragmentShader = - "#version 100\n" - "precision mediump float;" - "varying vec2 vuv;" - "uniform sampler2D texture;" - "uniform vec4 baseColor;" - "void main(void){" - " gl_FragColor = texture2D(texture, vuv) * baseColor;" - "}"; - glShaderSource(fragmentShaderId, 1, &fragmentShader, nullptr); - glCompileShader(fragmentShaderId); - - //プログラムオブジェクトの作成 - GLuint programId = glCreateProgram(); - glAttachShader(programId, vertexShaderId); - glAttachShader(programId, fragmentShaderId); - - // リンク - glLinkProgram(programId); - - glUseProgram(programId); - - return programId; -} diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.hpp index 4d323b6e..3ba0700b 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumDelegate.hpp @@ -96,11 +96,6 @@ class LAppMinimumDelegate */ void OnTouchMoved(double x, double y); - /** - * @brief シェーダーを登録する。 - */ - GLuint CreateShader(); - /** * @brief テクスチャマネージャーの取得 */ diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.cpp index 9c1a25fd..78e3e33c 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.cpp @@ -210,22 +210,10 @@ void LAppMinimumModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelJson, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } - if (_motions[name] != NULL) { ACubismMotion::Delete(_motions[name]); @@ -361,7 +349,7 @@ void LAppMinimumModel::Update() } -CubismMotionQueueEntryHandle LAppMinimumModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppMinimumModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority) { if (priority == PriorityForce) { @@ -391,30 +379,15 @@ CubismMotionQueueEntryHandle LAppMinimumModel::StartMotion(const csmChar* group, csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, nullptr, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, nullptr, NULL, NULL, _modelJson, group, no)); if (motion) { - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } autoDelete = true; // 終了時にメモリから削除 } DeleteBuffer(buffer, path.GetRawString()); } - else - { - motion->SetFinishedMotionHandler(onFinishedMotionHandler); - } //voice csmString voice = _modelJson->GetMotionSoundFileName(group, no); @@ -454,7 +427,7 @@ void LAppMinimumModel::SetExpression(const csmChar* expressionID) if (motion) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.hpp index 97211c3b..fc85ff79 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumModel.hpp @@ -76,10 +76,9 @@ class LAppMinimumModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 - * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.cpp index 65369207..25f1784a 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.cpp @@ -15,6 +15,7 @@ #include "LAppMinimumLive2DManager.hpp" #include "TouchManager.hpp" #include "LAppSprite.hpp" +#include "LAppSpriteShader.hpp" #include "LAppMinimumModel.hpp" #include @@ -27,7 +28,6 @@ using namespace LAppDefine; using namespace Csm; LAppMinimumView::LAppMinimumView(): - _programId(0), _renderSprite(nullptr), _renderTarget(SelectTarget_None) { @@ -49,6 +49,7 @@ LAppMinimumView::LAppMinimumView(): LAppMinimumView::~LAppMinimumView() { _renderBuffer.DestroyOffscreenSurface(); + delete _spriteShader; delete _renderSprite; delete _viewMatrix; @@ -95,15 +96,14 @@ void LAppMinimumView::Initialize() ViewLogicalMaxBottom, ViewLogicalMaxTop ); -} -void LAppMinimumView::InitializeShader() -{ - _programId = LAppMinimumDelegate::GetInstance()->CreateShader(); + // シェーダー作成委譲クラス + _spriteShader = new LAppSpriteShader(); } void LAppMinimumView::InitializeSprite() { + GLuint programId = _spriteShader->GetShaderId(); int width = LAppMinimumDelegate::GetInstance()->GetWindowWidth(); int height = LAppMinimumDelegate::GetInstance()->GetWindowHeight(); @@ -113,7 +113,7 @@ void LAppMinimumView::InitializeSprite() if (!_renderSprite) { - _renderSprite = new LAppSprite(x, y, width, height, 0, _programId); + _renderSprite = new LAppSprite(x, y, width, height, 0, programId); } else { diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.hpp index d3d7d522..4c4e42be 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.hpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppMinimumView.hpp @@ -16,6 +16,7 @@ class TouchManager; class LAppSprite; +class LAppSpriteShader; class LAppMinimumModel; /** @@ -55,11 +56,6 @@ class LAppMinimumView */ void Render(); - /** - * @brief シェーダーの初期化を行う。 - */ - void InitializeShader(); - /** * @brief 画像の初期化を行う。 */ @@ -150,11 +146,12 @@ class LAppMinimumView TouchManager* _touchManager; ///< タッチマネージャー Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix - GLuint _programId; ///< シェーダID // レンダリング先を別ターゲットにする方式の場合に使用 LAppSprite* _renderSprite; ///< モードによっては_renderBufferのテクスチャを描画 Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + LAppSpriteShader* _spriteShader; ///< シェーダー作成委譲クラス }; diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppSpriteShader.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppSpriteShader.cpp new file mode 100644 index 00000000..30515236 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppSpriteShader.cpp @@ -0,0 +1,73 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppSpriteShader.hpp" + +#include "LAppDefine.hpp" +#include "LAppPal.hpp" + +LAppSpriteShader::LAppSpriteShader() +{ + _programId = CreateShader(); +} + +LAppSpriteShader::~LAppSpriteShader() +{ + glDeleteShader(_programId); +} + +GLuint LAppSpriteShader::GetShaderId() const +{ + return _programId; +} + +GLuint LAppSpriteShader::CreateShader() +{ + // シェーダーのパスの作成 + Csm::csmString vertShaderFile(LAppDefine::ShaderPath); + vertShaderFile += LAppDefine::VertShaderName; + Csm::csmString fragShaderFile(LAppDefine::ShaderPath); + fragShaderFile += LAppDefine::FragShaderName; + + // シェーダーのコンパイル + GLuint vertexShaderId = CompileShader(vertShaderFile, GL_VERTEX_SHADER); + GLuint fragmentShaderId = CompileShader(fragShaderFile, GL_FRAGMENT_SHADER); + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + // 不要になったシェーダーオブジェクトの削除 + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); + + return programId; +} + +GLuint LAppSpriteShader::CompileShader(Csm::csmString filename, GLenum shaderType) +{ + // ファイル読み込み + Csm::csmSizeInt bufferSize = 0; + const char* shaderString = reinterpret_cast(LAppPal::LoadFileAsBytes(filename.GetRawString(), &bufferSize)); + const GLint glSize = (GLint)bufferSize; + + // コンパイル + GLuint shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, 1, &shaderString, &glSize); + glCompileShader(shaderId); + + // 読み込んだシェーダー文字列の開放 + LAppPal::ReleaseBytes(reinterpret_cast(const_cast(shaderString))); + + return shaderId; +} diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppSpriteShader.hpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppSpriteShader.hpp new file mode 100644 index 00000000..f62429a1 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppSpriteShader.hpp @@ -0,0 +1,52 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用のシェーダー設定を保持するクラス +*/ +class LAppSpriteShader +{ +public: + /** + * @brief コンストラクタ + */ + LAppSpriteShader(); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーIDを取得する + */ + GLuint GetShaderId() const; + +private: + /** + * @brief シェーダーを作成する。 + */ + GLuint CreateShader(); + + /** + * @brief シェーダーをコンパイルする + * コンパイルに失敗した場合には 0 が戻る。 + * + * @param[in] filename シェーダーファイル名 + * @param[in] shaderType 作成するシェーダーの種類 + */ + GLuint CompileShader(Csm::csmString filename, GLenum shaderType); + + GLuint _programId; ///< シェーダID +}; diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppTextureManager.cpp b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppTextureManager.cpp index edd758c8..699f90b3 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppTextureManager.cpp +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/cpp/LAppTextureManager.cpp @@ -92,6 +92,7 @@ void LAppTextureManager::ReleaseTextures() { for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; } @@ -106,6 +107,7 @@ void LAppTextureManager::ReleaseTexture(Csm::csmUint32 textureId) { continue; } + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; @@ -118,6 +120,7 @@ void LAppTextureManager::ReleaseTexture(std::string fileName) { if (_textures[i]->fileName == fileName) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/java/com/live2d/demo/MainActivity.java b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/java/com/live2d/demo/MainActivity.java index 6b4210be..5aa12baa 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/java/com/live2d/demo/MainActivity.java +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/app/src/main/java/com/live2d/demo/MainActivity.java @@ -18,20 +18,29 @@ public class MainActivity extends Activity { @Override - public boolean onTouchEvent(MotionEvent event) { - float pointX = event.getX(); - float pointY = event.getY(); - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - JniBridgeJava.nativeOnTouchesBegan(pointX, pointY); - break; - case MotionEvent.ACTION_UP: - JniBridgeJava.nativeOnTouchesEnded(pointX, pointY); - break; - case MotionEvent.ACTION_MOVE: - JniBridgeJava.nativeOnTouchesMoved(pointX, pointY); - break; - } + public boolean onTouchEvent(final MotionEvent event) { + final float pointX = event.getX(); + final float pointY = event.getY(); + + // GLSurfaceViewのイベント処理キューにタッチイベントを追加する。 + glSurfaceView.queueEvent( + new Runnable() { + @Override + public void run() { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + JniBridgeJava.nativeOnTouchesBegan(pointX, pointY); + break; + case MotionEvent.ACTION_UP: + JniBridgeJava.nativeOnTouchesEnded(pointX, pointY); + break; + case MotionEvent.ACTION_MOVE: + JniBridgeJava.nativeOnTouchesMoved(pointX, pointY); + break; + } + } + } + ); return super.onTouchEvent(event); } diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/build.gradle b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/build.gradle index 96e098eb..b8dfd496 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/build.gradle +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/build.gradle @@ -10,7 +10,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.1.1' + classpath 'com.android.tools.build:gradle:8.6.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle.properties b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle.properties index 90aa5318..11e79526 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle.properties +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle.properties @@ -19,17 +19,17 @@ android.useAndroidX=true android.enableJetifier=true # Android SDK version that will be used as the compile project -PROP_COMPILE_SDK_VERSION=34 +PROP_COMPILE_SDK_VERSION=35 # Android SDK version that will be used as the earliest version of android this application can run on PROP_MIN_SDK_VERSION=21 # Android SDK version that will be used as the latest version of android this application has been tested on -PROP_TARGET_SDK_VERSION=34 +PROP_TARGET_SDK_VERSION=35 # List of CPU Archtexture to build that application with -# Available architextures (armeabi-v7a | arm64-v8a | x86 | x86_64) +# Available architextures (arm64-v8a | x86 | x86_64) # To build for multiple architexture, use the `:` between them -# Example - PROP_APP_ABI=armeabi-v7a:arm64-v8a:x86:x86_64 -PROP_APP_ABI=armeabi-v7a:arm64-v8a:x86:x86_64 +# Example - PROP_APP_ABI=arm64-v8a:x86:x86_64 +PROP_APP_ABI=arm64-v8a:x86:x86_64 diff --git a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle/wrapper/gradle-wrapper.properties b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle/wrapper/gradle-wrapper.properties index ce869c6f..e910cd6c 100644 --- a/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle/wrapper/gradle-wrapper.properties +++ b/Samples/OpenGL/Demo/proj.android.cmake/Minimum/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Sep 21 19:36:40 JST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/.gitignore b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/.gitignore new file mode 100644 index 00000000..0e158c3f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/.gitignore @@ -0,0 +1,11 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/app.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/app.json5 new file mode 100644 index 00000000..aa42ed1c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.live2d.test", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/resources/base/element/string.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..30e0a078 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Full" + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/resources/base/media/app_icon.png b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/resources/base/media/app_icon.png new file mode 100644 index 00000000..cd45accb Binary files /dev/null and b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/AppScope/resources/base/media/app_icon.png differ diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/build-profile.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/build-profile.json5 new file mode 100644 index 00000000..be8e5fb9 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/build-profile.json5 @@ -0,0 +1,35 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS" + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/.gitignore b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/.gitignore new file mode 100644 index 00000000..36cebc08 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/build-profile.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/build-profile.json5 new file mode 100644 index 00000000..a1fc2d10 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/build-profile.json5 @@ -0,0 +1,19 @@ +{ + "apiType": 'stageMode', + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + } + }, + "targets": [ + { + "name": "default", + "runtimeOS": "HarmonyOS" + }, + { + "name": "ohosTest", + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/hvigorfile.ts b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/hvigorfile.ts new file mode 100644 index 00000000..c6edcd90 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/obfuscation-rules.txt b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/obfuscation-rules.txt new file mode 100644 index 00000000..51021121 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/obfuscation-rules.txt @@ -0,0 +1,18 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/oh-package-lock.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/oh-package-lock.json5 new file mode 100644 index 00000000..bae35e52 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/oh-package-lock.json5 @@ -0,0 +1,18 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "libDemo.so@src/main/cpp/types/libentry": "libDemo.so@src/main/cpp/types/libentry" + }, + "packages": { + "libDemo.so@src/main/cpp/types/libentry": { + "name": "libDemo.so", + "version": "1.0.0", + "resolved": "src/main/cpp/types/libentry", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/oh-package.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/oh-package.json5 new file mode 100644 index 00000000..d54754f6 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libDemo.so": "file:./src/main/cpp/types/libentry" + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/CMakeLists.txt b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 00000000..e0b9bb3b --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,87 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.4.1) + +# Set app name. +set(APP_NAME Demo) +# Set directory paths. +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../../..) +set(CORE_PATH ${SDK_ROOT_PATH}/Core) +set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) +set(THIRD_PARTY_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/thirdParty) +set(STB_PATH ${THIRD_PARTY_PATH}/stb) +set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SHADER_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/Shaders/StandardES) +set(COPY_RES_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../resources/rawfile) + +# Specify version of compiler. +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# The flag is enabled by default, so it needs to be disabled. +add_compile_options(-Wno-error=format-security) + +# Add Cubism Core. +# Import as static library. +add_library(Live2DCubismCore STATIC IMPORTED) +# Find library path. +set_target_properties(Live2DCubismCore + PROPERTIES + IMPORTED_LOCATION + ${CORE_PATH}/lib/harmonyos/${OHOS_ARCH}/libLive2DCubismCore.a + INTERFACE_INCLUDE_DIRECTORIES ${CORE_PATH}/include +) + +# Specify Cubism Framework rendering. +set(FRAMEWORK_SOURCE OpenGL) +# Add Cubism Native Framework. +add_subdirectory(${FRAMEWORK_PATH} ${CMAKE_CURRENT_BINARY_DIR}/Framework) +# Add rendering definition to framework. +target_compile_definitions(Framework PUBLIC CSM_TARGET_HARMONYOS_ES3) + +# Make library for android app. +add_library(${APP_NAME} SHARED) +# Add source files. +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) +# Link libraries to app. +target_link_libraries(${APP_NAME} + Framework + Live2DCubismCore + EGL + GLESv3 + hilog_ndk.z + ace_ndk.z + ace_napi.z + uv + librawfile.z.so +) +# Specify include directories. +target_include_directories(${APP_NAME} PRIVATE ${STB_PATH}) + +# Copy resource directory to build directory. +add_custom_command( + TARGET ${APP_NAME} + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${RES_PATH} ${COPY_RES_PATH}/Resources + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${SHADER_PATH} ${COPY_RES_PATH}/Shader +) + +# +# * USE_RENDER_TARGET +# Renderer draws to target of LAppView. +# * USE_MODEL_RENDER_TARGET +# Renderer draws to target of each LAppModel. +# * default +# Renderer draws to default main framebuffer. +# +# INFO: USE_RENDER_TARGET has higher priority than USE_MODEL_RENDER_TARGET. +# +# target_compile_definitions(${APP_NAME} +# PRIVATE +# USE_RENDER_TARGET +# USE_MODEL_RENDER_TARGET +# ) diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/CMakeLists.txt b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/CMakeLists.txt new file mode 100644 index 00000000..e93af90a --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/CMakeLists.txt @@ -0,0 +1,27 @@ +target_sources(${APP_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/NapiBridgeC.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/NapiBridgeC.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppAllocator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppAllocator.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppModel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppModel.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp +) diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppAllocator.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppAllocator.cpp new file mode 100644 index 00000000..005665b4 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppAllocator.cpp @@ -0,0 +1,54 @@ +/** + * 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. + */ + +#include "LAppAllocator.hpp" + +using namespace Csm; + +void* LAppAllocator::Allocate(const csmSizeType size) +{ + return malloc(size); +} + +void LAppAllocator::Deallocate(void* memory) +{ + free(memory); +} + +void* LAppAllocator::AllocateAligned(const csmSizeType size, const csmUint32 alignment) +{ + size_t offset, shift, alignedAddress; + void* allocation; + void** preamble; + + offset = alignment - 1 + sizeof(void*); + + allocation = Allocate(size + static_cast(offset)); + + alignedAddress = reinterpret_cast(allocation) + sizeof(void*); + + shift = alignedAddress % alignment; + + if (shift) + { + alignedAddress += (alignment - shift); + } + + preamble = reinterpret_cast(alignedAddress); + preamble[-1] = allocation; + + return reinterpret_cast(alignedAddress); +} + +void LAppAllocator::DeallocateAligned(void* alignedMemory) +{ + void** preamble; + + preamble = static_cast(alignedMemory); + + Deallocate(preamble[-1]); +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppAllocator.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppAllocator.hpp new file mode 100644 index 00000000..baada555 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppAllocator.hpp @@ -0,0 +1,52 @@ +/** + * 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. + */ + +#pragma once + +#include +#include + +/** +* @brief メモリアロケーションを実装するクラス。 +* +* メモリ確保・解放処理のインターフェースの実装。 +* フレームワークから呼び出される。 +* +*/ +class LAppAllocator : public Csm::ICubismAllocator +{ + /** + * @brief メモリ領域を割り当てる。 + * + * @param[in] size 割り当てたいサイズ。 + * @return 指定したメモリ領域 + */ + void* Allocate(const Csm::csmSizeType size); + + /** + * @brief メモリ領域を解放する + * + * @param[in] memory 解放するメモリ。 + */ + void Deallocate(void* memory); + + /** + * @brief + * + * @param[in] size 割り当てたいサイズ。 + * @param[in] alignment 割り当てたいサイズ。 + * @return alignedAddress + */ + void* AllocateAligned(const Csm::csmSizeType size, const Csm::csmUint32 alignment); + + /** + * @brief + * + * @param[in] alignedMemory 解放するメモリ。 + */ + void DeallocateAligned(void* alignedMemory); +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDefine.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDefine.cpp new file mode 100644 index 00000000..172ac2f8 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDefine.cpp @@ -0,0 +1,68 @@ +/** + * 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. + */ + +#include "LAppDefine.hpp" +#include + +namespace LAppDefine { + + using namespace Csm; + + // 画面 + const csmFloat32 ViewScale = 1.0f; + const csmFloat32 ViewMaxScale = 2.0f; + const csmFloat32 ViewMinScale = 0.8f; + + const csmFloat32 ViewLogicalLeft = -1.0f; + const csmFloat32 ViewLogicalRight = 1.0f; + const csmFloat32 ViewLogicalBottom = -1.0f; + const csmFloat32 ViewLogicalTop = 1.0f; + + const csmFloat32 ViewLogicalMaxLeft = -2.0f; + const csmFloat32 ViewLogicalMaxRight = 2.0f; + const csmFloat32 ViewLogicalMaxBottom = -2.0f; + const csmFloat32 ViewLogicalMaxTop = 2.0f; + + // 相対パス + const csmChar* ResourcesPath = "Resources/"; + + // モデルの後ろにある背景の画像ファイル + const csmChar* BackImageName = "back_class_normal.png"; + // 歯車 + const csmChar* GearImageName = "icon_gear.png"; + // 終了ボタン + const csmChar* PowerImageName = "close.png"; + + // シェーダー相対パス + const csmChar* ShaderPath = "Shader/"; + // 頂点シェーダー + const csmChar* VertShaderName = "VertSprite.vert"; + // フラグメントシェーダー + const csmChar* FragShaderName = "FragSprite.frag"; + + // モデル定義------------------------------------------ + // 外部定義ファイル(json)と合わせる + const csmChar* MotionGroupIdle = "Idle"; // アイドリング + const csmChar* MotionGroupTapBody = "TapBody"; // 体をタップしたとき + + // 外部定義ファイル(json)と合わせる + const csmChar* HitAreaNameHead = "Head"; + const csmChar* HitAreaNameBody = "Body"; + + // モーションの優先度定数 + const csmInt32 PriorityNone = 0; + const csmInt32 PriorityIdle = 1; + const csmInt32 PriorityNormal = 2; + const csmInt32 PriorityForce = 3; + + // デバッグ用ログの表示オプション + const csmBool DebugLogEnable = true; + const csmBool DebugTouchLogEnable = false; + + // Frameworkから出力するログのレベル設定 + const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Verbose; +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDefine.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDefine.hpp new file mode 100644 index 00000000..fc97dfe3 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDefine.hpp @@ -0,0 +1,64 @@ +/** + * 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. + */ + +#pragma once + +#include + +/** +* @brief Sample Appで使用する定数 +* +*/ +namespace LAppDefine { + + using namespace Csm; + + extern const csmFloat32 ViewScale; ///< 拡大縮小率 + extern const csmFloat32 ViewMaxScale; ///< 拡大縮小率の最大値 + extern const csmFloat32 ViewMinScale; ///< 拡大縮小率の最小値 + + extern const csmFloat32 ViewLogicalLeft; ///< 論理的なビュー座標系の左端の値 + extern const csmFloat32 ViewLogicalRight; ///< 論理的なビュー座標系の右端の値 + extern const csmFloat32 ViewLogicalBottom; ///< 論理的なビュー座標系の下端の値 + extern const csmFloat32 ViewLogicalTop; ///< 論理的なビュー座標系の上端の値 + + extern const csmFloat32 ViewLogicalMaxLeft; ///< 論理的なビュー座標系の左端の最大値 + extern const csmFloat32 ViewLogicalMaxRight; ///< 論理的なビュー座標系の右端の最大値 + extern const csmFloat32 ViewLogicalMaxBottom; ///< 論理的なビュー座標系の下端の最大値 + extern const csmFloat32 ViewLogicalMaxTop; ///< 論理的なビュー座標系の上端の最大値 + + extern const csmChar* ResourcesPath; ///< 素材パス + extern const csmChar* BackImageName; ///< 背景画像ファイル + extern const csmChar* GearImageName; ///< 歯車画像ファイル + extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* VertShaderName; ///< 頂点シェーダー + extern const csmChar* FragShaderName; ///< フラグメントシェーダー + + // モデル定義-------------------------------------------- + // 外部定義ファイル(json)と合わせる + extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト + extern const csmChar* MotionGroupTapBody; ///< 体をタップした時に再生するモーションのリスト + + // 外部定義ファイル(json)と合わせる + extern const csmChar* HitAreaNameHead; ///< 当たり判定の[Head]タグ + extern const csmChar* HitAreaNameBody; ///< 当たり判定の[Body]タグ + + // モーションの優先度定数 + extern const csmInt32 PriorityNone; ///< モーションの優先度定数: 0 + extern const csmInt32 PriorityIdle; ///< モーションの優先度定数: 1 + extern const csmInt32 PriorityNormal; ///< モーションの優先度定数: 2 + extern const csmInt32 PriorityForce; ///< モーションの優先度定数: 3 + + // デバッグ用ログの表示 + extern const csmBool DebugLogEnable; ///< デバッグ用ログ表示の有効・無効 + extern const csmBool DebugTouchLogEnable; ///< タッチ処理のデバッグ用ログ表示の有効・無効 + + // Frameworkから出力するログのレベル設定 + extern const CubismFramework::Option::LogLevel CubismLoggingLevel; +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDelegate.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDelegate.cpp new file mode 100644 index 00000000..95634504 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDelegate.cpp @@ -0,0 +1,244 @@ +/** + * 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. + */ + +#include "LAppDelegate.hpp" +#include +#include "LAppView.hpp" +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "LAppLive2DManager.hpp" +#include "LAppTextureManager.hpp" +#include "NapiBridgeC.hpp" + +using namespace Csm; +using namespace std; +using namespace LAppDefine; + +namespace { + LAppDelegate* s_instance = NULL; +} + +LAppDelegate* LAppDelegate::GetInstance() +{ + if (s_instance == NULL) + { + s_instance = new LAppDelegate(); + } + + return s_instance; +} + +void LAppDelegate::ReleaseInstance() +{ + if (s_instance != NULL) + { + delete s_instance; + } + + s_instance = NULL; +} + + +void LAppDelegate::Run() +{ + // 時間更新 + LAppPal::UpdateTime(); + + // 画面の初期化 + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearDepthf(1.0f); + + //描画更新 + if (_view != NULL) + { + _view->Render(); + } + eglSwapBuffers(_eglDisplay, _eglSurface); + + if(!_isActive) + { + NapiBridgeC::MoveTaskToBack(); + _isActive = true; + } +} + +void LAppDelegate::InitializeEgl() +{ + csmInt32 configAttribs[] = + { + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + EGLint winAttribs[] = + { + EGL_GL_COLORSPACE_KHR, + EGL_GL_COLORSPACE_SRGB_KHR, + EGL_NONE + }; + EGLint contextAttribs[] = + { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + csmInt32 configsNum; + + if (!_eglWindow) + { + LAppPal::PrintLogLn("Failed because `window` is null."); + return; + } + _eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(_eglDisplay, nullptr, nullptr)) + { + LAppPal::PrintLogLn("Failed to initialize `_eglDisplay`."); + _eglDisplay = EGL_NO_DISPLAY; + return; + } + + if (!eglChooseConfig(_eglDisplay, configAttribs, &_eglConfig, 1, &configsNum)) + { + LAppPal::PrintLogLn("`eglChooseConfig` error."); + return; + } + + _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig, _eglWindow, winAttribs); + if (!_eglSurface) + { + LAppPal::PrintLogLn("`_eglSurface` is null."); + return; + } + + _eglContext = eglCreateContext(_eglDisplay, _eglConfig, _eglSharedContext, contextAttribs); + if (!eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext)) + { + LAppPal::PrintLogLn("`eglMakeCurrent` error = %d", eglGetError()); + return; + } + + LAppPal::PrintLogLn("Successful initialization of EGL."); +} + +void LAppDelegate::ReleaseEgl() +{ + if (!eglDestroySurface(_eglDisplay, _eglSurface)) + { + LAppPal::PrintLogLn("`eglDestroySurface` failed."); + } + + if (!eglDestroyContext(_eglDisplay, _eglContext)) + { + LAppPal::PrintLogLn("`eglDestroyContext` failed."); + } + + if (!eglTerminate(_eglDisplay)) + { + LAppPal::PrintLogLn("`eglTerminate` failed."); + } + + _eglSurface = nullptr; + _eglContext = EGL_NO_CONTEXT; + _eglDisplay = EGL_NO_DISPLAY; + + LAppPal::PrintLogLn("Successful delete of EGL."); +} + +void LAppDelegate::InitializeDisplay() +{ + _textureManager = new LAppTextureManager(); + _view = new LAppView(); + LAppPal::UpdateTime(); + + //テクスチャサンプリング設定 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + //透過設定 + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + //Initialize cubism + CubismFramework::Initialize(); +} + +void LAppDelegate::ChangeDisplay(float width, float height) +{ + glViewport(0, 0, width, height); + _width = width; + _height = height; + + //AppViewの初期化 + _view->Initialize(); + _view->InitializeSprite(); +} + +LAppDelegate::LAppDelegate(): + _cubismOption(), + _captured(false), + _mouseX(0.0f), + _mouseY(0.0f), + _isActive(true), + _textureManager(NULL), + _view(NULL), + _eglDisplay(EGL_NO_DISPLAY), + _eglConfig(nullptr), + _eglSurface(nullptr), + _eglContext(EGL_NO_CONTEXT), + _eglSharedContext(EGL_NO_CONTEXT) +{ + // Setup Cubism + _cubismOption.LogFunction = LAppPal::PrintMessageLn; + _cubismOption.LoggingLevel = LAppDefine::CubismLoggingLevel; + CubismFramework::CleanUp(); + CubismFramework::StartUp(&_cubismAllocator, &_cubismOption); +} + +LAppDelegate::~LAppDelegate() +{ +} + +void LAppDelegate::OnTouchBegan(double x, double y) +{ + _mouseX = static_cast(x); + _mouseY = static_cast(y); + + if (_view != NULL) + { + _captured = true; + _view->OnTouchesBegan(_mouseX, _mouseY); + } +} + +void LAppDelegate::OnTouchEnded(double x, double y) +{ + _mouseX = static_cast(x); + _mouseY = static_cast(y); + + if (_view != NULL) + { + _captured = false; + _view->OnTouchesEnded(_mouseX, _mouseY); + } +} + +void LAppDelegate::OnTouchMoved(double x, double y) +{ + _mouseX = static_cast(x); + _mouseY = static_cast(y); + + if (_captured && _view != NULL) + { + _view->OnTouchesMoved(_mouseX, _mouseY); + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDelegate.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDelegate.hpp new file mode 100644 index 00000000..25a4279b --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppDelegate.hpp @@ -0,0 +1,158 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include +#include "LAppAllocator.hpp" + +class LAppView; +class LAppTextureManager; + +/** +* @brief アプリケーションクラス。 +* Cubism SDK の管理を行う。 +*/ +class LAppDelegate +{ +public: + /** + * @brief クラスのインスタンス(シングルトン)を返す。
+ * インスタンスが生成されていない場合は内部でインスタンを生成する。 + * + * @return クラスのインスタンス + */ + static LAppDelegate* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する。 + * + */ + static void ReleaseInstance(); + + /** + * @brief 実行処理。 + */ + void Run(); + + /** + * @brief EGLの設定 + * + */ + void InitializeEgl(); + + /** + * @brief EGLの破棄 + * + */ + void ReleaseEgl(); + + /** + * @brief OnSurfaceCreateのコールバック関数。 + * + */ + void InitializeDisplay(); + + /** + * @brief OnSurfaceChangedのコールバック関数。 + * + * @param width + * @param height + */ + void ChangeDisplay(float width, float height); + + /** + * @brief Touch開始。 + * + * @param[in] x x座標 + * @param[in] y x座標 + */ + void OnTouchBegan(double x, double y); + + /** + * @brief Touch終了。 + * + * @param[in] x x座標 + * @param[in] y x座標 + */ + void OnTouchEnded(double x, double y); + + /** + * @brief Touch移動。 + * + * @param[in] x x座標 + * @param[in] y x座標 + */ + void OnTouchMoved(double x, double y); + + /** + * @brief テクスチャマネージャーの取得 + */ + LAppTextureManager* GetTextureManager() { return _textureManager; } + + /** + * @brief ウインドウ幅の取得 + */ + int GetWindowWidth() { return _width; } + + /** + * @brief ウインドウ高さの取得 + */ + int GetWindowHeight() { return _height; } + + /** + * @brief windowの設定 + * + * @param window + */ + void SetWindow(void *window) { _eglWindow = reinterpret_cast(window); } + + /** + * @brief ウインドウの取得 + */ + const void* GetWindow() { return reinterpret_cast(_eglWindow); }; + + /** + * @brief アプリケーションを非アクティブにする。 + */ + void DeActivateApp() { _isActive = false; } + + /** + * @brief View情報を取得する。 + */ + LAppView* GetView() { return _view; } + +private: + /** + * @brief コンストラクタ + */ + LAppDelegate(); + + /** + * @brief デストラクタ + */ + ~LAppDelegate(); + + LAppAllocator _cubismAllocator; ///< Cubism SDK Allocator + Csm::CubismFramework::Option _cubismOption; ///< Cubism SDK Option + LAppTextureManager* _textureManager; ///< テクスチャマネージャー + LAppView* _view; ///< View情報 + int _width; ///< Windowの幅 + int _height; ///< windowの高さ + bool _captured; ///< クリックしているか + bool _isActive; ///< アプリがアクティブ状態なのか + float _mouseY; ///< マウスY座標 + float _mouseX; ///< マウスX座標 + EGLNativeWindowType _eglWindow; + EGLDisplay _eglDisplay; + EGLConfig _eglConfig; + EGLSurface _eglSurface; + EGLContext _eglContext; + EGLContext _eglSharedContext; +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppLive2DManager.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppLive2DManager.cpp new file mode 100644 index 00000000..c3686473 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppLive2DManager.cpp @@ -0,0 +1,272 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppLive2DManager.hpp" +#include +#include +#include +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "LAppDelegate.hpp" +#include "LAppModel.hpp" +#include "LAppView.hpp" +#include "NapiBridgeC.hpp" + +using namespace Csm; +using namespace LAppDefine; + +namespace { + LAppLive2DManager* s_instance = NULL; + + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion Began: %x", self); + } + + void FinishedMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion Finished: %x", self); + } + + int CompareCsmString(const void* a, const void* b) + { + return strcmp(reinterpret_cast(a)->GetRawString(), + reinterpret_cast(b)->GetRawString()); + } +} + +LAppLive2DManager* LAppLive2DManager::GetInstance() +{ + if (s_instance == NULL) + { + s_instance = new LAppLive2DManager(); + } + + return s_instance; +} + +void LAppLive2DManager::ReleaseInstance() +{ + if (s_instance != NULL) + { + delete s_instance; + } + + s_instance = NULL; +} + +LAppLive2DManager::LAppLive2DManager() + : _viewMatrix(NULL) + , _sceneIndex(0) +{ + _viewMatrix = new CubismMatrix44(); + SetUpModel(); + + ChangeScene(_sceneIndex); +} + +LAppLive2DManager::~LAppLive2DManager() +{ + ReleaseAllModel(); + delete _viewMatrix; +} + +void LAppLive2DManager::ReleaseAllModel() +{ + for (csmUint32 i = 0; i < _models.GetSize(); i++) + { + delete _models[i]; + } + + _models.Clear(); +} + +void LAppLive2DManager::SetUpModel() +{ + const char MODEL3_JSON[] = u8".model3.json"; + _modelDir.Clear(); + csmVector root = NapiBridgeC::GetAssetList(ResourcesPath); + for (size_t i = 0; i < root.GetSize(); i++) + { + csmString target(root[i]); + target.Append(MODEL3_JSON, sizeof(MODEL3_JSON) - 1); + csmString modelPath = csmString(ResourcesPath) + root[i]; + csmVector sub = NapiBridgeC::GetAssetList(modelPath.GetRawString()); + for (size_t j = 0; j < sub.GetSize(); j++) + { + if (target == sub[j]) + { + _modelDir.PushBack(root[i]); + break; + } + } + } + qsort(_modelDir.GetPtr(), _modelDir.GetSize(), sizeof(csmString), CompareCsmString); +} + +LAppModel* LAppLive2DManager::GetModel(csmUint32 no) const +{ + if (no < _models.GetSize()) + { + return _models[no]; + } + + return NULL; +} + +void LAppLive2DManager::OnDrag(csmFloat32 x, csmFloat32 y) const +{ + for (csmUint32 i = 0; i < _models.GetSize(); i++) + { + LAppModel* model = GetModel(i); + + model->SetDragging(x, y); + } +} + +void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) +{ + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]tap point: {x:%.2f y:%.2f}", x, y); + } + + for (csmUint32 i = 0; i < _models.GetSize(); i++) + { + if (_models[i]->HitTest(HitAreaNameHead, x, y)) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameHead); + } + _models[i]->SetRandomExpression(); + } + else if (_models[i]->HitTest(HitAreaNameBody, x, y)) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); + } + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); + } + } +} + +void LAppLive2DManager::OnUpdate() const +{ + int width = LAppDelegate::GetInstance()->GetWindowWidth(); + int height = LAppDelegate::GetInstance()->GetWindowHeight(); + + csmUint32 modelCount = _models.GetSize(); + for (csmUint32 i = 0; i < modelCount; ++i) + { + CubismMatrix44 projection; + LAppModel* model = GetModel(i); + + if (model->GetModel() == NULL) + { + LAppPal::PrintLogLn("Failed to model->GetModel()."); + continue; + } + + if (model->GetModel()->GetCanvasWidth() > 1.0f && width < height) + { + // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する + model->GetModelMatrix()->SetWidth(2.0f); + projection.Scale(1.0f, static_cast(width) / static_cast(height)); + } + else + { + projection.Scale(static_cast(height) / static_cast(width), 1.0f); + } + + // 必要があればここで乗算 + if (_viewMatrix != NULL) + { + projection.MultiplyByMatrix(_viewMatrix); + } + + // モデル1体描画前コール + LAppDelegate::GetInstance()->GetView()->PreModelDraw(*model); + + model->Update(); + model->Draw(projection);///< 参照渡しなのでprojectionは変質する + + // モデル1体描画後コール + LAppDelegate::GetInstance()->GetView()->PostModelDraw(*model); + } +} + +void LAppLive2DManager::NextScene() +{ + csmInt32 no = (_sceneIndex + 1) % _modelDir.GetSize(); + ChangeScene(no); +} + +void LAppLive2DManager::ChangeScene(csmInt32 index) +{ + _sceneIndex = index; + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]model index: %d", _sceneIndex); + } + + // model3.jsonのパスを決定する. + // ディレクトリ名とmodel3.jsonの名前を一致していることが条件 + csmString modelPath(ResourcesPath); + modelPath += _modelDir[index] + "/"; + csmString modelJsonName(_modelDir[index]); + modelJsonName += ".model3.json"; + + ReleaseAllModel(); + _models.PushBack(new LAppModel()); + _models[0]->LoadAssets(modelPath.GetRawString(), modelJsonName.GetRawString()); + + /* + * モデル半透明表示を行うサンプルを提示する。 + * ここでUSE_RENDER_TARGET、USE_MODEL_RENDER_TARGETが定義されている場合 + * 別のレンダリングターゲットにモデルを描画し、描画結果をテクスチャとして別のスプライトに張り付ける。 + */ + { +#if defined(USE_RENDER_TARGET) + // LAppViewの持つターゲットに描画を行う場合、こちらを選択 + LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ViewFrameBuffer; +#elif defined(USE_MODEL_RENDER_TARGET) + // 各LAppModelの持つターゲットに描画を行う場合、こちらを選択 + LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ModelFrameBuffer; +#else + // デフォルトのメインフレームバッファへレンダリングする(通常) + LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_None; +#endif + +#if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET) + // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす + _models.PushBack(new LAppModel()); + _models[1]->LoadAssets(modelPath.GetRawString(), modelJsonName.GetRawString()); + _models[1]->GetModelMatrix()->TranslateX(0.2f); +#endif + + LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); + + // 別レンダリング先を選択した際の背景クリア色 + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; + LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]); + } +} + +csmUint32 LAppLive2DManager::GetModelNum() const +{ + return _models.GetSize(); +} + +void LAppLive2DManager::SetViewMatrix(CubismMatrix44* m) +{ + for (int i = 0; i < 16; i++) { + _viewMatrix->GetArray()[i] = m->GetArray()[i]; + } +} + diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppLive2DManager.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppLive2DManager.hpp new file mode 100644 index 00000000..b6921446 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppLive2DManager.hpp @@ -0,0 +1,127 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include +#include + +class LAppModel; + +/** +* @brief サンプルアプリケーションにおいてCubismModelを管理するクラス
+* モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。 +* +*/ +class LAppLive2DManager +{ + +public: + /** + * @brief クラスのインスタンス(シングルトン)を返す。
+ * インスタンスが生成されていない場合は内部でインスタンを生成する。 + * + * @return クラスのインスタンス + */ + static LAppLive2DManager* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する。 + * + */ + static void ReleaseInstance(); + + /** + * @brief Resources フォルダにあるモデルフォルダ名をセットする + * + */ + void SetUpModel(); + + /** + * @brief 現在のシーンで保持しているモデルを返す + * + * @param[in] no モデルリストのインデックス値 + * @return モデルのインスタンスを返す。インデックス値が範囲外の場合はNULLを返す。 + */ + LAppModel* GetModel(Csm::csmUint32 no) const; + + /** + * @brief 現在のシーンで保持しているすべてのモデルを解放する + * + */ + void ReleaseAllModel(); + + /** + * @brief 画面をドラッグしたときの処理 + * + * @param[in] x 画面のX座標 + * @param[in] y 画面のY座標 + */ + void OnDrag(Csm::csmFloat32 x, Csm::csmFloat32 y) const; + + /** + * @brief 画面をタップしたときの処理 + * + * @param[in] x 画面のX座標 + * @param[in] y 画面のY座標 + */ + void OnTap(Csm::csmFloat32 x, Csm::csmFloat32 y); + + /** + * @brief 画面を更新するときの処理 + * モデルの更新処理および描画処理を行う + */ + void OnUpdate() const; + + /** + * @brief 次のシーンに切り替える
+ * サンプルアプリケーションではモデルセットの切り替えを行う。 + */ + void NextScene(); + + /** + * @brief シーンを切り替える
+ * サンプルアプリケーションではモデルセットの切り替えを行う。 + */ + void ChangeScene(Csm::csmInt32 index); + + /** + * @brief シーンインデックスの取得 + * @return シーンインデックスを返す + */ + Csm::csmInt32 GetSceneIndex() { return _sceneIndex; } + + /** + * @brief モデル個数を得る + * @return 所持モデル個数 + */ + Csm::csmUint32 GetModelNum() const; + + /** + * @brief viewMatrixをセットする + */ + void SetViewMatrix(Live2D::Cubism::Framework::CubismMatrix44* m); + +private: + /** + * @brief コンストラクタ + */ + LAppLive2DManager(); + + /** + * @brief デストラクタ + */ + virtual ~LAppLive2DManager(); + + Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列 + Csm::csmVector _models; ///< モデルインスタンスのコンテナ + Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値 + + Csm::csmVector _modelDir; ///< モデルディレクトリ名のコンテナ +}; diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppModel.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppModel.cpp similarity index 54% rename from Samples/Cocos2d-x/Demo/Classes/LAppModel.cpp rename to Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppModel.cpp index 73c89923..442bd6dd 100644 --- a/Samples/Cocos2d-x/Demo/Classes/LAppModel.cpp +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppModel.cpp @@ -1,72 +1,55 @@ -/** +/** * 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. */ -//Cubism Framework -#include "LAppDefine.hpp" #include "LAppModel.hpp" -#include "LAppPal.hpp" +#include +#include #include #include #include #include -#include +#include #include #include -#include "Motion/CubismMotionQueueEntry.hpp" -#include "SampleScene.h" - -//cocos2d -#include "base/CCDirector.h" -#include "renderer/CCTexture2D.h" -#include "renderer/CCTextureCache.h" - -using namespace std; -using namespace Csm; -using namespace Csm::Constant; -using namespace Csm::DefaultParameterId; -using namespace LAppDefine; -using namespace cocos2d::backend; - -#if USE_AUDIO_ENGINE -#include "audio/include/AudioEngine.h" -using namespace cocos2d::experimental; -#elif USE_SIMPLE_AUDIO_ENGINE -#include "audio/include/SimpleAudioEngine.h" -using namespace CocosDenshion; -#endif +#include +#include "LAppDefine.hpp" +#include "LAppPal.hpp" +#include "LAppTextureManager.hpp" +#include "LAppDelegate.hpp" -USING_NS_CC; +using namespace Live2D::Cubism::Framework; +using namespace Live2D::Cubism::Framework::DefaultParameterId; +using namespace LAppDefine; namespace { -csmByte* CreateBuffer(const csmChar* path, csmSizeInt* size) -{ - if (DebugLogEnable)LAppPal::PrintLogLn("[APP]create buffer: %s ", path); - return LAppPal::LoadFileAsBytes(path, size); -} + csmByte* CreateBuffer(const csmChar* path, csmSizeInt* size) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]create buffer: %s ", path); + } + return LAppPal::LoadFileAsBytes(path, size); + } -void DeleteBuffer(csmByte* buffer, const csmChar* path = "") -{ - if (DebugLogEnable) LAppPal::PrintLogLn("[APP]delete buffer: %s", path); - LAppPal::ReleaseBytes(buffer); -} + void DeleteBuffer(csmByte* buffer, const csmChar* path = "") + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]delete buffer: %s", path); + } + LAppPal::ReleaseBytes(buffer); + } } - LAppModel::LAppModel() : CubismUserModel() , _modelSetting(NULL) , _userTimeSeconds(0.0f) - , _renderSprite(NULL) { - if (MocConsistencyValidationEnable) - { - _mocConsistency = true; - } - if (DebugLogEnable) { _debugMode = true; @@ -78,29 +61,11 @@ LAppModel::LAppModel() _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(ParamBodyAngleX); _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(ParamEyeBallX); _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(ParamEyeBallY); - - _clearColor[0] = 1.0f; - _clearColor[1] = 1.0f; - _clearColor[2] = 1.0f; - _clearColor[3] = 0.0f; - - _renderBuffer = new Csm::Rendering::CubismOffscreenSurface_Cocos2dx; - - _groupCommand.init(0.0); } LAppModel::~LAppModel() { - if (_debugMode)LAppPal::PrintLogLn("[APP]delete model: %s", _modelSetting->GetModelFileName()); - - if (_renderSprite) - { - // Cocos本体が消滅した後ではこの呼び出しが出来ないことに注意 - _renderSprite->removeFromParentAndCleanup(true); - _renderSprite = NULL; - } - _renderBuffer->DestroyOffscreenSurface(); - delete _renderBuffer; + _renderBuffer.DestroyOffscreenSurface(); ReleaseMotions(); ReleaseExpressions(); @@ -110,21 +75,17 @@ LAppModel::~LAppModel() const csmChar* group = _modelSetting->GetMotionGroupName(i); ReleaseMotionGroup(group); } - CSM_DELETE(_modelSetting); - - //cocos2d - for (csmInt32 i = 0; i < _loadedTextures.GetSize(); i++) - { - Director::getInstance()->getTextureCache()->removeTexture(_loadedTextures[i]); - } - _loadedTextures.Clear(); + delete _modelSetting; } void LAppModel::LoadAssets(const csmChar* dir, const csmChar* fileName) { _modelHomeDir = dir; - if (_debugMode)LAppPal::PrintLogLn("[APP]load model setting: %s", fileName); + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]load model setting: %s", fileName); + } csmSizeInt size; const csmString path = csmString(dir) + fileName; @@ -137,8 +98,8 @@ void LAppModel::LoadAssets(const csmChar* dir, const csmChar* fileName) if (_model == NULL) { - LAppPal::PrintLogLn("Failed to LoadAssets()."); - return; + LAppPal::PrintLogLn("Failed to LoadAssets()."); + return; } CreateRenderer(); @@ -163,12 +124,14 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) csmString path = _modelSetting->GetModelFileName(); path = _modelHomeDir + path; - if (_debugMode)LAppPal::PrintLogLn("[APP]create model: %s", setting->GetModelFileName()); + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]create model: %s", setting->GetModelFileName()); + } buffer = CreateBuffer(path.GetRawString(), &size); - LoadModel(buffer, size, _mocConsistency); + LoadModel(buffer, size); DeleteBuffer(buffer, path.GetRawString()); - } //Expression @@ -232,11 +195,11 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) csmVector breathParameters; - breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleX, 0.0f, 15.0f, 6.5345f, 0.5f)); - breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleY, 0.0f, 8.0f, 3.5345f, 0.5f)); - breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleZ, 0.0f, 10.0f, 5.5345f, 0.5f)); - breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamBodyAngleX, 0.0f, 4.0f, 15.5345f, 0.5f)); - breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(ParamBreath), 0.5f, 0.5f, 3.2345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleX, 0.0f, 15.0f, 6.5345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleY, 0.0f, 8.0f, 3.5345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleZ, 0.0f, 10.0f, 5.5345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamBodyAngleX, 0.0f, 4.0f, 15.5345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(ParamBreath), 0.5f, 0.5f, 3.2345f, 0.5f)); _breath->SetParameters(breathParameters); } @@ -247,7 +210,7 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) csmString path = _modelSetting->GetUserDataFile(); path = _modelHomeDir + path; buffer = CreateBuffer(path.GetRawString(), &size); - LoadUserData(buffer,size); + LoadUserData(buffer, size); DeleteBuffer(buffer, path.GetRawString()); } @@ -271,8 +234,8 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) if (_modelSetting == NULL || _modelMatrix == NULL) { - LAppPal::PrintLogLn("Failed to SetupModel()."); - return; + LAppPal::PrintLogLn("Failed to SetupModel()."); + return; } //Layout @@ -305,26 +268,18 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmString path = _modelSetting->GetMotionFileName(group, i); path = _modelHomeDir + path; - if (_debugMode)LAppPal::PrintLogLn("[APP]load motion: %s => [%s_%d] ", path.GetRawString(), group, i); + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]load motion: %s => [%s_%d] ", path.GetRawString(), group, i); + } csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -335,19 +290,6 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) } DeleteBuffer(buffer, path.GetRawString()); - - csmString voice = _modelSetting->GetMotionSoundFileName(group, i); - if (strcmp(voice.GetRawString(), "") != 0) - { - csmString path = voice; - path = _modelHomeDir + path; - -#if USE_AUDIO_ENGINE - AudioEngine::preload(path.GetRawString()); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::getInstance()->preloadEffect(path.GetRawString()); -#endif - } } } @@ -361,12 +303,6 @@ void LAppModel::ReleaseMotionGroup(const csmChar* group) const { csmString path = voice; path = _modelHomeDir + path; - -#if USE_AUDIO_ENGINE - AudioEngine::uncache(path.GetRawString()); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::getInstance()->unloadEffect(path.GetRawString()); -#endif } } } @@ -473,7 +409,7 @@ void LAppModel::Update() // リップシンクの設定 if (_lipSync) { - csmFloat32 value = 0; // リアルタイムでリップシンクを行う場合、システムから音量を取得して0~1の範囲で値を入力します。 + csmFloat32 value = 0; // リアルタイムでリップシンクを行う場合、システムから音量を取得して0〜1の範囲で値を入力します。 for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i) { @@ -491,7 +427,7 @@ void LAppModel::Update() } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -499,7 +435,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else if (!_motionManager->ReserveMotion(priority)) { - if (_debugMode) LAppPal::PrintLogLn("[APP]can't start motion."); + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]can't start motion."); + } return InvalidMotionQueueEntryHandleValue; } @@ -518,21 +457,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -541,6 +469,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -550,18 +479,16 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt { csmString path = voice; path = _modelHomeDir + path; -#if USE_AUDIO_ENGINE - AudioEngine::play2d(path.GetRawString()); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::getInstance()->playEffect(path.GetRawString()); -#endif } - if (_debugMode)LAppPal::PrintLogLn("[APP]start motion: [%s_%d]", group, no); + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]start motion: [%s_%d]", group, no); + } return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -570,47 +497,40 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() { - if (_model == NULL)return; + if (_model == NULL) + { + return; + } - GetRenderer()->DrawModel(); + GetRenderer()->DrawModel(); } -void LAppModel::Draw(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer, CubismMatrix44& matrix) +void LAppModel::Draw(CubismMatrix44& matrix) { - if (_model == NULL)return; - - Csm::Rendering::CubismRenderer_Cocos2dx::StartFrame(commandBuffer); - - //commandBuffer->PushCommandGroup(); - - if (_renderBuffer->IsValid()) + if (_model == NULL) { - _renderBuffer->BeginDraw(commandBuffer, NULL); - _renderBuffer->Clear(commandBuffer, _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]); + return; } matrix.MultiplyByMatrix(_modelMatrix); - GetRenderer()->SetMvpMatrix(&matrix); + GetRenderer()->SetMvpMatrix(&matrix); DoDraw(); - - if (_renderBuffer->IsValid()) - { - _renderBuffer->EndDraw(commandBuffer); - } - - //commandBuffer->PopCommandGroup(); } csmBool LAppModel::HitTest(const csmChar* hitAreaName, csmFloat32 x, csmFloat32 y) { - if (_opacity < 1)return false; // 透明時は当たり判定なし。 + // 透明時は当たり判定なし。 + if (_opacity < 1) + { + return false; + } const csmInt32 count = _modelSetting->GetHitAreasCount(); for (csmInt32 i = 0; i < count; i++) { @@ -626,10 +546,14 @@ csmBool LAppModel::HitTest(const csmChar* hitAreaName, csmFloat32 x, csmFloat32 void LAppModel::SetExpression(const csmChar* expressionID) { ACubismMotion* motion = _expressions[expressionID]; - if (_debugMode) LAppPal::PrintLogLn("[APP]expression: [%s]", expressionID); + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]expression: [%s]", expressionID); + } + if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { @@ -639,7 +563,10 @@ void LAppModel::SetExpression(const csmChar* expressionID) void LAppModel::SetRandomExpression() { - if (_expressions.GetSize() == 0) return; + if (_expressions.GetSize() == 0) + { + return; + } csmInt32 no = rand() % _expressions.GetSize(); csmMap::const_iterator map_ite; @@ -656,7 +583,7 @@ void LAppModel::SetRandomExpression() } } -void LAppModel::ReloadRnederer() +void LAppModel::ReloadRenderer() { DeleteRenderer(); @@ -667,38 +594,30 @@ void LAppModel::ReloadRnederer() void LAppModel::SetupTextures() { - _loadedTextures.Clear(); for (csmInt32 modelTextureNumber = 0; modelTextureNumber < _modelSetting->GetTextureCount(); modelTextureNumber++) { // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ - if (strcmp(_modelSetting->GetTextureFileName(modelTextureNumber), "") == 0) continue; + if (strcmp(_modelSetting->GetTextureFileName(modelTextureNumber), "") == 0) + { + continue; + } + //OpenGLのテクスチャユニットにテクスチャをロードする csmString texturePath = _modelSetting->GetTextureFileName(modelTextureNumber); texturePath = _modelHomeDir + texturePath; - // Cocos2d-x - // テクスチャをファイルからロードする. ロードできなければnullptrが返る - Texture2D* texture = Director::getInstance()->getTextureCache()->addImage(std::string(texturePath.GetRawString())); - - // テクスチャが読めていなければバインド処理をスキップ - if(!texture) continue; - - const SamplerDescriptor texParams = { - SamplerFilter::LINEAR_MIPMAP_LINEAR, - SamplerFilter::LINEAR, - SamplerAddressMode::CLAMP_TO_EDGE, - SamplerAddressMode::CLAMP_TO_EDGE - }; - texture->setTexParameters(texParams); - texture->generateMipmap(); - _loadedTextures.PushBack(texture); + LAppTextureManager::TextureInfo* texture = LAppDelegate::GetInstance()->GetTextureManager()->CreateTextureFromPngFile(texturePath.GetRawString()); + const csmInt32 glTextueNumber = texture->id; - //Cocos2d - GetRenderer()->BindTexture(modelTextureNumber, texture); + //OpenGL + GetRenderer()->BindTexture(modelTextureNumber, glTextueNumber); } - GetRenderer()->IsPremultipliedAlpha(true); - +#ifdef PREMULTIPLIED_ALPHA_ENABLE + GetRenderer()->IsPremultipliedAlpha(true); +#else + GetRenderer()->IsPremultipliedAlpha(false); +#endif } void LAppModel::MotionEventFired(const csmString& eventValue) @@ -706,161 +625,7 @@ void LAppModel::MotionEventFired(const csmString& eventValue) CubismLogInfo("%s is fired on LAppModel!!", eventValue.GetRawString()); } -const csmVector& LAppModel::GetHitAreas(const Csm::CubismMatrix44& vpMatrix, const CubismVector2& windowSize) -{ - _hitArea.Clear(); - - for (csmInt32 i = 0; i < _modelSetting->GetHitAreasCount(); ++i) - { - _hitArea.PushBack(GetDrawableArea(GetModel()->GetDrawableIndex(_modelSetting->GetHitAreaId(i)),vpMatrix, windowSize)); - } - return _hitArea; -} - -const csmVector& LAppModel::GetUserDataAreas(const CubismMatrix44& vpMatrix, const CubismVector2& windowSize) -{ - _userArea.Clear(); - - if ( _modelUserData == NULL) - { - return _userArea; - } - - const csmVector& ans = _modelUserData->GetArtMeshUserDatas(); - - for ( csmUint32 i = 0; i < ans.GetSize(); ++i) - { - _userArea.PushBack(GetDrawableArea(GetModel()->GetDrawableIndex(ans[i]->TargetId), vpMatrix, windowSize)); - } - - return _userArea; -} - -csmRectF LAppModel::GetDrawableArea(csmInt32 drawableIndex, const CubismMatrix44& vpMatrix, const CubismVector2& windowSize) const -{ - CubismMatrix44 currentMatrix(vpMatrix); //Matrixをコピーしないと変質が次回に影響する - currentMatrix.MultiplyByMatrix(_modelMatrix); - - const csmInt32 count = _model->GetDrawableVertexCount(drawableIndex); - const csmFloat32* vertices = _model->GetDrawableVertices(drawableIndex); - - csmFloat32 left = vertices[0]; - csmFloat32 right = vertices[0]; - csmFloat32 top = vertices[1]; - csmFloat32 bottom = vertices[1]; - - for (csmInt32 j = 1; j < count; ++j) - { - CubismVector2 pos; - - pos.X = vertices[Constant::VertexOffset + j * Constant::VertexStep]; - pos.Y = vertices[Constant::VertexOffset + j * Constant::VertexStep + 1]; - - if (pos.X < left) - { - left = pos.X; // Min x - } - - if (pos.X > right) - { - right = pos.X; // Max x - } - - if (pos.Y < top) - { - top = pos.Y; // Min y - } - - if (pos.Y > bottom) - { - bottom = pos.Y; // Max y - } - } - - csmFloat32 convertLeft = left * currentMatrix.GetArray()[0] + top * currentMatrix.GetArray()[1]; - convertLeft = convertLeft * windowSize.X / 2 + windowSize.X / 2; - csmFloat32 convertTop = left * currentMatrix.GetArray()[4] + top * currentMatrix.GetArray()[5]; - convertTop = convertTop * windowSize.Y / 2 + windowSize.Y / 2; - csmFloat32 convertRight = right * currentMatrix.GetArray()[0] + bottom * currentMatrix.GetArray()[1]; - convertRight = convertRight * windowSize.X / 2 + windowSize.X / 2; - csmFloat32 convertBottom = right * currentMatrix.GetArray()[4] + bottom * currentMatrix.GetArray()[5]; - convertBottom = convertBottom * windowSize.Y / 2 + windowSize.Y / 2; - - return csmRectF(convertLeft, convertTop, (convertRight - convertLeft), (convertBottom - convertTop)); -} - -void LAppModel::MakeRenderingTarget() +Csm::Rendering::CubismOffscreenSurface_OpenGLES2& LAppModel::GetRenderBuffer() { - // RenderTexture::createは描画タイミングで呼ぶとAssert扱いになるので注意すること - if (!_renderSprite && !_renderBuffer->IsValid()) - { - int frameW = Director::getInstance()->getOpenGLView()->getFrameSize().width, frameH = Director::getInstance()->getOpenGLView()->getFrameSize().height; - -#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) - // Retina対策でこっちからとる - GLViewImpl *glimpl = (GLViewImpl *)Director::getInstance()->getOpenGLView(); - glfwGetFramebufferSize(glimpl->getWindow(), &frameW, &frameH); -#endif - - Size visibleSize = Director::getInstance()->getVisibleSize(); - Point origin = Director::getInstance()->getVisibleOrigin(); - - _renderSprite = RenderTexture::create(frameW, frameH, cocos2d::backend::PixelFormat::RGBA8888); - _renderSprite->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); - _renderSprite->getSprite()->getTexture()->setAntiAliasTexParameters(); - _renderSprite->getSprite()->setBlendFunc(BlendFunc::ALPHA_NON_PREMULTIPLIED); - _renderSprite->getSprite()->setOpacityModifyRGB(false); - // サンプルシーンへ登録 - SampleScene::getInstance()->addChild(_renderSprite); - _renderSprite->setVisible(true); - - // _renderSpriteのテクスチャを作成する - _renderSprite->getSprite()->getTexture()->setTexParameters( - cocos2d::Texture2D::TexParams( - cocos2d::backend::SamplerFilter::LINEAR, // MagFilter - cocos2d::backend::SamplerFilter::LINEAR, // MinFilter - cocos2d::backend::SamplerAddressMode::CLAMP_TO_EDGE, // AddressingMode S - cocos2d::backend::SamplerAddressMode::CLAMP_TO_EDGE // AddressingMode T - ) - ); - - // レンダリングバッファの描画先をそのテクスチャにする - _renderBuffer->CreateOffscreenSurface(frameW, frameH, _renderSprite); - } -} - -void LAppModel::SetSpriteColor(float r, float g, float b, float a) -{ - if (_renderSprite != NULL) - { - _renderSprite->getSprite()->setColor(Color3B(static_cast(255.0f * r), static_cast(255.0f * g), static_cast(255.0f * b))); - _renderSprite->getSprite()->setOpacity(static_cast(255.0f * a)); - } -} - -csmBool LAppModel::HasMocConsistencyFromFile(const csmChar* mocFileName) -{ - CSM_ASSERT(strcmp(mocFileName, "")); - - csmByte* buffer; - csmSizeInt size; - - csmString path = mocFileName; - path = _modelHomeDir + path; - - buffer = CreateBuffer(path.GetRawString(), &size); - - csmBool consistency = CubismMoc::HasMocConsistencyFromUnrevivedMoc(buffer, size); - if (!consistency) - { - CubismLogInfo("Inconsistent MOC3."); - } - else - { - CubismLogInfo("Consistent MOC3."); - } - - DeleteBuffer(buffer); - - return consistency; + return _renderBuffer; } diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppModel.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppModel.hpp similarity index 65% rename from Samples/Cocos2d-x/Demo/Classes/LAppModel.hpp rename to Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppModel.hpp index 46d32349..abda11c1 100644 --- a/Samples/Cocos2d-x/Demo/Classes/LAppModel.hpp +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppModel.hpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -7,14 +7,11 @@ #pragma once -#include "2d/CCRenderTexture.h" #include #include #include #include -#include -#include "LAppDefine.hpp" -#include "AppDelegate.h" +#include /** * @brief ユーザーが実際に使用するモデルの実装クラス
@@ -39,13 +36,13 @@ class LAppModel : public Csm::CubismUserModel * @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する * */ - void LoadAssets(const Csm::csmChar dir[], const Csm::csmChar fileName[]); + void LoadAssets(const Csm::csmChar* dir, const Csm::csmChar* fileName); /** * @brief レンダラを再構築する * */ - void ReloadRnederer(); + void ReloadRenderer(); /** * @brief モデルの更新処理。モデルのパラメータから描画状態を決定する。 @@ -58,7 +55,7 @@ class LAppModel : public Csm::CubismUserModel * * @param[in] matrix View-Projection行列 */ - void Draw(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer, Csm::CubismMatrix44& matrix); + void Draw(Csm::CubismMatrix44& matrix); /** * @brief 引数で指定したモーションの再生を開始する。 @@ -67,9 +64,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -77,9 +75,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする @@ -110,32 +109,10 @@ class LAppModel : public Csm::CubismUserModel */ virtual Csm::csmBool HitTest(const Csm::csmChar* hitAreaName, Csm::csmFloat32 x, Csm::csmFloat32 y); - Csm::csmRectF GetDrawableArea(Csm::csmInt32 drawableIndex, const Csm::CubismMatrix44& vpMatrix, const Csm::CubismVector2& windowSize) const; - const Csm::csmVector& GetHitAreas(const Csm::CubismMatrix44& vpMatrix, const Csm::CubismVector2& windowSize); - const Csm::csmVector& GetUserDataAreas(const Csm::CubismMatrix44& vpMatrix, const Csm::CubismVector2& windowSize); - - /** - * @brief 別ターゲットに描画する際に使用するバッファ・スプライトを作成し、 - * スプライトをSampleSceneへ登録する - */ - void MakeRenderingTarget(); - /** - * @brief 別ターゲットに描画する際のスプライト色設定 - * @param[in] r 赤(0.0~1.0) - * @param[in] g 緑(0.0~1.0) - * @param[in] b 青(0.0~1.0) - * @param[in] a α(0.0~1.0) + * @brief 別ターゲットに描画する際に使用するバッファの取得 */ - void SetSpriteColor(float r, float g, float b, float a); - - /** - * @brief .moc3ファイルの整合性をチェックする - * - * @param[in] mocName MOC3ファイル名 - * @return MOC3に整合性があれば'true'、そうでなければ'false'。 - */ - Csm::csmBool HasMocConsistencyFromFile(const Csm::csmChar* mocFileName); + Csm::Rendering::CubismOffscreenSurface_OpenGLES2& GetRenderBuffer(); protected: /** @@ -190,29 +167,21 @@ class LAppModel : public Csm::CubismUserModel */ void ReleaseExpressions(); - Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報 - Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ - Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] - + Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報 + Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ + Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] Csm::csmVector _eyeBlinkIds; ///< モデルに設定されたまばたき機能用パラメータID - Csm::csmVector _lipSyncIds; ///< モデルに設定されたリップシンク機能用パラメータID - - Csm::csmMap _motions; ///< 読み込まれているモーションのリスト - Csm::csmMap _expressions; ///< 読み込まれている表情のリスト - - Csm::csmVector_hitArea; - Csm::csmVector_userArea; - - const Csm::CubismId* _idParamAngleX; ///< パラメータID: ParamAngleX - const Csm::CubismId* _idParamAngleY; ///< パラメータID: ParamAngleX - const Csm::CubismId* _idParamAngleZ; ///< パラメータID: ParamAngleX - const Csm::CubismId* _idParamBodyAngleX; ///< パラメータID: ParamBodyAngleX - const Csm::CubismId* _idParamEyeBallX; ///< パラメータID: ParamEyeBallX - const Csm::CubismId* _idParamEyeBallY; ///< パラメータID: ParamEyeBallXY - - Csm::Rendering::CubismOffscreenSurface_Cocos2dx* _renderBuffer; ///< モードによってはCubismOffscreenSurfaceのテクスチャを描画 - cocos2d::RenderTexture* _renderSprite; ///< _renderBufferを描画するスプライト - float _clearColor[4]; ///< _renderBufferをクリアする際の色 - Csm::csmVector _loadedTextures; - cocos2d::GroupCommand _groupCommand; + Csm::csmVector _lipSyncIds; ///< モデルに設定されたリップシンク機能用パラメータID + Csm::csmMap _motions; ///< 読み込まれているモーションのリスト + Csm::csmMap _expressions; ///< 読み込まれている表情のリスト + Csm::csmVector _hitArea; + Csm::csmVector _userArea; + const Csm::CubismId* _idParamAngleX; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamAngleY; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamAngleZ; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamBodyAngleX; ///< パラメータID: ParamBodyAngleX + const Csm::CubismId* _idParamEyeBallX; ///< パラメータID: ParamEyeBallX + const Csm::CubismId* _idParamEyeBallY; ///< パラメータID: ParamEyeBallXY + + Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先 }; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppPal.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppPal.cpp new file mode 100644 index 00000000..0aca5212 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppPal.cpp @@ -0,0 +1,79 @@ +/** + * 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. + */ + +#include "LAppPal.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LAppDefine.hpp" +#include "NapiBridgeC.hpp" + +using std::endl; +using namespace Csm; +using namespace std; +using namespace LAppDefine; + +double LAppPal::s_currentFrame = 0.0; +double LAppPal::s_lastFrame = 0.0; +double LAppPal::s_deltaTime = 0.0; + +csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) +{ + //filePath;// + const char* path = filePath.c_str(); + + // file buffer + char* buf = NapiBridgeC::LoadFile(path, outSize); + + return reinterpret_cast(buf); +} + +void LAppPal::ReleaseBytes(csmByte* byteData) +{ + delete[] byteData; +} + +csmFloat32 LAppPal::GetDeltaTime() +{ + return static_cast(s_deltaTime); +} + +void LAppPal::UpdateTime() +{ + s_currentFrame = GetSystemTime(); + s_deltaTime = s_currentFrame - s_lastFrame; + s_lastFrame = s_currentFrame; +} + +void LAppPal::PrintLogLn(const csmChar* format, ...) +{ + va_list args; + csmChar buf[256]; + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + // 標準出力でレンダリング + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "[live2dDemo]", buf); + va_end(args); +} + +void LAppPal::PrintMessageLn(const csmChar* message) +{ + PrintLogLn("%s", message); +} + +double LAppPal::GetSystemTime() +{ + struct timespec res; + clock_gettime(CLOCK_MONOTONIC, &res); + return (res.tv_sec + res.tv_nsec * 1e-9); +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppPal.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppPal.hpp new file mode 100644 index 00000000..451d21ed --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppPal.hpp @@ -0,0 +1,88 @@ +/** + * 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. + */ + +#pragma once + +#include +#include + +/** +* @brief プラットフォーム依存機能を抽象化する Cubism Platform Abstraction Layer. +* +* ファイル読み込みや時刻取得等のプラットフォームに依存する関数をまとめる +* +*/ +class LAppPal +{ +public: + /** + * @brief ファイルをバイトデータとして読み込む + * + * ファイルをバイトデータとして読み込む + * + * @param[in] filePath 読み込み対象ファイルのパス + * @param[out] outSize ファイルサイズ + * @return バイトデータ + */ + static Csm::csmByte* LoadFileAsBytes(const std::string filePath, Csm::csmSizeInt* outSize); + + + /** + * @brief バイトデータを解放する + * + * バイトデータを解放する + * + * @param[in] byteData 解放したいバイトデータ + */ + static void ReleaseBytes(Csm::csmByte* byteData); + + /** + * @biref デルタ時間(前回フレームとの差分)を取得する + * + * @return デルタ時間[ms] + * + */ + static Csm::csmFloat32 GetDeltaTime(); + + /** + * @biref デルタ時間の更新 + * + */ + static void UpdateTime(); + + /** + * @brief ログを出力し最後に改行する + * + * ログを出力し最後に改行する + * + * @param[in] format 書式付文字列 + * @param[in] ... (可変長引数)文字列 + * + */ + static void PrintLogLn(const Csm::csmChar* format, ...); + + /** + * @brief メッセージを出力し最後に改行する + * + * メッセージを出力し最後に改行する + * + * @param[in] message 文字列 + * + */ + static void PrintMessageLn(const Csm::csmChar* message); + +private: + /** + * @brief システムタイムの取得 + */ + static double GetSystemTime(); + + static double s_currentFrame; + static double s_lastFrame; + static double s_deltaTime; +}; + diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSprite.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSprite.cpp new file mode 100644 index 00000000..868e70f3 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSprite.cpp @@ -0,0 +1,130 @@ +/** + * 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. + */ + +#include "LAppSprite.hpp" + +LAppSprite::LAppSprite(float x, float y, float width, float height, GLuint textureId, GLuint programId) + : _rect() +{ + _rect.left = (x - width * 0.5f); + _rect.right = (x + width * 0.5f); + _rect.up = (y + height * 0.5f); + _rect.down = (y - height * 0.5f); + _textureId = textureId; + + // 何番目のattribute変数か + _positionLocation = glGetAttribLocation(programId, "position"); + _uvLocation = glGetAttribLocation(programId, "uv"); + _textureLocation = glGetUniformLocation(programId, "texture"); + _colorLocation = glGetUniformLocation(programId, "baseColor"); + + _spriteColor[0] = 1.0f; + _spriteColor[1] = 1.0f; + _spriteColor[2] = 1.0f; + _spriteColor[3] = 1.0f; +} + +LAppSprite::~LAppSprite() +{ +} + +void LAppSprite::ReSize(float x, float y, float width, float height) +{ + _rect.left = (x - width * 0.5f); + _rect.right = (x + width * 0.5f); + _rect.up = (y + height * 0.5f); + _rect.down = (y - height * 0.5f); +} + +void LAppSprite::Render() const +{ + const GLfloat uvVertex[] = + { + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + }; + + + // attribute属性を有効にする + glEnableVertexAttribArray(_positionLocation); + glEnableVertexAttribArray(_uvLocation); + + // uniform属性の登録 + glUniform1i(_textureLocation, 0); + + // 頂点データ + float positionVertex[] = + { + (_rect.right - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.up - _maxHeight * 0.5f) / (_maxHeight * 0.5f), + (_rect.left - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.up - _maxHeight * 0.5f) / (_maxHeight * 0.5f), + (_rect.left - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.down - _maxHeight * 0.5f) / (_maxHeight * 0.5f), + (_rect.right - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.down - _maxHeight * 0.5f) / (_maxHeight * 0.5f) + }; + + // attribute属性を登録 + glVertexAttribPointer(_positionLocation, 2, GL_FLOAT, false, 0, positionVertex); + glVertexAttribPointer(_uvLocation, 2, GL_FLOAT, false, 0, uvVertex); + + glUniform4f(_colorLocation, _spriteColor[0], _spriteColor[1], _spriteColor[2], _spriteColor[3]); + + // モデルの描画 + glBindTexture(GL_TEXTURE_2D, _textureId); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +void LAppSprite::RenderImmidiate(GLuint textureId, const GLfloat uvVertex[8]) const +{ + // attribute属性を有効にする + glEnableVertexAttribArray(_positionLocation); + glEnableVertexAttribArray(_uvLocation); + + // uniform属性の登録 + glUniform1i(_textureLocation, 0); + + // 頂点データ + float positionVertex[] = + { + (_rect.right - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.up - _maxHeight * 0.5f) / (_maxHeight * 0.5f), + (_rect.left - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.up - _maxHeight * 0.5f) / (_maxHeight * 0.5f), + (_rect.left - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.down - _maxHeight * 0.5f) / (_maxHeight * 0.5f), + (_rect.right - _maxWidth * 0.5f) / (_maxWidth * 0.5f), (_rect.down - _maxHeight * 0.5f) / (_maxHeight * 0.5f) + }; + + // attribute属性を登録 + glVertexAttribPointer(_positionLocation, 2, GL_FLOAT, false, 0, positionVertex); + glVertexAttribPointer(_uvLocation, 2, GL_FLOAT, false, 0, uvVertex); + + glUniform4f(_colorLocation, _spriteColor[0], _spriteColor[1], _spriteColor[2], _spriteColor[3]); + + // モデルの描画 + glBindTexture(GL_TEXTURE_2D, textureId); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +bool LAppSprite::IsHit(float pointX, float pointY) const +{ + //Y座標は変換する必要あり + float y = _maxHeight - pointY; + + return (pointX >= _rect.left && pointX <= _rect.right && y <= _rect.up && y >= _rect.down); +} + +void LAppSprite::SetColor(float r, float g, float b, float a) +{ + _spriteColor[0] = r; + _spriteColor[1] = g; + _spriteColor[2] = b; + _spriteColor[3] = a; +} + +void LAppSprite::SetWindowSize(int width, int height) +{ + _maxWidth = width; + _maxHeight = height; +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSprite.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSprite.hpp new file mode 100644 index 00000000..d0618159 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSprite.hpp @@ -0,0 +1,116 @@ +/** + * 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. + */ + +#pragma once + +#include + +/** +* @brief スプライトを実装するクラス。 +* +* テクスチャID、Rectの管理。 +* +*/ +class LAppSprite +{ +public: + /** + * @brief Rect 構造体。 + */ + struct Rect + { + public: + float left; ///< 左辺 + float right; ///< 右辺 + float up; ///< 上辺 + float down; ///< 下辺 + }; + + /** + * @brief コンストラクタ + * + * @param[in] x x座標 + * @param[in] y y座標 + * @param[in] width 横幅 + * @param[in] height 高さ + * @param[in] textureId テクスチャID + * @param[in] programId シェーダID + */ + LAppSprite(float x, float y, float width, float height, GLuint textureId, GLuint programId); + + /** + * @brief デストラクタ + */ + ~LAppSprite(); + + /** + * @brief スプライトサイズ変更 + * + * @param[in] x x座標 + * @param[in] y y座標 + * @param[in] width 横幅 + * @param[in] height 高さ + */ + void ReSize(float x, float y, float width, float height); + + /** + * @brief Getter テクスチャID + * @return テクスチャIDを返す + */ + GLuint GetTextureId() { return _textureId; } + + /** + * @brief 描画する + * + */ + void Render() const; + + /** + * @brief テクスチャIDを指定して描画する + * + */ + void RenderImmidiate(GLuint textureId, const GLfloat uvVertex[8]) const; + + /** + * @brief コンストラクタ + * + * @param[in] pointX x座標 + * @param[in] pointY y座標 + */ + bool IsHit(float pointX, float pointY) const; + + /** + * @brief 色設定 + * + * @param[in] r (0.0~1.0) + * @param[in] g (0.0~1.0) + * @param[in] b (0.0~1.0) + * @param[in] a (0.0~1.0) + */ + void SetColor(float r, float g, float b, float a); + + /** + * @brief ウインドウサイズ設定 + * + * @param[in] width 横幅 + * @param[in] height 高さ + */ + void SetWindowSize(int width, int height); + +private: + GLuint _textureId; ///< テクスチャID + Rect _rect; ///< 矩形 + int _positionLocation; ///< 位置アトリビュート + int _uvLocation; ///< UVアトリビュート + int _textureLocation; ///< テクスチャアトリビュート + int _colorLocation; ///< カラーアトリビュート + + float _spriteColor[4]; ///< 表示カラー + int _maxWidth; ///< ウインドウ幅 + int _maxHeight; ///< ウインドウ高さ +}; + diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSpriteShader.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSpriteShader.cpp new file mode 100644 index 00000000..d0ed5c40 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSpriteShader.cpp @@ -0,0 +1,106 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppSpriteShader.hpp" +#include +#include "LAppDefine.hpp" +#include "LAppPal.hpp" + +LAppSpriteShader::LAppSpriteShader() +{ + _programId = CreateShader(); +} + +LAppSpriteShader::~LAppSpriteShader() +{ + glDeleteShader(_programId); +} + +GLuint LAppSpriteShader::GetShaderId() const +{ + return _programId; +} + +GLuint LAppSpriteShader::CreateShader() +{ + // シェーダーのパスの作成 + Csm::csmString vertShaderFile(LAppDefine::ShaderPath); + vertShaderFile += LAppDefine::VertShaderName; + Csm::csmString fragShaderFile(LAppDefine::ShaderPath); + fragShaderFile += LAppDefine::FragShaderName; + + // シェーダーのコンパイル + GLuint vertexShaderId = CompileShader(vertShaderFile, GL_VERTEX_SHADER); + GLuint fragmentShaderId = CompileShader(fragShaderFile, GL_FRAGMENT_SHADER); + + if (!vertexShaderId || !fragmentShaderId) + { + return 0; + } + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + // 不要になったシェーダーオブジェクトの削除 + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); + + return programId; +} + +bool LAppSpriteShader::CheckShader(GLuint shaderId) +{ + GLint status; + GLint logLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) + { + GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); + glGetShaderInfoLog(shaderId, logLength, &logLength, log); + CubismLogError("Shader compile log: %s", log); + CSM_FREE(log); + } + + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + glDeleteShader(shaderId); + return false; + } + + return true; +} + +GLuint LAppSpriteShader::CompileShader(Csm::csmString filename, GLenum shaderType) +{ + // ファイル読み込み + Csm::csmSizeInt bufferSize = 0; + const char* shaderString = reinterpret_cast(LAppPal::LoadFileAsBytes(filename.GetRawString(), &bufferSize)); + const GLint glSize = (GLint)bufferSize; + + // コンパイル + GLuint shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, 1, &shaderString, &glSize); + glCompileShader(shaderId); + + // 読み込んだシェーダー文字列の開放 + LAppPal::ReleaseBytes(reinterpret_cast(const_cast(shaderString))); + + if (!CheckShader(shaderId)) + { + return 0; + } + + return shaderId; +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSpriteShader.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSpriteShader.hpp new file mode 100644 index 00000000..71438c9f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppSpriteShader.hpp @@ -0,0 +1,55 @@ +/** + * 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. + */ + +#pragma once + +#include +#include + +/** +* @brief スプライト用のシェーダー設定を保持するクラス +*/ +class LAppSpriteShader +{ +public: + /** + * @brief コンストラクタ + */ + LAppSpriteShader(); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーIDを取得する + */ + GLuint GetShaderId() const; + +private: + /** + * @brief シェーダーを作成する。 + */ + GLuint CreateShader(); + + /** + * @brief CreateShader内部関数 エラーチェック + */ + bool CheckShader(GLuint shaderId); + + /** + * @brief シェーダーをコンパイルする + * コンパイルに失敗した場合には 0 が戻る。 + * + * @param[in] filename シェーダーファイル名 + * @param[in] shaderType 作成するシェーダーの種類 + */ + GLuint CompileShader(Csm::csmString filename, GLenum shaderType); + + GLuint _programId; ///< シェーダID +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppTextureManager.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppTextureManager.cpp new file mode 100644 index 00000000..699f90b3 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppTextureManager.cpp @@ -0,0 +1,129 @@ +/** + * 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. + */ + +#include "LAppTextureManager.hpp" +#include +#define STBI_NO_STDIO +#define STBI_ONLY_PNG +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#include "LAppPal.hpp" + +LAppTextureManager::LAppTextureManager() +{ +} + +LAppTextureManager::~LAppTextureManager() +{ + ReleaseTextures(); +} + +LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile(std::string fileName) +{ + //search loaded texture already. + for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) + { + if (_textures[i]->fileName == fileName) + { + return _textures[i]; + } + } + + GLuint textureId; + int width, height, channels; + unsigned int size; + unsigned char* png; + unsigned char* address; + + address = LAppPal::LoadFileAsBytes(fileName, &size); + + // png情報を取得する + png = stbi_load_from_memory( + address, + static_cast(size), + &width, + &height, + &channels, + STBI_rgb_alpha); + { +#ifdef PREMULTIPLIED_ALPHA_ENABLE + unsigned int* fourBytes = reinterpret_cast(png); + for (int i = 0; i < width * height; i++) + { + unsigned char* p = png + i * 4; + fourBytes[i] = Premultiply(p[0], p[1], p[2], p[3]); + } +#endif + } + + // OpenGL用のテクスチャを生成する + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, png); + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + // 解放処理 + stbi_image_free(png); + LAppPal::ReleaseBytes(address); + + LAppTextureManager::TextureInfo* textureInfo = new LAppTextureManager::TextureInfo(); + if (textureInfo != NULL) + { + textureInfo->fileName = fileName; + textureInfo->width = width; + textureInfo->height = height; + textureInfo->id = textureId; + + _textures.PushBack(textureInfo); + } + + return textureInfo; + +} + +void LAppTextureManager::ReleaseTextures() +{ + for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) + { + glDeleteTextures(1, &(_textures[i]->id)); + delete _textures[i]; + } + + _textures.Clear(); +} + +void LAppTextureManager::ReleaseTexture(Csm::csmUint32 textureId) +{ + for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) + { + if (_textures[i]->id != textureId) + { + continue; + } + glDeleteTextures(1, &(_textures[i]->id)); + delete _textures[i]; + _textures.Remove(i); + break; + } +} + +void LAppTextureManager::ReleaseTexture(std::string fileName) +{ + for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) + { + if (_textures[i]->fileName == fileName) + { + glDeleteTextures(1, &(_textures[i]->id)); + delete _textures[i]; + _textures.Remove(i); + break; + } + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppTextureManager.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppTextureManager.hpp new file mode 100644 index 00000000..310ddf9f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppTextureManager.hpp @@ -0,0 +1,99 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include + +/** +* @brief テクスチャ管理クラス +* +* 画像読み込み、管理を行うクラス。 +*/ +class LAppTextureManager +{ +public: + + /** + * @brief 画像情報構造体 + */ + struct TextureInfo + { + GLuint id; ///< テクスチャID + int width; ///< 横幅 + int height; ///< 高さ + std::string fileName; ///< ファイル名 + }; + + /** + * @brief コンストラクタ + */ + LAppTextureManager(); + + /** + * @brief デストラクタ + * + */ + ~LAppTextureManager(); + + + /** + * @brief プリマルチプライ処理 + * + * @param[in] red 画像のRed値 + * @param[in] green 画像のGreen値 + * @param[in] blue 画像のBlue値 + * @param[in] alpha 画像のAlpha値 + * + * @return プリマルチプライ処理後のカラー値 + */ + inline unsigned int Premultiply(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha) + { + return static_cast(\ + (red * (alpha + 1) >> 8) | \ + ((green * (alpha + 1) >> 8) << 8) | \ + ((blue * (alpha + 1) >> 8) << 16) | \ + (((alpha)) << 24) \ + ); + } + + /** + * @brief 画像読み込み + * + * @param[in] fileName 読み込む画像ファイルパス名 + * @return 画像情報。読み込み失敗時はNULLを返す + */ + TextureInfo* CreateTextureFromPngFile(std::string fileName); + + /** + * @brief 画像の解放 + * + * 配列に存在する画像全てを解放する + */ + void ReleaseTextures(); + + /** + * @brief 画像の解放 + * + * 指定したテクスチャIDの画像を解放する + * @param[in] textureId 解放するテクスチャID + **/ + void ReleaseTexture(Csm::csmUint32 textureId); + + /** + * @brief 画像の解放 + * + * 指定した名前の画像を解放する + * @param[in] fileName 解放する画像ファイルパス名 + **/ + void ReleaseTexture(std::string fileName); + +private: + Csm::csmVector _textures; +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppView.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppView.cpp new file mode 100644 index 00000000..e4c5ba26 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppView.cpp @@ -0,0 +1,391 @@ +/** + * 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. + */ + +#include "LAppView.hpp" +#include +#include +#include "LAppPal.hpp" +#include "LAppDelegate.hpp" +#include "LAppLive2DManager.hpp" +#include "LAppTextureManager.hpp" +#include "LAppDefine.hpp" +#include "TouchManager.hpp" +#include "LAppSprite.hpp" +#include "LAppSpriteShader.hpp" +#include "LAppModel.hpp" + +#include +#include + +using namespace std; +using namespace LAppDefine; + +LAppView::LAppView(): + _back(NULL), + _gear(NULL), + _power(NULL), + _changeModel(false), + _renderSprite(NULL), + _renderTarget(SelectTarget_None) +{ + _clearColor[0] = 1.0f; + _clearColor[1] = 1.0f; + _clearColor[2] = 1.0f; + _clearColor[3] = 0.0f; + + // タッチ関係のイベント管理 + _touchManager = new TouchManager(); + + // デバイス座標からスクリーン座標に変換するための + _deviceToScreen = new CubismMatrix44(); + + // 画面の表示の拡大縮小や移動の変換を行う行列 + _viewMatrix = new CubismViewMatrix(); +} + +LAppView::~LAppView() +{ + _renderBuffer.DestroyOffscreenSurface(); + delete _renderSprite; + + delete _spriteShader; + delete _viewMatrix; + delete _deviceToScreen; + delete _touchManager; + delete _back; + delete _gear; + delete _power; +} + +void LAppView::Initialize() +{ + int width = LAppDelegate::GetInstance()->GetWindowWidth(); + int height = LAppDelegate::GetInstance()->GetWindowHeight(); + + // 縦サイズを基準とする + float ratio = static_cast(width) / static_cast(height); + float left = -ratio; + float right = ratio; + float bottom = ViewLogicalLeft; + float top = ViewLogicalRight; + + _viewMatrix->SetScreenRect(left, right, bottom, top); // デバイスに対応する画面の範囲。 Xの左端, Xの右端, Yの下端, Yの上端 + _viewMatrix->Scale(ViewScale, ViewScale); + + _deviceToScreen->LoadIdentity(); + if (width > height) + { + float screenW = fabsf(right - left); + _deviceToScreen->ScaleRelative(screenW / width, -screenW / width); + } + else + { + float screenH = fabsf(top - bottom); + _deviceToScreen->ScaleRelative(screenH / height, -screenH / height); + } + _deviceToScreen->TranslateRelative(-width * 0.5f, -height * 0.5f); + + // 表示範囲の設定 + _viewMatrix->SetMaxScale(ViewMaxScale); // 限界拡大率 + _viewMatrix->SetMinScale(ViewMinScale); // 限界縮小率 + + // 表示できる最大範囲 + _viewMatrix->SetMaxScreenRect( + ViewLogicalMaxLeft, + ViewLogicalMaxRight, + ViewLogicalMaxBottom, + ViewLogicalMaxTop + ); + + _spriteShader = new LAppSpriteShader(); +} + +void LAppView::InitializeSprite() +{ + GLuint programId = _spriteShader->GetShaderId(); + + int width = LAppDelegate::GetInstance()->GetWindowWidth(); + int height = LAppDelegate::GetInstance()->GetWindowHeight(); + + LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager(); + const string resourcesPath = ResourcesPath; + + string imageName = BackImageName; + LAppTextureManager::TextureInfo* backgroundTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + float x = width * 0.5f; + float y = height * 0.5f; + float fWidth = (backgroundTexture->width * 2.0f); + float fHeight = (height * 0.95f); + + if(_back == NULL) + { + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId); + } + else + { + _back->ReSize(x, y, fWidth, fHeight); + } + + + imageName = GearImageName; + LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = (width - gearTexture->width * 0.5f - 96.f); + y = (height - gearTexture->height * 0.5f); + fWidth = static_cast(gearTexture->width); + fHeight = static_cast(gearTexture->height); + + if(_gear == NULL) + { + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId); + } + else + { + _gear->ReSize(x, y, fWidth, fHeight); + } + + imageName = PowerImageName; + LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); + + x = (width - powerTexture->width * 0.5f - 96.f); + y = (powerTexture->height * 0.5f); + fWidth = static_cast(powerTexture->width); + fHeight = static_cast(powerTexture->height); + + if(_power == NULL) + { + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId); + } + else + { + _power->ReSize(x, y, fWidth, fHeight); + } + + // 画面全体を覆うサイズ + x = width * 0.5f; + y = height * 0.5f; + + if (_renderSprite == NULL) + { + _renderSprite = new LAppSprite(x, y, width, height, 0, programId); + } + else + { + _renderSprite->ReSize(x, y, width, height); + } +} + +void LAppView::Render() +{ + // 画面サイズを取得する + int maxWidth = LAppDelegate::GetInstance()->GetWindowWidth(); + int maxHeight = LAppDelegate::GetInstance()->GetWindowHeight(); + _back->SetWindowSize(maxWidth, maxHeight); + _gear->SetWindowSize(maxWidth, maxHeight); + _power->SetWindowSize(maxWidth, maxHeight); + + _back->Render(); + _gear->Render(); + _power->Render(); + + if(_changeModel) + { + _changeModel = false; + LAppLive2DManager::GetInstance()->NextScene(); + } + + LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance(); + + //Live2DManager->SetViewMatrix(_viewMatrix); + + // Cubism更新・描画 + Live2DManager->OnUpdate(); + + // 各モデルが持つ描画ターゲットをテクスチャとする場合 + if (_renderTarget == SelectTarget_ModelFrameBuffer && _renderSprite) + { + const GLfloat uvVertex[] = + { + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + }; + + for (csmUint32 i = 0; i < Live2DManager->GetModelNum(); i++) + { + LAppModel* model = Live2DManager->GetModel(i); + float alpha = i < 1 ? 1.0f : model->GetOpacity(); // 片方のみ不透明度を取得できるようにする + _renderSprite->SetColor(1.0f, 1.0f, 1.0f, alpha); + + if (model) + { + _renderSprite->SetWindowSize(maxWidth, maxHeight); + _renderSprite->RenderImmidiate(model->GetRenderBuffer().GetColorBuffer(), uvVertex); + } + } + } +} + +void LAppView::OnTouchesBegan(float pointX, float pointY) const +{ + _touchManager->TouchesBegan(pointX, pointY); +} + +void LAppView::OnTouchesMoved(float pointX, float pointY) const +{ + float viewX = this->TransformViewX(_touchManager->GetX()); + float viewY = this->TransformViewY(_touchManager->GetY()); + + _touchManager->TouchesMoved(pointX, pointY); + + LAppLive2DManager::GetInstance()->OnDrag(viewX, viewY); +} + +void LAppView::OnTouchesEnded(float pointX, float pointY) +{ + // タッチ終了 + LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance(); + live2DManager->OnDrag(0.0f, 0.0f); + { + + // シングルタップ + float x = _deviceToScreen->TransformX(_touchManager->GetX()); // 論理座標変換した座標を取得。 + float y = _deviceToScreen->TransformY(_touchManager->GetY()); // 論理座標変換した座標を取得。 + if (DebugTouchLogEnable) + { + LAppPal::PrintLogLn("[APP]touchesEnded x:%.2f y:%.2f", x, y); + } + live2DManager->OnTap(x, y); + + // 歯車にタップしたか + if (_gear->IsHit(pointX, pointY)) + { + _changeModel = true; + } + + // 電源ボタンにタップしたか + if (_power->IsHit(pointX, pointY)) + { + LAppDelegate::GetInstance()->DeActivateApp(); + } + } +} + +float LAppView::TransformViewX(float deviceX) const +{ + float screenX = _deviceToScreen->TransformX(deviceX); // 論理座標変換した座標を取得。 + return _viewMatrix->InvertTransformX(screenX); // 拡大、縮小、移動後の値。 +} + +float LAppView::TransformViewY(float deviceY) const +{ + float screenY = _deviceToScreen->TransformY(deviceY); // 論理座標変換した座標を取得。 + return _viewMatrix->InvertTransformY(screenY); // 拡大、縮小、移動後の値。 +} + +float LAppView::TransformScreenX(float deviceX) const +{ + return _deviceToScreen->TransformX(deviceX); +} + +float LAppView::TransformScreenY(float deviceY) const +{ + return _deviceToScreen->TransformY(deviceY); +} + +void LAppView::PreModelDraw(LAppModel &refModel) +{ + // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ + Csm::Rendering::CubismOffscreenSurface_OpenGLES2* useTarget = NULL; + + if (_renderTarget != SelectTarget_None) + {// 別のレンダリングターゲットへ向けて描画する場合 + + // 使用するターゲット + useTarget = (_renderTarget == SelectTarget_ViewFrameBuffer) ? &_renderBuffer : &refModel.GetRenderBuffer(); + + if (!useTarget->IsValid()) + {// 描画ターゲット内部未作成の場合はここで作成 + int width = LAppDelegate::GetInstance()->GetWindowWidth(); + int height = LAppDelegate::GetInstance()->GetWindowHeight(); + + // モデル描画キャンバス + useTarget->CreateOffscreenSurface(static_cast(width), static_cast(height)); + } + + // レンダリング開始 + useTarget->BeginDraw(); + useTarget->Clear(_clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]); // 背景クリアカラー + } +} + +void LAppView::PostModelDraw(LAppModel &refModel) +{ + // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ + Csm::Rendering::CubismOffscreenSurface_OpenGLES2* useTarget = NULL; + + if (_renderTarget != SelectTarget_None) + {// 別のレンダリングターゲットへ向けて描画する場合 + + // 使用するターゲット + useTarget = (_renderTarget == SelectTarget_ViewFrameBuffer) ? &_renderBuffer : &refModel.GetRenderBuffer(); + + // レンダリング終了 + useTarget->EndDraw(); + + // LAppViewの持つフレームバッファを使うなら、スプライトへの描画はここ + if (_renderTarget == SelectTarget_ViewFrameBuffer && _renderSprite) + { + const GLfloat uvVertex[] = + { + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + }; + + _renderSprite->SetColor(1.0f, 1.0f, 1.0f, GetSpriteAlpha(0)); + + // 画面サイズを取得する + int maxWidth = LAppDelegate::GetInstance()->GetWindowWidth(); + int maxHeight = LAppDelegate::GetInstance()->GetWindowHeight(); + _renderSprite->SetWindowSize(maxWidth, maxHeight); + + _renderSprite->RenderImmidiate(useTarget->GetColorBuffer(), uvVertex); + } + } +} + +void LAppView::SwitchRenderingTarget(SelectTarget targetType) +{ + _renderTarget = targetType; +} + +void LAppView::SetRenderTargetClearColor(float r, float g, float b) +{ + _clearColor[0] = r; + _clearColor[1] = g; + _clearColor[2] = b; +} + +float LAppView::GetSpriteAlpha(int assign) const +{ + // assignの数値に応じて適当に決定 + float alpha = 0.25f + static_cast(assign) * 0.5f; // サンプルとしてαに適当な差をつける + if (alpha > 1.0f) + { + alpha = 1.0f; + } + if (alpha < 0.1f) + { + alpha = 0.1f; + } + + return alpha; +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppView.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppView.hpp new file mode 100644 index 00000000..94247d2a --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppView.hpp @@ -0,0 +1,159 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include "CubismFramework.hpp" +#include + +class TouchManager; +class LAppSprite; +class LAppSpriteShader; +class LAppModel; + +/** +* @brief 描画クラス +*/ +class LAppView +{ +public: + + /** + * @brief LAppModelのレンダリング先 + */ + enum SelectTarget + { + SelectTarget_None, ///< デフォルトのフレームバッファにレンダリング + SelectTarget_ModelFrameBuffer, ///< LAppModelが各自持つフレームバッファにレンダリング + SelectTarget_ViewFrameBuffer, ///< LAppViewの持つフレームバッファにレンダリング + }; + + /** + * @brief コンストラクタ + */ + LAppView(); + + /** + * @brief デストラクタ + */ + ~LAppView(); + + /** + * @brief 初期化する。 + */ + void Initialize(); + + /** + * @brief 描画する。 + */ + void Render(); + + /** + * @brief 画像の初期化を行う。 + */ + void InitializeSprite(); + + /** + * @brief タッチされたときに呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesBegan(float pointX, float pointY) const; + + /** + * @brief タッチしているときにポインタが動いたら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesMoved(float pointX, float pointY) const; + + /** + * @brief タッチが終了したら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesEnded(float pointX, float pointY); + + /** + * @brief X座標をView座標に変換する。 + * + * @param[in] deviceX デバイスX座標 + */ + float TransformViewX(float deviceX) const; + + /** + * @brief Y座標をView座標に変換する。 + * + * @param[in] deviceY デバイスY座標 + */ + float TransformViewY(float deviceY) const; + + /** + * @brief X座標をScreen座標に変換する。 + * + * @param[in] deviceX デバイスX座標 + */ + float TransformScreenX(float deviceX) const; + + /** + * @brief Y座標をScreen座標に変換する。 + * + * @param[in] deviceY デバイスY座標 + */ + float TransformScreenY(float deviceY) const; + + /** + * @brief モデル1体を描画する直前にコールされる + */ + void PreModelDraw(LAppModel &refModel); + + /** + * @brief モデル1体を描画した直後にコールされる + */ + void PostModelDraw(LAppModel &refModel); + + /** + * @brief 別レンダリングターゲットにモデルを描画するサンプルで + * 描画時のαを決定する + */ + float GetSpriteAlpha(int assign) const; + + /** + * @brief レンダリング先を切り替える + */ + void SwitchRenderingTarget(SelectTarget targetType); + + /** + * @brief レンダリング先をデフォルト以外に切り替えた際の背景クリア色設定 + * @param[in] r 赤(0.0~1.0) + * @param[in] g 緑(0.0~1.0) + * @param[in] b 青(0.0~1.0) + */ + void SetRenderTargetClearColor(float r, float g, float b); + +private: + TouchManager* _touchManager; ///< タッチマネージャー + Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 + Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix + LAppSprite* _back; ///< 背景画像 + LAppSprite* _gear; ///< ギア画像 + LAppSprite* _power; ///< 電源画像 + bool _changeModel; ///< モデル切り替えフラグ + + // レンダリング先を別ターゲットにする方式の場合に使用 + LAppSprite* _renderSprite; ///< モードによっては_renderBufferのテクスチャを描画 + Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング + SelectTarget _renderTarget; ///< レンダリング先の選択肢 + float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + LAppSpriteShader* _spriteShader; ///< シェーダー作成委譲クラス +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppWavFileHandler.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppWavFileHandler.cpp new file mode 100644 index 00000000..6958448d --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppWavFileHandler.cpp @@ -0,0 +1,352 @@ +/** + * 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. + */ + +#include "LAppWavFileHandler.hpp" +#include +#include +#include "LAppPal.hpp" + +LAppWavFileHandler::LAppWavFileHandler() + : _rawData(NULL) + , _pcmData(NULL) + , _userTimeSeconds(0.0f) + , _lastRms(0.0f) + , _sampleOffset(0) +{ +} + +LAppWavFileHandler::~LAppWavFileHandler() +{ + if (_rawData != NULL) + { + CSM_FREE(_rawData); + } + + if (_pcmData != NULL) + { + ReleasePcmData(); + } +} + +Csm::csmBool LAppWavFileHandler::Update(Csm::csmFloat32 deltaTimeSeconds) +{ + Csm::csmUint32 goalOffset; + Csm::csmFloat32 rms; + + // データロード前/ファイル末尾に達した場合は更新しない + if ((_pcmData == NULL) + || (_sampleOffset >= _wavFileInfo._samplesPerChannel)) + { + _lastRms = 0.0f; + return false; + } + + // 経過時間後の状態を保持 + _userTimeSeconds += deltaTimeSeconds; + goalOffset = static_cast(_userTimeSeconds * _wavFileInfo._samplingRate); + if (goalOffset > _wavFileInfo._samplesPerChannel) + { + goalOffset = _wavFileInfo._samplesPerChannel; + } + + // RMS計測 + rms = 0.0f; + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + for (Csm::csmUint32 sampleCount = _sampleOffset; sampleCount < goalOffset; sampleCount++) + { + Csm::csmFloat32 pcm = _pcmData[channelCount][sampleCount]; + rms += pcm * pcm; + } + } + rms = sqrt(rms / (_wavFileInfo._numberOfChannels * (goalOffset - _sampleOffset))); + + _lastRms = rms; + _sampleOffset = goalOffset; + return true; +} + +void LAppWavFileHandler::Start(const Csm::csmString& filePath) +{ + // WAVファイルのロード + if (!LoadWavFile(filePath)) + { + return; + } + + // サンプル参照位置を初期化 + _sampleOffset = 0; + _userTimeSeconds = 0.0f; + + // RMS値をリセット + _lastRms = 0.0f; +} + +Csm::csmFloat32 LAppWavFileHandler::GetRms() const +{ + return _lastRms; +} + +const LAppWavFileHandler::WavFileInfo& LAppWavFileHandler::GetWavFileInfo() const +{ + return _wavFileInfo; +} + +const Csm::csmByte* LAppWavFileHandler::GetRawData() const +{ + return _rawData; +} + +Csm::csmUint64 LAppWavFileHandler::GetRawDataSize() const +{ + return _rawDataSize; +} + +Csm::csmVector LAppWavFileHandler::GetPcmData() const +{ + Csm::csmVector buffer; + + for (Csm::csmUint32 sampleCount = 0; sampleCount < _wavFileInfo._samplesPerChannel; sampleCount++) + { + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + buffer.PushBack(_pcmData[channelCount][sampleCount]); + } + } + + return buffer; +} + +void LAppWavFileHandler::GetPcmDataChannel(Csm::csmFloat32* dst, Csm::csmUint32 useChannel) const +{ + for (Csm::csmUint32 sampleCount = 0; sampleCount < _wavFileInfo._samplesPerChannel; sampleCount++) + { + dst[sampleCount] = _pcmData[useChannel][sampleCount]; + } +} + +Csm::csmFloat32 LAppWavFileHandler::NormalizePcmSample(Csm::csmUint32 bitsPerSample, Csm::csmByte* data, Csm::csmUint32 dataSize) +{ + Csm::csmInt32 pcm32; + + // 32ビット幅に拡張してから-1~1の範囲に丸める + switch (bitsPerSample) + { + case 8: + if (1 <= dataSize) + { + const Csm::csmUint8 ret = data[0]; + pcm32 = static_cast(ret) - 128; + pcm32 <<= 24; + } + else + { + pcm32 = 0; + } + break; + case 16: + if (2 <= dataSize) + { + const Csm::csmUint16 ret = (data[1] << 8) | data[0]; + pcm32 = ret << 16; + } + else + { + pcm32 = 0; + } + break; + case 24: + if (3 <= dataSize) + { + const Csm::csmUint32 ret = (data[2] << 16) | (data[1] << 8) | data[0]; + pcm32 = ret << 8; + } + else + { + pcm32 = 0; + } + break; + case 32: + if (4 <= dataSize) + { + const Csm::csmUint32 ret = (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]; + pcm32 = ret << 0; + } + else + { + pcm32 = 0; + } + break; + default: + // 対応していないビット幅 + pcm32 = 0; + break; + } + + return static_cast(pcm32) / INT32_MAX; +} + +Csm::csmBool LAppWavFileHandler::LoadWavFile(const Csm::csmString& filePath) +{ + Csm::csmBool ret; + + // 既にwavファイルロード済みならば領域開放 + if (_rawData != NULL) + { + CSM_FREE(_rawData); + _rawDataSize = 0; + } + if (_pcmData != NULL) + { + ReleasePcmData(); + } + + // ファイルロード + _byteReader._fileByte = LAppPal::LoadFileAsBytes(filePath.GetRawString(), &(_byteReader._fileSize)); + _byteReader._readOffset = 0; + + // ファイルロードに失敗しているか、先頭のシグネチャ"RIFF"を入れるサイズもない場合は失敗 + if ((_byteReader._fileByte == NULL) || (_byteReader._fileSize < 4)) + { + return false; + } + + // ファイル名 + _wavFileInfo._fileName = filePath; + + do { + // シグネチャ "RIFF" + if (!_byteReader.GetCheckSignature("RIFF")) + { + ret = false; + break; + } + // ファイルサイズ-8(読み飛ばし) + _byteReader.Get32LittleEndian(); + // シグネチャ "WAVE" + if (!_byteReader.GetCheckSignature("WAVE")) + { + ret = false; + break; + } + // シグネチャ "fmt " + if (!_byteReader.GetCheckSignature("fmt ")) + { + ret = false; + break; + } + // fmtチャンクサイズ + const Csm::csmUint32 fmtChunkSize = _byteReader.Get32LittleEndian(); + // フォーマットIDは1(リニアPCM)以外受け付けない + if (_byteReader.Get16LittleEndian() != 1) + { + ret = false; + break; + } + // チャンネル数 + _wavFileInfo._numberOfChannels = _byteReader.Get16LittleEndian(); + // サンプリングレート + _wavFileInfo._samplingRate = _byteReader.Get32LittleEndian(); + // 平均データ速度 + _wavFileInfo._avgBytesPerSec = _byteReader.Get32LittleEndian(); + // ブロックサイズ + _wavFileInfo._blockAlign = _byteReader.Get16LittleEndian(); + // 量子化ビット数 + _wavFileInfo._bitsPerSample = _byteReader.Get16LittleEndian(); + // fmtチャンクの拡張部分の読み飛ばし + if (fmtChunkSize > 16) + { + _byteReader._readOffset += (fmtChunkSize - 16); + } + // "data"チャンクが出現するまで読み飛ばし + while (!(_byteReader.GetCheckSignature("data")) + && (_byteReader._readOffset < _byteReader._fileSize)) + { + _byteReader._readOffset += _byteReader.Get32LittleEndian(); + } + // ファイル内に"data"チャンクが出現しなかった + if (_byteReader._readOffset >= _byteReader._fileSize) + { + ret = false; + break; + } + // サンプル数 + { + const Csm::csmUint32 dataChunkSize = _byteReader.Get32LittleEndian(); + _wavFileInfo._samplesPerChannel = (dataChunkSize * 8) / (_wavFileInfo._bitsPerSample * _wavFileInfo._numberOfChannels); + } + // 領域確保 + _rawDataSize = static_cast(_wavFileInfo._blockAlign) * static_cast(_wavFileInfo._samplesPerChannel); + _rawData = static_cast(CSM_MALLOC(sizeof(Csm::csmByte) * _rawDataSize)); + _pcmData = static_cast(CSM_MALLOC(sizeof(Csm::csmFloat32*) * _wavFileInfo._numberOfChannels)); + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + _pcmData[channelCount] = static_cast(CSM_MALLOC(sizeof(Csm::csmFloat32) * _wavFileInfo._samplesPerChannel)); + } + // 波形データ取得 + Csm::csmUint64 rawPos = 0; + for (Csm::csmUint32 sampleCount = 0; sampleCount < _wavFileInfo._samplesPerChannel; sampleCount++) + { + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + // 正規化前 + for (Csm::csmUint32 byteCount = 0; byteCount < _wavFileInfo._bitsPerSample / 8; byteCount++) + { + _rawData[rawPos++] = _byteReader._fileByte[_byteReader._readOffset + byteCount]; + } + // 正規化後 + _pcmData[channelCount][sampleCount] = GetPcmSample(); + } + } + + ret = true; + + } while (false); + + // ファイル開放 + LAppPal::ReleaseBytes(_byteReader._fileByte); + _byteReader._fileByte = NULL; + _byteReader._fileSize = 0; + + return ret; +} + +Csm::csmFloat32 LAppWavFileHandler::GetPcmSample() +{ + Csm::csmInt32 pcm32; + + // 32ビット幅に拡張してから-1~1の範囲に丸める + switch (_wavFileInfo._bitsPerSample) + { + case 8: + pcm32 = static_cast(_byteReader.Get8()) - 128; + pcm32 <<= 24; + break; + case 16: + pcm32 = _byteReader.Get16LittleEndian() << 16; + break; + case 24: + pcm32 = _byteReader.Get24LittleEndian() << 8; + break; + default: + // 対応していないビット幅 + pcm32 = 0; + break; + } + + return static_cast(pcm32) / INT32_MAX; +} + +void LAppWavFileHandler::ReleasePcmData() +{ + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + CSM_FREE(_pcmData[channelCount]); + } + CSM_FREE(_pcmData); + _pcmData = NULL; +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppWavFileHandler.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppWavFileHandler.hpp new file mode 100644 index 00000000..bd8e54cb --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/LAppWavFileHandler.hpp @@ -0,0 +1,234 @@ +/** + * 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. + */ + +#pragma once + +#include +#include + + /** + * @brief wavファイルハンドラ + * @attention 16bit wav ファイル読み込みのみ実装済み + */ +class LAppWavFileHandler +{ +public: + /** + * @brief 読み込んだwavfileの情報 + */ + struct WavFileInfo + { + /** + * @brief コンストラクタ + */ + WavFileInfo() : _fileName(""), _numberOfChannels(0), + _bitsPerSample(0), _samplingRate(0), _samplesPerChannel(0), + _avgBytesPerSec(0), _blockAlign(0) + { } + + Csm::csmString _fileName; ///< ファイル名 + Csm::csmUint32 _numberOfChannels; ///< チャンネル数 + Csm::csmUint32 _bitsPerSample; ///< サンプルあたりビット数 + Csm::csmUint32 _samplingRate; ///< サンプリングレート + Csm::csmUint32 _samplesPerChannel; ///< 1チャンネルあたり総サンプル数 + Csm::csmUint32 _avgBytesPerSec; ///< 平均データ速度 + Csm::csmUint32 _blockAlign; ///< ブロックサイズ + } _wavFileInfo; + + /** + * @brief コンストラクタ + */ + LAppWavFileHandler(); + + /** + * @brief デストラクタ + */ + ~LAppWavFileHandler(); + + /** + * @brief wavファイルハンドラの内部状態更新 + * + * @param[in] deltaTimeSeconds デルタ時間[秒] + * @retval true 更新されている + * @retval false 更新されていない + */ + Csm::csmBool Update(Csm::csmFloat32 deltaTimeSeconds); + + /** + * @brief 引数で指定したwavファイルの読み込みを開始する + * + * @param[in] filePath wavファイルのパス + */ + void Start(const Csm::csmString& filePath); + + /** + * @brief 現在のRMS値取得 + * + * @retval csmFloat32 RMS値 + */ + Csm::csmFloat32 GetRms() const; + + /** + * @brief ファイル情報を取得 + * + * @retval ファイル情報 + */ + const WavFileInfo& GetWavFileInfo() const; + + /** + * @brief 正規化前のデータを取得 + * + * @retval 正規化前のデータ + */ + const Csm::csmByte* GetRawData() const; + + /** + * @brief 正規化前のデータの大きさを取得 + * + * @retval 正規化前のデータの大きさ + */ + Csm::csmUint64 GetRawDataSize() const; + + /** + * @brief 正規化データを取得する + * + * @retval 正規化データ + */ + Csm::csmVector GetPcmData() const; + + /** + * @brief 引数で指定したチャンネルの正規化データを取得する + * + * @param[in] dst 格納先 + * @param[in] useChannel 使用するチャンネル + */ + void GetPcmDataChannel(Csm::csmFloat32* dst, Csm::csmUint32 useChannel) const; + + /** + * @brief -1~1の範囲の1サンプル取得 + * + * @param[in] bitsPerSample ビット深度 + * @param[in] data 正規化したいデータ + * @param[in] dataSize 正規化したいデータの大きさ + * + * @retval csmFloat32 正規化されたサンプル + */ + static Csm::csmFloat32 NormalizePcmSample(Csm::csmUint32 bitsPerSample, Csm::csmByte* data, Csm::csmUint32 dataSize); + +private: + /** + * @brief wavファイルのロード + * + * @param[in] filePath wavファイルのパス + * @retval true 読み込み成功 + * @retval false 読み込み失敗 + */ + Csm::csmBool LoadWavFile(const Csm::csmString& filePath); + + /** + * @brief PCMデータの解放 + */ + void ReleasePcmData(); + + /** + * @brief -1~1の範囲の1サンプル取得 + * @retval csmFloat32 正規化されたサンプル + */ + Csm::csmFloat32 GetPcmSample(); + + /** + * @brief バイトリーダ + */ + struct ByteReader { + /** + * @brief コンストラクタ + */ + ByteReader() : _fileByte(NULL), _fileSize(0), _readOffset(0) + { } + + /** + * @brief 8ビット読み込み + * @return Csm::csmUint8 読み取った8ビット値 + */ + Csm::csmUint8 Get8() + { + const Csm::csmUint8 ret = _fileByte[_readOffset]; + _readOffset++; + return ret; + } + + /** + * @brief 16ビット読み込み(リトルエンディアン) + * @return Csm::csmUint16 読み取った16ビット値 + */ + Csm::csmUint16 Get16LittleEndian() + { + const Csm::csmUint16 ret = (_fileByte[_readOffset + 1] << 8) | _fileByte[_readOffset]; + _readOffset += 2; + return ret; + } + + /** + * @brief 24ビット読み込み(リトルエンディアン) + * @return Csm::csmUint32 読み取った24ビット値(下位24ビットに設定) + */ + Csm::csmUint32 Get24LittleEndian() + { + const Csm::csmUint32 ret = + (_fileByte[_readOffset + 2] << 16) | (_fileByte[_readOffset + 1] << 8) + | _fileByte[_readOffset]; + _readOffset += 3; + return ret; + } + + /** + * @brief 32ビット読み込み(リトルエンディアン) + * @return Csm::csmUint32 読み取った32ビット値 + */ + Csm::csmUint32 Get32LittleEndian() + { + const Csm::csmUint32 ret = + (_fileByte[_readOffset + 3] << 24) | (_fileByte[_readOffset + 2] << 16) + | (_fileByte[_readOffset + 1] << 8) | _fileByte[_readOffset]; + _readOffset += 4; + return ret; + } + + /** + * @brief シグネチャの取得と参照文字列との一致チェック + * @param[in] reference 検査対象のシグネチャ文字列 + * @retval true 一致している + * @retval false 一致していない + */ + Csm::csmBool GetCheckSignature(const Csm::csmString& reference) + { + Csm::csmChar getSignature[4] = { 0, 0, 0, 0 }; + const Csm::csmChar* referenceString = reference.GetRawString(); + if (reference.GetLength() != 4) + { + return false; + } + for (Csm::csmUint32 signatureOffset = 0; signatureOffset < 4; signatureOffset++) + { + getSignature[signatureOffset] = static_cast(Get8()); + } + return (getSignature[0] == referenceString[0]) && (getSignature[1] == referenceString[1]) + && (getSignature[2] == referenceString[2]) && (getSignature[3] == referenceString[3]); + } + + Csm::csmByte* _fileByte; ///< ロードしたファイルのバイト列 + Csm::csmSizeInt _fileSize; ///< ファイルサイズ + Csm::csmUint32 _readOffset; ///< ファイル参照位置 + } _byteReader; + + Csm::csmByte* _rawData; ///< 正規化される前のバイト列 + Csm::csmUint64 _rawDataSize; ///< 正規化される前のバイト列の大きさ + Csm::csmFloat32** _pcmData; ///< -1から1の範囲で表現された音声データ配列 + Csm::csmUint32 _sampleOffset; ///< サンプル参照位置 + Csm::csmFloat32 _lastRms; ///< 最後に計測したRMS値 + Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] + }; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/NapiBridgeC.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/NapiBridgeC.cpp new file mode 100644 index 00000000..558ba13f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/NapiBridgeC.cpp @@ -0,0 +1,355 @@ +/** + * 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. + */ + +#include "NapiBridgeC.hpp" +#include +#include +#include +#include +#include +#include +#include "rawfile/raw_file_manager.h" +#include "rawfile/raw_file.h" +#include "rawfile/raw_dir.h" +#include "LAppDelegate.hpp" +#include "LAppPal.hpp" + +using namespace Csm; + +static csmString g_Id; +static NativeResourceManager *g_NativeResourceManager = nullptr; +static OH_NativeXComponent *g_NativeXComponent; +static OH_NativeXComponent_Callback g_Callback; +static napi_threadsafe_function g_MoveTaskToBack; +static std::atomic g_IsSurfaceChanged; +static std::atomic g_TouchEvent; +static std::atomic g_IsTouchEvent; +static std::atomic g_IsLoop; + +static csmBool CheckComponent(OH_NativeXComponent *component) +{ + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) + { + return false; + } + + return g_Id == idStr; +} + +static napi_value ConvertBooleanToNapiValue(napi_env env, bool result) +{ + napi_value state; + napi_status status = napi_get_boolean(env, result, &state); + if (status != napi_ok) + { + LAppPal::PrintLogLn("Convert boolean error."); + return nullptr; + } + + return state; +} + +csmVector NapiBridgeC::GetAssetList(const csmString &path) +{ + csmVector assetList; + RawDir *rawDir; + int count; + + if (g_NativeResourceManager) + { + rawDir = OH_ResourceManager_OpenRawDir(g_NativeResourceManager, path.GetRawString()); + count = OH_ResourceManager_GetRawFileCount(rawDir); + for (int i = 0; i < count; i++) + { + assetList.PushBack(OH_ResourceManager_GetRawFileName(rawDir, i)); + } + OH_ResourceManager_CloseRawDir(rawDir); + } + + return assetList; +} + +char *NapiBridgeC::LoadFile(const char *filePath, unsigned int *outSize) +{ + RawFile *rawFile; + long length; + char *buffer = nullptr; + + if (g_NativeResourceManager) + { + rawFile = OH_ResourceManager_OpenRawFile(g_NativeResourceManager, filePath); + if (!rawFile) + { + LAppPal::PrintLogLn("LoadFile failed."); + return nullptr; + } + length = OH_ResourceManager_GetRawFileSize(rawFile); + buffer = new char[length]; + *outSize = static_cast(OH_ResourceManager_ReadRawFile(rawFile, buffer, length)); + + OH_ResourceManager_CloseRawFile(rawFile); + } + + return buffer; +} + +void NapiBridgeC::MoveTaskToBack() +{ + napi_call_threadsafe_function(g_MoveTaskToBack, nullptr, napi_tsfn_blocking); +} + +static void CallMoveTaskToBack(napi_env env, napi_value jsFunc, void* context, void* data) +{ + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_call_function(env, undefined, jsFunc, 0, nullptr, nullptr); +} + +static void AsyncLoop(napi_env env, void* data) +{ + uint64_t width; + uint64_t height; + OH_NativeXComponent_TouchEvent touchEvent; + int32_t ret; + + LAppPal::PrintLogLn("Start SubThread."); + + LAppDelegate::GetInstance()->InitializeEgl(); + LAppDelegate::GetInstance()->InitializeDisplay(); + + while (g_IsLoop) + { + if (g_IsSurfaceChanged) + { + ret = OH_NativeXComponent_GetXComponentSize(g_NativeXComponent, LAppDelegate::GetInstance()->GetWindow(), &width, &height); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) + { + LAppDelegate::GetInstance()->ChangeDisplay(width, height); + } + g_IsSurfaceChanged = false; + } + if (g_IsTouchEvent) + { + touchEvent = g_TouchEvent; + switch (touchEvent.type) + { + case OH_NATIVEXCOMPONENT_DOWN: + LAppDelegate::GetInstance()->OnTouchBegan(touchEvent.x, touchEvent.y); + break; + case OH_NATIVEXCOMPONENT_UP: + LAppDelegate::GetInstance()->OnTouchEnded(touchEvent.x, touchEvent.y); + break; + case OH_NATIVEXCOMPONENT_MOVE: + LAppDelegate::GetInstance()->OnTouchMoved(touchEvent.x, touchEvent.y); + break; + } + g_IsTouchEvent = false; + } + + LAppDelegate::GetInstance()->Run(); + } + LAppDelegate::GetInstance()->ReleaseEgl(); + LAppDelegate::GetInstance()->ReleaseInstance(); +} + +static void AsyncCallback(napi_env env, napi_status status, void* data) +{ + LAppPal::PrintLogLn("Call AsyncCallback."); + + napi_delete_async_work(env, *reinterpret_cast(data)); + CSM_FREE(data); +} + +static napi_value InitializeMainLoop(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value argv[2]; + napi_value workName; + napi_async_work* asyncWork; + napi_status status; + + LAppPal::PrintLogLn("Start InitSurface."); + + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + g_NativeResourceManager = OH_ResourceManager_InitNativeResourceManager(env, argv[0]); + + // create moveTaskToBack function + status = napi_create_threadsafe_function(env, argv[1], nullptr, workName, 0, 1, nullptr, nullptr, nullptr, CallMoveTaskToBack, &g_MoveTaskToBack); + if (status != napi_ok) + { + LAppPal::PrintLogLn("Failed to create moveTaskToBack function."); + return ConvertBooleanToNapiValue(env, false); + } + + // create async + g_IsSurfaceChanged = true; + g_IsTouchEvent = false; + g_IsLoop = true; + status = napi_create_string_utf8(env, "live2dDemoLoop", NAPI_AUTO_LENGTH, &workName); + if (status != napi_ok) + { + LAppPal::PrintLogLn("Failed to obtain the name of the async process."); + return ConvertBooleanToNapiValue(env, false); + } + asyncWork = reinterpret_cast(CSM_MALLOC(sizeof(napi_async_work))); + if (!asyncWork) + { + LAppPal::PrintLogLn("Memory allocation failed."); + return ConvertBooleanToNapiValue(env, false); + } + status = napi_create_async_work(env, NULL, workName, AsyncLoop, AsyncCallback, asyncWork, asyncWork); + if (status != napi_ok) + { + LAppPal::PrintLogLn("Failed to create async process."); + return ConvertBooleanToNapiValue(env, false); + } + status = napi_queue_async_work(env, *asyncWork); + if (status != napi_ok) + { + LAppPal::PrintLogLn("Failed to queue async process."); + return ConvertBooleanToNapiValue(env, false); + } + + return ConvertBooleanToNapiValue(env, true); +} + +static void OnSurfaceCreated(OH_NativeXComponent *component, void *window) +{ + LAppPal::PrintLogLn("Start OnSurfaceCreated."); + + if (!CheckComponent(component)) + { + LAppPal::PrintLogLn("OnSurfaceCreated failed."); + return; + } + + LAppDelegate::GetInstance()->SetWindow(window); +} + +static void OnSurfaceChanged(OH_NativeXComponent *component, void *window) +{ + LAppPal::PrintLogLn("Start OnSurfaceChanged."); + + if (!CheckComponent(component)) + { + LAppPal::PrintLogLn("OnSurfaceChanged failed."); + return; + } + + g_IsSurfaceChanged = true; +} + +static void OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) +{ + LAppPal::PrintLogLn("Start OnSurfaceDestroyed."); + + g_IsLoop = false; + + if (g_NativeResourceManager) + { + OH_ResourceManager_ReleaseNativeResourceManager(g_NativeResourceManager); + g_NativeResourceManager = nullptr; + } + + napi_release_threadsafe_function(g_MoveTaskToBack, napi_tsfn_release); +} + +static void DispatchTouchEvent(OH_NativeXComponent *component, void *window) +{ + LAppPal::PrintLogLn("Start DispatchTouchEvent."); + + OH_NativeXComponent_TouchEvent touchEvent; + int32_t ret; + + ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) + { + LAppPal::PrintLogLn("DispatchTouchEvent failed."); + return; + } + g_TouchEvent = touchEvent; + g_IsTouchEvent = true; +} + +static bool Export(napi_env env, napi_value exports) +{ + napi_status status; + napi_value exportInstance = nullptr; + OH_NativeXComponent *nativeXComponent = nullptr; + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + + status = napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance); + if (status != napi_ok) + { + return false; + } + + status = napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)); + if (status != napi_ok) + { + return false; + } + + ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) + { + return false; + } + + g_Id = idStr; + g_NativeXComponent = nativeXComponent; + + g_Callback.OnSurfaceCreated = OnSurfaceCreated; + g_Callback.OnSurfaceChanged = OnSurfaceChanged; + g_Callback.OnSurfaceDestroyed = OnSurfaceDestroyed; + g_Callback.DispatchTouchEvent = DispatchTouchEvent; + OH_NativeXComponent_RegisterCallback(g_NativeXComponent, &g_Callback); + + return true; +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + LAppPal::PrintLogLn("Start Init."); + + napi_property_descriptor desc[] = + { + { "initializeMainLoop", nullptr, InitializeMainLoop, nullptr, nullptr, nullptr, napi_default, nullptr } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + + if (!Export(env, exports)) + { + LAppPal::PrintLogLn("Init failed."); + } + + return exports; +} +EXTERN_C_END + +static napi_module demoModule = +{ + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "Demo", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) +{ + napi_module_register(&demoModule); +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/NapiBridgeC.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/NapiBridgeC.hpp new file mode 100644 index 00000000..156d58fc --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/NapiBridgeC.hpp @@ -0,0 +1,33 @@ +/** + * 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. + */ + +#pragma once +#include +#include + +/** +* @brief Napi Bridge Class +*/ +class NapiBridgeC +{ +public: + /** + * @brief Assets 取得 + */ + static Csm::csmVector GetAssetList(const Csm::csmString& path); + + /** + * @brief ファイル読み込み + */ + static char* LoadFile(const char* filePath, unsigned int* outSize); + + /** + * @brief アプリをバックグラウンドに移動 + */ + static void MoveTaskToBack(); + +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/TouchManager.cpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/TouchManager.cpp new file mode 100644 index 00000000..60003c38 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/TouchManager.cpp @@ -0,0 +1,97 @@ +/** + * 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. + */ + +#include "TouchManager.hpp" +#include + +TouchManager::TouchManager() + : _startY(0.0f) + , _startX(0.0f) + , _lastX(0.0f) + , _lastY(0.0f) + , _lastX1(0.0f) + , _lastY1(0.0f) + , _lastX2(0.0f) + , _lastY2(0.0f) + , _lastTouchDistance(0.0f) + , _deltaX(0.0f) + , _deltaY(0.0f) + , _scale(1.0f) + , _touchSingle(false) + , _flipAvailable(false) +{ } + +void TouchManager::TouchesBegan(float deviceX, float deviceY) +{ + _lastX = deviceX; + _lastY = deviceY; + _startX = deviceX; + _startY = deviceY; + _lastTouchDistance = -1.0f; + _flipAvailable = true; + _touchSingle = true; +} + +void TouchManager::TouchesMoved(float deviceX, float deviceY) +{ + _lastX = deviceX; + _lastY = deviceY; + _lastTouchDistance = -1.0f; + _touchSingle = true; +} + +void TouchManager::TouchesMoved(float deviceX1, float deviceY1, float deviceX2, float deviceY2) +{ + float distance = CalculateDistance(deviceX1, deviceY1, deviceX2, deviceY2); + float centerX = (deviceX1 + deviceX2) * 0.5f; + float centerY = (deviceY1 + deviceY2) * 0.5f; + + if (_lastTouchDistance > 0.0f) + { + _scale = powf(distance / _lastTouchDistance, 0.75f); + _deltaX = CalculateMovingAmount(deviceX1 - _lastX1, deviceX2 - _lastX2); + _deltaY = CalculateMovingAmount(deviceY1 - _lastY1, deviceY2 - _lastY2); + } + else + { + _scale = 1.0f; + _deltaX = 0.0f; + _deltaY = 0.0f; + } + + _lastX = centerX; + _lastY = centerY; + _lastX1 = deviceX1; + _lastY1 = deviceY1; + _lastX2 = deviceX2; + _lastY2 = deviceY2; + _lastTouchDistance = distance; + _touchSingle = false; +} + +float TouchManager::GetFlickDistance() const +{ + return CalculateDistance(_startX, _startY, _lastX, _lastY); +} + +float TouchManager::CalculateDistance(float x1, float y1, float x2, float y2) const +{ + return sqrtf((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); +} + +float TouchManager::CalculateMovingAmount(float v1, float v2) +{ + if ((v1 > 0.0f) != (v2 > 0.0f)) + { + return 0.0f; + } + + float sign = v1 > 0.0f ? 1.0f : -1.0f; + float absoluteValue1 = fabsf(v1); + float absoluteValue2 = fabsf(v2); + return sign * ((absoluteValue1 < absoluteValue2) ? absoluteValue1 : absoluteValue2); +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/TouchManager.hpp b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/TouchManager.hpp new file mode 100644 index 00000000..3ec0d57c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/src/TouchManager.hpp @@ -0,0 +1,109 @@ +/** + * 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. + */ + +#pragma once + +/** +* @brief タッチマネジャー +*/ +class TouchManager +{ +public: + /** + * @brief コンストラクタ + */ + TouchManager(); + + float GetCenterX() const { return _lastX; } + float GetCenterY() const { return _lastY; } + float GetDeltaX() const { return _deltaX; } + float GetDeltaY() const{ return _deltaY; } + float GetStartX() const{ return _startX; } + float GetStartY() const{ return _startY; } + float GetScale() const { return _scale; } + float GetX() const{ return _lastX; } + float GetY() const{ return _lastY; } + float GetX1() const{ return _lastX1; } + float GetY1() const{ return _lastY1; } + float GetX2() const{ return _lastX2; } + float GetY2() const{ return _lastY2; } + bool IsSingleTouch() const { return _touchSingle; } + bool IsFlickAvailable() const { return _flipAvailable; } + void DisableFlick() { _flipAvailable = false; } + + /* + * @brief タッチ開始時イベント + * + * @param[in] deviceY タッチした画面のyの値 + * @param[in] deviceX タッチした画面のxの値 + */ + void TouchesBegan(float deviceX, float deviceY); + + /* + * @brief ドラッグ時のイベント + * + * @param[in] deviceX タッチした画面のyの値 + * @param[in] deviceY タッチした画面のxの値 + */ + void TouchesMoved(float deviceX, float deviceY); + + /* + * @brief ドラッグ時のイベント + * + * @param[in] deviceX1 1つめのタッチした画面のxの値 + * @param[in] deviceY1 1つめのタッチした画面のyの値 + * @param[in] deviceX2 2つめのタッチした画面のxの値 + * @param[in] deviceY2 2つめのタッチした画面のyの値 + */ + void TouchesMoved(float deviceX1, float deviceY1, float deviceX2, float deviceY2); + + /* + * @brief フリックの距離測定 + * + * @return フリック距離 + */ + float GetFlickDistance() const; + +private: + /* + * @brief 点1から点2への距離を求める + * + * @param[in] x1 1つめのタッチした画面のxの値 + * @param[in] y1 1つめのタッチした画面のyの値 + * @param[in] x2 2つめのタッチした画面のxの値 + * @param[in] y2 2つめのタッチした画面のyの値 + * @return 2点の距離 + */ + float CalculateDistance(float x1, float y1, float x2, float y2) const; + + /* + * 二つの値から、移動量を求める。 + * 違う方向の場合は移動量0。同じ方向の場合は、絶対値が小さい方の値を参照する + * + * @param[in] v1 1つめの移動量 + * @param[in] v2 2つめの移動量 + * + * @return 小さい方の移動量 + */ + float CalculateMovingAmount(float v1, float v2); + + float _startY; // タッチを開始した時のxの値 + float _startX; // タッチを開始した時のyの値 + float _lastX; // シングルタッチ時のxの値 + float _lastY; // シングルタッチ時のyの値 + float _lastX1; // ダブルタッチ時の一つ目のxの値 + float _lastY1; // ダブルタッチ時の一つ目のyの値 + float _lastX2; // ダブルタッチ時の二つ目のxの値 + float _lastY2; // ダブルタッチ時の二つ目のyの値 + float _lastTouchDistance; // 2本以上でタッチしたときの指の距離 + float _deltaX; // 前回の値から今回の値へのxの移動距離。 + float _deltaY; // 前回の値から今回の値へのyの移動距離。 + float _scale; // このフレームで掛け合わせる拡大率。拡大操作中以外は1。 + bool _touchSingle; // シングルタッチ時はtrue + bool _flipAvailable; // フリップが有効かどうか + +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/types/libentry/Demo.d.ts b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/types/libentry/Demo.d.ts new file mode 100644 index 00000000..7b830046 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/types/libentry/Demo.d.ts @@ -0,0 +1,11 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +import resourceManager from '@ohos.resourceManager'; + +type moveTaskToBack = () => void; +export const initializeMainLoop: (resourceManager: resourceManager.ResourceManager, callback: moveTaskToBack) => boolean; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/types/libentry/oh-package.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 00000000..ee80ae34 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,6 @@ +{ + "name": "libDemo.so", + "types": "./Demo.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/ets/entryability/EntryAbility.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 00000000..c035ea47 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,52 @@ +/** + * 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 AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import { WindowManager } from '@kit.SpeechKit'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, '[live2dDemo]', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, '[live2dDemo]', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, '[live2dDemo]', '%{public}s', 'Ability onWindowStageCreate'); + + WindowManager.setWindowStage(windowStage); + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, '[live2dDemo]', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, '[live2dDemo]', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, '[live2dDemo]', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, '[live2dDemo]', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, '[live2dDemo]', '%{public}s', 'Ability onBackground'); + } +}; diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/ets/pages/Index.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/ets/pages/Index.ets new file mode 100644 index 00000000..181952c8 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,36 @@ +/** + * 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 hilog from '@ohos.hilog'; +import { WindowManager } from '@kit.SpeechKit'; +import live2dDemo from 'libDemo.so'; + +function moveTaskToBack(): void { + WindowManager.getWindowStage().getMainWindowSync().minimize(); +} + +@Entry +@Component +struct Index { + private xComponentId = 'Demo'; + + build() { + Stack() { + XComponent({ id: this.xComponentId, type: XComponentType.SURFACE, libraryname: 'Demo' }) + .onLoad(() => { + hilog.info(0x0000, '[live2dDemo]', 'onLoad'); + live2dDemo.initializeMainLoop(getContext().resourceManager, moveTaskToBack); + }) + .key('Demo') + .onDestroy(() => { + hilog.info(0x0000, '[live2dDemo]', 'onDestroy'); + }) + .width('100%') + .height('100%') + } + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/module.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/module.json5 new file mode 100644 index 00000000..ab62bce4 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/module.json5 @@ -0,0 +1,39 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "orientation": "auto_rotation_landscape", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/element/color.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..162a7b6f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/element/string.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..caf640fb --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Demo" + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/media/icon.png b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/media/icon.png new file mode 100644 index 00000000..cd45accb Binary files /dev/null and b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/media/icon.png differ diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/media/startIcon.png b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 00000000..366f7645 Binary files /dev/null and b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/media/startIcon.png differ diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/profile/main_pages.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 00000000..1898d94f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/en_US/element/string.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 00000000..caf640fb --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Demo" + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/zh_CN/element/string.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 00000000..c30b672c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Demo" + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/test/Ability.test.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 00000000..1e8ea5ef --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/test/List.test.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 00000000..e03f9252 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testability/TestAbility.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 00000000..02322aee --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,50 @@ +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs; + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments(); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testability/pages/Index.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 00000000..09efea4a --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets new file mode 100644 index 00000000..c5bbc0b7 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets @@ -0,0 +1,47 @@ +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import Want from '@ohos.app.ability.Want'; + +let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined +let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err : Error) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + const bundleName = abilityDelegatorArguments.bundleName; + const testAbilityName = 'TestAbility'; + let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + const want: Want = { + bundleName: bundleName, + abilityName: testAbilityName + }; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.startAbility(want, (err, data) => { + hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/module.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/module.json5 new file mode 100644 index 00000000..d0dc5d54 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/module.json5 @@ -0,0 +1,38 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/element/color.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 00000000..162a7b6f --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/element/string.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 00000000..406cd120 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/media/icon.png b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 00000000..ce307a88 Binary files /dev/null and b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/profile/test_pages.json b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 00000000..b7e7343c --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/test/List.test.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/test/List.test.ets new file mode 100644 index 00000000..957e75b9 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/test/LocalUnit.test.ets b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/test/LocalUnit.test.ets new file mode 100644 index 00000000..e16d5311 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest',() => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/hvigor/hvigor-config.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/hvigor/hvigor-config.json5 new file mode 100644 index 00000000..941ccf5d --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/hvigor/hvigor-config.json5 @@ -0,0 +1,5 @@ +{ + "modelVersion": "5.0.0", + "dependencies": { + } +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/hvigorfile.ts b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/hvigorfile.ts new file mode 100644 index 00000000..f3cb9f1a --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/oh-package-lock.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/oh-package-lock.json5 new file mode 100644 index 00000000..ea0c5005 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/oh-package-lock.json5 @@ -0,0 +1,20 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/hypium@1.0.11": "@ohos/hypium@1.0.11" + }, + "packages": { + "@ohos/hypium@1.0.11": { + "name": "@ohos/hypium", + "version": "1.0.11", + "integrity": "sha512-KawcLnv43C3QIYv1UbDnKCFX3MohtDxGuFvzlUxT/qf2DBilR56Ws6zrj90LdH6PjloJQwOPESuBQIHBACAK7w==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.11.tgz", + "shasum": "fa799d273fa7d921701578c5e7084849354a4af0", + "registryType": "ohpm" + } + } +} \ No newline at end of file diff --git a/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/oh-package.json5 b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/oh-package.json5 new file mode 100644 index 00000000..fa973010 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.harmonyos.cmake/Full/oh-package.json5 @@ -0,0 +1,14 @@ +{ + "modelVersion": "5.0.0", + "name": "full", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.11" + } +} diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/CMakeLists.txt b/Samples/OpenGL/Demo/proj.ios.cmake/CMakeLists.txt index 4f0782ae..ee71b46f 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.ios.cmake/CMakeLists.txt @@ -107,7 +107,7 @@ set_xcode_property(${APP_NAME} set_xcode_property(${APP_NAME} DEVELOPMENT_TEAM "" "All") set_xcode_property(${APP_NAME} CODE_SIGN_IDENTITY "iPhone Developer" "All") set_xcode_property(${APP_NAME} - PRODUCT_BUNDLE_IDENTIFIER "com.live2d.demo-4-r7" "All" + PRODUCT_BUNDLE_IDENTIFIER "com.live2d.demo-5-r.2" "All" ) set_xcode_property(${APP_NAME} TARGETED_DEVICE_FAMILY "1,2" "All") if(PLATFORM STREQUAL "OS64") diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/Info.plist b/Samples/OpenGL/Demo/proj.ios.cmake/src/Info.plist index f9ef5b74..534b663c 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/Info.plist +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/Info.plist @@ -31,12 +31,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationLandscapeLeft - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppLive2DManager.mm b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppLive2DManager.mm index a1be10d9..d7c33181 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppLive2DManager.mm +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppLive2DManager.mm @@ -25,6 +25,11 @@ @implementation LAppLive2DManager static LAppLive2DManager* s_instance = nil; +void BeganMotion(Csm::ACubismMotion* self) +{ + LAppPal::PrintLogLn("Motion began: %x", self); +} + void FinishedMotion(Csm::ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -166,7 +171,7 @@ - (void)onTap:(Csm::csmFloat32)x floatY:(Csm::csmFloat32)y; { LAppPal::PrintLogLn("[APP]hit area: [%s]", LAppDefine::HitAreaNameBody); } - _models[i]->StartRandomMotion(LAppDefine::MotionGroupTapBody, LAppDefine::PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(LAppDefine::MotionGroupTapBody, LAppDefine::PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -271,9 +276,9 @@ - (void)changeScene:(Csm::csmInt32)index; _models[1]->GetModelMatrix()->TranslateX(0.2f); #endif - float clearColorR = 1.0f; - float clearColorG = 1.0f; - float clearColorB = 1.0f; + float clearColorR = 0.0f; + float clearColorG = 0.0f; + float clearColorB = 0.0f; AppDelegate* delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate]; ViewController* view = [delegate viewController]; diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.h b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.h index 780d625e..7ddec7dd 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.h +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.h @@ -65,9 +65,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -75,9 +76,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.mm b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.mm index 14d3317e..4b27cac6 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.mm +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppModel.mm @@ -276,21 +276,10 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -428,7 +417,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -458,21 +447,10 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -481,6 +459,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -499,7 +478,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -508,7 +487,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -564,7 +543,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppTextureManager.mm b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppTextureManager.mm index a0d344c9..18fa1319 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppTextureManager.mm +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/LAppTextureManager.mm @@ -118,6 +118,7 @@ - (void)releaseTextures { for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; } @@ -132,6 +133,7 @@ - (void)releaseTextureWithId:(Csm::csmUint32)textureId { continue; } + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; @@ -144,6 +146,7 @@ - (void)releaseTextureByName:(std::string)fileName; { if (_textures[i]->fileName == fileName) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/ViewController.mm b/Samples/OpenGL/Demo/proj.ios.cmake/src/ViewController.mm index 9d9e4774..f12f6cc6 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/ViewController.mm +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/ViewController.mm @@ -355,15 +355,7 @@ - (void)PreModelDraw:(LAppModel&)refModel int height = screenRect.size.height; // モデル描画キャンバス - // PadとPhoneで縦横を変えている - if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) - { - useTarget->CreateOffscreenSurface(height, width); - } - else - { - useTarget->CreateOffscreenSurface(width, height); - } + useTarget->CreateOffscreenSurface(height, width); } // レンダリング開始 diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.h b/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.h index e9b35442..8d3b449d 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.h +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.h @@ -9,6 +9,7 @@ #define MinLAppModel_h #import +#import #import #import #import @@ -65,10 +66,9 @@ class MinLAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 - * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.mm b/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.mm index 15b61698..d8e3dc2f 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.mm +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppModel.mm @@ -202,22 +202,10 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } - if (_motions[name] != NULL) { ACubismMotion::Delete(_motions[name]); @@ -339,7 +327,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") } -CubismMotionQueueEntryHandle MinLAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle MinLAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority) { if (priority == PriorityForce) { @@ -369,30 +357,15 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, NULL, NULL, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } autoDelete = true; // 終了時にメモリから削除 } DeleteBuffer(buffer, path.GetRawString()); } - else - { - motion->SetFinishedMotionHandler(onFinishedMotionHandler); - } if (_debugMode) { @@ -424,7 +397,7 @@ void DeleteBuffer(csmByte* buffer, const csmChar* path = "") if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppTextureManager.mm b/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppTextureManager.mm index c420b6ff..17fa9fe7 100644 --- a/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppTextureManager.mm +++ b/Samples/OpenGL/Demo/proj.ios.cmake/src/minimum/MinLAppTextureManager.mm @@ -118,6 +118,7 @@ - (void)releaseTextures { for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; } @@ -132,6 +133,7 @@ - (void)releaseTextureWithId:(Csm::csmUint32)textureId { continue; } + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; @@ -144,6 +146,7 @@ - (void)releaseTextureByName:(std::string)fileName; { if (_textures[i]->fileName == fileName) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/CMakeLists.txt b/Samples/OpenGL/Demo/proj.linux.cmake/CMakeLists.txt index eb5cfb1e..75b6a5ff 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.linux.cmake/CMakeLists.txt @@ -11,6 +11,7 @@ set(STB_PATH ${THIRD_PARTY_PATH}/stb) set(GLEW_PATH ${THIRD_PARTY_PATH}/glew) set(GLFW_PATH ${THIRD_PARTY_PATH}/glfw) set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SAMPLE_SHADER_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/Shaders/Standard) # Set project. project(${APP_NAME}) @@ -68,6 +69,7 @@ find_package(OpenGL REQUIRED) add_executable(${APP_NAME}) # Add source files. add_subdirectory(src) + # Link libraries to app. target_link_libraries(${APP_NAME} Framework @@ -81,9 +83,8 @@ target_include_directories(${APP_NAME} PRIVATE ${STB_PATH}) add_custom_command( TARGET ${APP_NAME} POST_BUILD - COMMAND - ${CMAKE_COMMAND} -E - copy_directory ${RES_PATH} $/Resources + COMMAND ${CMAKE_COMMAND} -E copy_directory ${RES_PATH} $/Resources + COMMAND ${CMAKE_COMMAND} -E copy_directory ${SAMPLE_SHADER_PATH} $/SampleShaders ) # You can change target that renderer draws by enabling following definition. diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/CMakeLists.txt b/Samples/OpenGL/Demo/proj.linux.cmake/src/CMakeLists.txt index cc79f718..7d572b8c 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/CMakeLists.txt @@ -38,6 +38,8 @@ else () ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.cpp index 862b7da9..3e75327c 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.cpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.cpp @@ -211,24 +211,10 @@ void CubismUserModelExtend::PreloadMotionGroup(const csmChar* group) csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // モーションデータの読み込み - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelJson, group, i)); if (tmpMotion) { - // フェードインの時間を取得 - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - // フェードアウトの時間を取得 - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } - if (_motions[name]) { // インスタンスを破棄 @@ -268,10 +254,9 @@ void CubismUserModelExtend::ReleaseModelSetting() * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 -* @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ -Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority) { // モーション数が取得出来なかった、もしくは0の時 if (!(_modelJson->GetMotionCount(group))) @@ -307,33 +292,16 @@ Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm:: csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // 一番先頭のモーションを読み込む - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, NULL, NULL, _modelJson, group, no)); if (motion) { - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } - // 終了時にメモリから削除 autoDelete = true; } DeleteBuffer(buffer, path.GetRawString()); } - else - { - // モーションの再生終了コールバックを登録 - motion->SetFinishedMotionHandler(onFinishedMotionHandler); - } // 優先度を設定してモーションを始める return _motionManager->StartMotionPriority(motion, autoDelete, priority); diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.hpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.hpp index d0b486d4..c7f9aeab 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.hpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/CubismUserModelExtend.hpp @@ -59,10 +59,9 @@ class CubismUserModelExtend : * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 - * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority); /** * @brief 解放 diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.cpp index 20008c42..d7226d27 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.cpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.cpp @@ -37,6 +37,13 @@ namespace LAppDefine { // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = "SampleShaders/"; + // 頂点シェーダー + const csmChar* VertShaderName = "VertSprite.vert"; + // フラグメントシェーダー + const csmChar* FragShaderName = "FragSprite.frag"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.hpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.hpp index 8641224a..c4e76bcd 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.hpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDefine.hpp @@ -36,6 +36,10 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* VertShaderName; ///< 頂点シェーダー + extern const csmChar* FragShaderName; ///< フラグメントシェーダー + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.cpp index 1f8bd85b..6298e6f1 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.cpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.cpp @@ -107,9 +107,6 @@ bool LAppDelegate::Initialize() _windowHeight = height; glViewport(0, 0, _windowWidth, _windowHeight); - //AppViewの初期化 - _view->Initialize(); - // Cubism3の初期化 InitializeCubism(); @@ -118,7 +115,8 @@ bool LAppDelegate::Initialize() //load model LAppLive2DManager::GetInstance(); - //load sprite + //AppViewの初期化 + _view->Initialize(); _view->InitializeSprite(); return GL_TRUE; @@ -260,48 +258,6 @@ void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) _view->OnTouchesMoved(_mouseX, _mouseY); } -GLuint LAppDelegate::CreateShader() -{ - //バーテックスシェーダのコンパイル - GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - const char* vertexShader = - "#version 120\n" - "attribute vec3 position;" - "attribute vec2 uv;" - "varying vec2 vuv;" - "void main(void){" - " gl_Position = vec4(position, 1.0);" - " vuv = uv;" - "}"; - glShaderSource(vertexShaderId, 1, &vertexShader, NULL); - glCompileShader(vertexShaderId); - - //フラグメントシェーダのコンパイル - GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragmentShader = - "#version 120\n" - "varying vec2 vuv;" - "uniform sampler2D texture;" - "uniform vec4 baseColor;" - "void main(void){" - " gl_FragColor = texture2D(texture, vuv) * baseColor;" - "}"; - glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL); - glCompileShader(fragmentShaderId); - - //プログラムオブジェクトの作成 - GLuint programId = glCreateProgram(); - glAttachShader(programId, vertexShaderId); - glAttachShader(programId, fragmentShaderId); - - // リンク - glLinkProgram(programId); - - glUseProgram(programId); - - return programId; -} - void LAppDelegate::SetExecuteAbsolutePath() { char path[1024]; diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.hpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.hpp index cac0f996..deb338b3 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.hpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppDelegate.hpp @@ -71,11 +71,6 @@ class LAppDelegate */ void OnMouseCallBack(GLFWwindow* window, double x, double y); - /** - * @brief シェーダーを登録する。 - */ - GLuint CreateShader(); - /** * @brief Window情報を取得する。 */ diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppLive2DManager.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppLive2DManager.cpp index b9c5c73d..959ec4ca 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppLive2DManager.cpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppLive2DManager.cpp @@ -29,6 +29,11 @@ using namespace LAppDefine; namespace { LAppLive2DManager* s_instance = NULL; + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion began: %x", self); + } + void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -184,7 +189,7 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) { LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); } - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -288,7 +293,7 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) _models[1]->GetModelMatrix()->TranslateX(0.2f); #endif - float clearColor[3] = { 1.0f, 1.0f, 1.0f }; + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.cpp index 739d1a88..cf965d76 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.cpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.cpp @@ -276,21 +276,10 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -443,7 +432,7 @@ void LAppModel::Update() } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -473,21 +462,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -496,6 +474,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -515,7 +494,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -524,7 +503,7 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -580,7 +559,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.hpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.hpp index 46f72277..3142d523 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.hpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppModel.hpp @@ -66,9 +66,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -76,9 +77,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppSpriteShader.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppSpriteShader.cpp new file mode 100644 index 00000000..3f200cdd --- /dev/null +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppSpriteShader.cpp @@ -0,0 +1,107 @@ +/** + * 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. + */ + +#include "LAppSpriteShader.hpp" + +#include "LAppDefine.hpp" +#include "LAppLive2DManager.hpp" +#include "LAppPal.hpp" + +LAppSpriteShader::LAppSpriteShader() +{ + _programId = CreateShader(); +} + +LAppSpriteShader::~LAppSpriteShader() +{ + glDeleteShader(_programId); +} + +GLuint LAppSpriteShader::GetShaderId() const +{ + return _programId; +} + +GLuint LAppSpriteShader::CreateShader() +{ + // シェーダーのパスの作成 + Csm::csmString vertShaderFile(LAppDefine::ShaderPath); + vertShaderFile += LAppDefine::VertShaderName; + Csm::csmString fragShaderFile(LAppDefine::ShaderPath); + fragShaderFile += LAppDefine::FragShaderName; + + // シェーダーのコンパイル + GLuint vertexShaderId = CompileShader(vertShaderFile, GL_VERTEX_SHADER); + GLuint fragmentShaderId = CompileShader(fragShaderFile, GL_FRAGMENT_SHADER); + + if (!vertexShaderId || !fragmentShaderId) + { + return 0; + } + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + // 不要になったシェーダーオブジェクトの削除 + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); + + return programId; +} + +bool LAppSpriteShader::CheckShader(GLuint shaderId) +{ + GLint status; + GLint logLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) + { + GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); + glGetShaderInfoLog(shaderId, logLength, &logLength, log); + CubismLogError("Shader compile log: %s", log); + CSM_FREE(log); + } + + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + glDeleteShader(shaderId); + return false; + } + + return true; +} + +GLuint LAppSpriteShader::CompileShader(Csm::csmString filename, GLenum shaderType) +{ + // ファイル読み込み + Csm::csmSizeInt bufferSize = 0; + const char* shaderString = reinterpret_cast(LAppPal::LoadFileAsBytes(filename.GetRawString(), &bufferSize)); + const GLint glSize = (GLint)bufferSize; + + // コンパイル + GLuint shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, 1, &shaderString, &glSize); + glCompileShader(shaderId); + + // 読み込んだシェーダー文字列の開放 + LAppPal::ReleaseBytes(reinterpret_cast(const_cast(shaderString))); + + if (!CheckShader(shaderId)) + { + return 0; + } + + return shaderId; +} diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppSpriteShader.hpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppSpriteShader.hpp new file mode 100644 index 00000000..93e6d058 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppSpriteShader.hpp @@ -0,0 +1,57 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用のシェーダー設定を保持するクラス +*/ +class LAppSpriteShader +{ +public: + /** + * @brief コンストラクタ + */ + LAppSpriteShader(); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーIDを取得する + */ + GLuint GetShaderId() const; + +private: + /** + * @brief シェーダーを作成する。 + */ + GLuint CreateShader(); + + /** + * @brief CreateShader内部関数 エラーチェック + */ + bool CheckShader(GLuint shaderId); + + /** + * @brief シェーダーをコンパイルする + * コンパイルに失敗した場合には 0 が戻る。 + * + * @param[in] filename シェーダーファイル名 + * @param[in] shaderType 作成するシェーダーの種類 + */ + GLuint CompileShader(Csm::csmString filename, GLenum shaderType); + + GLuint _programId; ///< シェーダID +}; diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppTextureManager.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppTextureManager.cpp index 99678f42..8d95eacf 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppTextureManager.cpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppTextureManager.cpp @@ -100,6 +100,7 @@ void LAppTextureManager::ReleaseTextures() { for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; } @@ -114,6 +115,7 @@ void LAppTextureManager::ReleaseTexture(Csm::csmUint32 textureId) { continue; } + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; @@ -126,6 +128,7 @@ void LAppTextureManager::ReleaseTexture(std::string fileName) { if (_textures[i]->fileName == fileName) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.cpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.cpp index 48e727d4..23e49b11 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.cpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.cpp @@ -15,6 +15,7 @@ #include "LAppDefine.hpp" #include "TouchManager.hpp" #include "LAppSprite.hpp" +#include "LAppSpriteShader.hpp" #include "LAppModel.hpp" #include @@ -24,7 +25,6 @@ using namespace std; using namespace LAppDefine; LAppView::LAppView(): - _programId(0), _back(NULL), _gear(NULL), _power(NULL), @@ -48,6 +48,7 @@ LAppView::LAppView(): LAppView::~LAppView() { _renderBuffer.DestroyOffscreenSurface(); + delete _spriteShader; delete _renderSprite; delete _viewMatrix; @@ -102,6 +103,9 @@ void LAppView::Initialize() ViewLogicalMaxBottom, ViewLogicalMaxTop ); + + // シェーダー作成 + _spriteShader = new LAppSpriteShader(); } void LAppView::Render() @@ -145,7 +149,7 @@ void LAppView::Render() void LAppView::InitializeSprite() { - _programId = LAppDelegate::GetInstance()->CreateShader(); + GLuint programId = _spriteShader->GetShaderId(); int width, height; glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); @@ -160,7 +164,7 @@ void LAppView::InitializeSprite() float y = height * 0.5f; float fWidth = static_cast(backgroundTexture->width * 2.0f); float fHeight = static_cast(height) * 0.95f; - _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _programId); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId); imageName = GearImageName; LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); @@ -169,7 +173,7 @@ void LAppView::InitializeSprite() y = static_cast(height - gearTexture->height * 0.5f); fWidth = static_cast(gearTexture->width); fHeight = static_cast(gearTexture->height); - _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _programId); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId); imageName = PowerImageName; LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); @@ -178,12 +182,12 @@ void LAppView::InitializeSprite() y = static_cast(powerTexture->height * 0.5f); fWidth = static_cast(powerTexture->width); fHeight = static_cast(powerTexture->height); - _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _programId); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId); // 画面全体を覆うサイズ x = width * 0.5f; y = height * 0.5f; - _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, _programId); + _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, programId); } diff --git a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.hpp b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.hpp index c8cc61aa..f27760e5 100644 --- a/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.hpp +++ b/Samples/OpenGL/Demo/proj.linux.cmake/src/LAppView.hpp @@ -16,6 +16,7 @@ class TouchManager; class LAppSprite; +class LAppSpriteShader; class LAppModel; /** @@ -150,7 +151,6 @@ class LAppView TouchManager* _touchManager; ///< タッチマネージャー Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix - GLuint _programId; ///< シェーダID LAppSprite* _back; ///< 背景画像 LAppSprite* _gear; ///< ギア画像 LAppSprite* _power; ///< 電源画像 @@ -160,4 +160,6 @@ class LAppView Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + LAppSpriteShader* _spriteShader; ///< シェーダー作成委譲クラス }; diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/CMakeLists.txt b/Samples/OpenGL/Demo/proj.mac.cmake/CMakeLists.txt index dadeff84..2abc3745 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.mac.cmake/CMakeLists.txt @@ -11,6 +11,7 @@ set(STB_PATH ${THIRD_PARTY_PATH}/stb) set(GLEW_PATH ${THIRD_PARTY_PATH}/glew) set(GLFW_PATH ${THIRD_PARTY_PATH}/glfw) set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SAMPLE_SHADER_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/Shaders/Standard) # Set project. project(${APP_NAME}) @@ -70,6 +71,7 @@ find_package(OpenGL REQUIRED) add_executable(${APP_NAME}) # Add source files. add_subdirectory(src) + # Link libraries to app. target_link_libraries(${APP_NAME} Framework @@ -86,6 +88,9 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy_directory ${RES_PATH} $/Resources + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${SAMPLE_SHADER_PATH} $/SampleShaders ) # You can change target that renderer draws by enabling following definition. diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/CMakeLists.txt b/Samples/OpenGL/Demo/proj.mac.cmake/src/CMakeLists.txt index cc79f718..7d572b8c 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/CMakeLists.txt @@ -38,6 +38,8 @@ else () ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.cpp index 5e7bc5c2..8edc3c7b 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.cpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.cpp @@ -211,21 +211,7 @@ void CubismUserModelExtend::PreloadMotionGroup(const csmChar* group) csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // モーションデータの読み込み - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); - - // フェードインの時間を取得 - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - // フェードアウトの時間を取得 - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelJson, group, i)); if (_motions[name]) { @@ -265,10 +251,9 @@ void CubismUserModelExtend::ReleaseModelSetting() * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 -* @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ -Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority) { // モーション数が取得出来なかった、もしくは0の時 if (!(_modelJson->GetMotionCount(group))) @@ -304,30 +289,13 @@ Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm:: csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // 一番先頭のモーションを読み込む - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); - - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } + motion = static_cast(LoadMotion(buffer, size, NULL, NULL, NULL, _modelJson, group, no)); // 終了時にメモリから削除 autoDelete = true; DeleteBuffer(buffer, path.GetRawString()); } - else - { - // モーションの再生終了コールバックを登録 - motion->SetFinishedMotionHandler(onFinishedMotionHandler); - } // 優先度を設定してモーションを始める return _motionManager->StartMotionPriority(motion, autoDelete, priority); diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.hpp index d0b486d4..c7f9aeab 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.hpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/CubismUserModelExtend.hpp @@ -59,10 +59,9 @@ class CubismUserModelExtend : * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 - * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority); /** * @brief 解放 diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.cpp index 20008c42..d7226d27 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.cpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.cpp @@ -37,6 +37,13 @@ namespace LAppDefine { // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = "SampleShaders/"; + // 頂点シェーダー + const csmChar* VertShaderName = "VertSprite.vert"; + // フラグメントシェーダー + const csmChar* FragShaderName = "FragSprite.frag"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.hpp index 8641224a..c4e76bcd 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.hpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDefine.hpp @@ -36,6 +36,10 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* VertShaderName; ///< 頂点シェーダー + extern const csmChar* FragShaderName; ///< フラグメントシェーダー + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.cpp index 4a14a258..f5bd8c96 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.cpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.cpp @@ -106,9 +106,6 @@ bool LAppDelegate::Initialize() _windowWidth = width; _windowHeight = height; - //AppViewの初期化 - _view->Initialize(); - // Cubism SDK の初期化 InitializeCubism(); @@ -117,7 +114,8 @@ bool LAppDelegate::Initialize() //load model LAppLive2DManager::GetInstance(); - //load sprite + //AppViewの初期化 + _view->Initialize(); _view->InitializeSprite(); return GL_TRUE; @@ -258,48 +256,6 @@ void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) _view->OnTouchesMoved(_mouseX, _mouseY); } -GLuint LAppDelegate::CreateShader() -{ - //バーテックスシェーダのコンパイル - GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - const char* vertexShader = - "#version 120\n" - "attribute vec3 position;" - "attribute vec2 uv;" - "varying vec2 vuv;" - "void main(void){" - " gl_Position = vec4(position, 1.0);" - " vuv = uv;" - "}"; - glShaderSource(vertexShaderId, 1, &vertexShader, NULL); - glCompileShader(vertexShaderId); - - //フラグメントシェーダのコンパイル - GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragmentShader = - "#version 120\n" - "varying vec2 vuv;" - "uniform sampler2D texture;" - "uniform vec4 baseColor;" - "void main(void){" - " gl_FragColor = texture2D(texture, vuv) * baseColor;" - "}"; - glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL); - glCompileShader(fragmentShaderId); - - //プログラムオブジェクトの作成 - GLuint programId = glCreateProgram(); - glAttachShader(programId, vertexShaderId); - glAttachShader(programId, fragmentShaderId); - - // リンク - glLinkProgram(programId); - - glUseProgram(programId); - - return programId; -} - void LAppDelegate::SetExecuteAbsolutePath() { char path[1024]; diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.hpp index 9b94810d..a7327b22 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.hpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppDelegate.hpp @@ -71,11 +71,6 @@ class LAppDelegate */ void OnMouseCallBack(GLFWwindow* window, double x, double y); - /** - * @brief シェーダーを登録する。 - */ - GLuint CreateShader(); - /** * @brief Window情報を取得する。 */ diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppLive2DManager.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppLive2DManager.cpp index b4527f05..a93996af 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppLive2DManager.cpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppLive2DManager.cpp @@ -30,6 +30,11 @@ using namespace LAppDefine; namespace { LAppLive2DManager* s_instance = NULL; + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion began: %x", self); + } + void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -186,7 +191,7 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) { LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); } - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -288,7 +293,7 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) _models[1]->GetModelMatrix()->TranslateX(0.2f); #endif - float clearColor[3] = { 1.0f, 1.0f, 1.0f }; + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.cpp index 739d1a88..cf965d76 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.cpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.cpp @@ -276,21 +276,10 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -443,7 +432,7 @@ void LAppModel::Update() } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -473,21 +462,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -496,6 +474,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -515,7 +494,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -524,7 +503,7 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -580,7 +559,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.hpp index 46f72277..3142d523 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.hpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppModel.hpp @@ -66,9 +66,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -76,9 +77,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppSpriteShader.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppSpriteShader.cpp new file mode 100644 index 00000000..a7ae720a --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppSpriteShader.cpp @@ -0,0 +1,110 @@ +/** + * 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. + */ + +#include "LAppSpriteShader.hpp" +#include +#include "LAppDefine.hpp" +#include "LAppPal.hpp" + +using namespace LAppDefine; + +LAppSpriteShader::LAppSpriteShader(csmString executeAbsolutePath) +{ + _programId = CreateShader(executeAbsolutePath); +} + +LAppSpriteShader::~LAppSpriteShader() +{ + glDeleteShader(_programId); +} + +GLuint LAppSpriteShader::GetShaderId() const +{ + return _programId; +} + +GLuint LAppSpriteShader::CreateShader(csmString executeAbsolutePath) +{ + // シェーダーのパスの作成 + Csm::csmString vertShaderFileName(executeAbsolutePath); + vertShaderFileName += ShaderPath; + vertShaderFileName += VertShaderName; + Csm::csmString fragShaderFileName(executeAbsolutePath); + fragShaderFileName += ShaderPath; + fragShaderFileName += FragShaderName; + + // 各シェーダーのコンパイル + GLuint vertexShaderId = CompileShader(vertShaderFileName, GL_VERTEX_SHADER); + GLuint fragmentShaderId = CompileShader(fragShaderFileName, GL_FRAGMENT_SHADER); + + if (!vertexShaderId || !fragmentShaderId) + { + return 0; + } + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + // 不要になったシェーダーオブジェクトの削除 + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); + + return programId; +} + +bool LAppSpriteShader::CheckShader(GLuint shaderId) +{ + GLint status; + GLint logLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) + { + GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); + glGetShaderInfoLog(shaderId, logLength, &logLength, log); + CubismLogError("Shader compile log: %s", log); + CSM_FREE(log); + } + + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + glDeleteShader(shaderId); + return false; + } + + return true; +} + +GLuint LAppSpriteShader::CompileShader(Csm::csmString filename, GLenum shaderType) +{ + // ファイル読み込み + Csm::csmSizeInt bufferSize = 0; + const char* shaderString = reinterpret_cast(LAppPal::LoadFileAsBytes(filename.GetRawString(), &bufferSize)); + const GLint glSize = (GLint)bufferSize; + + // コンパイル + GLuint shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, 1, &shaderString, &glSize); + glCompileShader(shaderId); + + // 読み込んだシェーダー文字列の開放 + LAppPal::ReleaseBytes(reinterpret_cast(const_cast(shaderString))); + + if (!CheckShader(shaderId)) + { + return 0; + } + + return shaderId; +} diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppSpriteShader.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppSpriteShader.hpp new file mode 100644 index 00000000..99cd936d --- /dev/null +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppSpriteShader.hpp @@ -0,0 +1,61 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用のシェーダー設定を保持するクラス +*/ +class LAppSpriteShader +{ +public: + /** + * @brief コンストラクタ + * + * @param[in] executeAbsolutePath 絶対パス + */ + LAppSpriteShader(Csm::csmString executeAbsolutePath); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーIDを取得する + */ + GLuint GetShaderId() const; + +private: + /** + * @brief シェーダーを作成する。 + * + * @param[in] executeAbsolutePath 絶対パス + */ + GLuint CreateShader(Csm::csmString executeAbsolutePath); + + /** + * @brief CreateShader内部関数 エラーチェック + */ + bool CheckShader(GLuint shaderId); + + /** + * @brief シェーダーをコンパイルする + * コンパイルに失敗した場合は 0 が戻る。 + * + * @param[in] filename シェーダーファイル名 + * @param[in] shaderType 作成するシェーダーの種類 + */ + GLuint CompileShader(Csm::csmString filename, GLenum shaderType); + + GLuint _programId; ///< シェーダID +}; diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppTextureManager.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppTextureManager.cpp index 99678f42..8d95eacf 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppTextureManager.cpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppTextureManager.cpp @@ -100,6 +100,7 @@ void LAppTextureManager::ReleaseTextures() { for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; } @@ -114,6 +115,7 @@ void LAppTextureManager::ReleaseTexture(Csm::csmUint32 textureId) { continue; } + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; @@ -126,6 +128,7 @@ void LAppTextureManager::ReleaseTexture(std::string fileName) { if (_textures[i]->fileName == fileName) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.cpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.cpp index 6c48cf05..c49af1c5 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.cpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.cpp @@ -15,6 +15,7 @@ #include "LAppDefine.hpp" #include "TouchManager.hpp" #include "LAppSprite.hpp" +#include "LAppSpriteShader.hpp" #include "LAppModel.hpp" #include @@ -24,7 +25,6 @@ using namespace std; using namespace LAppDefine; LAppView::LAppView(): - _programId(0), _back(NULL), _gear(NULL), _power(NULL), @@ -48,6 +48,7 @@ LAppView::LAppView(): LAppView::~LAppView() { _renderBuffer.DestroyOffscreenSurface(); + delete _spriteShader; delete _renderSprite; delete _viewMatrix; @@ -102,6 +103,9 @@ void LAppView::Initialize() ViewLogicalMaxBottom, ViewLogicalMaxTop ); + + // シェーダー作成 + _spriteShader = new LAppSpriteShader(LAppDelegate::GetInstance()->GetExecuteAbsolutePath().c_str()); } void LAppView::Render() @@ -153,7 +157,7 @@ void LAppView::Render() void LAppView::InitializeSprite() { - _programId = LAppDelegate::GetInstance()->CreateShader(); + GLuint programId = _spriteShader->GetShaderId(); int width, height; glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); @@ -168,7 +172,7 @@ void LAppView::InitializeSprite() float y = height * 0.5f; float fWidth = static_cast(backgroundTexture->width * 2.0f); float fHeight = static_cast(height) * 0.95f; - _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _programId); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId); imageName = GearImageName; LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); @@ -177,7 +181,7 @@ void LAppView::InitializeSprite() y = static_cast(height - gearTexture->height * 0.5f); fWidth = static_cast(gearTexture->width); fHeight = static_cast(gearTexture->height); - _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _programId); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId); imageName = PowerImageName; LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); @@ -186,12 +190,12 @@ void LAppView::InitializeSprite() y = static_cast(powerTexture->height * 0.5f); fWidth = static_cast(powerTexture->width); fHeight = static_cast(powerTexture->height); - _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _programId); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId); // 画面全体を覆うサイズ x = width * 0.5f; y = height * 0.5f; - _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, _programId); + _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, programId); } diff --git a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.hpp b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.hpp index c8cc61aa..888ef85d 100644 --- a/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.hpp +++ b/Samples/OpenGL/Demo/proj.mac.cmake/src/LAppView.hpp @@ -16,6 +16,7 @@ class TouchManager; class LAppSprite; +class LAppSpriteShader; class LAppModel; /** @@ -150,7 +151,6 @@ class LAppView TouchManager* _touchManager; ///< タッチマネージャー Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix - GLuint _programId; ///< シェーダID LAppSprite* _back; ///< 背景画像 LAppSprite* _gear; ///< ギア画像 LAppSprite* _power; ///< 電源画像 @@ -160,4 +160,6 @@ class LAppView Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + LAppSpriteShader* _spriteShader; ///< シェーダー作成委譲クラス }; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/CMakeLists.txt b/Samples/OpenGL/Demo/proj.win.cmake/CMakeLists.txt index 68bed6db..8c0b94cd 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.win.cmake/CMakeLists.txt @@ -17,6 +17,7 @@ set(STB_PATH ${THIRD_PARTY_PATH}/stb) set(GLEW_PATH ${THIRD_PARTY_PATH}/glew) set(GLFW_PATH ${THIRD_PARTY_PATH}/glfw) set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SAMPLE_SHADER_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/Shaders/Standard) # Set project. project(${APP_NAME}) @@ -54,10 +55,7 @@ else() message(FATAL_ERROR "[${APP_NAME}] Invalid linker flag ${CMAKE_EXE_LINKER_FLAGS}.") endif() # Detect compiler. -if(MSVC_VERSION MATCHES 1800) - # Visual Studio 2013 - set(COMPILER 120) -elseif(MSVC_VERSION MATCHES 1900) +if(MSVC_VERSION MATCHES 1900) # Visual Studio 2015 set(COMPILER 140) elseif(MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) @@ -66,7 +64,7 @@ elseif(MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) elseif(MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) # Visual Studio 2019 set(COMPILER 142) -elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) +elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1950) # Visual Studio 2022 set(COMPILER 143) elseif(MSVC) @@ -117,6 +115,7 @@ find_package(OpenGL REQUIRED) add_executable(${APP_NAME}) # Add source files. add_subdirectory(src) + # Link libraries to app. target_link_libraries(${APP_NAME} Framework @@ -135,9 +134,8 @@ target_compile_options(${APP_NAME} PRIVATE /MP) add_custom_command( TARGET ${APP_NAME} POST_BUILD - COMMAND - ${CMAKE_COMMAND} -E - copy_directory ${RES_PATH} $/Resources + COMMAND ${CMAKE_COMMAND} -E copy_directory ${RES_PATH} $/Resources + COMMAND ${CMAKE_COMMAND} -E copy_directory ${SAMPLE_SHADER_PATH} $/SampleShaders ) # Set project properties. diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2013.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2013.bat deleted file mode 100644 index 50de20fd..00000000 --- a/Samples/OpenGL/Demo/proj.win.cmake/scripts/nmake_msvc2013.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2013 -set MSVC_NUMBER=12 -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat -set GENERATOR=nmake - -call "%SCRIPT_PATH%_msvc_common.bat" -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2013.bat b/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2013.bat deleted file mode 100644 index d11674f6..00000000 --- a/Samples/OpenGL/Demo/proj.win.cmake/scripts/proj_msvc2013.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -setlocal - -set SCRIPT_PATH=%~dp0 -set MSVC_VERSION=2013 -set MSVC_NUMBER=12 -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat -set GENERATOR=proj - -call "%SCRIPT_PATH%_msvc_common.bat" -if %errorlevel% neq 0 pause & exit /b %errorlevel% - -pause & exit /b 0 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/CMakeLists.txt b/Samples/OpenGL/Demo/proj.win.cmake/src/CMakeLists.txt index cc79f718..7d572b8c 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/CMakeLists.txt +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/CMakeLists.txt @@ -38,6 +38,8 @@ else () ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpriteShader.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.cpp index a74b3ac1..02d994c1 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.cpp @@ -194,24 +194,10 @@ void CubismUserModelExtend::PreloadMotionGroup(const csmChar* group) csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // モーションデータの読み込み - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelJson, group, i)); if (tmpMotion) { - // フェードインの時間を取得 - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - // フェードアウトの時間を取得 - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } - if (_motions[name]) { // インスタンスを破棄 @@ -251,10 +237,9 @@ void CubismUserModelExtend::ReleaseModelSetting() * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 -* @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ -Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority) { // モーション数が取得出来なかった、もしくは0の時 if (!(_modelJson->GetMotionCount(group))) @@ -290,33 +275,16 @@ Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm:: csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); // 一番先頭のモーションを読み込む - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, NULL, NULL, _modelJson, group, no)); if (motion) { - csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } - // 終了時にメモリから削除 autoDelete = true; } DeleteBuffer(buffer, path.GetRawString()); } - else - { - // モーションの再生終了コールバックを登録 - motion->SetFinishedMotionHandler(onFinishedMotionHandler); - } // 優先度を設定してモーションを始める return _motionManager->StartMotionPriority(motion, autoDelete, priority); diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.hpp index f2569437..533313f0 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.hpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/CubismUserModelExtend.hpp @@ -74,10 +74,9 @@ class CubismUserModelExtend : * @param[in] group モーショングループ名 * @param[in] no グループ内の番号 * @param[in] priority 優先度 - * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority); /** * @brief 解放 diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.cpp index 2ca324cc..b20f54de 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.cpp @@ -37,6 +37,13 @@ namespace LAppDefine { // 終了ボタン const csmChar* PowerImageName = "close.png"; + // シェーダー相対パス + const csmChar* ShaderPath = "SampleShaders/"; + // 頂点シェーダー + const csmChar* VertShaderName = "VertSprite.vert"; + // フラグメントシェーダー + const csmChar* FragShaderName = "FragSprite.frag"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.hpp index 4a6a063b..f79deab1 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.hpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDefine.hpp @@ -35,6 +35,10 @@ namespace LAppDefine { extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル + extern const csmChar* ShaderPath; ///< シェーダーパス + extern const csmChar* VertShaderName; ///< 頂点シェーダー + extern const csmChar* FragShaderName; ///< フラグメントシェーダー + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.cpp index 65595ad6..f16efbd8 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.cpp @@ -103,12 +103,12 @@ bool LAppDelegate::Initialize() _windowWidth = width; _windowHeight = height; - //AppViewの初期化 - _view->Initialize(); - // Cubism SDK の初期化 InitializeCubism(); + //AppViewの初期化 + _view->Initialize(); + return GL_TRUE; } @@ -209,8 +209,6 @@ void LAppDelegate::InitializeCubism() CubismMatrix44 projection; LAppPal::UpdateTime(); - - _view->InitializeSprite(); } void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) @@ -255,76 +253,3 @@ void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) _view->OnTouchesMoved(_mouseX, _mouseY); } - -GLuint LAppDelegate::CreateShader() -{ - //バーテックスシェーダのコンパイル - GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - const char* vertexShader = - "#version 120\n" - "attribute vec3 position;" - "attribute vec2 uv;" - "varying vec2 vuv;" - "void main(void){" - " gl_Position = vec4(position, 1.0);" - " vuv = uv;" - "}"; - glShaderSource(vertexShaderId, 1, &vertexShader, NULL); - glCompileShader(vertexShaderId); - if(!CheckShader(vertexShaderId)) - { - return 0; - } - - //フラグメントシェーダのコンパイル - GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragmentShader = - "#version 120\n" - "varying vec2 vuv;" - "uniform sampler2D texture;" - "uniform vec4 baseColor;" - "void main(void){" - " gl_FragColor = texture2D(texture, vuv) * baseColor;" - "}"; - glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL); - glCompileShader(fragmentShaderId); - if (!CheckShader(fragmentShaderId)) - { - return 0; - } - - //プログラムオブジェクトの作成 - GLuint programId = glCreateProgram(); - glAttachShader(programId, vertexShaderId); - glAttachShader(programId, fragmentShaderId); - - // リンク - glLinkProgram(programId); - - glUseProgram(programId); - - return programId; -} - -bool LAppDelegate::CheckShader(GLuint shaderId) -{ - GLint status; - GLint logLength; - glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) - { - GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); - glGetShaderInfoLog(shaderId, logLength, &logLength, log); - CubismLogError("Shader compile log: %s", log); - CSM_FREE(log); - } - - glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); - if (status == GL_FALSE) - { - glDeleteShader(shaderId); - return false; - } - - return true; -} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.hpp index ad74ab8c..7738c597 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.hpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppDelegate.hpp @@ -69,11 +69,6 @@ class LAppDelegate */ void OnMouseCallBack(GLFWwindow* window, double x, double y); - /** - * @brief シェーダーを登録する。 - */ - GLuint CreateShader(); - /** * @brief Window情報を取得する。 */ @@ -112,11 +107,6 @@ class LAppDelegate */ void InitializeCubism(); - /** - * @brief CreateShader内部関数 エラーチェック - */ - bool CheckShader(GLuint shaderId); - LAppAllocator _cubismAllocator; ///< Cubism SDK Allocator Csm::CubismFramework::Option _cubismOption; ///< Cubism SDK Option GLFWwindow* _window; ///< OpenGL ウィンドウ diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppLive2DManager.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppLive2DManager.cpp index f03ce031..a85a22c2 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppLive2DManager.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppLive2DManager.cpp @@ -6,6 +6,7 @@ */ #include "LAppLive2DManager.hpp" +#include #include #include #include @@ -25,6 +26,11 @@ using namespace std; namespace { LAppLive2DManager* s_instance = NULL; + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion Began: %x", self); + } + void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -87,30 +93,43 @@ void LAppLive2DManager::SetUpModel() { // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 + // 一部文字が受け取れないためワイド文字で受け取ってUTF8に変換し格納する。 + csmString crawlPath(ResourcesPath); crawlPath += "*.*"; - struct _finddata_t fdata; - intptr_t fh = _findfirst(crawlPath.GetRawString(), &fdata); - if (fh == -1) return; + wchar_t wideStr[MAX_PATH]; + csmChar name[MAX_PATH]; + LAppPal::ConvertMultiByteToWide(crawlPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata; + intptr_t fh = _wfindfirst(wideStr, &fdata); + if (fh == -1) + { + return; + } _modelDir.Clear(); - while (_findnext(fh, &fdata) == 0) + while (_wfindnext(fh, &fdata) == 0) { - if ((fdata.attrib & _A_SUBDIR) && strcmp(fdata.name, "..") != 0) + if ((fdata.attrib & _A_SUBDIR) && wcscmp(fdata.name, L"..") != 0) { + LAppPal::ConvertWideToMultiByte(fdata.name, name, MAX_PATH); + // フォルダと同名の.model3.jsonがあるか探索する csmString model3jsonPath(ResourcesPath); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath.Append(1, '/'); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath += ".model3.json"; - struct _finddata_t fdata2; - if (_findfirst(model3jsonPath.GetRawString(), &fdata2) != -1) + LAppPal::ConvertMultiByteToWide(model3jsonPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata2; + if (_wfindfirst(wideStr, &fdata2) != -1) { - _modelDir.PushBack(csmString(fdata.name)); + _modelDir.PushBack(csmString(name)); } } } @@ -170,7 +189,7 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) { LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); } - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -276,7 +295,7 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); // 別レンダリング先を選択した際の背景クリア色 - float clearColor[3] = { 1.0f, 1.0f, 1.0f }; + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]); } } diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.cpp index 68dafd06..d62b1195 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.cpp @@ -280,21 +280,10 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -447,7 +436,7 @@ void LAppModel::Update() } -CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -477,21 +466,10 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); if (motion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -500,6 +478,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -519,7 +498,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt return _motionManager->StartMotionPriority(motion, autoDelete, priority); } -CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -528,7 +507,7 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -584,7 +563,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.hpp index 9c8a70b1..555797d6 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.hpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppModel.hpp @@ -66,9 +66,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -76,9 +77,10 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ - Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.cpp index 8e0f7cc0..263309c3 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.cpp @@ -6,6 +6,7 @@ */ #include "LAppPal.hpp" +#include #include #include #include @@ -27,12 +28,12 @@ double LAppPal::s_deltaTime = 0.0; csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { - //filePath;// - const char* path = filePath.c_str(); + wchar_t wideStr[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0U, filePath.c_str(), -1, wideStr, MAX_PATH); int size = 0; - struct stat statBuf; - if (stat(path, &statBuf) == 0) + struct _stat statBuf; + if (_wstat(wideStr, &statBuf) == 0) { size = statBuf.st_size; @@ -40,7 +41,7 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat succeeded but file size is zero. path:%s", path); + PrintLogLn("Stat succeeded but file size is zero. path:%s", filePath.c_str()); } return NULL; } @@ -49,27 +50,33 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat failed. errno:%d path:%s", errno, path); + PrintLogLn("Stat failed. errno:%d path:%s", errno, filePath.c_str()); } return NULL; } - std::fstream file; - file.open(path, std::ios::in | std::ios::binary); + std::wfstream file; + file.open(wideStr, std::ios::in | std::ios::binary); if (!file.is_open()) { if (DebugLogEnable) { - PrintLogLn("File open failed. path:%s", path); + PrintLogLn("File open failed. path:%s", filePath.c_str()); } return NULL; } - char* buf = new char[size]; - file.read(buf, size); - file.close(); + // ファイル名はワイド文字で探しているがファイルの中身はutf-8なので、1バイトずつ取得する。 *outSize = size; + csmChar* buf = new char[*outSize]; + std::wfilebuf* fileBuf = file.rdbuf(); + for (csmUint32 i = 0; i < *outSize; i++) + { + buf[i] = fileBuf->sbumpc(); + } + file.close(); + return reinterpret_cast(buf); } @@ -129,3 +136,13 @@ void LAppPal::PrintMessageLn(const csmChar* message) { PrintLogLn("%s", message); } + +bool LAppPal::ConvertMultiByteToWide(const csmChar* multiByte, wchar_t* wide, int wideSize) +{ + return MultiByteToWideChar(CP_UTF8, 0U, multiByte, -1, wide, wideSize) != 0; +} + +bool LAppPal::ConvertWideToMultiByte(const wchar_t* wide, csmChar* multiByte, int multiByteSize) +{ + return WideCharToMultiByte(CP_UTF8, 0U, wide, -1, multiByte, multiByteSize, NULL, NULL) != 0; +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.hpp index ac365794..f23c871b 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.hpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppPal.hpp @@ -92,6 +92,24 @@ class LAppPal */ static void PrintMessageLn(const Csm::csmChar* message); + /** + * @brief マルチバイト文字からワイド文字に変換する + * + * @param[in] multiByte 変換元 + * @param[in] wide 格納先 + * @param[in] wideSize 格納先の大きさ + */ + static bool ConvertMultiByteToWide(const Csm::csmChar* multiByte, wchar_t* wide, int wideSize); + + /** + * @brief ワイド文字からマルチバイト文字に変換する + * + * @param[in] wide 変換元 + * @param[in] multiByte 格納先 + * @param[in] multiByteSize 格納先の大きさ + */ + static bool ConvertWideToMultiByte(const wchar_t* wide, Csm::csmChar* multiByte, int multiByteSize); + private: static double s_currentFrame; static double s_lastFrame; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppSpriteShader.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppSpriteShader.cpp new file mode 100644 index 00000000..5a225711 --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppSpriteShader.cpp @@ -0,0 +1,108 @@ +/** + * 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. + */ + +#include "LAppSpriteShader.hpp" +#include +#include "LAppDefine.hpp" +#include "LAppPal.hpp" + +using namespace LAppDefine; + +LAppSpriteShader::LAppSpriteShader() +{ + _programId = CreateShader(); +} + +LAppSpriteShader::~LAppSpriteShader() +{ + glDeleteShader(_programId); +} + +GLuint LAppSpriteShader::GetShaderId() const +{ + return _programId; +} + +GLuint LAppSpriteShader::CreateShader() +{ + // シェーダーのパスの作成 + Csm::csmString vertShaderFile(ShaderPath); + vertShaderFile += VertShaderName; + Csm::csmString fragShaderFile(ShaderPath); + fragShaderFile += FragShaderName; + + // シェーダーのコンパイル + GLuint vertexShaderId = CompileShader(vertShaderFile, GL_VERTEX_SHADER); + GLuint fragmentShaderId = CompileShader(fragShaderFile, GL_FRAGMENT_SHADER); + + if (!vertexShaderId || !fragmentShaderId) + { + return 0; + } + + //プログラムオブジェクトの作成 + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexShaderId); + glAttachShader(programId, fragmentShaderId); + + // リンク + glLinkProgram(programId); + + glUseProgram(programId); + + // 不要になったシェーダーオブジェクトの削除 + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); + + return programId; +} + +bool LAppSpriteShader::CheckShader(GLuint shaderId) +{ + GLint status; + GLint logLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) + { + GLchar* log = reinterpret_cast(CSM_MALLOC(logLength)); + glGetShaderInfoLog(shaderId, logLength, &logLength, log); + CubismLogError("Shader compile log: %s", log); + CSM_FREE(log); + } + + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + glDeleteShader(shaderId); + return false; + } + + return true; +} + +GLuint LAppSpriteShader::CompileShader(Csm::csmString filename, GLenum shaderType) +{ + // ファイル読み込み + Csm::csmSizeInt bufferSize = 0; + const char* shaderString = reinterpret_cast(LAppPal::LoadFileAsBytes(filename.GetRawString(), &bufferSize)); + const GLint glSize = (GLint)bufferSize; + + // コンパイル + GLuint shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, 1, &shaderString, &glSize); + glCompileShader(shaderId); + + // 読み込んだシェーダー文字列の開放 + LAppPal::ReleaseBytes(reinterpret_cast(const_cast(shaderString))); + + if (!CheckShader(shaderId)) + { + return 0; + } + + return shaderId; +} diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppSpriteShader.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppSpriteShader.hpp new file mode 100644 index 00000000..cff144bc --- /dev/null +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppSpriteShader.hpp @@ -0,0 +1,57 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用のシェーダー設定を保持するクラス +*/ +class LAppSpriteShader +{ +public: + /** + * @brief コンストラクタ + */ + LAppSpriteShader(); + + /** + * @brief デストラクタ + */ + ~LAppSpriteShader(); + + /** + * @brief シェーダーIDを取得する + */ + GLuint GetShaderId() const; + +private: + /** + * @brief シェーダーオブジェクトを作成する。 + */ + GLuint CreateShader(); + + /** + * @brief CreateShader内部関数 エラーチェック + */ + bool CheckShader(GLuint shaderId); + + /** + * @brief シェーダーをコンパイルする。 + * コンパイルに失敗した場合には 0 が戻る。 + * + * @param[in] filename シェーダーファイル名 + * @param[in] shaderType 作成するシェーダーの種類 + */ + GLuint CompileShader(Csm::csmString filename, GLenum shaderType); + + GLuint _programId; ///< シェーダID +}; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppTextureManager.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppTextureManager.cpp index b3af708b..b7eee2e7 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppTextureManager.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppTextureManager.cpp @@ -93,6 +93,7 @@ void LAppTextureManager::ReleaseTextures() { for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; } @@ -107,6 +108,7 @@ void LAppTextureManager::ReleaseTexture(Csm::csmUint32 textureId) { continue; } + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; @@ -119,6 +121,7 @@ void LAppTextureManager::ReleaseTexture(std::string fileName) { if (_textures[i]->fileName == fileName) { + glDeleteTextures(1, &(_textures[i]->id)); delete _textures[i]; _textures.Remove(i); break; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.cpp index 12cc7533..7bac5404 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.cpp @@ -15,13 +15,13 @@ #include "LAppDefine.hpp" #include "TouchManager.hpp" #include "LAppSprite.hpp" +#include "LAppSpriteShader.hpp" #include "LAppModel.hpp" using namespace std; using namespace LAppDefine; LAppView::LAppView(): - _programId(0), _back(NULL), _gear(NULL), _power(NULL), @@ -46,6 +46,7 @@ LAppView::LAppView(): LAppView::~LAppView() { _renderBuffer.DestroyOffscreenSurface(); + delete _spriteShader; delete _renderSprite; delete _viewMatrix; delete _deviceToScreen; @@ -99,6 +100,11 @@ void LAppView::Initialize() ViewLogicalMaxBottom, ViewLogicalMaxTop ); + + // シェーダー作成 + _spriteShader = new LAppSpriteShader(); + + InitializeSprite(); } void LAppView::Render() @@ -149,7 +155,7 @@ void LAppView::Render() void LAppView::InitializeSprite() { - _programId = LAppDelegate::GetInstance()->CreateShader(); + GLuint programId = _spriteShader->GetShaderId(); int width, height; glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); @@ -164,7 +170,7 @@ void LAppView::InitializeSprite() float y = height * 0.5f; float fWidth = static_cast(backgroundTexture->width * 2.0f); float fHeight = static_cast(height * 0.95f); - _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _programId); + _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId); imageName = GearImageName; LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); @@ -173,7 +179,7 @@ void LAppView::InitializeSprite() y = static_cast(height - gearTexture->height * 0.5f); fWidth = static_cast(gearTexture->width); fHeight = static_cast(gearTexture->height); - _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _programId); + _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId); imageName = PowerImageName; LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName); @@ -182,12 +188,12 @@ void LAppView::InitializeSprite() y = static_cast(powerTexture->height * 0.5f); fWidth = static_cast(powerTexture->width); fHeight = static_cast(powerTexture->height); - _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _programId); + _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId); // 画面全体を覆うサイズ x = width * 0.5f; y = height * 0.5f; - _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, _programId); + _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, programId); } void LAppView::OnTouchesBegan(float px, float py) const diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.hpp b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.hpp index 3d8751db..59077bb6 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.hpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/LAppView.hpp @@ -17,6 +17,7 @@ class TouchManager; class LAppSprite; class LAppModel; +class LAppSpriteShader; /** * @brief 描画クラス @@ -150,7 +151,6 @@ class LAppView TouchManager* _touchManager; ///< タッチマネージャー Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix - GLuint _programId; ///< シェーダID LAppSprite* _back; ///< 背景画像 LAppSprite* _gear; ///< ギア画像 LAppSprite* _power; ///< 電源画像 @@ -160,4 +160,6 @@ class LAppView Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + + LAppSpriteShader* _spriteShader; ///< シェーダー作成委譲クラス }; diff --git a/Samples/OpenGL/Demo/proj.win.cmake/src/main.cpp b/Samples/OpenGL/Demo/proj.win.cmake/src/main.cpp index 07b6e814..e0729bdf 100644 --- a/Samples/OpenGL/Demo/proj.win.cmake/src/main.cpp +++ b/Samples/OpenGL/Demo/proj.win.cmake/src/main.cpp @@ -6,17 +6,25 @@ */ #include "LAppDelegate.hpp" +#include int main() { + // Setting the console character encoding to UTF-8 + UINT preConsoleOutputCP = GetConsoleOutputCP(); + SetConsoleOutputCP(65001); + // create the application instance if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE) { + SetConsoleOutputCP(preConsoleOutputCP); return 1; } LAppDelegate::GetInstance()->Run(); + SetConsoleOutputCP(preConsoleOutputCP); + return 0; } diff --git a/Samples/OpenGL/README.ja.md b/Samples/OpenGL/README.ja.md index ff97206a..07d68dd0 100644 --- a/Samples/OpenGL/README.ja.md +++ b/Samples/OpenGL/README.ja.md @@ -13,8 +13,8 @@ OpenGL で実装したアプリケーションのサンプル実装です。 | --- | --- | | [GLEW] | 2.2.0 | | [GLFW] | 3.4 | -| [ios-cmake] | 4.4.1 | -| [stb_image.h] | 2.29 | +| [ios-cmake] | 4.5.0 | +| [stb_image.h] | 2.30 | その他の開発環境・動作確認環境はトップディレクトリにある [README.md](/README.ja.md) を参照してください。 @@ -27,6 +27,8 @@ OpenGL で実装したアプリケーションのサンプル実装です。 │ ├─ proj.android.cmake │ │ ├─Full # Full Demo Android Studio project │ │ └─Minimum # Minimum Demo Android Studio project +│ ├─ proj.harmonyos.cmake +│ │ └─Full # Full Demo DevEco Studio project │ ├─ proj.ios.cmake # CMake project for iOS │ ├─ proj.linux.cmake # CMake project for Linux │ ├─ proj.mac.cmake # CMake project for macOS @@ -64,6 +66,10 @@ NOTE: 事前に下記の SDK のダウンロードが必要です * NDK * CMake +### proj.harmonyos.cmake + +このディレクトリにはフルバージョンの DevEco Studio プロジェクトが含まれます。 + ### proj.ios.cmake iOS 用の CMake プロジェクトです。 @@ -146,14 +152,12 @@ Windows 用の CMake プロジェクトです。 | プラットフォーム | スクリプト名 | | --- | --- | | Linux *1 / macOS | `setup_glew_glfw` | -| Windows *2 | `setup_glew_glfw.bat` | +| Windows | `setup_glew_glfw.bat` | スクリプト内の `GLEW_VERSION` 及び `GLFW_VERSION` を変更することで、ダウンロードするバージョンを変更できます。 *1 Linuxでは GLFW が依存するライブラリのインストールが必要になる場合がございますので、公式ページを参考に依存関係にあるライブラリをすべてインストールしてください。 [GLFW.org Dependencies for X11 on Unix-like systems](https://www.glfw.org/docs/latest/compile_guide.html#compile_deps_x11) -*2 `Visual Studio 2013` をご利用の際、追加対応が必要となる場合がございます。 -詳しくは [NOTICE.md](/NOTICE.ja.md) をご確認ください。 ## ios-cmake のセットアップ diff --git a/Samples/OpenGL/README.md b/Samples/OpenGL/README.md index f820e95a..c879b5b2 100644 --- a/Samples/OpenGL/README.md +++ b/Samples/OpenGL/README.md @@ -13,8 +13,8 @@ This is a sample implementation of an application implemented with OpenGL. | --- | --- | | [GLEW] | 2.2.0 | | [GLFW] | 3.4 | -| [ios-cmake] | 4.4.1 | -| [stb_image.h] | 2.29 | +| [ios-cmake] | 4.5.0 | +| [stb_image.h] | 2.30 | For other development environments and operation environments, see [README.md](/README.md) in the top directory. @@ -27,6 +27,8 @@ For other development environments and operation environments, see [README.md](/ │ ├─ proj.android.cmake │ │ ├─Full # Full Demo Android Studio project │ │ └─Minimum # Minimum Demo Android Studio project +│ ├─ proj.harmonyos.cmake +│ │ └─Full # Full Demo DevEco Studio project │ ├─ proj.ios.cmake # CMake project for iOS │ ├─ proj.linux.cmake # CMake project for Linux │ ├─ proj.mac.cmake # CMake project for macOS @@ -64,6 +66,10 @@ NOTE: You need to download the following SDKs in advance. * NDK * CMake +### proj.harmonyos.cmake + +This directory contains one DevEco Studio projects: the full version. + ### proj.ios.cmake CMake project for iOS. @@ -146,14 +152,12 @@ Download GLEW and GLFW by running the script in the `script` directory. | Platform | Script name | | --- | --- | | Linux *1 / macOS | `setup_glew_glfw` | -| Windows *2 | `setup_glew_glfw.bat` | +| Windows | `setup_glew_glfw.bat` | You can change the version to download by changing `GLEW_VERSION` and `GLFW_VERSION` in the script. *1 On Linux, it may be necessary to install libraries on which GLFW depends. Please refer to the official page to install all libraries on which GLFW depends. [GLFW.org Dependencies for X11 on Unix-like systems](https://www.glfw.org/docs/latest/compile_guide.html#compile_deps_x11) -*2 Additional support may be required when using `Visual Studio 2013`. -See [NOTICE.md](/NOTICE.md) for details. ## ios-cmake setup diff --git a/Samples/OpenGL/Shaders/Standard/FragSprite.frag b/Samples/OpenGL/Shaders/Standard/FragSprite.frag new file mode 100644 index 00000000..fdf6f444 --- /dev/null +++ b/Samples/OpenGL/Shaders/Standard/FragSprite.frag @@ -0,0 +1,17 @@ +/** + * 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. + */ + +#version 120 + +varying vec2 vuv; +uniform sampler2D texture; +uniform vec4 baseColor; + +void main(void) +{ + gl_FragColor = texture2D(texture, vuv) * baseColor; +} diff --git a/Samples/OpenGL/Shaders/Standard/VertSprite.vert b/Samples/OpenGL/Shaders/Standard/VertSprite.vert new file mode 100644 index 00000000..9793598c --- /dev/null +++ b/Samples/OpenGL/Shaders/Standard/VertSprite.vert @@ -0,0 +1,18 @@ +/** + * 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. + */ + +#version 120 + +attribute vec3 position; +attribute vec2 uv; +varying vec2 vuv; + +void main(void) +{ + gl_Position = vec4(position, 1.0); + vuv = uv; +} diff --git a/Samples/OpenGL/Shaders/StandardES/FragSprite.frag b/Samples/OpenGL/Shaders/StandardES/FragSprite.frag new file mode 100644 index 00000000..fb3cb0e3 --- /dev/null +++ b/Samples/OpenGL/Shaders/StandardES/FragSprite.frag @@ -0,0 +1,19 @@ +/** + * 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. + */ + +#version 100 + +precision mediump float; + +varying vec2 vuv; +uniform sampler2D texture; +uniform vec4 baseColor; + +void main(void) +{ + gl_FragColor = texture2D(texture, vuv) * baseColor; +} diff --git a/Samples/OpenGL/Shaders/StandardES/VertSprite.vert b/Samples/OpenGL/Shaders/StandardES/VertSprite.vert new file mode 100644 index 00000000..0ae4e4a7 --- /dev/null +++ b/Samples/OpenGL/Shaders/StandardES/VertSprite.vert @@ -0,0 +1,18 @@ +/** + * 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. + */ + +#version 100 + +attribute vec3 position; +attribute vec2 uv; +varying vec2 vuv; + +void main(void) +{ + gl_Position = vec4(position, 1.0); + vuv = uv; +} diff --git a/Samples/OpenGL/thirdParty/scripts/setup_glew_glfw_vs2013.bat b/Samples/OpenGL/thirdParty/scripts/setup_glew_glfw_vs2013.bat deleted file mode 100644 index 9dc97117..00000000 --- a/Samples/OpenGL/thirdParty/scripts/setup_glew_glfw_vs2013.bat +++ /dev/null @@ -1,45 +0,0 @@ -@echo off - -set GLEW_VERSION=2.1.0 -set GLFW_VERSION=3.4 - -set SCRIPT_PATH=%~dp0 - -cd %SCRIPT_PATH%/.. - -:::::::::::::::: -:: Setup GLEW :: -:::::::::::::::: - -:: Download and extract the archive. -echo - Setup GLEW %GLEW_VERSION% -echo Downloading... -curl -fsSL -o glew.zip ^ - "https://github.com/nigels-com/glew/releases/download/glew-%GLEW_VERSION%/glew-%GLEW_VERSION%.zip" -if %errorlevel% neq 0 pause & exit /b %errorlevel% -echo Extracting... -powershell "$progressPreference = 'silentlyContinue'; expand-archive -force glew.zip ." -if %errorlevel% neq 0 pause & exit /b %errorlevel% -ren glew-%GLEW_VERSION% glew -del glew.zip - -:::::::::::::::: -:: Setup GLFW :: -:::::::::::::::: - -echo. - -:: Download and extract the archive. -echo - Setup GLFW %GLFW_VERSION% -echo Downloading... -curl -fsSL -o glfw.zip ^ - https://github.com/glfw/glfw/releases/download/%GLFW_VERSION%/glfw-%GLFW_VERSION%.zip -if %errorlevel% neq 0 pause & exit /b %errorlevel% -echo Extracting... -powershell "$progressPreference = 'silentlyContinue'; expand-archive -force glfw.zip ." -if %errorlevel% neq 0 pause & exit /b %errorlevel% -ren glfw-%GLFW_VERSION% glfw -del glfw.zip - -echo. -pause diff --git a/Samples/OpenGL/thirdParty/scripts/setup_ios_cmake b/Samples/OpenGL/thirdParty/scripts/setup_ios_cmake index 50315928..84399633 100644 --- a/Samples/OpenGL/thirdParty/scripts/setup_ios_cmake +++ b/Samples/OpenGL/thirdParty/scripts/setup_ios_cmake @@ -2,7 +2,7 @@ set -ue -IOS_CMAKE_VERSION=4.4.1 +IOS_CMAKE_VERSION=4.5.0 SCRIPT_PATH=$(cd $(dirname $0) && pwd) diff --git a/Samples/OpenGL/thirdParty/stb/README.md b/Samples/OpenGL/thirdParty/stb/README.md index f228dac1..6a8a4870 100644 --- a/Samples/OpenGL/thirdParty/stb/README.md +++ b/Samples/OpenGL/thirdParty/stb/README.md @@ -5,16 +5,18 @@ stb single-file public domain (or MIT licensed) libraries for C/C++ +# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries. + Noteworthy: * image loader: [stb_image.h](stb_image.h) * image writer: [stb_image_write.h](stb_image_write.h) -* image resizer: [stb_image_resize.h](stb_image_resize.h) +* image resizer: [stb_image_resize2.h](stb_image_resize2.h) * font text rasterizer: [stb_truetype.h](stb_truetype.h) * typesafe containers: [stb_ds.h](stb_ds.h) -Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize -by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. +Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize +by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts. @@ -22,10 +24,10 @@ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.22 | audio | 5584 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_hexwave.h](stb_hexwave.h)** | 0.5 | audio | 680 | audio waveform synthesizer -**[stb_image.h](stb_image.h)** | 2.28 | graphics | 7987 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.26 | graphics | 5077 | parse, decode, and rasterize characters from truetype fonts +**[stb_image.h](stb_image.h)** | 2.30 | graphics | 7988 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.26 | graphics | 5079 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.16 | graphics | 1724 | image writing to disk: PNG, TGA, BMP -**[stb_image_resize.h](stb_image_resize.h)** | 0.97 | graphics | 2634 | resize images larger/smaller with good quality +**[stb_image_resize2.h](stb_image_resize2.h)** | 2.12 | graphics | 10601 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 1.01 | graphics | 623 | simple 2D rectangle packer with decent quality **[stb_perlin.h](stb_perlin.h)** | 0.5 | graphics | 428 | perlin's revised simplex noise w/ different seeds **[stb_ds.h](stb_ds.h)** | 0.67 | utility | 1895 | typesafe dynamic array and hash tables for C, will compile in C++ @@ -36,14 +38,14 @@ library | lastest version | category | LoC | description **[stb_easy_font.h](stb_easy_font.h)** | 1.1 | 3D graphics | 305 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.42 | game dev | 4187 | embeddable tilemap editor **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.7 | game dev | 1221 | herringbone Wang tile map generator -**[stb_c_lexer.h](stb_c_lexer.h)** | 0.12 | parsing | 940 | simplify writing parsers for C-like languages +**[stb_c_lexer.h](stb_c_lexer.h)** | 0.12 | parsing | 941 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.94 | math | 433 | more useful 32-bit modulus e.g. "euclidean divide" **[stb_connected_comp...](stb_connected_components.h)** | 0.96 | misc | 1049 | incrementally compute reachability on grids **[stb_leakcheck.h](stb_leakcheck.h)** | 0.6 | misc | 194 | quick-and-dirty malloc/free leak-checking **[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL Total libraries: 21 -Total lines of C code: 43117 +Total lines of C code: 51088 FAQ diff --git a/Samples/OpenGL/thirdParty/stb/stb_image.h b/Samples/OpenGL/thirdParty/stb/stb_image.h index 5e807a0a..9eedabed 100644 --- a/Samples/OpenGL/thirdParty/stb/stb_image.h +++ b/Samples/OpenGL/thirdParty/stb/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: @@ -48,6 +48,8 @@ LICENSE RECENT REVISION HISTORY: + 2.30 (2024-05-31) avoid erroneous gcc warning + 2.29 (2023-05-xx) optimizations 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.26 (2020-07-13) many minor fixes @@ -1072,8 +1074,8 @@ static int stbi__addints_valid(int a, int b) return a <= INT_MAX - b; } -// returns 1 if the product of two signed shorts is valid, 0 on overflow. -static int stbi__mul2shorts_valid(short a, short b) +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) { if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid @@ -3384,13 +3386,13 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) return 1; } -static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) { // some JPEGs have junk at end, skip over it but if we find what looks // like a valid marker, resume there while (!stbi__at_eof(j->s)) { - int x = stbi__get8(j->s); - while (x == 255) { // might be a marker + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker if (stbi__at_eof(j->s)) return STBI__MARKER_none; x = stbi__get8(j->s); if (x != 0x00 && x != 0xff) { @@ -4176,6 +4178,7 @@ typedef struct { stbi_uc *zbuffer, *zbuffer_end; int num_bits; + int hit_zeof_once; stbi__uint32 code_buffer; char *zout; @@ -4242,9 +4245,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) int b,s; if (a->num_bits < 16) { if (stbi__zeof(a)) { - return -1; /* report error for unexpected end of data. */ + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); } - stbi__fill_bits(a); } b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b) { @@ -4309,6 +4323,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) int len,dist; if (z == 256) { a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } return 1; } if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data @@ -4320,7 +4341,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); - if (zout + len > a->zout_end) { + if (len > a->zout_end - zout) { if (!stbi__zexpand(a, zout, len)) return 0; zout = a->zout; } @@ -4464,6 +4485,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) if (!stbi__parse_zlib_header(a)) return 0; a->num_bits = 0; a->code_buffer = 0; + a->hit_zeof_once = 0; do { final = stbi__zreceive(a,1); type = stbi__zreceive(a,2); @@ -4619,9 +4641,8 @@ enum { STBI__F_up=2, STBI__F_avg=3, STBI__F_paeth=4, - // synthetic filters used for first scanline to avoid needing a dummy row of 0s - STBI__F_avg_first, - STBI__F_paeth_first + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first }; static stbi_uc first_row_filter[5] = @@ -4630,29 +4651,56 @@ static stbi_uc first_row_filter[5] = STBI__F_sub, STBI__F_none, STBI__F_avg_first, - STBI__F_paeth_first + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub }; static int stbi__paeth(int a, int b, int c) { - int p = a + b - c; - int pa = abs(p-a); - int pb = abs(p-b); - int pc = abs(p-c); - if (pa <= pb && pa <= pc) return a; - if (pb <= pc) return b; - return c; + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; } static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { - int bytes = (depth == 16? 2 : 1); + int bytes = (depth == 16 ? 2 : 1); stbi__context *s = a->s; stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; int k; int img_n = s->img_n; // copy it into a local for later @@ -4664,8 +4712,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); img_len = (img_width_bytes + 1) * y; // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, @@ -4673,189 +4724,137 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r // so just check for raw_len < img_len always. if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *prior; + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; int filter = *raw++; - if (filter > 4) - return stbi__err("invalid filter","Corrupt PNG"); - - if (depth < 8) { - if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); - cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place - filter_bytes = 1; - width = img_width_bytes; + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; } - prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; - // handle first byte explicitly - for (k=0; k < filter_bytes; ++k) { - switch (filter) { - case STBI__F_none : cur[k] = raw[k]; break; - case STBI__F_sub : cur[k] = raw[k]; break; - case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; - case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; - case STBI__F_avg_first : cur[k] = raw[k]; break; - case STBI__F_paeth_first: cur[k] = raw[k]; break; - } - } - - if (depth == 8) { - if (img_n != out_n) - cur[img_n] = 255; // first pixel - raw += img_n; - cur += out_n; - prior += out_n; - } else if (depth == 16) { - if (img_n != out_n) { - cur[filter_bytes] = 255; // first pixel top byte - cur[filter_bytes+1] = 255; // first pixel bottom byte - } - raw += filter_bytes; - cur += output_bytes; - prior += output_bytes; - } else { - raw += 1; - cur += 1; - prior += 1; + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; } - // this is a little gross, so that we don't switch per-pixel or per-component - if (depth < 8 || img_n == out_n) { - int nk = (width - 1)*filter_bytes; - #define STBI__CASE(f) \ - case f: \ - for (k=0; k < nk; ++k) - switch (filter) { - // "none" filter turns into a memcpy here; make that explicit. - case STBI__F_none: memcpy(cur, raw, nk); break; - STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; - STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; - STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; - STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; - } - #undef STBI__CASE - raw += nk; - } else { - STBI_ASSERT(img_n+1 == out_n); - #define STBI__CASE(f) \ - case f: \ - for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ - for (k=0; k < filter_bytes; ++k) - switch (filter) { - STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; - STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; - STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; - STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; - STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; - } - #undef STBI__CASE - - // the loop above sets the high byte of the pixels' alpha, but for - // 16 bit png files we also need the low byte set. we'll do that here. - if (depth == 16) { - cur = a->out + stride*j; // start at the beginning of the row again - for (i=0; i < x; ++i,cur+=output_bytes) { - cur[filter_bytes+1] = 255; - } - } - } - } + raw += nk; - // we make a separate pass to expand bits to pixels; for performance, - // this could run two scanlines behind the above code, so it won't - // intefere with filtering but will still be in the cache. - if (depth < 8) { - for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; - // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit - // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; - // note that the final byte might overshoot and write more data than desired. - // we can allocate enough data that this never writes out of memory, but it - // could also overwrite the next scanline. can it overwrite non-empty data - // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. - // so we need to explicitly clamp the final ones - + // expand bits to bytes first if (depth == 4) { - for (k=x*img_n; k >= 2; k-=2, ++in) { - *cur++ = scale * ((*in >> 4) ); - *cur++ = scale * ((*in ) & 0x0f); + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; } - if (k > 0) *cur++ = scale * ((*in >> 4) ); } else if (depth == 2) { - for (k=x*img_n; k >= 4; k-=4, ++in) { - *cur++ = scale * ((*in >> 6) ); - *cur++ = scale * ((*in >> 4) & 0x03); - *cur++ = scale * ((*in >> 2) & 0x03); - *cur++ = scale * ((*in ) & 0x03); + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; } - if (k > 0) *cur++ = scale * ((*in >> 6) ); - if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); - if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); - } else if (depth == 1) { - for (k=x*img_n; k >= 8; k-=8, ++in) { - *cur++ = scale * ((*in >> 7) ); - *cur++ = scale * ((*in >> 6) & 0x01); - *cur++ = scale * ((*in >> 5) & 0x01); - *cur++ = scale * ((*in >> 4) & 0x01); - *cur++ = scale * ((*in >> 3) & 0x01); - *cur++ = scale * ((*in >> 2) & 0x01); - *cur++ = scale * ((*in >> 1) & 0x01); - *cur++ = scale * ((*in ) & 0x01); + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; } - if (k > 0) *cur++ = scale * ((*in >> 7) ); - if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); - if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); - if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); - if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); - if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); - if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); } - if (img_n != out_n) { - int q; - // insert alpha = 255 - cur = a->out + stride*j; + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); if (img_n == 1) { - for (q=x-1; q >= 0; --q) { - cur[q*2+1] = 255; - cur[q*2+0] = cur[q]; + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; } } else { STBI_ASSERT(img_n == 3); - for (q=x-1; q >= 0; --q) { - cur[q*4+3] = 255; - cur[q*4+2] = cur[q*3+2]; - cur[q*4+1] = cur[q*3+1]; - cur[q*4+0] = cur[q*3+0]; + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; } } } } - } else if (depth == 16) { - // force the image data from big-endian to platform-native. - // this is done in a separate pass due to the decoding relying - // on the data being untouched, but could probably be done - // per-line during decode if care is taken. - stbi_uc *cur = a->out; - stbi__uint16 *cur16 = (stbi__uint16*)cur; - - for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { - *cur16 = (cur[0] << 8) | cur[1]; - } } + STBI_FREE(filter_buf); + if (!all_ok) return 0; + return 1; } @@ -5161,9 +5160,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } if (z->depth == 16) { - for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning + tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is } else { - for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + for (k = 0; k < s->img_n && k < 3; ++k) + tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger } } break; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/CMakeLists.txt b/Samples/Vulkan/Demo/proj.linux.cmake/CMakeLists.txt new file mode 100644 index 00000000..370015ce --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/CMakeLists.txt @@ -0,0 +1,119 @@ +cmake_minimum_required(VERSION 3.16) + +# Set app name. +set(APP_NAME Demo) +# Set directory paths. +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) +set(CORE_PATH ${SDK_ROOT_PATH}/Core) +set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework) +set(THIRD_PARTY_PATH ${SDK_ROOT_PATH}/Samples/Vulkan/thirdParty) +set(STB_PATH ${THIRD_PARTY_PATH}/stb) +set(GLFW_PATH ${THIRD_PARTY_PATH}/glfw) +set(RES_PATH ${SDK_ROOT_PATH}/Samples/Resources) +set(SAMPLE_SHADER_PATH ${SDK_ROOT_PATH}/Samples/Vulkan/Shaders) +set(FRAMEWORK_SHADER_PATH ${FRAMEWORK_PATH}/src/Rendering/Vulkan/Shaders) + +# Set project. +project(${APP_NAME}) + +# Define output directory. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/${APP_NAME}) +# Set configuration (Release and Debug only). +set(CMAKE_CONFIGURATION_TYPES Debug Release + CACHE STRING "Configurations" FORCE +) +# Suppress generation of ZERO_CHECK project. +set(CMAKE_SUPPRESS_REGENERATION ON) + +# Surpress GLFW process. +set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) +set(BUILD_UTILS OFF CACHE BOOL "" FORCE) + +# Specify version of compiler. +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# Add Cubism Core. +# Import as static library. +add_library(Live2DCubismCore STATIC IMPORTED) +# Find library path. +set_target_properties(Live2DCubismCore + PROPERTIES + IMPORTED_LOCATION ${CORE_PATH}/lib/linux/x86_64/libLive2DCubismCore.a + INTERFACE_INCLUDE_DIRECTORIES ${CORE_PATH}/include +) + +# Add GLFW. +add_subdirectory(${GLFW_PATH} ${CMAKE_CURRENT_BINARY_DIR}/glfw) + +# Specify Cubism Framework rendering. +set(FRAMEWORK_SOURCE Vulkan) +# Add Cubism Native Framework. +add_subdirectory(${FRAMEWORK_PATH} ${CMAKE_CURRENT_BINARY_DIR}/Framework) +# Link libraries to framework. +target_link_libraries(Framework Live2DCubismCore) + +# Find vulkan libraries. +find_package(Vulkan REQUIRED) + +# Make executable app. +add_executable(${APP_NAME}) +# Add source files. +add_subdirectory(src) +# Add shader files. +add_subdirectory(${SAMPLE_SHADER_PATH} ${CMAKE_CURRENT_BINARY_DIR}/SampleShaders) +add_subdirectory(${FRAMEWORK_SHADER_PATH} ${CMAKE_CURRENT_BINARY_DIR}/FrameworkShaders) +add_dependencies(Framework SampleShaders) +add_dependencies(Framework FrameworkShaders) + +# Link libraries to app. +target_link_libraries(${APP_NAME} + Framework + glfw + ${Vulkan_LIBRARIES} +) +# Specify include directories. +target_include_directories(${APP_NAME} PRIVATE ${STB_PATH}) +target_include_directories(${APP_NAME} PRIVATE ${Vulkan_INCLUDE_DIRS}) + +# Link libraries to framework. +target_include_directories(Framework PUBLIC ${Vulkan_INCLUDE_DIRS}) +# Link libraries to framework. +target_link_libraries(Framework Live2DCubismCore ${Vulkan_LIBRARIES}) + +# Copy resource directory to build directory. +add_custom_command( + TARGET ${APP_NAME} + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${RES_PATH} $/Resources + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_CURRENT_BINARY_DIR}/SampleShaders/compiledShaders $/SampleShaders + COMMAND + ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_CURRENT_BINARY_DIR}/FrameworkShaders/compiledShaders $/FrameworkShaders + +) + +# You can change target that renderer draws by enabling following definition. +# +# * USE_RENDER_TARGET +# Renderer draws to target of LAppView. +# * USE_MODEL_RENDER_TARGET +# Renderer draws to target of each LAppModel. +# * default +# Renderer draws to default main framebuffer. +# +# INFO: USE_RENDER_TARGET has higher priority than USE_MODEL_RENDER_TARGET. +# +# target_compile_definitions(${APP_NAME} +# PRIVATE +# USE_RENDER_TARGET +# USE_MODEL_RENDER_TARGET +# ) diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/scripts/make_gcc b/Samples/Vulkan/Demo/proj.linux.cmake/scripts/make_gcc new file mode 100644 index 00000000..4441a911 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/scripts/make_gcc @@ -0,0 +1,46 @@ +#!/usr/bin/env sh + +set -ue + +SCRIPT_PATH=$(cd $(dirname $0) && pwd) +CMAKE_PATH=$SCRIPT_PATH/.. +BUILD_PATH=$SCRIPT_PATH/../build/make_gcc +MINIMUM_DEMO="OFF" +DATA="" + +if [ "$#" -ne 0 ]; then + DATA="$1" +fi + +while : +do + + if [ -z "$DATA" ]; then + echo "Choose which format you would like to create the demo." + echo "Full version : 1" + echo "Minimum version : 2" + read -p "Your Choice : " DATA + fi + + case "$DATA" in + "1" ) + echo "Making Full Demo" + MINIMUM_DEMO="OFF" + break ;; + "2" ) + echo "Making Minimum Demo" + MINIMUM_DEMO="ON" + break ;; + * ) + echo "You need to enter a valid number." + DATA="" ;; + esac +done + +# Run CMake. +cmake -S "$CMAKE_PATH" \ + -B "$BUILD_PATH" \ + -D CMAKE_BUILD_TYPE=Release \ + -D CSM_MINIMUM_DEMO=$MINIMUM_DEMO \ + -D GLFW_BUILD_WAYLAND=OFF +cd "$BUILD_PATH" && make diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/CMakeLists.txt b/Samples/Vulkan/Demo/proj.linux.cmake/src/CMakeLists.txt new file mode 100644 index 00000000..393f6c09 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/CMakeLists.txt @@ -0,0 +1,57 @@ +if (CSM_MINIMUM_DEMO) + target_sources(${APP_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/LAppAllocator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppAllocator.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/mainMinimum.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismUserModelExtend.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismUserModelExtend.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismSampleViewMatrix.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CubismSampleViewMatrix.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/VulkanManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/VulkanManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/MouseActionManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MouseActionManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/SwapchainManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SwapchainManager.hpp + ) +else () + target_sources(${APP_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/LAppAllocator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppAllocator.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppWavFileHandler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppWavFileHandler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppModel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppModel.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/VulkanManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/VulkanManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/SwapchainManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SwapchainManager.hpp + ) +endif () diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismSampleViewMatrix.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismSampleViewMatrix.cpp new file mode 100644 index 00000000..4b51b646 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismSampleViewMatrix.cpp @@ -0,0 +1,69 @@ +/** + * 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. + */ + +#include + +#include "CubismSampleViewMatrix.hpp" +#include "LAppDefine.hpp" + +#include + +CubismSampleViewMatrix::CubismSampleViewMatrix(Csm::CubismMatrix44*& deviceToScreen, int windowWidth, int windowHeight) + : CubismViewMatrix() +{ + if (windowWidth == 0 || windowHeight == 0) + { + return; + } + + // 縦サイズを基準とする + float ratio = static_cast(windowWidth) / static_cast(windowHeight); + float left = -ratio; + float right = ratio; + float bottom = LAppDefine::ViewLogicalLeft; + float top = LAppDefine::ViewLogicalRight; + + // デバイスに対応する画面の範囲を設定 + SetScreenRect(left, right, bottom, top); + + if (windowWidth > windowHeight) + { + float screenW = fabsf(right - left); + // 行列の拡大率を相対的に設定 + deviceToScreen->ScaleRelative(screenW / windowWidth, -screenW / windowWidth); + } + else + { + float screenH = fabsf(top - bottom); + // 行列の拡大率を相対的に設定 + deviceToScreen->ScaleRelative(screenH / windowHeight, -screenH / windowHeight); + } + + // 行列の位置を起点に移動を行う + deviceToScreen->TranslateRelative(-windowWidth * 0.5f, -windowHeight * 0.5f); + + // 拡大率を設定 + Scale(LAppDefine::ViewScale, LAppDefine::ViewScale); + + // 最大拡大率を設定 + SetMaxScale(LAppDefine::ViewMaxScale); + + // 最小拡大率を設定 + SetMinScale(LAppDefine::ViewMinScale); + + // デバイスに対応する論理座標上の移動可能範囲を設定 + SetMaxScreenRect( + LAppDefine::ViewLogicalMaxLeft, + LAppDefine::ViewLogicalMaxRight, + LAppDefine::ViewLogicalMaxBottom, + LAppDefine::ViewLogicalMaxTop + ); +} + +CubismSampleViewMatrix::~CubismSampleViewMatrix() +{ +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismSampleViewMatrix.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismSampleViewMatrix.hpp new file mode 100644 index 00000000..c55cd046 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismSampleViewMatrix.hpp @@ -0,0 +1,27 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include + +/** +* @brief CubismViewMatrixを継承したクラス +* +* ビュー行列を Cubism で扱いやすいように機能を加えてラップしたもの。 +* +*/ +class CubismSampleViewMatrix : + public Csm::CubismViewMatrix +{ +public: + CubismSampleViewMatrix(Csm::CubismMatrix44*& deviceToScreen, int windowWidth, int windowHeight); ///< コンストラクタ + + ~CubismSampleViewMatrix(); ///< デストラクタ +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismUserModelExtend.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismUserModelExtend.cpp new file mode 100644 index 00000000..d8062532 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismUserModelExtend.cpp @@ -0,0 +1,496 @@ +/** + * 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. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "MouseActionManager.hpp" +#include "VulkanManager.hpp" + +#include "CubismUserModelExtend.hpp" + +using namespace Live2D::Cubism::Framework; +using namespace DefaultParameterId; +using namespace LAppDefine; + +namespace { + /** + * @bref バッファの作成 + * + * ファイルをバイトデータとして読み込む + */ + csmByte* CreateBuffer(const csmChar* path, csmSizeInt* size) + { + return LAppPal::LoadFileAsBytes(path, size); + } + + /** + * @bref バッファの消去 + * + * バイトデータの解放 + */ + void DeleteBuffer(csmByte* buffer, const csmChar* path = "") + { + LAppPal::ReleaseBytes(buffer); + } +} + +CubismUserModelExtend::CubismUserModelExtend(const std::string modelDirectoryName, const std::string _currentModelDirectory) + : CubismUserModel() + , _modelJson(NULL) + , _userTimeSeconds(0.0f) + , _modelDirName(modelDirectoryName) + , _currentModelDirectory(_currentModelDirectory) + , _textureManager(new LAppTextureManager()) +{ + // パラメータIDの取得 + _idParamAngleX = CubismFramework::GetIdManager()->GetId(ParamAngleX); + _idParamAngleY = CubismFramework::GetIdManager()->GetId(ParamAngleY); + _idParamAngleZ = CubismFramework::GetIdManager()->GetId(ParamAngleZ); + _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(ParamBodyAngleX); + _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(ParamEyeBallX); + _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(ParamEyeBallY); +} + +CubismUserModelExtend::~CubismUserModelExtend() +{ + // モデルの設定データの解放 + ReleaseModelSetting(); + + // テクスチャマネージャーの解放 + delete _textureManager; +} + +void CubismUserModelExtend::LoadAssets(const Csm::csmChar* fileName) +{ + csmSizeInt size; + const csmString path = csmString(_currentModelDirectory.c_str()) + fileName; + + csmByte* buffer = CreateBuffer(path.GetRawString(), &size); + _modelJson = new CubismModelSettingJson(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + + // モデルの生成 + SetupModel(); +} + +void CubismUserModelExtend::SetupModel() +{ + _updating = true; + _initialized = false; + + csmByte* buffer; + csmSizeInt size; + + //Cubism Model + if (strcmp(_modelJson->GetModelFileName(), "")) + { + csmString path = _modelJson->GetModelFileName(); + path = csmString(_currentModelDirectory.c_str()) + path; + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadModel(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + // 表情データの読み込み + if (_modelJson->GetExpressionCount() > 0) + { + const csmInt32 count = _modelJson->GetExpressionCount(); + for (csmInt32 i = 0; i < count; i++) + { + csmString name = _modelJson->GetExpressionName(i); + csmString path = _modelJson->GetExpressionFileName(i); + path = csmString(_currentModelDirectory.c_str()) + path; + + buffer = CreateBuffer(path.GetRawString(), &size); + ACubismMotion* motion = LoadExpression(buffer, size, name.GetRawString()); + + if (motion) + { + if (_expressions[name]) + { + ACubismMotion::Delete(_expressions[name]); + _expressions[name] = nullptr; + } + _expressions[name] = motion; + } + + DeleteBuffer(buffer, path.GetRawString()); + } + } + + //ポーズデータの読み込み + if (strcmp(_modelJson->GetPoseFileName(), "")) + { + csmString path = _modelJson->GetPoseFileName(); + path = csmString(_currentModelDirectory.c_str()) + path; + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadPose(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + // 物理演算データの読み込み + if (strcmp(_modelJson->GetPhysicsFileName(), "")) + { + csmString path = _modelJson->GetPhysicsFileName(); + path = csmString(_currentModelDirectory.c_str()) + path; + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadPhysics(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + // モデルに付属するユーザーデータの読み込み + if (strcmp(_modelJson->GetUserDataFile(), "")) + { + csmString path = _modelJson->GetUserDataFile(); + path = csmString(_currentModelDirectory.c_str()) + path; + buffer = CreateBuffer(path.GetRawString(), &size); + LoadUserData(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + // Layout + csmMap layout; + _modelJson->GetLayoutMap(layout); + // レイアウト情報から位置を設定 + _modelMatrix->SetupFromLayout(layout); + + // パラメータを保存 + _model->SaveParameters(); + + // モーションデータの読み込み + for (csmInt32 i = 0; i < _modelJson->GetMotionGroupCount(); i++) + { + const csmChar* group = _modelJson->GetMotionGroupName(i); + // モーションデータをグループ名から一括でロードする + PreloadMotionGroup(group); + } + + _motionManager->StopAllMotions(); + + // レンダラの作成 + CreateRenderer(); + + // テクスチャのセットアップ + SetupTextures(); + + _updating = false; + _initialized = true; +} + +void CubismUserModelExtend::PreloadMotionGroup(const csmChar* group) +{ + // グループに登録されているモーション数を取得 + const csmInt32 count = _modelJson->GetMotionCount(group); + + for (csmInt32 i = 0; i < count; i++) + { + //ex) idle_0 + // モーションのファイル名とパスの取得 + csmString name = Utils::CubismString::GetFormatedString("%s_%d", group, i); + csmString path = _modelJson->GetMotionFileName(group, i); + path = csmString(_currentModelDirectory.c_str()) + path; + + csmByte* buffer; + csmSizeInt size; + buffer = CreateBuffer(path.GetRawString(), &size); + // モーションデータの読み込み + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + + if (tmpMotion) + { + // フェードインの時間を取得 + csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i); + if (fadeTime >= 0.0f) + { + tmpMotion->SetFadeInTime(fadeTime); + } + + // フェードアウトの時間を取得 + fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, i); + if (fadeTime >= 0.0f) + { + tmpMotion->SetFadeOutTime(fadeTime); + } + + if (_motions[name]) + { + // インスタンスを破棄 + ACubismMotion::Delete(_motions[name]); + } + _motions[name] = tmpMotion; + } + + DeleteBuffer(buffer, path.GetRawString()); + } +} + +void CubismUserModelExtend::ReleaseModelSetting() +{ + // モーションの解放 + for (Csm::csmMap::const_iterator iter = _motions.Begin(); iter != _motions.End(); ++iter) + { + Csm::ACubismMotion::Delete(iter->Second); + } + + _motions.Clear(); + + // すべての表情データを解放する + for (Csm::csmMap::const_iterator iter = _expressions.Begin(); iter != _expressions.End(); ++iter) + { + Csm::ACubismMotion::Delete(iter->Second); + } + + _expressions.Clear(); + + delete(_modelJson); +} + +/** +* @brief 引数で指定したモーションの再生を開始する。 +* +* @param[in] group モーショングループ名 +* @param[in] no グループ内の番号 +* @param[in] priority 優先度 +* @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 +* @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 +*/ +Csm::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) +{ + // モーション数が取得出来なかった、もしくは0の時 + if (!(_modelJson->GetMotionCount(group))) + { + return Csm::InvalidMotionQueueEntryHandleValue; + } + + if (priority == LAppDefine::PriorityForce) + { + // 予約中のモーションの優先度を設定する + _motionManager->SetReservePriority(priority); + } + else if (!_motionManager->ReserveMotion(priority)) + { + return Csm::InvalidMotionQueueEntryHandleValue; + } + + // 指定された.motion3.jsonのファイル名を取得 + const Csm::csmString fileName = _modelJson->GetMotionFileName(group, no); + + //ex) idle_0 + // モーションのデータを生成 + csmString name = Utils::CubismString::GetFormatedString("%s_%d", group, no); + CubismMotion* motion = static_cast(_motions[name.GetRawString()]); + csmBool autoDelete = false; + + if (!motion) + { + csmString path = fileName; + path = csmString(_currentModelDirectory.c_str()) + path; + + csmByte* buffer; + csmSizeInt size; + buffer = CreateBuffer(path.GetRawString(), &size); + // 一番先頭のモーションを読み込む + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + + if (motion) + { + csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no); + if (fadeTime >= 0.0f) + { + motion->SetFadeInTime(fadeTime); + } + + fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no); + if (fadeTime >= 0.0f) + { + motion->SetFadeOutTime(fadeTime); + } + + // 終了時にメモリから削除 + autoDelete = true; + } + + DeleteBuffer(buffer, path.GetRawString()); + } + else + { + // モーションの再生終了コールバックを登録 + motion->SetFinishedMotionHandler(onFinishedMotionHandler); + } + + // 優先度を設定してモーションを始める + return _motionManager->StartMotionPriority(motion, autoDelete, priority); +} + +void CubismUserModelExtend::ModelParamUpdate() +{ + // 前のフレームとの差分を取得 + const Csm::csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime(); + _userTimeSeconds += deltaTimeSeconds; + + // ドラッグ情報を更新 + _dragManager->Update(deltaTimeSeconds); + _dragX = _dragManager->GetX(); + _dragY = _dragManager->GetY(); + + // モーションによるパラメータ更新の有無 + Csm::csmBool motionUpdated = false; + + //----------------------------------------------------------------- + // 前回セーブされた状態をロード + _model->LoadParameters(); + + if (_motionManager->IsFinished()) + { + // モーションの再生がない場合、始めに登録されているモーションを再生する + StartMotion(LAppDefine::MotionGroupIdle, 0, LAppDefine::PriorityIdle); + } + else + { + // モーションを更新し、パラメータを反映 + motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); + } + + // 状態を保存 + _model->SaveParameters(); + //----------------------------------------------------------------- + + if (_expressionManager) + { + // 表情でパラメータ更新(相対変化) + _expressionManager->UpdateMotion(_model, deltaTimeSeconds); + } + + //ドラッグによる変化 + /** + *ドラッグによる顔の向きの調整 + * -30から30の値を加える + */ + _model->AddParameterValue(_idParamAngleX, _dragX * 30.0f); + _model->AddParameterValue(_idParamAngleY, _dragY * 30.0f); + _model->AddParameterValue(_idParamAngleZ, _dragX * _dragY * -30.0f); + + //ドラッグによる体の向きの調整 + _model->AddParameterValue(_idParamBodyAngleX, _dragX * 10.0f); // -10から10の値を加える + + //ドラッグによる目の向きの調整 + _model->AddParameterValue(_idParamEyeBallX, _dragX); // -1から1の値を加える + _model->AddParameterValue(_idParamEyeBallY, _dragY); + + // 物理演算の設定 + if (_physics) + { + _physics->Evaluate(_model, deltaTimeSeconds); + } + + // ポーズの設定 + if (_pose) + { + _pose->UpdateParameters(_model, deltaTimeSeconds); + } + + // モデルのパラメータ情報を更新 + _model->Update(); +} + +void CubismUserModelExtend::Draw(Csm::CubismMatrix44& matrix) +{ + if (!_model) + { + return; + } + + // 現在の行列に行列を乗算 + matrix.MultiplyByMatrix(_modelMatrix); + + // 行列をモデルビュープロジェクション行列を設定 + GetRenderer()->SetMvpMatrix(&matrix); + + // モデルの描画を命令・実行する + GetRenderer()->DrawModel(); +} + +void CubismUserModelExtend::SetupTextures() +{ + for (csmInt32 modelTextureNumber = 0; modelTextureNumber < _modelJson->GetTextureCount(); modelTextureNumber++) + { + // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ + if (!strcmp(_modelJson->GetTextureFileName(modelTextureNumber), "")) + { + continue; + } + + // OpenGLのテクスチャユニットにテクスチャをロードする + csmString texturePath = _modelJson->GetTextureFileName(modelTextureNumber); + texturePath = csmString(_currentModelDirectory.c_str()) + texturePath; + + LAppTextureManager::TextureInfo* texture = _textureManager->CreateTextureFromPngFile( + texturePath.GetRawString(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + if (texture) + { + const csmUint32 textureManageId = texture->Id; + CubismImageVulkan image; + if (_textureManager->GetTexture(textureManageId, image)) + { + GetRenderer()->BindTexture(image); + } + } + } + + // 乗算済みアルファ値の有効化・無効化を設定 + GetRenderer()->IsPremultipliedAlpha(false); +} + +void CubismUserModelExtend::ModelOnUpdate(GLFWwindow* window) +{ + int width, height; + // ウィンドウサイズを取得 + glfwGetWindowSize(window, &width, &height); + + Csm::CubismMatrix44 projection; + // 念のため単位行列に初期化 + projection.LoadIdentity(); + + if (_model->GetCanvasWidth() > 1.0f && width < height) + { + // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する + GetModelMatrix()->SetWidth(2.0f); + projection.Scale(1.0f, static_cast(width) / static_cast(height)); + } + else + { + projection.Scale(static_cast(height) / static_cast(width), 1.0f); + } + + // 必要があればここで乗算 + if (MouseActionManager::GetInstance()->GetViewMatrix() != NULL) + { + projection.MultiplyByMatrix(MouseActionManager::GetInstance()->GetViewMatrix()); + } + + // モデルのパラメータを更新 + ModelParamUpdate(); + + // モデルの描画を更新 + Draw(projection); ///< 参照渡しなのでprojectionは変質する +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismUserModelExtend.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismUserModelExtend.hpp new file mode 100644 index 00000000..d0b486d4 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/CubismUserModelExtend.hpp @@ -0,0 +1,120 @@ +/** + * 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. + */ + +#pragma once + +#include + +#include +#include +#include + +#include "LAppTextureManager.hpp" + + /** + * @brief CubismUserModelを継承するサンプルクラス + * + * CubismUserModelを継承するサンプルクラス + * このクラスを拡張し、独自の処理を実装する。 + * + */ +class CubismUserModelExtend : + public Csm::CubismUserModel +{ +public: + CubismUserModelExtend(const std::string modelDirectoryName, const std::string _currentModelDirectory); ///< コンストラクタ + ~CubismUserModelExtend(); ///< デストラクタ + + /** + * @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する + * + */ + void LoadAssets(const Csm::csmChar* fileName); + + /** + * @brief モデルの更新 + * + * モデルの状態や描画を更新する + */ + void ModelOnUpdate(GLFWwindow* window); + +private: + /** + * @brief model3.jsonからモデルを生成する + * + * model3.jsonの記述に従ってモデル生成、モーション、物理演算などのコンポーネント生成を行う + * + * @param[in] setting ICubismModelSettingのインスタンス + * + */ + void SetupModel(); + + /** + * @brief 引数で指定したモーションの再生を開始する + * + * @param[in] group モーショングループ名 + * @param[in] no グループ内の番号 + * @param[in] priority 優先度 + * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 + */ + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL); + + /** + * @brief 解放 + * + * モデルの設定データの解放の処理を行う + */ + void ReleaseModelSetting(); + + /** + * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す + * + * @param[in] matrix View-Projection行列 + */ + void Draw(Csm::CubismMatrix44& matrix); + + /** + * @brief モデルのパラメータ情報の更新 + * + * モデルのパラメータの情報を更新する + */ + void ModelParamUpdate(); + + /** + * @brief OpenGLのテクスチャユニットにテクスチャをロードする + * + */ + void SetupTextures(); + + /** + * @brief モーションデータをグループ名から一括でロードする。 + * + * モーションデータの名前は内部でModelSettingから取得する。 + * + * @param[in] group モーションデータのグループ名 + */ + void PreloadMotionGroup(const Csm::csmChar * group); + + std::string _modelDirName; ///< モデルセッティングが置かれたディレクトリの名称 + std::string _currentModelDirectory; ///< モデルセッティングが置かれたディレクトリ + + Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] + Csm::CubismModelSettingJson* _modelJson; ///< モデルセッティング情報 + Csm::csmVector _eyeBlinkIds; ///< モデルに設定されたまばたき機能用パラメータID + Csm::csmMap _motions; ///< 読み込まれているモーションのリスト + Csm::csmMap _expressions; ///< 読み込まれている表情のリスト + + LAppTextureManager* _textureManager; ///< テクスチャマネージャー + + const Csm::CubismId* _idParamAngleX; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamAngleY; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamAngleZ; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamBodyAngleX; ///< パラメータID: ParamBodyAngleX + const Csm::CubismId* _idParamEyeBallX; ///< パラメータID: ParamEyeBallX + const Csm::CubismId* _idParamEyeBallY; ///< パラメータID: ParamEyeBallXY +}; diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppAllocator.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppAllocator.cpp similarity index 64% rename from Samples/Cocos2d-x/Demo/Classes/LAppAllocator.cpp rename to Samples/Vulkan/Demo/proj.linux.cmake/src/LAppAllocator.cpp index c36f278b..9353bef9 100644 --- a/Samples/Cocos2d-x/Demo/Classes/LAppAllocator.cpp +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppAllocator.cpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -6,30 +6,30 @@ */ #include "LAppAllocator.hpp" -#include using namespace Csm; -void * LAppAllocator::Allocate(const csmSizeType size) +void* LAppAllocator::Allocate(const csmSizeType size) { return malloc(size); } void LAppAllocator::Deallocate(void* memory) { - if (memory) { free(memory); } + free(memory); } -void * LAppAllocator::AllocateAligned(const csmSizeType size, const csmUint32 alignment) +void* LAppAllocator::AllocateAligned(const csmSizeType size, const csmUint32 alignment) { size_t offset, shift, alignedAddress; - void *allocation, **preamble; + void* allocation; + void** preamble; offset = alignment - 1 + sizeof(void*); allocation = Allocate(size + static_cast(offset)); - alignedAddress = (size_t)allocation + sizeof(void*); + alignedAddress = reinterpret_cast(allocation) + sizeof(void*); shift = alignedAddress % alignment; @@ -38,17 +38,17 @@ void * LAppAllocator::AllocateAligned(const csmSizeType size, const csmUint32 al alignedAddress += (alignment - shift); } - preamble = (void**)alignedAddress; + preamble = reinterpret_cast(alignedAddress); preamble[-1] = allocation; - return (void*)alignedAddress; + return reinterpret_cast(alignedAddress); } void LAppAllocator::DeallocateAligned(void* alignedMemory) { void** preamble; - preamble = (void**)alignedMemory; + preamble = static_cast(alignedMemory); Deallocate(preamble[-1]); } diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppAllocator.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppAllocator.hpp new file mode 100644 index 00000000..baada555 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppAllocator.hpp @@ -0,0 +1,52 @@ +/** + * 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. + */ + +#pragma once + +#include +#include + +/** +* @brief メモリアロケーションを実装するクラス。 +* +* メモリ確保・解放処理のインターフェースの実装。 +* フレームワークから呼び出される。 +* +*/ +class LAppAllocator : public Csm::ICubismAllocator +{ + /** + * @brief メモリ領域を割り当てる。 + * + * @param[in] size 割り当てたいサイズ。 + * @return 指定したメモリ領域 + */ + void* Allocate(const Csm::csmSizeType size); + + /** + * @brief メモリ領域を解放する + * + * @param[in] memory 解放するメモリ。 + */ + void Deallocate(void* memory); + + /** + * @brief + * + * @param[in] size 割り当てたいサイズ。 + * @param[in] alignment 割り当てたいサイズ。 + * @return alignedAddress + */ + void* AllocateAligned(const Csm::csmSizeType size, const Csm::csmUint32 alignment); + + /** + * @brief + * + * @param[in] alignedMemory 解放するメモリ。 + */ + void DeallocateAligned(void* alignedMemory); +}; diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppDefine.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDefine.cpp similarity index 88% rename from Samples/Cocos2d-x/Demo/Classes/LAppDefine.cpp rename to Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDefine.cpp index 07e23eb5..20008c42 100644 --- a/Samples/Cocos2d-x/Demo/Classes/LAppDefine.cpp +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDefine.cpp @@ -1,12 +1,12 @@ -/** +/** * 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. */ -#include #include "LAppDefine.hpp" +#include namespace LAppDefine { @@ -20,15 +20,22 @@ namespace LAppDefine { const csmFloat32 ViewLogicalLeft = -1.0f; const csmFloat32 ViewLogicalRight = 1.0f; const csmFloat32 ViewLogicalBottom = -1.0f; - const csmFloat32 ViewLogicalTop = -1.0f; + const csmFloat32 ViewLogicalTop = 1.0f; const csmFloat32 ViewLogicalMaxLeft = -2.0f; const csmFloat32 ViewLogicalMaxRight = 2.0f; const csmFloat32 ViewLogicalMaxBottom = -2.0f; const csmFloat32 ViewLogicalMaxTop = 2.0f; + // 相対パス + const csmChar* ResourcesPath = "Resources/"; + // モデルの後ろにある背景の画像ファイル const csmChar* BackImageName = "back_class_normal.png"; + // 歯車 + const csmChar* GearImageName = "icon_gear.png"; + // 終了ボタン + const csmChar* PowerImageName = "close.png"; // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる @@ -45,13 +52,9 @@ namespace LAppDefine { const csmInt32 PriorityNormal = 2; const csmInt32 PriorityForce = 3; - // MOC3の整合性検証オプション - const csmBool MocConsistencyValidationEnable = true; - // デバッグ用ログの表示オプション const csmBool DebugLogEnable = true; const csmBool DebugTouchLogEnable = false; - const csmBool DebugDrawRectEnable = false; // Frameworkから出力するログのレベル設定 const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Verbose; diff --git a/Samples/Cocos2d-x/Demo/Classes/LAppDefine.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDefine.hpp similarity index 67% rename from Samples/Cocos2d-x/Demo/Classes/LAppDefine.hpp rename to Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDefine.hpp index 79b0d791..8641224a 100644 --- a/Samples/Cocos2d-x/Demo/Classes/LAppDefine.hpp +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDefine.hpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -10,9 +10,9 @@ #include /** - * @brief Sample Appで使用する定数 - * - */ +* @brief Sample Appで使用する定数 +* +*/ namespace LAppDefine { using namespace Csm; @@ -31,29 +31,29 @@ namespace LAppDefine { extern const csmFloat32 ViewLogicalMaxBottom; ///< 論理的なビュー座標系の下端の最大値 extern const csmFloat32 ViewLogicalMaxTop; ///< 論理的なビュー座標系の上端の最大値 - extern const csmChar* BackImageName; ///< 背景画像ファイル + extern const csmChar* ResourcesPath; ///< 素材パス + extern const csmChar* BackImageName; ///< 背景画像ファイル + extern const csmChar* GearImageName; ///< 歯車画像ファイル + extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル // モデル定義-------------------------------------------- - // 外部定義ファイル(json)と合わせる - extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト - extern const csmChar* MotionGroupTapBody; ///< 体をタップした時に再生するモーションのリスト + // 外部定義ファイル(json)と合わせる + extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト + extern const csmChar* MotionGroupTapBody; ///< 体をタップした時に再生するモーションのリスト - // 外部定義ファイル(json)と合わせる - extern const csmChar* HitAreaNameHead; ///< 当たり判定の[Head]タグ - extern const csmChar* HitAreaNameBody; ///< 当たり判定の[Body]タグ + // 外部定義ファイル(json)と合わせる + extern const csmChar* HitAreaNameHead; ///< 当たり判定の[Head]タグ + extern const csmChar* HitAreaNameBody; ///< 当たり判定の[Body]タグ - // モーションの優先度定数 + // モーションの優先度定数 extern const csmInt32 PriorityNone; ///< モーションの優先度定数: 0 extern const csmInt32 PriorityIdle; ///< モーションの優先度定数: 1 extern const csmInt32 PriorityNormal; ///< モーションの優先度定数: 2 extern const csmInt32 PriorityForce; ///< モーションの優先度定数: 3 - extern const csmBool MocConsistencyValidationEnable; ///< MOC3の整合性検証機能の有効・無効 - - // デバッグ用ログの表示 + // デバッグ用ログの表示 extern const csmBool DebugLogEnable; ///< デバッグ用ログ表示の有効・無効 extern const csmBool DebugTouchLogEnable; ///< タッチ処理のデバッグ用ログ表示の有効・無効 - extern const csmBool DebugDrawRectEnable; // Frameworkから出力するログのレベル設定 extern const CubismFramework::Option::LogLevel CubismLoggingLevel; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDelegate.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDelegate.cpp new file mode 100644 index 00000000..50ff246e --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDelegate.cpp @@ -0,0 +1,295 @@ +/** + * 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. + */ + +#include "LAppDelegate.hpp" +#include +#include +#include +#include +#include "LAppView.hpp" +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "LAppLive2DManager.hpp" +#include "LAppTextureManager.hpp" +#include + +using namespace Csm; +using namespace std; +using namespace LAppDefine; + +namespace { + LAppDelegate* s_instance = NULL; +} + +LAppDelegate* LAppDelegate::GetInstance() +{ + if (s_instance == NULL) + { + s_instance = new LAppDelegate(); + } + + return s_instance; +} + +void LAppDelegate::ReleaseInstance() +{ + if (s_instance != NULL) + { + delete s_instance; + } + + s_instance = NULL; +} + +bool LAppDelegate::Initialize() +{ + if (DebugLogEnable) + { + LAppPal::PrintLogLn("START"); + } + + // GLFWの初期化 + if (glfwInit() == GL_FALSE) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("Can't initilize GLFW"); + } + return GL_FALSE; + } + // Windowの生成_ + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + _window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL); + + if (_window == NULL) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("Can't create GLFW window."); + } + glfwTerminate(); + return GL_FALSE; + } + + glfwSetWindowUserPointer(_window, VulkanManager::GetInstance()); + + // Windowのコンテキストをカレントに設定 + glfwMakeContextCurrent(_window); + glfwSwapInterval(1); + + //コールバック関数の登録 + glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack); + glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack); + glfwSetFramebufferSizeCallback(_window, EventHandler::FrameBufferResizeCallback); + + // ウィンドウサイズ記憶 + int width, height; + glfwGetWindowSize(_window, &width, &height); + _windowWidth = width; + _windowHeight = height; + + //setup cubism + _cubismOption.LogFunction = LAppPal::PrintMessage; + _cubismOption.LoggingLevel = LAppDefine::CubismLoggingLevel; + Csm::CubismFramework::StartUp(&_cubismAllocator, &_cubismOption); + + // CubismSDKの初期化 + InitializeCubism(); + + // vulkanデバイスの作成 + VulkanManager::GetInstance()->Initialize(_window); + SwapchainManager* swapchainManager = VulkanManager::GetInstance()->GetSwapchainManager(); + // レンダラにvulkanManagerの変数を渡す + Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::InitializeConstantSettings( + VulkanManager::GetInstance()->GetDevice(), VulkanManager::GetInstance()->GetPhysicalDevice(), + VulkanManager::GetInstance()->GetCommandPool(), VulkanManager::GetInstance()->GetGraphicQueue(), + swapchainManager->GetImageCount(), swapchainManager->GetExtent(), + VulkanManager::GetInstance()->GetSwapchainImageView(), swapchainManager->GetSwapchainImageFormat(), + VulkanManager::GetInstance()->GetDepthFormat() + ); + + //AppViewの初期化 + _view->Initialize(); + + SetExecuteAbsolutePath(); + + //load model + LAppLive2DManager::GetInstance(); + + //load sprite + _view->InitializeSprite(); + + return GL_TRUE; +} + +void LAppDelegate::Release() +{ + delete _textureManager; + delete _view; + + // リソースを解放 + LAppLive2DManager::ReleaseInstance(); + + //Cubism3の解放 + CubismFramework::Dispose(); + + VulkanManager::GetInstance()->Destroy(); + + // Windowの削除 + glfwDestroyWindow(_window); + glfwTerminate(); +} + +bool LAppDelegate::RecreateSwapchain() +{ + int width = 0, height = 0; + if (VulkanManager::GetInstance()->GetIsWindowSizeChanged()) + { + glfwGetFramebufferSize(_window, &width, &height); + while (width == 0 || height == 0) + { + glfwGetFramebufferSize(_window, &width, &height); + glfwWaitEvents(); + } + + VulkanManager::GetInstance()->RecreateSwapchain(); + Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::SetRenderTarget( + VulkanManager::GetInstance()->GetSwapchainImage(), + VulkanManager::GetInstance()->GetSwapchainImageView(), + VulkanManager::GetInstance()->GetSwapchainManager()->GetSwapchainImageFormat(), + VulkanManager::GetInstance()->GetSwapchainManager()->GetExtent() + ); + + // AppViewの初期化 + _view->Initialize(); + // スプライトサイズを再設定 + _view->ResizeSprite(width, height); + // オフスクリーンを再作成する + _view->DestroyOffscreenSurface(); + // サイズを保存しておく + _windowWidth = width; + _windowHeight = height; + VulkanManager::GetInstance()->SetIsWindowSizeChanged(false); + return true; + } + return false; +} + +void LAppDelegate::Run() +{ + //メインループ + while (glfwWindowShouldClose(_window) == GL_FALSE && !_isEnd) + { + // Poll for and process events + glfwPollEvents(); + + // 時間更新 + LAppPal::UpdateTime(); + VulkanManager::GetInstance()->UpdateDrawFrame(); + + if (RecreateSwapchain()) + { + continue; + } + + //描画更新 + _view->Render(); + + VulkanManager::GetInstance()->PostDraw(); + RecreateSwapchain(); + } + + Release(); + + LAppDelegate::ReleaseInstance(); +} + +LAppDelegate::LAppDelegate(): + _cubismOption(), + _window(NULL), + _captured(false), + _mouseX(0.0f), + _mouseY(0.0f), + _isEnd(false), + _windowWidth(0), + _windowHeight(0) +{ + _executeAbsolutePath = ""; + _view = new LAppView(); + _textureManager = new LAppTextureManager(); +} + +LAppDelegate::~LAppDelegate() +{} + +void LAppDelegate::InitializeCubism() +{ + //Initialize cubism + CubismFramework::Initialize(); + + //default proj + CubismMatrix44 projection; + + LAppPal::UpdateTime(); +} + +void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) +{ + if (_view == NULL) + { + return; + } + if (GLFW_MOUSE_BUTTON_LEFT != button) + { + return; + } + + if (GLFW_PRESS == action) + { + _captured = true; + _view->OnTouchesBegan(_mouseX, _mouseY); + } + else if (GLFW_RELEASE == action) + { + if (_captured) + { + _captured = false; + _view->OnTouchesEnded(_mouseX, _mouseY); + } + } +} + +void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) +{ + _mouseX = static_cast(x); + _mouseY = static_cast(y); + + if (!_captured) + { + return; + } + if (_view == NULL) + { + return; + } + + _view->OnTouchesMoved(_mouseX, _mouseY); +} + +void LAppDelegate::SetExecuteAbsolutePath() +{ + char path[1024]; + ssize_t len = readlink("/proc/self/exe", path, 1024 - 1); + + if (len != -1) + { + path[len] = '\0'; + } + + this->_executeAbsolutePath = dirname(path); + this->_executeAbsolutePath += "/"; +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDelegate.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDelegate.hpp new file mode 100644 index 00000000..871f1075 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppDelegate.hpp @@ -0,0 +1,168 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include "Type/csmVector.hpp" +#include "LAppAllocator.hpp" +#include "VulkanManager.hpp" + +class LAppView; +class LAppTextureManager; + +/** +* @brief アプリケーションクラス。 +* Cubism SDK の管理を行う。 +*/ +class LAppDelegate +{ +public: + /** + * @brief クラスのインスタンス(シングルトン)を返す。
+ * インスタンスが生成されていない場合は内部でインスタンを生成する。 + * + * @return クラスのインスタンス + */ + static LAppDelegate* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する。 + * + */ + static void ReleaseInstance(); + + /** + * @brief APPに必要なものを初期化する。 + */ + bool Initialize(); + + /** + * @brief 解放する。 + */ + void Release(); + + /** + * @brief スワップチェーンの再作成を行う。 + */ + bool RecreateSwapchain(); + + /** + * @brief 実行処理。 + */ + void Run(); + + /** + * @brief Vulkan用 glfwSetMouseButtonCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] button ボタン種類 + * @param[in] action 実行結果 + * @param[in] modify + */ + void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify); + + /** + * @brief Vulkan用 glfwSetCursorPosCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] x x座標 + * @param[in] y x座標 + */ + void OnMouseCallBack(GLFWwindow* window, double x, double y); + + /** + * @brief Window情報を取得する。 + */ + GLFWwindow* GetWindow() { return _window; } + + /** + * @brief View情報を取得する。 + */ + LAppView* GetView() { return _view; } + + /** + * @brief アプリケーションを終了するかどうか。 + */ + bool GetIsEnd() { return _isEnd; } + + /** + * @brief アプリケーションを終了する。 + */ + void AppEnd() { _isEnd = true; } + + /** + * @brief アプリケーションの実行パスを設定する。 + */ + void SetExecuteAbsolutePath(); + + /** + * @brief アプリケーションの実行パスを取得する。 + */ + std::string GetExecuteAbsolutePath() { return _executeAbsolutePath;} + + /** + * @brief テクスチャマネージャーを取得する。 + */ + LAppTextureManager* GetTextureManager() { return _textureManager; } + +private: + /** + * @brief コンストラクタ + */ + LAppDelegate(); + + /** + * @brief デストラクタ + */ + ~LAppDelegate(); + + /** + * @brief Cubism SDKの初期化 + */ + void InitializeCubism(); + + LAppAllocator _cubismAllocator; ///< Cubism SDK Allocator + Csm::CubismFramework::Option _cubismOption; ///< Cubism SDK Option + GLFWwindow* _window; ///< ウィンドウ + LAppView* _view; ///< View情報 + bool _captured; ///< クリックしているか + float _mouseX; ///< マウスX座標 + float _mouseY; ///< マウスY座標 + bool _isEnd; ///< APP終了しているか + LAppTextureManager* _textureManager; ///< テクスチャマネージャー + std::string _executeAbsolutePath; ///< アプリケーションの実行パス + + int _windowWidth; ///< Initialize関数で設定したウィンドウ幅 + int _windowHeight; ///< Initialize関数で設定したウィンドウ高さ +}; + +class EventHandler +{ +public: + /** + * @brief glfwSetMouseButtonCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) + { + LAppDelegate::GetInstance()->OnMouseCallBack(window, button, action, modify); + } + + /** + * @brief glfwSetCursorPosCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, double x, double y) + { + LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y); + } + + static void FrameBufferResizeCallback(GLFWwindow* window, int width, int height) + { + VulkanManager* app = reinterpret_cast(glfwGetWindowUserPointer(window)); + app->SetFrameBufferResized(true); + } +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppLive2DManager.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppLive2DManager.cpp new file mode 100644 index 00000000..ec3c1e20 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppLive2DManager.cpp @@ -0,0 +1,319 @@ +/** + * 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. + */ + +#include "LAppLive2DManager.hpp" +#include +#include +#include +#include +#include +#include +#include +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "LAppDelegate.hpp" +#include "LAppModel.hpp" +#include "LAppView.hpp" + +using namespace Csm; +using namespace LAppDefine; + +namespace { + LAppLive2DManager* s_instance = NULL; + + void BeganMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion Began: %x", self); + } + + void FinishedMotion(ACubismMotion* self) + { + LAppPal::PrintLogLn("Motion Finished: %x", self); + } + + int CompareCsmString(const void* a, const void* b) + { + return strcmp(reinterpret_cast(a)->GetRawString(), + reinterpret_cast(b)->GetRawString()); + } +} + +LAppLive2DManager* LAppLive2DManager::GetInstance() +{ + if (s_instance == NULL) + { + s_instance = new LAppLive2DManager(); + } + + return s_instance; +} + +void LAppLive2DManager::ReleaseInstance() +{ + if (s_instance != NULL) + { + delete s_instance; + } + + s_instance = NULL; +} + +LAppLive2DManager::LAppLive2DManager() + : _viewMatrix(NULL) + , _sceneIndex(0) +{ + _viewMatrix = new CubismMatrix44(); + SetUpModel(); + + ChangeScene(_sceneIndex); +} + +LAppLive2DManager::~LAppLive2DManager() +{ + ReleaseAllModel(); + delete _viewMatrix; +} + +void LAppLive2DManager::ReleaseAllModel() +{ + for (csmUint32 i = 0; i < _models.GetSize(); i++) + { + delete _models[i]; + } + + _models.Clear(); +} + +void LAppLive2DManager::SetUpModel() +{ + // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 + // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 + struct dirent *dirent; + csmString crawlPath(LAppDelegate::GetInstance()->GetExecuteAbsolutePath().c_str()); + crawlPath += ResourcesPath; + + DIR *pDir = opendir(crawlPath.GetRawString()); + if (pDir == NULL) + { + return; + } + + _modelDir.Clear(); + + while ((dirent = readdir(pDir)) != NULL) + { + if ((dirent->d_type & DT_DIR) && strcmp(dirent->d_name, "..") != 0) + { + // フォルダと同名の.model3.jsonがあるか探索する + struct dirent *dirent2; + + csmString modelName(dirent->d_name); + + csmString modelPath(crawlPath); + modelPath += modelName; + modelPath.Append(1, '/'); + + csmString model3jsonName(modelName); + model3jsonName += ".model3.json"; + + DIR *pDir2 = opendir(modelPath.GetRawString()); + while ((dirent2 = readdir(pDir2)) != NULL) + { + if (strcmp(dirent2->d_name, model3jsonName.GetRawString()) == 0) + { + _modelDir.PushBack(csmString(dirent->d_name)); + } + } + closedir(pDir2); + } + } + closedir(pDir); + qsort(_modelDir.GetPtr(), _modelDir.GetSize(), sizeof(csmString), CompareCsmString); +} + +csmVector LAppLive2DManager::GetModelDir() const +{ + return _modelDir; +} + +csmInt32 LAppLive2DManager::GetModelDirSize() const +{ + return _modelDir.GetSize(); +} + +LAppModel* LAppLive2DManager::GetModel(csmUint32 no) const +{ + if (no < _models.GetSize()) + { + return _models[no]; + } + + return NULL; +} + +void LAppLive2DManager::OnDrag(csmFloat32 x, csmFloat32 y) const +{ + for (csmUint32 i = 0; i < _models.GetSize(); i++) + { + LAppModel* model = GetModel(i); + + model->SetDragging(x, y); + } +} + +void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) +{ + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]tap point: {x:%.2f y:%.2f}", x, y); + } + + for (csmUint32 i = 0; i < _models.GetSize(); i++) + { + if (_models[i]->HitTest(HitAreaNameHead, x, y)) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameHead); + } + _models[i]->SetRandomExpression(); + } + else if (_models[i]->HitTest(HitAreaNameBody, x, y)) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); + } + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); + } + } +} + +void LAppLive2DManager::OnUpdate() const +{ + int width, height; + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); + + VulkanManager* vulkanManager = VulkanManager::GetInstance(); + + csmUint32 modelCount = _models.GetSize(); + for (csmUint32 i = 0; i < modelCount; ++i) + { + CubismMatrix44 projection; + LAppModel* model = GetModel(i); + + if (model->GetModel() == NULL) + { + LAppPal::PrintLogLn("Failed to model->GetModel()."); + continue; + } + + if (model->GetModel()->GetCanvasWidth() > 1.0f && width < height) + { + // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する + model->GetModelMatrix()->SetWidth(2.0f); + projection.Scale(1.0f, static_cast(width) / static_cast(height)); + } + else + { + projection.Scale(static_cast(height) / static_cast(width), 1.0f); + } + + // 必要があればここで乗算 + if (_viewMatrix != NULL) + { + projection.MultiplyByMatrix(_viewMatrix); + } + + LAppDelegate::GetInstance()->GetView()->PreModelDraw(*model); + model->Update(); + model->Draw(projection);///< 参照渡しなのでprojectionは変質する + LAppDelegate::GetInstance()->GetView()->PostModelDraw(*model); + } +} + +void LAppLive2DManager::NextScene() +{ + csmInt32 no = (_sceneIndex + 1) % GetModelDirSize(); + ChangeScene(no); +} + +void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) +{ + _sceneIndex = index; + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]model index: %d", _sceneIndex); + } + + // ModelDir[]に保持したディレクトリ名から + // model3.jsonのパスを決定する. + // ディレクトリ名とmodel3.jsonの名前を一致させておくこと. + const csmString& model = _modelDir[index]; + LAppPal::PrintLogLn("[APP]_modelDir: %s", model.GetRawString()); + + csmString modelPath(LAppDelegate::GetInstance()->GetExecuteAbsolutePath().c_str()); + modelPath += ResourcesPath; + modelPath += model; + modelPath.Append(1, '/'); + + csmString modelJsonName(model); + modelJsonName += ".model3.json"; + + VulkanManager* vulkanManager = VulkanManager::GetInstance(); + vkDeviceWaitIdle(vulkanManager->GetDevice()); + + ReleaseAllModel(); + _models.PushBack(new LAppModel()); +#if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET) + Csm::Rendering::CubismRenderer_Vulkan::EnableChangeRenderTarget(); +#endif + + _models[0]->LoadAssets(vulkanManager->GetDevice(), vulkanManager->GetTextureFormat(), modelPath.GetRawString(), modelJsonName.GetRawString()); + + /* + * モデル半透明表示を行うサンプルを提示する。 + * ここでUSE_RENDER_TARGET、USE_MODEL_RENDER_TARGETが定義されている場合 + * 別のレンダリングターゲットにモデルを描画し、描画結果をテクスチャとして別のスプライトに張り付ける。 + */ + { +#if defined(USE_RENDER_TARGET) + // LAppViewの持つターゲットに描画を行う場合、こちらを選択 + LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ViewFrameBuffer; +#elif defined(USE_MODEL_RENDER_TARGET) + // 各LAppModelの持つターゲットに描画を行う場合、こちらを選択 + LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ModelFrameBuffer; +#else + // デフォルトのメインフレームバッファへレンダリングする(通常) + LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_None; +#endif + +#if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET) + // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす + _models.PushBack(new LAppModel()); + _models[1]->LoadAssets(VulkanManager::GetInstance()->GetDevice(), vulkanManager->GetTextureFormat(), modelPath.GetRawString(), modelJsonName.GetRawString()); + _models[1]->GetModelMatrix()->TranslateX(0.2f); +#endif + LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); + + float clearColor[3] = { 0.0f, 0.0f, 0.0f }; + LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]); + } +} + +csmUint32 LAppLive2DManager::GetModelNum() const +{ + return _models.GetSize(); +} + +void LAppLive2DManager::SetViewMatrix(CubismMatrix44* m) +{ + for (int i = 0; i < 16; i++) + { + _viewMatrix->GetArray()[i] = m->GetArray()[i]; + } +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppLive2DManager.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppLive2DManager.hpp new file mode 100644 index 00000000..b5b93801 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppLive2DManager.hpp @@ -0,0 +1,132 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include +#include "VulkanManager.hpp" + +class LAppModel; + +/** +* @brief サンプルアプリケーションにおいてCubismModelを管理するクラス
+* モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。 +* +*/ +class LAppLive2DManager +{ +public: + /** + * @brief クラスのインスタンス(シングルトン)を返す。
+ * インスタンスが生成されていない場合は内部でインスタンを生成する。 + * + * @return クラスのインスタンス + */ + static LAppLive2DManager* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する。 + * + */ + static void ReleaseInstance(); + + /** + * @brief Resources フォルダにあるモデルフォルダ名をセットする + * + */ + void SetUpModel(); + + /** + * @brief Resources フォルダにあるモデルフォルダ名を取得する + * + */ + Csm::csmVector GetModelDir() const; + + /** + * @brief Resources フォルダにあるモデルフォルダのサイズを取得する + * + */ + Csm::csmInt32 GetModelDirSize() const; + + /** + * @brief 現在のシーンで保持しているモデルを返す + * + * @param[in] no モデルリストのインデックス値 + * @return モデルのインスタンスを返す。インデックス値が範囲外の場合はNULLを返す。 + */ + LAppModel* GetModel(Csm::csmUint32 no) const; + + /** + * @brief 現在のシーンで保持しているすべてのモデルを解放する + * + */ + void ReleaseAllModel(); + + /** + * @brief 画面をドラッグしたときの処理 + * + * @param[in] x 画面のX座標 + * @param[in] y 画面のY座標 + */ + void OnDrag(Csm::csmFloat32 x, Csm::csmFloat32 y) const; + + /** + * @brief 画面をタップしたときの処理 + * + * @param[in] x 画面のX座標 + * @param[in] y 画面のY座標 + */ + void OnTap(Csm::csmFloat32 x, Csm::csmFloat32 y); + + /** + * @brief 画面を更新するときの処理 + * モデルの更新処理および描画処理を行う + */ + void OnUpdate() const; + + /** + * @brief 次のシーンに切り替える
+ * サンプルアプリケーションではモデルセットの切り替えを行う。 + */ + void NextScene(); + + /** + * @brief シーンを切り替える
+ * サンプルアプリケーションではモデルセットの切り替えを行う。 + */ + void ChangeScene(Csm::csmInt32 index); + + /** + * @brief モデル個数を得る + * @return 所持モデル個数 + */ + Csm::csmUint32 GetModelNum() const; + + /** + * @brief viewMatrixをセットする + */ + void SetViewMatrix(Live2D::Cubism::Framework::CubismMatrix44* m); + +private: + /** + * @brief コンストラクタ + */ + LAppLive2DManager(); + + /** + * @brief デストラクタ + */ + virtual ~LAppLive2DManager(); + + Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列 + Csm::csmVector _models; ///< モデルインスタンスのコンテナ + Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値 + + Csm::csmVector _modelDir; ///< モデルディレクトリ名のコンテナ +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppModel.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppModel.cpp new file mode 100644 index 00000000..3f79ef24 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppModel.cpp @@ -0,0 +1,652 @@ +/** + * 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. + */ + +#include "LAppModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LAppDefine.hpp" +#include "LAppPal.hpp" +#include "LAppTextureManager.hpp" +#include "LAppDelegate.hpp" + +using namespace Live2D::Cubism::Framework; +using namespace Live2D::Cubism::Framework::DefaultParameterId; +using namespace LAppDefine; + +namespace { + csmByte* CreateBuffer(const csmChar* path, csmSizeInt* size) + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]create buffer: %s ", path); + } + return LAppPal::LoadFileAsBytes(path, size); + } + + void DeleteBuffer(csmByte* buffer, const csmChar* path = "") + { + if (DebugLogEnable) + { + LAppPal::PrintLogLn("[APP]delete buffer: %s", path); + } + LAppPal::ReleaseBytes(buffer); + } +} + +LAppModel::LAppModel() + : CubismUserModel() + , _modelSetting(NULL) + , _userTimeSeconds(0.0f) +{ + if (DebugLogEnable) + { + _debugMode = true; + } + + _idParamAngleX = CubismFramework::GetIdManager()->GetId(ParamAngleX); + _idParamAngleY = CubismFramework::GetIdManager()->GetId(ParamAngleY); + _idParamAngleZ = CubismFramework::GetIdManager()->GetId(ParamAngleZ); + _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(ParamBodyAngleX); + _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(ParamEyeBallX); + _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(ParamEyeBallY); +} + +LAppModel::~LAppModel() +{ + _renderBuffer.DestroyOffscreenSurface(VulkanManager::GetInstance()->GetDevice()); + + ReleaseMotions(); + ReleaseExpressions(); + + for (csmInt32 i = 0; i < _modelSetting->GetMotionGroupCount(); i++) + { + const csmChar* group = _modelSetting->GetMotionGroupName(i); + ReleaseMotionGroup(group); + } + delete(_modelSetting); +} + +void LAppModel::LoadAssets(VkDevice device, VkFormat imageFormat, const csmChar* dir, const csmChar* fileName) +{ + _modelHomeDir = dir; + + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]load model setting: %s", fileName); + } + + csmSizeInt size; + const csmString path = csmString(dir) + fileName; + + csmByte* buffer = CreateBuffer(path.GetRawString(), &size); + ICubismModelSetting* setting = new CubismModelSettingJson(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + + SetupModel(setting); + + if (_model == NULL) + { + LAppPal::PrintLogLn("Failed to LoadAssets()."); + return; + } + + CreateRenderer(); + + SetupTextures(device, imageFormat); +} + +void LAppModel::SetupModel(ICubismModelSetting* setting) +{ + _updating = true; + _initialized = false; + _modelSetting = setting; + + csmByte* buffer; + csmSizeInt size; + + //Cubism Model + if (strcmp(_modelSetting->GetModelFileName(), "") != 0) + { + csmString path = _modelSetting->GetModelFileName(); + path = _modelHomeDir + path; + + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]create model: %s", setting->GetModelFileName()); + } + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadModel(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + //Expression + if (_modelSetting->GetExpressionCount() > 0) + { + const csmInt32 count = _modelSetting->GetExpressionCount(); + for (csmInt32 i = 0; i < count; i++) + { + csmString name = _modelSetting->GetExpressionName(i); + csmString path = _modelSetting->GetExpressionFileName(i); + path = _modelHomeDir + path; + + buffer = CreateBuffer(path.GetRawString(), &size); + ACubismMotion* motion = LoadExpression(buffer, size, name.GetRawString()); + + if (motion) + { + if (_expressions[name] != NULL) + { + ACubismMotion::Delete(_expressions[name]); + _expressions[name] = NULL; + } + _expressions[name] = motion; + } + + DeleteBuffer(buffer, path.GetRawString()); + } + } + + //Physics + if (strcmp(_modelSetting->GetPhysicsFileName(), "") != 0) + { + csmString path = _modelSetting->GetPhysicsFileName(); + path = _modelHomeDir + path; + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadPhysics(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + //Pose + if (strcmp(_modelSetting->GetPoseFileName(), "") != 0) + { + csmString path = _modelSetting->GetPoseFileName(); + path = _modelHomeDir + path; + + buffer = CreateBuffer(path.GetRawString(), &size); + LoadPose(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + //EyeBlink + if (_modelSetting->GetEyeBlinkParameterCount() > 0) + { + _eyeBlink = CubismEyeBlink::Create(_modelSetting); + } + + //Breath + { + _breath = CubismBreath::Create(); + + csmVector breathParameters; + + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleX, 0.0f, 15.0f, 6.5345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleY, 0.0f, 8.0f, 3.5345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleZ, 0.0f, 10.0f, 5.5345f, 0.5f)); + breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamBodyAngleX, 0.0f, 4.0f, 15.5345f, 0.5f)); + breathParameters.PushBack( + CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(ParamBreath), 0.5f, 0.5f, 3.2345f, 0.5f)); + + _breath->SetParameters(breathParameters); + } + + //UserData + if (strcmp(_modelSetting->GetUserDataFile(), "") != 0) + { + csmString path = _modelSetting->GetUserDataFile(); + path = _modelHomeDir + path; + buffer = CreateBuffer(path.GetRawString(), &size); + LoadUserData(buffer, size); + DeleteBuffer(buffer, path.GetRawString()); + } + + // EyeBlinkIds + { + csmInt32 eyeBlinkIdCount = _modelSetting->GetEyeBlinkParameterCount(); + for (csmInt32 i = 0; i < eyeBlinkIdCount; ++i) + { + _eyeBlinkIds.PushBack(_modelSetting->GetEyeBlinkParameterId(i)); + } + } + + // LipSyncIds + { + csmInt32 lipSyncIdCount = _modelSetting->GetLipSyncParameterCount(); + for (csmInt32 i = 0; i < lipSyncIdCount; ++i) + { + _lipSyncIds.PushBack(_modelSetting->GetLipSyncParameterId(i)); + } + } + + if (_modelSetting == NULL || _modelMatrix == NULL) + { + LAppPal::PrintLogLn("Failed to SetupModel()."); + return; + } + + //Layout + csmMap layout; + _modelSetting->GetLayoutMap(layout); + _modelMatrix->SetupFromLayout(layout); + + _model->SaveParameters(); + + for (csmInt32 i = 0; i < _modelSetting->GetMotionGroupCount(); i++) + { + const csmChar* group = _modelSetting->GetMotionGroupName(i); + PreloadMotionGroup(group); + } + + _motionManager->StopAllMotions(); + + _updating = false; + _initialized = true; +} + +void LAppModel::PreloadMotionGroup(const csmChar* group) +{ + const csmInt32 count = _modelSetting->GetMotionCount(group); + + for (csmInt32 i = 0; i < count; i++) + { + //ex) idle_0 + csmString name = Utils::CubismString::GetFormatedString("%s_%d", group, i); + csmString path = _modelSetting->GetMotionFileName(group, i); + path = _modelHomeDir + path; + + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]load motion: %s => [%s_%d] ", path.GetRawString(), group, i); + } + + csmByte* buffer; + csmSizeInt size; + buffer = CreateBuffer(path.GetRawString(), &size); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); + + if (tmpMotion) + { + tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); + + if (_motions[name] != NULL) + { + ACubismMotion::Delete(_motions[name]); + } + _motions[name] = tmpMotion; + } + + DeleteBuffer(buffer, path.GetRawString()); + } +} + +void LAppModel::ReleaseMotionGroup(const csmChar* group) const +{ + const csmInt32 count = _modelSetting->GetMotionCount(group); + for (csmInt32 i = 0; i < count; i++) + { + csmString voice = _modelSetting->GetMotionSoundFileName(group, i); + if (strcmp(voice.GetRawString(), "") != 0) + { + csmString path = voice; + path = _modelHomeDir + path; + } + } +} + +/** +* @brief すべてのモーションデータの解放 +* +* すべてのモーションデータを解放する。 +*/ +void LAppModel::ReleaseMotions() +{ + for (csmMap::const_iterator iter = _motions.Begin(); iter != _motions.End(); ++iter) + { + ACubismMotion::Delete(iter->Second); + } + + _motions.Clear(); +} + +/** +* @brief すべての表情データの解放 +* +* すべての表情データを解放する。 +*/ +void LAppModel::ReleaseExpressions() +{ + for (csmMap::const_iterator iter = _expressions.Begin(); iter != _expressions.End(); ++iter) + { + ACubismMotion::Delete(iter->Second); + } + + _expressions.Clear(); +} + +void LAppModel::Update() +{ + const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime(); + _userTimeSeconds += deltaTimeSeconds; + + _dragManager->Update(deltaTimeSeconds); + _dragX = _dragManager->GetX(); + _dragY = _dragManager->GetY(); + + // モーションによるパラメータ更新の有無 + csmBool motionUpdated = false; + + //----------------------------------------------------------------- + _model->LoadParameters(); // 前回セーブされた状態をロード + if (_motionManager->IsFinished()) + { + // モーションの再生がない場合、待機モーションの中からランダムで再生する + StartRandomMotion(MotionGroupIdle, PriorityIdle); + } + else + { + motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新 + } + _model->SaveParameters(); // 状態を保存 + //----------------------------------------------------------------- + + // 不透明度 + _opacity = _model->GetModelOpacity(); + + // まばたき + if (!motionUpdated) + { + if (_eyeBlink != NULL) + { + // メインモーションの更新がないとき + _eyeBlink->UpdateParameters(_model, deltaTimeSeconds); // 目パチ + } + } + + if (_expressionManager != NULL) + { + _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化) + } + + //ドラッグによる変化 + //ドラッグによる顔の向きの調整 + _model->AddParameterValue(_idParamAngleX, _dragX * 30); // -30から30の値を加える + _model->AddParameterValue(_idParamAngleY, _dragY * 30); + _model->AddParameterValue(_idParamAngleZ, _dragX * _dragY * -30); + + //ドラッグによる体の向きの調整 + _model->AddParameterValue(_idParamBodyAngleX, _dragX * 10); // -10から10の値を加える + + //ドラッグによる目の向きの調整 + _model->AddParameterValue(_idParamEyeBallX, _dragX); // -1から1の値を加える + _model->AddParameterValue(_idParamEyeBallY, _dragY); + + // 呼吸など + if (_breath != NULL) + { + _breath->UpdateParameters(_model, deltaTimeSeconds); + } + + // 物理演算の設定 + if (_physics != NULL) + { + _physics->Evaluate(_model, deltaTimeSeconds); + } + + // リップシンクの設定 + if (_lipSync) + { + // リアルタイムでリップシンクを行う場合、システムから音量を取得して0〜1の範囲で値を入力します。 + csmFloat32 value = 0.0f; + + // 状態更新/RMS値取得 + _wavFileHandler.Update(deltaTimeSeconds); + value = _wavFileHandler.GetRms(); + + for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i) + { + _model->AddParameterValue(_lipSyncIds[i], value, 0.8f); + } + } + + // ポーズの設定 + if (_pose != NULL) + { + _pose->UpdateParameters(_model, deltaTimeSeconds); + } + + _model->Update(); +} + +CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, + ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) +{ + if (priority == PriorityForce) + { + _motionManager->SetReservePriority(priority); + } + else if (!_motionManager->ReserveMotion(priority)) + { + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]can't start motion."); + } + return InvalidMotionQueueEntryHandleValue; + } + + const csmString fileName = _modelSetting->GetMotionFileName(group, no); + + //ex) idle_0 + csmString name = Utils::CubismString::GetFormatedString("%s_%d", group, no); + CubismMotion* motion = static_cast(_motions[name.GetRawString()]); + csmBool autoDelete = false; + + if (motion == NULL) + { + csmString path = fileName; + path = _modelHomeDir + path; + + csmByte* buffer; + csmSizeInt size; + buffer = CreateBuffer(path.GetRawString(), &size); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); + + if (motion) + { + motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); + autoDelete = true; // 終了時にメモリから削除 + } + + DeleteBuffer(buffer, path.GetRawString()); + } + else + { + motion->SetBeganMotionHandler(onBeganMotionHandler); + motion->SetFinishedMotionHandler(onFinishedMotionHandler); + } + + //voice + csmString voice = _modelSetting->GetMotionSoundFileName(group, no); + if (strcmp(voice.GetRawString(), "") != 0) + { + csmString path = voice; + path = _modelHomeDir + path; + _wavFileHandler.Start(path); + } + + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]start motion: [%s_%d]", group, no); + } + return _motionManager->StartMotionPriority(motion, autoDelete, priority); +} + +CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, + ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) +{ + if (_modelSetting->GetMotionCount(group) == 0) + { + return InvalidMotionQueueEntryHandleValue; + } + + csmInt32 no = rand() % _modelSetting->GetMotionCount(group); + + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); +} + +void LAppModel::DoDraw() +{ + if (_model == NULL) + { + return; + } + + GetRenderer()->DrawModel(); +} + +void LAppModel::Draw(CubismMatrix44& matrix) +{ + if (_model == NULL) + { + return; + } + + matrix.MultiplyByMatrix(_modelMatrix); + + GetRenderer()->SetMvpMatrix(&matrix); + DoDraw(); +} + +csmBool LAppModel::HitTest(const csmChar* hitAreaName, csmFloat32 x, csmFloat32 y) +{ + // 透明時は当たり判定なし。 + if (_opacity < 1) + { + return false; + } + const csmInt32 count = _modelSetting->GetHitAreasCount(); + for (csmInt32 i = 0; i < count; i++) + { + if (strcmp(_modelSetting->GetHitAreaName(i), hitAreaName) == 0) + { + const CubismIdHandle drawID = _modelSetting->GetHitAreaId(i); + return IsHit(drawID, x, y); + } + } + return false; // 存在しない場合はfalse +} + +void LAppModel::SetExpression(const csmChar* expressionID) +{ + ACubismMotion* motion = _expressions[expressionID]; + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]expression: [%s]", expressionID); + } + + if (motion != NULL) + { + _expressionManager->StartMotion(motion, false); + } + else + { + if (_debugMode) + { + LAppPal::PrintLogLn("[APP]expression[%s] is null ", expressionID); + } + } +} + +void LAppModel::SetRandomExpression() +{ + if (_expressions.GetSize() == 0) + { + return; + } + + csmInt32 no = rand() % _expressions.GetSize(); + csmMap::const_iterator map_ite; + csmInt32 i = 0; + for (map_ite = _expressions.Begin(); map_ite != _expressions.End(); map_ite++) + { + if (i == no) + { + csmString name = (*map_ite).First; + SetExpression(name.GetRawString()); + return; + } + i++; + } +} + +void LAppModel::ReloadRenderer(VkDevice device, VkFormat surfaceFormat) +{ + DeleteRenderer(); + + CreateRenderer(); + + SetupTextures(device, surfaceFormat); +} + +void LAppModel::SetupTextures(VkDevice device, VkFormat surfaceFormat) +{ + _bindTextureId.Clear(); + + for (csmInt32 modelTextureNumber = 0; modelTextureNumber < _modelSetting->GetTextureCount(); modelTextureNumber++) + { + // テクスチャ名が空文字だった場合はロード・バインド処理をスキップ + if (strcmp(_modelSetting->GetTextureFileName(modelTextureNumber), "") == 0) + { + continue; + } + + //OpenGLのテクスチャユニットにテクスチャをロードする + csmString texturePath = _modelSetting->GetTextureFileName(modelTextureNumber); + texturePath = _modelHomeDir + texturePath; + + LAppTextureManager::TextureInfo* texture = LAppDelegate::GetInstance()->GetTextureManager()->CreateTextureFromPngFile( + texturePath.GetRawString(), surfaceFormat, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + if (texture) + { + const csmUint32 textureManageId = texture->Id; + CubismImageVulkan image; + if (LAppDelegate::GetInstance()->GetTextureManager()->GetTexture(textureManageId, image)) + { + GetRenderer()->BindTexture(image); + _bindTextureId.PushBack(textureManageId); + } + } + } + +#ifdef PREMULTIPLIED_ALPHA_ENABLE + GetRenderer()->IsPremultipliedAlpha(true); +#else + GetRenderer()->IsPremultipliedAlpha(false); +#endif + +} + +void LAppModel::MotionEventFired(const csmString& eventValue) +{ + CubismLogInfo("%s is fired on LAppModel!!", eventValue.GetRawString()); +} + +Csm::Rendering::CubismOffscreenSurface_Vulkan& LAppModel::GetRenderBuffer() +{ + return _renderBuffer; +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppModel.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppModel.hpp new file mode 100644 index 00000000..fa8592da --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppModel.hpp @@ -0,0 +1,199 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "LAppWavFileHandler.hpp" + +/** + * @brief ユーザーが実際に使用するモデルの実装クラス
+ * モデル生成、機能コンポーネント生成、更新処理とレンダリングの呼び出しを行う。 + * + */ +class LAppModel : public Csm::CubismUserModel +{ +public: + /** + * @brief コンストラクタ + */ + LAppModel(); + + /** + * @brief デストラクタ + * + */ + virtual ~LAppModel(); + + /** + * @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する + * + * @param[in] device デバイス + * @param[in] dir ディレクトリ名 + * @param[in] fileName アセット名 + */ + void LoadAssets(VkDevice device, VkFormat imageFormat, const Csm::csmChar* dir, const Csm::csmChar* fileName); + + /** + * @brief レンダラを再構築する + * + * @param[in] device デバイス + */ + void ReloadRenderer(VkDevice device, VkFormat surfaceFormat); + + /** + * @brief モデルの更新処理。モデルのパラメータから描画状態を決定する。 + * + */ + void Update(); + + /** + * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。 + * + * @param[in] IsWindowSizeChanged ウィンドウサイズが変更されたか + * @param[in] matrix View-Projection行列 + */ + void Draw(Csm::CubismMatrix44& matrix); + + /** + * @brief 引数で指定したモーションの再生を開始する。 + * + * @param[in] group モーショングループ名 + * @param[in] no グループ内の番号 + * @param[in] priority 優先度 + * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 + */ + Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, + Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); + + /** + * @brief ランダムに選ばれたモーションの再生を開始する。 + * + * @param[in] group モーショングループ名 + * @param[in] priority 優先度 + * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 + */ + Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, + Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); + + /** + * @brief 引数で指定した表情モーションをセットする + * + * @param expressionID 表情モーションのID + */ + void SetExpression(const Csm::csmChar* expressionID); + + /** + * @brief ランダムに選ばれた表情モーションをセットする + * + */ + void SetRandomExpression(); + + /** + * @brief イベントの発火を受け取る + * + */ + virtual void MotionEventFired(const Live2D::Cubism::Framework::csmString& eventValue); + + /** + * @brief 当たり判定テスト。
+ * 指定IDの頂点リストから矩形を計算し、座標が矩形範囲内か判定する。 + * + * @param[in] hitAreaName 当たり判定をテストする対象のID + * @param[in] x 判定を行うX座標 + * @param[in] y 判定を行うY座標 + */ + virtual Csm::csmBool HitTest(const Csm::csmChar* hitAreaName, Csm::csmFloat32 x, Csm::csmFloat32 y); + + /** + * @brief 別ターゲットに描画する際に使用するバッファの取得 + */ + Csm::Rendering::CubismOffscreenSurface_Vulkan& GetRenderBuffer(); + +protected: + /** + * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。 + * + */ + void DoDraw(); + +private: + /** + * @brief model3.jsonからモデルを生成する。
+ * model3.jsonの記述に従ってモデル生成、モーション、物理演算などのコンポーネント生成を行う。 + * + * @param[in] setting ICubismModelSettingのインスタンス + * + */ + void SetupModel(Csm::ICubismModelSetting* setting); + + /** + * @brief OpenGLのテクスチャユニットにテクスチャをロードする + * + * @param[in] device デバイス + */ + void SetupTextures(VkDevice device, VkFormat surfaceFormat); + + /** + * @brief モーションデータをグループ名から一括でロードする。
+ * モーションデータの名前は内部でModelSettingから取得する。 + * + * @param[in] group モーションデータのグループ名 + */ + void PreloadMotionGroup(const Csm::csmChar* group); + + /** + * @brief モーションデータをグループ名から一括で解放する。
+ * モーションデータの名前は内部でModelSettingから取得する。 + * + * @param[in] group モーションデータのグループ名 + */ + void ReleaseMotionGroup(const Csm::csmChar* group) const; + + /** + * @brief すべてのモーションデータの解放 + * + * すべてのモーションデータを解放する。 + */ + void ReleaseMotions(); + + /** + * @brief すべての表情データの解放 + * + * すべての表情データを解放する。 + */ + void ReleaseExpressions(); + + Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報 + Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ + Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] + Csm::csmVector _eyeBlinkIds; ///< モデルに設定されたまばたき機能用パラメータID + Csm::csmVector _lipSyncIds; ///< モデルに設定されたリップシンク機能用パラメータID + Csm::csmMap _motions; ///< 読み込まれているモーションのリスト + Csm::csmMap _expressions; ///< 読み込まれている表情のリスト + Csm::csmVector _hitArea; + Csm::csmVector _userArea; + const Csm::CubismId* _idParamAngleX; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamAngleY; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamAngleZ; ///< パラメータID: ParamAngleX + const Csm::CubismId* _idParamBodyAngleX; ///< パラメータID: ParamBodyAngleX + const Csm::CubismId* _idParamEyeBallX; ///< パラメータID: ParamEyeBallX + const Csm::CubismId* _idParamEyeBallY; ///< パラメータID: ParamEyeBallXY + + LAppWavFileHandler _wavFileHandler; ///< wavファイルハンドラ + + Csm::Rendering::CubismOffscreenSurface_Vulkan _renderBuffer; ///< フレームバッファ以外の描画先 + Csm::csmVector _bindTextureId; ///< テクスチャID +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppPal.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppPal.cpp new file mode 100644 index 00000000..04c423da --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppPal.cpp @@ -0,0 +1,122 @@ +/** + * 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. + */ + +#include "LAppPal.hpp" +#include +#include +#include +#include +#include +#include +#define GLFW_INCLUDE_VULKAN +#include +#include +#include "LAppDefine.hpp" + +using std::endl; +using namespace Csm; +using namespace std; +using namespace LAppDefine; + +double LAppPal::s_currentFrame = 0.0; +double LAppPal::s_lastFrame = 0.0; +double LAppPal::s_deltaTime = 0.0; + +csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) +{ + //filePath;// + const char* path = filePath.c_str(); + + int size = 0; + struct stat statBuf; + if (stat(path, &statBuf) == 0) + { + size = statBuf.st_size; + + if (size == 0) + { + if (DebugLogEnable) + { + PrintLogLn("Stat succeeded but file size is zero. path:%s", path); + } + return NULL; + } + } + else + { + if (DebugLogEnable) + { + PrintLogLn("Stat failed. errno:%d path:%s", errno, path); + } + return NULL; + } + + std::fstream file; + file.open(path, std::ios::in | std::ios::binary); + if (!file.is_open()) + { + if (DebugLogEnable) + { + PrintLogLn("File open failed. path:%s", path); + } + return NULL; + } + + char* buf = new char[size]; + file.read(buf, size); + file.close(); + + *outSize = size; + return reinterpret_cast(buf); +} + +void LAppPal::ReleaseBytes(csmByte* byteData) +{ + delete[] byteData; +} + +csmFloat32 LAppPal::GetDeltaTime() +{ + return static_cast(s_deltaTime); +} + +void LAppPal::UpdateTime() +{ + s_currentFrame = glfwGetTime(); + s_deltaTime = s_currentFrame - s_lastFrame; + s_lastFrame = s_currentFrame; +} + +void LAppPal::PrintLog(const csmChar* format, ...) +{ + va_list args; + csmChar buf[256]; + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); // 標準出力でレンダリング + std::cout << buf; + va_end(args); +} + +void LAppPal::PrintLogLn(const csmChar* format, ...) +{ + va_list args; + csmChar buf[256]; + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); // 標準出力でレンダリング + std::cout << buf << std::endl; + va_end(args); +} + +void LAppPal::PrintMessage(const csmChar* message) +{ + PrintLog("%s", message); +} + +void LAppPal::PrintMessageLn(const csmChar* message) +{ + PrintLogLn("%s", message); +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppPal.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppPal.hpp new file mode 100644 index 00000000..5b1ee036 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppPal.hpp @@ -0,0 +1,101 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include +#include +#include + +/** +* @brief プラットフォーム依存機能を抽象化する Cubism Platform Abstraction Layer. +* +* ファイル読み込みや時刻取得等のプラットフォームに依存する関数をまとめる +* +*/ +class LAppPal +{ +public: + /** + * @brief ファイルをバイトデータとして読み込む + * + * ファイルをバイトデータとして読み込む + * + * @param[in] filePath 読み込み対象ファイルのパス + * @param[out] outSize ファイルサイズ + * @return バイトデータ + */ + static Csm::csmByte* LoadFileAsBytes(const std::string filePath, Csm::csmSizeInt* outSize); + + + /** + * @brief バイトデータを解放する + * + * バイトデータを解放する + * + * @param[in] byteData 解放したいバイトデータ + */ + static void ReleaseBytes(Csm::csmByte* byteData); + + /** + * @biref デルタ時間(前回フレームとの差分)を取得する + * + * @return デルタ時間[ms] + * + */ + static Csm::csmFloat32 GetDeltaTime(); + + static void UpdateTime(); + + /** + * @brief ログを出力する + * + * ログを出力する + * + * @param[in] format 書式付文字列 + * @param[in] ... (可変長引数)文字列 + * + */ + static void PrintLog(const Csm::csmChar* format, ...); + + /** + * @brief ログを出力し最後に改行する + * + * ログを出力し最後に改行する + * + * @param[in] format 書式付文字列 + * @param[in] ... (可変長引数)文字列 + * + */ + static void PrintLogLn(const Csm::csmChar* format, ...); + + /** + * @brief メッセージを出力する + * + * メッセージを出力する + * + * @param[in] message 文字列 + * + */ + static void PrintMessage(const Csm::csmChar* message); + + /** + * @brief メッセージを出力し最後に改行する + * + * メッセージを出力し最後に改行する + * + * @param[in] message 文字列 + * + */ + static void PrintMessageLn(const Csm::csmChar* message); + +private: + static double s_currentFrame; + static double s_lastFrame; + static double s_deltaTime; +}; + diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppSprite.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppSprite.cpp new file mode 100644 index 00000000..47c30fd0 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppSprite.cpp @@ -0,0 +1,258 @@ +/** + * 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. + */ + +#include "LAppSprite.hpp" +#include "LAppTextureManager.hpp" +#include "VulkanManager.hpp" + +using namespace Csm; + +LAppSprite::LAppSprite( + VkDevice device, VkPhysicalDevice physicalDevice, VulkanManager* vkManager, float x, float y, float width, float height, + Csm::csmUint32 textureId, VkImageView view, VkSampler sampler, VkDescriptorSetLayout descriptorSetLayout) + : _rect() + , _textureId(textureId) +{ + _rect.Left = (x - width * 0.5f); + _rect.Right = (x + width * 0.5f); + _rect.Up = (y - height * 0.5f); + _rect.Down = (y + height * 0.5f); + + _spriteColor[0] = 1.0f; + _spriteColor[1] = 1.0f; + _spriteColor[2] = 1.0f; + _spriteColor[3] = 1.0f; + + if (_vertexBuffer.GetBuffer() == VK_NULL_HANDLE) + { + VkDeviceSize bufferSize = sizeof(SpriteVertex) * VertexNum; // 総長 構造体サイズ*個数 + _stagingBuffer.CreateBuffer(device, physicalDevice, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + _stagingBuffer.Map(device, bufferSize); + _vertexBuffer.CreateBuffer(device, physicalDevice, bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + if (_indexBuffer.GetBuffer() == VK_NULL_HANDLE) + { + uint16_t idx[IndexNum] = { + 0, 1, 2, + 1, 3, 2 + }; + + uint64_t bufferSize = sizeof(uint16_t) * IndexNum; + + CubismBufferVulkan stagingBuffer; + stagingBuffer.CreateBuffer(device, physicalDevice, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + stagingBuffer.Map(device, bufferSize); + stagingBuffer.MemCpy(idx, bufferSize); + stagingBuffer.UnMap(device); + + _indexBuffer.CreateBuffer(device, physicalDevice, bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + VkCommandBuffer commandBuffer = vkManager->BeginSingleTimeCommands(); + VkBufferCopy copyRegion{}; + copyRegion.size = bufferSize; + vkCmdCopyBuffer(commandBuffer, stagingBuffer.GetBuffer(), _indexBuffer.GetBuffer(), 1, ©Region); + vkManager->SubmitCommand(commandBuffer); + + stagingBuffer.Destroy(device); + } + + if (_uniformBuffer.GetBuffer() == VK_NULL_HANDLE) + { + _uniformBuffer.CreateBuffer(device, physicalDevice, sizeof(SpriteUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + _uniformBuffer.Map(device, VK_WHOLE_SIZE); + } + + VkDescriptorPoolSize poolSizes[2]{}; + poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + poolSizes[0].descriptorCount = 1; + poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + poolSizes[1].descriptorCount = 1; + + VkDescriptorPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.poolSizeCount = 2; + poolInfo.pPoolSizes = poolSizes; + poolInfo.maxSets = 1; + + if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &_descriptorPool) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create descriptor pool!"); + } + + CreateDescriptorSet(device, descriptorSetLayout); + if (view != NULL && sampler != NULL) + { + SetDescriptorUpdated(false); + UpdateDescriptorSet(device, view, sampler); + } +} + +LAppSprite::~LAppSprite() +{} + +void LAppSprite::Release(VkDevice device) +{ + _vertexBuffer.Destroy(device); + _stagingBuffer.Destroy(device); + _indexBuffer.Destroy(device); + _uniformBuffer.Destroy(device); + vkDestroyDescriptorPool(device, _descriptorPool, nullptr); +} + +void LAppSprite::CreateDescriptorSet(VkDevice device, VkDescriptorSetLayout descriptorSetLayout) +{ + VkDescriptorSetAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = _descriptorPool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &descriptorSetLayout; + if (vkAllocateDescriptorSets(device, &allocInfo, &_descriptorSet) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to allocate descriptor sets!"); + } +} + +void LAppSprite::UpdateData(VulkanManager* vkManager, int maxWidth, int maxHeight) const +{ + if (maxWidth == 0 || maxHeight == 0) + { + return; // この際は描画できず + } + + SpriteVertex vtx[VertexNum] = { + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.5f, 0.0f, 1.0f, 0.0f}, + {0.0f, 0.5f, 0.0f, 1.0f}, + {0.5f, 0.5f, 1.0f, 1.0f}, + }; + + vtx[0].X = (_rect.Left - maxWidth * 0.5f) / (maxWidth * 0.5f); + vtx[0].Y = (_rect.Down - maxHeight * 0.5f) / (maxHeight * 0.5f); + vtx[1].X = (_rect.Right - maxWidth * 0.5f) / (maxWidth * 0.5f); + vtx[1].Y = (_rect.Down - maxHeight * 0.5f) / (maxHeight * 0.5f); + vtx[2].X = (_rect.Left - maxWidth * 0.5f) / (maxWidth * 0.5f); + vtx[2].Y = (_rect.Up - maxHeight * 0.5f) / (maxHeight * 0.5f); + vtx[3].X = (_rect.Right - maxWidth * 0.5f) / (maxWidth * 0.5f); + vtx[3].Y = (_rect.Up - maxHeight * 0.5f) / (maxHeight * 0.5f); + + SpriteVertex vertex; + csmVector vertices; + for (SpriteVertex vt : vtx) + { + vertex.X = vt.X; + vertex.Y = vt.Y; + vertex.U = vt.U; + vertex.V = vt.V; + vertices.PushBack(vertex); + } + + VkCommandBuffer commandBuffer = vkManager->BeginSingleTimeCommands(); + csmUint32 bufferSize = sizeof(SpriteVertex) * vertices.GetSize(); + + _stagingBuffer.MemCpy(vertices.GetPtr(), bufferSize); + + VkBufferCopy copyRegion{}; + copyRegion.size = bufferSize; + vkCmdCopyBuffer(commandBuffer, _stagingBuffer.GetBuffer(), _vertexBuffer.GetBuffer(), 1, ©Region); + + vkManager->SubmitCommand(commandBuffer); + + //ユニフォームバッファ設定 + SpriteUBO _ubo; + _ubo.SpriteColor[0] = _spriteColor[0]; + _ubo.SpriteColor[1] = _spriteColor[1]; + _ubo.SpriteColor[2] = _spriteColor[2]; + _ubo.SpriteColor[3] = _spriteColor[3]; + _uniformBuffer.MemCpy(&_ubo, sizeof(SpriteUBO)); +} + +void LAppSprite::UpdateDescriptorSet(VkDevice device, VkImageView view, VkSampler sampler) +{ + if (!isDescriptorUpdated) + { + csmVector descriptorWrites; + descriptorWrites.Resize(2); + + VkDescriptorBufferInfo uniformBufferInfo{}; + uniformBufferInfo.buffer = _uniformBuffer.GetBuffer(); + uniformBufferInfo.offset = 0; + uniformBufferInfo.range = VK_WHOLE_SIZE; + + descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[0].dstSet = _descriptorSet; + descriptorWrites[0].dstBinding = 0; + descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorWrites[0].descriptorCount = 1; + descriptorWrites[0].pBufferInfo = &uniformBufferInfo; + + VkDescriptorImageInfo imageInfo; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.imageView = view; + imageInfo.sampler = sampler; + + descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[1].dstSet = _descriptorSet; + descriptorWrites[1].dstBinding = 1; + descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrites[1].descriptorCount = 1; + descriptorWrites[1].pImageInfo = &imageInfo; + + vkUpdateDescriptorSets(device, descriptorWrites.GetSize(), descriptorWrites.GetPtr(), 0, NULL); + isDescriptorUpdated = true; + } +} + +void LAppSprite::SetDescriptorUpdated(bool frag) +{ + isDescriptorUpdated = frag; +} + +void LAppSprite::Render(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanManager* vkManager, int windowWidth, int windowHeight) +{ + UpdateData(vkManager, windowWidth, windowHeight); + VkBuffer vertexBuffers[] = {_vertexBuffer.GetBuffer()}; + VkDeviceSize offsets[] = {0}; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); + vkCmdBindIndexBuffer(commandBuffer, _indexBuffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT16); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &_descriptorSet, 0,nullptr); + vkCmdDrawIndexed(commandBuffer, IndexNum, 1, 0, 0, 0); +} + +bool LAppSprite::IsHit(int windowWidth, int windowHeight, float pointX, float pointY) const +{ + if(windowWidth==0 || windowHeight==0) + { + return false; + } + float y = pointY; + + return (pointX >= _rect.Left && pointX <= _rect.Right && y >= _rect.Up && y <= _rect.Down); +} + +void LAppSprite::SetColor(float r, float g, float b, float a) +{ + _spriteColor[0] = r; + _spriteColor[1] = g; + _spriteColor[2] = b; + _spriteColor[3] = a; +} + +void LAppSprite::ResetRect(float x, float y, float width, float height) +{ + _rect.Left = (x - width * 0.5f); + _rect.Right = (x + width * 0.5f); + _rect.Up = (y - height * 0.5f); + _rect.Down = (y + height * 0.5f); +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppSprite.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppSprite.hpp new file mode 100644 index 00000000..85f0f139 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppSprite.hpp @@ -0,0 +1,207 @@ +/** + * 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. + */ + +#pragma once +#include + +// 前方宣言 +class VulkanManager; + +/** +* @brief スプライトを実装するクラス。 +* +* テクスチャID、Rectの管理。 +* +*/ +class LAppSprite +{ +public: + /** + * @brief Rect 構造体。 + */ + struct Rect + { + public: + float Left; ///< 左辺 + float Right; ///< 右辺 + float Up; ///< 上辺 + float Down; ///< 下辺 + }; + /** + * @brief 頂点情報を保持する構造体 + * + */ + struct SpriteVertex + { + float X, Y; // Position + float U, V; // UVs + + /** + * @brief 頂点入力のバインド設定を指定する + */ + static VkVertexInputBindingDescription GetBindingDescription() + { + VkVertexInputBindingDescription bindingDescription{}; + bindingDescription.binding = 0; + bindingDescription.stride = sizeof(SpriteVertex); + bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + return bindingDescription; + } + + /** + * @brief 頂点入力の構造を指定する + */ + static void GetAttributeDescriptions(VkVertexInputAttributeDescription attributeDescriptions[2]) + { + attributeDescriptions[0].binding = 0; + attributeDescriptions[0].location = 0; + attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT; + attributeDescriptions[0].offset = offsetof(SpriteVertex, X); + attributeDescriptions[1].binding = 0; + attributeDescriptions[1].location = 1; + attributeDescriptions[1].format = VK_FORMAT_R32G32_SFLOAT; + attributeDescriptions[1].offset = offsetof(SpriteVertex, U); + } + }; + + /** + * @brief スプライト用ユニフォームバッファオブジェクトの中身を保持する構造体 + * + */ + struct SpriteUBO + { + float SpriteColor[4]; + }; + + /** + * @brief コンストラクタ + * + * @param[in] device デバイス + * @param[in] physicalDevice 物理デバイス + * @param[in] vkManager Vulkanリソースマネージャ + * @param[in] x x座標 + * @param[in] y y座標 + * @param[in] width 横幅 + * @param[in] height 高さ + * @param[in] textureId テクスチャID + * @param[in] view テクスチャビュー + * @param[in] sampler テクスチャサンプラー + * @param[in] descriptorSetLayout ディスクリプタセット + */ + LAppSprite( + VkDevice device, VkPhysicalDevice physicalDevice, VulkanManager* vkManager, float x, float y, float width, float height, + uint32_t textureId, VkImageView view, VkSampler sampler, VkDescriptorSetLayout descriptorSetLayout + ); + + /** + * @brief デストラクタ + */ + ~LAppSprite(); + + /** + * @brief リソースを開放する + * + * @param[in] device デバイス + */ + void Release(VkDevice device); + + /** + * @brief ディスクリプタセットを作成する + * + * @param[in] device デバイス + * @param[in] descriptorSetLayout ディスクリプタセットレイアウト + */ + void CreateDescriptorSet(VkDevice device, VkDescriptorSetLayout descriptorSetLayout); + + /** + * @brief ユニフォームバッファを更新する + * + * @param[in] vkManager Vulkanリソースマネージャ + * @param[in] maxWidth 最大幅 + * @param[in] maxHeight 最大高さ + */ + void UpdateData(VulkanManager* vkManager, int maxWidth, int maxHeight) const; + + /** + * @brief ディスクリプタセットを更新する + * + * @param[in] device デバイス + * @param[in] view テクスチャビュー + * @param[in] sampler テクスチャサンプラー + */ + void UpdateDescriptorSet(VkDevice device, VkImageView view, VkSampler sampler); + + /** + * @brief ディスクリプタセットの更新フラグを設定する + * + * @param[in] frag フラグ + */ + void SetDescriptorUpdated(bool frag); + + /** + * @brief 描画する + * + * @param[in] commandBuffer コマンドバッファ + * @param[in] pipelineLayout パイプラインレイアウト + * @param[in] vkManager Vulkanリソースマネージャ + * @param[in] windowWidth ウィンドウ幅 + * @param[in] windowHeight ウィンドウ高さ + */ + void Render(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanManager* vkManager, int windowWidth, int windowHeight); + + /** + * @brief コンストラクタ + * + * @param[in] windowWidth ウィンドウ幅 + * @param[in] windowHeight ウィンドウ高さ + * @param[in] pointX x座標 + * @param[in] pointY y座標 + */ + bool IsHit(int windowWidth, int windowHeight, float pointX, float pointY) const; + + /** + * @brief 色設定 + * + * @param[in] r (0.0~1.0) + * @param[in] g (0.0~1.0) + * @param[in] b (0.0~1.0) + * @param[in] a (0.0~1.0) + */ + void SetColor(float r, float g, float b, float a); + + /** + * @brief サイズ再設定 + * + * @param[in] x x座標 + * @param[in] y y座標 + * @param[in] width 横幅 + * @param[in] height 高さ + */ + void ResetRect(float x, float y, float width, float height); + + /** + * @brief Getter テクスチャID + * @return テクスチャIDを返す + */ + uint32_t GetTextureId() { return _textureId; } + + +private: + static const uint16_t VertexNum = 4; + static const uint16_t IndexNum = 6; + Csm::csmUint32 _textureId; ///< テクスチャID + Rect _rect; ///< 矩形 + float _spriteColor[4]; ///< 表示カラー + Live2D::Cubism::Framework::CubismBufferVulkan _vertexBuffer; ///< 頂点バッファ + Live2D::Cubism::Framework::CubismBufferVulkan _stagingBuffer; ///< ステージングバッファ + Live2D::Cubism::Framework::CubismBufferVulkan _indexBuffer; ///< インデックスバッファ + Live2D::Cubism::Framework::CubismBufferVulkan _uniformBuffer; ///< ユニフォームバッファ + VkDescriptorPool _descriptorPool; ///< ディスクリプタプール + VkDescriptorSet _descriptorSet; ///< ディスクリプタセット モデルの数 + bool isDescriptorUpdated; +}; + diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppTextureManager.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppTextureManager.cpp new file mode 100644 index 00000000..dad71698 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppTextureManager.cpp @@ -0,0 +1,331 @@ +/** + * 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. + */ + +#include "LAppTextureManager.hpp" +#include +#define STBI_NO_STDIO +#define STBI_ONLY_PNG +#define STB_IMAGE_IMPLEMENTATION +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif +#include "stb_image.h" +#if defined(__clang__) +#pragma clang diagnostic pop +#endif +#include "LAppPal.hpp" +#include "LAppDelegate.hpp" + +using namespace Live2D::Cubism::Framework; + +LAppTextureManager::LAppTextureManager() + : _sequenceId(0) + , _mipLevels(0) +{ +} + +LAppTextureManager::~LAppTextureManager() +{ + ReleaseTextures(); +} + +void LAppTextureManager::CopyBufferToImage(VkCommandBuffer commandBuffer, const VkBuffer& buffer, VkImage image, + uint32_t width, uint32_t height) +{ + VkBufferImageCopy region{}; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageOffset = {0, 0, 0}; + region.imageExtent = { + width, + height, + 1 + }; + + vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); +} + +void LAppTextureManager::GenerateMipmaps(CubismImageVulkan image, uint32_t texWidth, uint32_t texHeight, + uint32_t mipLevels) +{ + VkCommandBuffer commandBuffer = VulkanManager::GetInstance()->BeginSingleTimeCommands(); + + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image.GetImage(); + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.levelCount = 1; + + int32_t mipWidth = texWidth; + int32_t mipHeight = texHeight; + + for (uint32_t i = 1; i < mipLevels; i++) + { + barrier.subresourceRange.baseMipLevel = i - 1; + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + vkCmdPipelineBarrier(commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + 0, nullptr, + 0, nullptr, + 1, &barrier); + + VkImageBlit blit{}; + blit.srcOffsets[0] = {0, 0, 0}; + blit.srcOffsets[1] = {mipWidth, mipHeight, 1}; + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.mipLevel = i - 1; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = 1; + blit.dstOffsets[0] = {0, 0, 0}; + blit.dstOffsets[1] = {mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1}; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.mipLevel = i; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = 1; + + vkCmdBlitImage(commandBuffer, + image.GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image.GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &blit, + VK_FILTER_LINEAR); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + vkCmdPipelineBarrier(commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + 0, nullptr, + 0, nullptr, + 1, &barrier); + + if (mipWidth > 1) + { + mipWidth /= 2; + } + + if (mipHeight > 1) + { + mipHeight /= 2; + } + } + + barrier.subresourceRange.baseMipLevel = mipLevels - 1; + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + vkCmdPipelineBarrier(commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + 0, nullptr, + 0, nullptr, + 1, &barrier); + + VulkanManager::GetInstance()->SubmitCommand(commandBuffer); +} + +LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile( + std::string fileName, VkFormat format, + VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags imageProperties) +{ + VkDevice device = VulkanManager::GetInstance()->GetDevice(); + VkPhysicalDevice physicalDevice = VulkanManager::GetInstance()->GetPhysicalDevice(); + + //search loaded texture already. + for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++) + { + if (_texturesInfo[i]->FileName == fileName) + { + return _texturesInfo[i]; + } + } + + int width, height, channels; + unsigned int size; + unsigned char* png; + unsigned char* address; + + address = LAppPal::LoadFileAsBytes(fileName, &size); + + // png情報を取得する + png = stbi_load_from_memory( + address, + static_cast(size), + &width, + &height, + &channels, + STBI_rgb_alpha); + { +#ifdef PREMULTIPLIED_ALPHA_ENABLE + unsigned int* fourBytes = reinterpret_cast(png); + for (int i = 0; i < width * height; i++) + { + unsigned char* p = png + i * 4; + fourBytes[i] = Premultiply(p[0], p[1], p[2], p[3]); + } +#endif + } + + VkDeviceSize imageSize = static_cast(width * height * 4); + if (!png) + { + LAppPal::PrintLogLn("could'nt load texture image."); + } + + CubismBufferVulkan stagingBuffer; + stagingBuffer.CreateBuffer(device, physicalDevice, imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + stagingBuffer.Map(device, imageSize); + stagingBuffer.MemCpy(png, imageSize); + stagingBuffer.UnMap(device); + + // 解放処理 + stbi_image_free(png); + LAppPal::ReleaseBytes(address); + + _mipLevels = static_cast(std::floor(std::log2(std::max(width, height)))) + 1; + + CubismImageVulkan textureImage; + + textureImage.CreateImage(device, physicalDevice, width, height, _mipLevels, format, tiling, usage); + VkCommandBuffer commandBuffer = VulkanManager::GetInstance()->BeginSingleTimeCommands(); + textureImage.SetImageLayout(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, _mipLevels, VK_IMAGE_ASPECT_COLOR_BIT); + CopyBufferToImage(commandBuffer, stagingBuffer.GetBuffer(), textureImage.GetImage(), width, height); + VulkanManager::GetInstance()->SubmitCommand(commandBuffer); + GenerateMipmaps(textureImage, width, height, _mipLevels); + textureImage.CreateView(device, format, VK_IMAGE_ASPECT_COLOR_BIT, _mipLevels); + VkPhysicalDeviceProperties properties{}; + vkGetPhysicalDeviceProperties(physicalDevice, &properties); + textureImage.CreateSampler(device, properties.limits.maxSamplerAnisotropy, _mipLevels); + _textures.PushBack(textureImage); + + LAppTextureManager::TextureInfo* textureInfo = new LAppTextureManager::TextureInfo(); + if (textureInfo != NULL) + { + _sequenceId++; + textureInfo->FileName = fileName; + textureInfo->Width = width; + textureInfo->Height = height; + textureInfo->Id = _sequenceId; + _texturesInfo.PushBack(textureInfo); + } + stagingBuffer.Destroy(device); + return textureInfo; +} + +void LAppTextureManager::ReleaseTextures() +{ + VkDevice device = VulkanManager::GetInstance()->GetDevice(); + + for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++) + { + _textures[i].Destroy(device); + delete _texturesInfo[i]; + } + + _texturesInfo.Clear(); +} + +void LAppTextureManager::ReleaseTexture(Csm::csmUint32 textureId) +{ + VkDevice device = VulkanManager::GetInstance()->GetDevice(); + + for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++) + { + if (_texturesInfo[i]->Id != textureId) + { + continue; + } + // ID一致 + // info除去 + delete _texturesInfo[i]; + + // 実体除去 + VkDevice device = VulkanManager::GetInstance()->GetDevice(); + _textures[i].Destroy(device); + + _texturesInfo.Remove(i); + _textures.Remove(i); + _sequenceId--; + break; + } +} + +void LAppTextureManager::ReleaseTexture(std::string fileName) +{ + for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++) + { + if (_texturesInfo[i]->FileName == fileName) + { + // info除去 + delete _texturesInfo[i]; + + // 実体除去 + if (_texturesInfo[i] != VK_NULL_HANDLE) + { + VkDevice device = VulkanManager::GetInstance()->GetDevice(); + _textures[i].Destroy(device); + _texturesInfo[i] = VK_NULL_HANDLE; + } + _texturesInfo.Remove(i); + _texturesInfo.Remove(i); + break; + } + } + if (_texturesInfo.GetSize() == 0) + { + _texturesInfo.Clear(); + } + if (_texturesInfo.GetSize() == 0) + { + _texturesInfo.Clear(); + } + +} + +LAppTextureManager::TextureInfo* LAppTextureManager::GetTextureInfoById(uint32_t textureId) const +{ + for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++) + { + if (_texturesInfo[i]->Id == textureId) + { + return _texturesInfo[i]; + } + } + + return NULL; +} + +bool LAppTextureManager::GetTexture(Csm::csmUint64 textureId, CubismImageVulkan& retTexture) const +{ + for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++) + { + if (_texturesInfo[i]->Id == textureId) + { + retTexture = _textures[i]; + return true; + } + } + + return false; +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppTextureManager.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppTextureManager.hpp new file mode 100644 index 00000000..0ca4acf8 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppTextureManager.hpp @@ -0,0 +1,150 @@ +/** + * 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. + */ + +#pragma once +#include +#include +#include +#include + +/** +* @brief テクスチャ管理クラス +* +* 画像読み込み、管理を行うクラス。 +*/ +class LAppTextureManager +{ +public: + /** + * @brief 画像情報構造体 + */ + struct TextureInfo + { + uint32_t Id; ///< テクスチャID + int Width = 0; ///< 横幅 + int Height = 0; ///< 高さ + std::string FileName; ///< ファイル名 + }; + + /** + * @brief コンストラクタ + */ + LAppTextureManager(); + + /** + * @brief デストラクタ + * + */ + ~LAppTextureManager(); + + /** + * @brief プリマルチプライ処理 + * + * @param[in] red 画像のRed値 + * @param[in] green 画像のGreen値 + * @param[in] blue 画像のBlue値 + * @param[in] alpha 画像のAlpha値 + * + * @return プリマルチプライ処理後のカラー値 + */ + inline unsigned int Premultiply(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha) + { + return static_cast(\ + (red * (alpha + 1) >> 8) | \ + ((green * (alpha + 1) >> 8) << 8) | \ + ((blue * (alpha + 1) >> 8) << 16) | \ + (((alpha)) << 24) \ + ); + } + + /** + * @brief バッファをイメージにコピーする + * + * @param[in] commandBuffer コマンドバッファ + * @param[in] buffer バッファ + * @param[in] image イメージ + * @param[in] width 画像の横幅 + * @param[in] height 画像の縦幅 + */ + void CopyBufferToImage(VkCommandBuffer commandBuffer, const VkBuffer& buffer, VkImage image, uint32_t width, + uint32_t height); + + /** + * @brief ミップマップを作成する + * + * @param[in] image イメージ + * @param[in] texWidth 画像の幅 + * @param[in] texHeight 画像の高さ + * @param[in] mipLevels ミップレべル + */ + void GenerateMipmaps(Live2D::Cubism::Framework::CubismImageVulkan image, uint32_t texWidth, uint32_t texHeight, + uint32_t mipLevels); + + /** + * @brief 画像ファイルを読み込む + * + * @param[in] fileName 読み込む画像ファイルパス名 + * @param[in] format 画像フォーマット + * @param[in] tiling 画像データのタイリング配置の設定 + * @param[in] usage     画像の使用フラグ + * @param[in] imageProperties + * + * @return 作成したイメージのリソース。読み込み失敗時はNULLを返す。 + */ + TextureInfo* CreateTextureFromPngFile( + std::string fileName, + VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags imageProperties + ); + + /** + * @brief 画像の解放 + * + * 配列に存在する画像全てを解放する + */ + void ReleaseTextures(); + + /** + * @brief 画像の解放 + * + * 指定したテクスチャIDの画像を解放する + * @param[in] textureId 解放するテクスチャID + **/ + void ReleaseTexture(Csm::csmUint32 textureId); + + /** + * @brief 画像の解放 + * + * 指定した名前の画像を解放する + * @param[in] fileName 解放する画像ファイルパス名 + **/ + void ReleaseTexture(std::string fileName); + + /** + * @brief テクスチャIDからテクスチャ情報を得る + * + * @param textureId[in] 取得したいテクスチャID + * + * @return テクスチャが存在していればTextureInfoが返る + */ + TextureInfo* GetTextureInfoById(uint32_t textureId) const; + + /** + * @brief テクスチャIDからテクスチャ情報を得る + * + * @param textureId[in] 取得したいテクスチャID + * @param retTexture 取得したいテクスチャを入れる変数 + * + * @return テクスチャが存在していればTextureInfoが返る + */ + bool GetTexture(Csm::csmUint64 textureId, Live2D::Cubism::Framework::CubismImageVulkan& retTexture) const; + +private: + Csm::csmVector _texturesInfo; + Csm::csmVector _textures; + Csm::csmUint32 _sequenceId; ///< イメージのインデックス + uint32_t _mipLevels; ///< ミップレベル +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppView.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppView.cpp new file mode 100644 index 00000000..58a39499 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppView.cpp @@ -0,0 +1,762 @@ +/** + * 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. + */ + +#include "LAppView.hpp" +#include +#include +#include "LAppPal.hpp" +#include "LAppDelegate.hpp" +#include "LAppLive2DManager.hpp" +#include "LAppTextureManager.hpp" +#include "LAppDefine.hpp" +#include "TouchManager.hpp" +#include "LAppSprite.hpp" +#include "LAppModel.hpp" + +using namespace std; +using namespace LAppDefine; + +LAppView::LAppView(): + _back(NULL), + _gear(NULL), + _power(NULL), + _renderSprite(NULL), + _renderTarget(SelectTarget_None), + _fragShaderModule(VK_NULL_HANDLE), + _vertShaderModule(VK_NULL_HANDLE), + _descriptorSetLayout(VK_NULL_HANDLE), + _pipeline(VK_NULL_HANDLE), + _pipelineLayout(VK_NULL_HANDLE) +{ + _clearColor[0] = 1.0f; + _clearColor[1] = 1.0f; + _clearColor[2] = 1.0f; + _clearColor[3] = 0.0f; + + // タッチ関係のイベント管理 + _touchManager = new TouchManager(); + + // デバイス座標からスクリーン座標に変換するための + _deviceToScreen = new CubismMatrix44(); + + // 画面の表示の拡大縮小や移動の変換を行う行列 + _viewMatrix = new CubismViewMatrix(); +} + +LAppView::~LAppView() +{ + VkDevice device = VulkanManager::GetInstance()->GetDevice(); + Cleanup(device); + vkDestroyDescriptorSetLayout(device, _descriptorSetLayout, nullptr); + vkDestroyShaderModule(device, _vertShaderModule, nullptr); + vkDestroyShaderModule(device, _fragShaderModule, nullptr); + _renderBuffer.DestroyOffscreenSurface(device); + delete _viewMatrix; + delete _deviceToScreen; + delete _touchManager; + + _back->Release(device); + _gear->Release(device); + _power->Release(device); + _renderSprite->Release(device); + delete _back; + delete _gear; + delete _power; + delete _renderSprite; +} + +void LAppView::Initialize() +{ + int width, height; + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); + + if(width==0 || height==0) + { + return; + } + + // 縦サイズを基準とする + float ratio = static_cast(width) / static_cast(height); + float left = -ratio; + float right = ratio; + float bottom = ViewLogicalLeft; + float top = ViewLogicalRight; + + _viewMatrix->SetScreenRect(left, right, bottom, top); // デバイスに対応する画面の範囲。 Xの左端, Xの右端, Yの下端, Yの上端 + _viewMatrix->Scale(ViewScale, ViewScale); + + _deviceToScreen->LoadIdentity(); + if (width > height) + { + float screenW = fabsf(right - left); + _deviceToScreen->ScaleRelative(screenW / width, -screenW / width); + } + else + { + float screenH = fabsf(top - bottom); + _deviceToScreen->ScaleRelative(screenH / height, -screenH / height); + } + _deviceToScreen->TranslateRelative(-width * 0.5f, -height * 0.5f); + + // 表示範囲の設定 + _viewMatrix->SetMaxScale(ViewMaxScale); // 限界拡大率 + _viewMatrix->SetMinScale(ViewMinScale); // 限界縮小率 + + // 表示できる最大範囲 + _viewMatrix->SetMaxScreenRect( + ViewLogicalMaxLeft, + ViewLogicalMaxRight, + ViewLogicalMaxBottom, + ViewLogicalMaxTop + ); +} + +void LAppView::ChangeBeginLayout(VkCommandBuffer commandBuffer) +{ + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkImageMemoryBarrier memoryBarrier{}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + memoryBarrier.srcAccessMask = 0; + memoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + memoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + memoryBarrier.image = vkManager->GetSwapchainImage(); + memoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); +} + +void LAppView::BeginRendering(VkCommandBuffer commandBuffer, float r, float g, float b, float a, bool isClear) +{ + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkRenderingAttachmentInfoKHR colorAttachment{}; + colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; + colorAttachment.imageView = vkManager->GetSwapchainImageView(); + colorAttachment.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + if (isClear) + { + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + } + else + { + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + } + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.clearValue = {r, g, b, a}; + + VkRenderingInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + renderingInfo.renderArea = {{0, 0}, {vkManager->GetSwapchainManager()->GetExtent()}}; + renderingInfo.layerCount = 1; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &colorAttachment; + + vkCmdBeginRendering(commandBuffer, &renderingInfo); +} + +void LAppView::ChangeEndLayout(VkCommandBuffer commandBuffer) +{ + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkImageMemoryBarrier memoryBarrier{}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + memoryBarrier.dstAccessMask = 0; + memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + memoryBarrier.image = vkManager->GetSwapchainImage(); + memoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); +} + +void LAppView::EndRendering(VkCommandBuffer commandBuffer) +{ + vkCmdEndRendering(commandBuffer); +} + +void LAppView::Render() +{ + LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance(); + if (!live2DManager) + { + return; + } + + //スプライト描画 + int width, height; + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkCommandBuffer commandBuffer = vkManager->BeginSingleTimeCommands(); + ChangeBeginLayout(commandBuffer); + BeginRendering(commandBuffer, 0.0, 0.0, 0.0, 1.0, true); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline); + _back->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + _gear->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + _power->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + EndRendering(commandBuffer); + vkManager->SubmitCommand(commandBuffer, true); + + live2DManager->SetViewMatrix(_viewMatrix); + + // Cubism更新・描画 + live2DManager->OnUpdate(); + + // 各モデルが持つ描画ターゲットをテクスチャとする場合 + if (_renderTarget == SelectTarget_ModelFrameBuffer && _renderSprite) + { + for (csmUint32 i = 0; i < live2DManager->GetModelNum(); i++) + { + LAppModel* model = live2DManager->GetModel(i); + commandBuffer = vkManager->BeginSingleTimeCommands(); + _renderSprite->SetDescriptorUpdated(false); + _renderSprite->UpdateDescriptorSet(vkManager->GetDevice(), + model->GetRenderBuffer().GetTextureView(), + model->GetRenderBuffer().GetTextureSampler()); + BeginRendering(commandBuffer, 0.f, 0.f, 0.3, 1.f, false); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline); + + float alpha = i < 1 ? 1.0f : model->GetOpacity(); // サンプルとしてαに適当な差をつける + _renderSprite->SetColor(1.0f, 1.0f, 1.0f, alpha); + if (model) + { + _renderSprite->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + } + EndRendering(commandBuffer); + vkManager->SubmitCommand(commandBuffer); + } + } + + commandBuffer = vkManager->BeginSingleTimeCommands(); + ChangeEndLayout(commandBuffer); + vkManager->SubmitCommand(commandBuffer); +} + +VkShaderModule LAppView::CreateShaderModule(VkDevice device, std::string filename) +{ + std::ifstream file(filename, std::ios::ate | std::ios::binary); + + if (!file.is_open()) + { + CubismLogError("failed to open file!"); + } + + csmInt32 fileSize = (csmInt32)file.tellg(); + csmVector buffer(fileSize); + + file.seekg(0); + file.read(buffer.GetPtr(), fileSize); + file.close(); + + VkShaderModuleCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = fileSize; + createInfo.pCode = reinterpret_cast(buffer.GetPtr()); + + VkShaderModule shaderModule; + if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) + { + CubismLogError("failed to create shader module!"); + } + + return shaderModule; +} + +void LAppView::CreateDescriptorSetLayout(VkDevice device) +{ + VkDescriptorSetLayoutBinding bindings[2]; + + bindings[0].binding = 0; + bindings[0].descriptorCount = 1; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + bindings[0].pImmutableSamplers = nullptr; + bindings[0].stageFlags = VK_SHADER_STAGE_ALL; + + bindings[1].binding = 1; + bindings[1].descriptorCount = 1; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[1].pImmutableSamplers = nullptr; + bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + + VkDescriptorSetLayoutCreateInfo layoutInfo{}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.bindingCount = sizeof(bindings) / sizeof(bindings[0]); + layoutInfo.pBindings = bindings; + + if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &_descriptorSetLayout) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create descriptor set layout!"); + } +} + +void LAppView::CreateSpriteGraphicsPipeline(VkDevice device, VkExtent2D extent, VkShaderModule vertShaderModule, + VkShaderModule fragShaderModule, VkFormat swapchainFormat) +{ + VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertShaderStageInfo.module = vertShaderModule; + vertShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; + fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragShaderStageInfo.module = fragShaderModule; + fragShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; + + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + + VkVertexInputBindingDescription bindingDescription = LAppSprite::SpriteVertex::GetBindingDescription(); + VkVertexInputAttributeDescription attributeDescriptions[2]{}; + LAppSprite::SpriteVertex::GetAttributeDescriptions(attributeDescriptions); + vertexInputInfo.vertexBindingDescriptionCount = 1; + vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; + vertexInputInfo.vertexAttributeDescriptionCount = sizeof(attributeDescriptions) / sizeof(attributeDescriptions[0]); + vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions; + + VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssembly.primitiveRestartEnable = VK_FALSE; + + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = extent; + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = (float)scissor.extent.width; + viewport.height = (float)scissor.extent.height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkPipelineViewportStateCreateInfo viewportState{}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizer{}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + + VkPipelineMultisampleStateCreateInfo multisampling{}; + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState colorBlendAttachment{}; + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT + | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo colorBlending{}; + colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlending.logicOpEnable = VK_FALSE; + colorBlending.logicOp = VK_LOGIC_OP_COPY; + colorBlending.attachmentCount = 1; + colorBlending.pAttachments = &colorBlendAttachment; + + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &_descriptorSetLayout; + + if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &_pipelineLayout) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create pipeline layout!"); + } + + VkPipelineRenderingCreateInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachmentFormats = &swapchainFormat; + + VkGraphicsPipelineCreateInfo pipelineInfo{}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.stageCount = 2; + pipelineInfo.pStages = shaderStages; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &inputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &rasterizer; + pipelineInfo.pMultisampleState = &multisampling; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.layout = _pipelineLayout; + pipelineInfo.subpass = 0; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + pipelineInfo.pNext = &renderingInfo; + + if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_pipeline) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create graphics pipeline!"); + } +} + +void LAppView::InitializeSprite() +{ + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkDevice device = vkManager->GetDevice(); + VkPhysicalDevice physicalDevice = vkManager->GetPhysicalDevice(); + SwapchainManager* swapchainManager = vkManager->GetSwapchainManager(); + _vertShaderModule = CreateShaderModule(device, "SampleShaders/VertSprite.spv"); + _fragShaderModule = CreateShaderModule(device, "SampleShaders/FragSprite.spv"); + CreateDescriptorSetLayout(device); + CreateSpriteGraphicsPipeline(device, swapchainManager->GetExtent(), _vertShaderModule, _fragShaderModule, + vkManager->GetSwapchainManager()->GetSwapchainImageFormat()); + + int width, height; + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); + + LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager(); + const string resourcesPath = LAppDelegate::GetInstance()->GetExecuteAbsolutePath() + ResourcesPath; + + string imageName; + CubismImageVulkan textureImage; + float x; + float y; + float fWidth; + float fHeight; + + imageName = BackImageName; + LAppTextureManager::TextureInfo* backgroundTexture = textureManager->CreateTextureFromPngFile( + resourcesPath + imageName, vkManager->GetTextureFormat(), VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + LAppDelegate::GetInstance()->GetTextureManager()->GetTexture(backgroundTexture->Id, textureImage); + + x = width * 0.5f; + y = height * 0.5f; + fWidth = static_cast(backgroundTexture->Width * 2.0f); + fHeight = static_cast(height * 0.95f); + _back = new LAppSprite(device, physicalDevice, vkManager, x, y, fWidth, fHeight, backgroundTexture->Id, + textureImage.GetView(), textureImage.GetSampler(), _descriptorSetLayout); + + imageName = GearImageName; + LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile( + resourcesPath + imageName, vkManager->GetTextureFormat(), VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + LAppDelegate::GetInstance()->GetTextureManager()->GetTexture(gearTexture->Id, textureImage); + + //X:右向き正、Y:下向き正 + x = static_cast(width - gearTexture->Width * 0.5f); + y = static_cast(gearTexture->Height * 0.5f); + fWidth = static_cast(gearTexture->Width); + fHeight = static_cast(gearTexture->Height); + _gear = new LAppSprite(device, physicalDevice, vkManager, x, y, fWidth, fHeight, gearTexture->Id, + textureImage.GetView(), textureImage.GetSampler(), _descriptorSetLayout); + + imageName = PowerImageName; + LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile( + resourcesPath + imageName, vkManager->GetTextureFormat(), VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + LAppDelegate::GetInstance()->GetTextureManager()->GetTexture(powerTexture->Id, textureImage); + + //X:右向き正、Y:下向き正 + x = static_cast(width - powerTexture->Width * 0.5f); + y = static_cast(height - powerTexture->Height * 0.5f); + fWidth = static_cast(powerTexture->Width); + fHeight = static_cast(powerTexture->Height); + _power = new LAppSprite(device, physicalDevice, vkManager, x, y, fWidth, fHeight, powerTexture->Id, + textureImage.GetView(), textureImage.GetSampler(), _descriptorSetLayout); + + // 画面全体を覆うサイズ + x = width * 0.5f; + y = height * 0.5f; + _renderSprite = new LAppSprite(device, physicalDevice, vkManager, x, y, static_cast(width), static_cast(height),0, NULL, NULL, _descriptorSetLayout); +} + +void LAppView::OnTouchesBegan(float px, float py) const +{ + _touchManager->TouchesBegan(px, py); +} + +void LAppView::OnTouchesMoved(float px, float py) const +{ + float viewX = this->TransformViewX(_touchManager->GetX()); + float viewY = this->TransformViewY(_touchManager->GetY()); + + _touchManager->TouchesMoved(px, py); + + LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance(); + Live2DManager->OnDrag(viewX, viewY); +} + +void LAppView::OnTouchesEnded(float px, float py) const +{ + // タッチ終了 + LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance(); + live2DManager->OnDrag(0.0f, 0.0f); + { + // シングルタップ + float x = _deviceToScreen->TransformX(_touchManager->GetX()); // 論理座標変換した座標を取得。 + float y = _deviceToScreen->TransformY(_touchManager->GetY()); // 論理座標変換した座標を取得。 + if (DebugTouchLogEnable) + { + LAppPal::PrintLogLn("[APP]touchesEnded x:%.2f y:%.2f", x, y); + } + live2DManager->OnTap(x, y); + + // 画面サイズの取得 + int windowWidth, windowHeight; + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &windowWidth, &windowHeight); + + // 歯車にタップしたか + if (_gear->IsHit(windowWidth, windowHeight, px, py)) + { + live2DManager->NextScene(); + } + + // 電源ボタンにタップしたか + if (_power->IsHit(windowWidth, windowHeight, px, py)) + { + LAppDelegate::GetInstance()->AppEnd(); + } + } +} + +float LAppView::TransformViewX(float deviceX) const +{ + float screenX = _deviceToScreen->TransformX(deviceX); // 論理座標変換した座標を取得。 + return _viewMatrix->InvertTransformX(screenX); // 拡大、縮小、移動後の値。 +} + +float LAppView::TransformViewY(float deviceY) const +{ + float screenY = _deviceToScreen->TransformY(deviceY); // 論理座標変換した座標を取得。 + return _viewMatrix->InvertTransformY(screenY); // 拡大、縮小、移動後の値。 +} + +float LAppView::TransformScreenX(float deviceX) const +{ + return _deviceToScreen->TransformX(deviceX); +} + +float LAppView::TransformScreenY(float deviceY) const +{ + return _deviceToScreen->TransformY(deviceY); +} + +void LAppView::PreModelDraw(LAppModel &refModel) +{ + if (_renderTarget == SelectTarget_None) + { + // 通常のスワップチェーンイメージへと描画 + VulkanManager* vkManager = VulkanManager::GetInstance(); + Csm::Rendering::CubismRenderer_Vulkan::SetRenderTarget(vkManager->GetSwapchainImage(), + vkManager->GetSwapchainImageView(), + vkManager->GetSwapchainManager()->GetSwapchainImageFormat(), + vkManager->GetSwapchainManager()->GetExtent()); + } + else + { + // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ + Csm::Rendering::CubismOffscreenSurface_Vulkan* useTarget = NULL; + // 使用するターゲット + useTarget = (_renderTarget == SelectTarget_ViewFrameBuffer) ? &_renderBuffer : &refModel.GetRenderBuffer(); + + // 別のレンダリングターゲットへ向けて描画する場合 + if (!useTarget->IsValid()) + { + // 描画ターゲット内部未作成の場合はここで作成 + int bufWidth, bufHeight; + glfwGetFramebufferSize(LAppDelegate::GetInstance()->GetWindow(), &bufWidth, &bufHeight); + VulkanManager* vkManager = VulkanManager::GetInstance(); + if(bufWidth!=0 && bufHeight!=0) + { + // モデル描画キャンバス + useTarget->CreateOffscreenSurface(vkManager->GetDevice(), vkManager->GetPhysicalDevice(), + static_cast(bufWidth), static_cast(bufHeight), + vkManager->GetImageFormat(), + vkManager->GetDepthFormat() + ); + _renderSprite->SetDescriptorUpdated(false); + } + } + Csm::Rendering::CubismRenderer_Vulkan::SetRenderTarget(useTarget->GetTextureImage(), useTarget->GetTextureView(), + VulkanManager::GetInstance()->GetImageFormat(), + VkExtent2D{useTarget->GetBufferWidth(), useTarget->GetBufferHeight()}); + } +} + +void LAppView::PostModelDraw(LAppModel &refModel) +{ + // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ + Csm::Rendering::CubismOffscreenSurface_Vulkan* useTarget = NULL; + + if (_renderTarget != SelectTarget_None) + { + // 別のレンダリングターゲットへ向けて描画する場合 + + // 使用するターゲット + useTarget = (_renderTarget == SelectTarget_ViewFrameBuffer) ? &_renderBuffer : &refModel.GetRenderBuffer(); + + // LAppViewの持つフレームバッファを使うなら、スプライトへの描画はここ + if (_renderTarget == SelectTarget_ViewFrameBuffer && _renderSprite) + { + int width, height; + glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkCommandBuffer commandBuffer = vkManager->BeginSingleTimeCommands(); + _renderSprite->UpdateDescriptorSet(vkManager->GetDevice(), useTarget->GetTextureView(), + useTarget->GetTextureSampler()); + BeginRendering(commandBuffer, 0.f, 0.f, 0.3, 1.f, false); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline); + _renderSprite->SetColor(1.0f, 1.0f, 1.0f, GetSpriteAlpha(0)); + _renderSprite->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + EndRendering(commandBuffer); + vkManager->SubmitCommand(commandBuffer); + } + } + + // レンダーターゲットをスワップチェーンのものへと戻す + VulkanManager* vkManager = VulkanManager::GetInstance(); + Csm::Rendering::CubismRenderer_Vulkan::SetRenderTarget(vkManager->GetSwapchainImage(), + vkManager->GetSwapchainImageView(), + vkManager->GetSwapchainManager()->GetSwapchainImageFormat(), + vkManager->GetSwapchainManager()->GetExtent()); +} + +void LAppView::SwitchRenderingTarget(SelectTarget targetType) +{ + _renderTarget = targetType; +} + +void LAppView::SetRenderTargetClearColor(float r, float g, float b) +{ + _clearColor[0] = r; + _clearColor[1] = g; + _clearColor[2] = b; +} + +float LAppView::GetSpriteAlpha(int assign) const +{ + // assignの数値に応じて適当に決定 + float alpha = 0.25f + static_cast(assign) * 0.5f; // サンプルとしてαに適当な差をつける + if (alpha > 1.0f) + { + alpha = 1.0f; + } + if (alpha < 0.1f) + { + alpha = 0.1f; + } + + return alpha; +} + +void LAppView::Cleanup(VkDevice device) +{ + vkDestroyPipelineLayout(device, _pipelineLayout, nullptr); + vkDestroyPipeline(device, _pipeline, nullptr); +} + +void LAppView::ResizeSprite(int width, int height) +{ + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkDevice device = vkManager->GetDevice(); + SwapchainManager* swapchainManager = vkManager->GetSwapchainManager(); + Cleanup(device); + CreateSpriteGraphicsPipeline(device, swapchainManager->GetExtent(), _vertShaderModule, _fragShaderModule, + vkManager->GetSwapchainManager()->GetSwapchainImageFormat()); + + LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager(); + if (!textureManager) + { + return; + } + + float x = 0.0f; + float y = 0.0f; + float fWidth = 0.0f; + float fHeight = 0.0f; + + if (_back) + { + uint32_t id = _back->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = width * 0.5f; + y = height * 0.5f; + fWidth = static_cast(texInfo->Width * 2); + fHeight = static_cast(height) * 0.95f; + _back->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_power) + { + uint32_t id = _power->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(width - texInfo->Width * 0.5f); + y = static_cast(height - texInfo->Height * 0.5f); + fWidth = static_cast(texInfo->Width); + fHeight = static_cast(texInfo->Height); + _power->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_gear) + { + uint32_t id = _gear->GetTextureId(); + LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id); + if (texInfo) + { + x = static_cast(width - texInfo->Width * 0.5f); + y = static_cast(texInfo->Height * 0.5f); + fWidth = static_cast(texInfo->Width); + fHeight = static_cast(texInfo->Height); + _gear->ResetRect(x, y, fWidth, fHeight); + } + } + + if (_renderSprite) + { + x = width * 0.5f; + y = height * 0.5f; + _renderSprite->ResetRect(x, y, static_cast(width), static_cast(height)); + } +} + +void LAppView::DestroyOffscreenSurface() +{ + LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance(); + if (_renderTarget == SelectTarget_ViewFrameBuffer) + { + _renderBuffer.DestroyOffscreenSurface(VulkanManager::GetInstance()->GetDevice()); + } + else if (_renderTarget == SelectTarget_ModelFrameBuffer) + { + for (csmUint32 i = 0; i < live2DManager->GetModelNum(); i++) + { + LAppModel* model = live2DManager->GetModel(i); + model->GetRenderBuffer(). + DestroyOffscreenSurface(VulkanManager::GetInstance()->GetDevice()); + } + } +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppView.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppView.hpp new file mode 100644 index 00000000..3afe1b35 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppView.hpp @@ -0,0 +1,241 @@ +/** + * 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. + */ + +#pragma once +#include +#include +#include +#include +#include "CubismFramework.hpp" + +class TouchManager; +class LAppSprite; +class LAppModel; + +/** +* @brief 描画クラス +*/ +class LAppView +{ +public: + + /** + * @brief LAppModelのレンダリング先 + */ + enum SelectTarget + { + SelectTarget_None, ///< デフォルトのフレームバッファにレンダリング + SelectTarget_ModelFrameBuffer, ///< LAppModelが各自持つフレームバッファにレンダリング + SelectTarget_ViewFrameBuffer, ///< LAppViewの持つフレームバッファにレンダリング + }; + + /** + * @brief コンストラクタ + */ + LAppView(); + + /** + * @brief デストラクタ + */ + ~LAppView(); + + /** + * @brief 初期化する。 + */ + void Initialize(); + + /** + * @brief レイアウトを変更する。 + * @param[in] commandBuffer -> コマンドバッファ + */ + void ChangeBeginLayout(VkCommandBuffer commandBuffer); + + /** + * @brief レイアウトを変更する。 + * @param[in] commandBuffer -> コマンドバッファ + */ + void ChangeEndLayout(VkCommandBuffer commandBuffer); + + /** + * @brief レンダリングを開始する。 + * @param[in] commandBuffer -> コマンドバッファ + * @param[in] r -> r + * @param[in] g -> g + * @param[in] b -> b + * @param[in] a -> a + * @param[in] isClear -> クリアするかのフラグ + */ + void BeginRendering(VkCommandBuffer commandBuffer, float r, float g, float b, float a, bool isClear); + + + /** + * @brief レンダリングを終了する。 + * + * @param[in] commandBuffer -> コマンドバッファ + */ + void EndRendering(VkCommandBuffer commandBuffer); + + /** + * @brief 描画する。 + */ + void Render(); + /** + * @brief シェーダーモジュ―ルを作成する + * + * @param[in] device -> デバイス + * @param[in] filename -> シェーダーのファイル名 + */ + VkShaderModule CreateShaderModule(VkDevice device, std::string filename); + + /** + * @brief スプライト用のディスクリプタセットのレイアウトを作成する。 + * + * @param[in] device 論理デバイス + */ + void CreateDescriptorSetLayout(VkDevice device); + + /** + * @brief スプライト用のパイプラインを作成する。 + * + * @param[in] device デバイス + * @param[in] extent フレームバッファのサイズ + * @param[in] vertShaderModule 頂点シェーダのモジュール + * @param[in] fragShaderModule フラグメントシェーダのモジュール + */ + void CreateSpriteGraphicsPipeline(VkDevice device, VkExtent2D extent, VkShaderModule vertShaderModule, + VkShaderModule fragShaderModule, VkFormat swapchainFormat); + + /** + * @brief 画像の初期化を行う。 + */ + void InitializeSprite(); + + /** + * @brief タッチされたときに呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesBegan(float pointX, float pointY) const; + + /** + * @brief タッチしているときにポインタが動いたら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesMoved(float pointX, float pointY) const; + + /** + * @brief タッチが終了したら呼ばれる。 + * + * @param[in] pointX スクリーンX座標 + * @param[in] pointY スクリーンY座標 + */ + void OnTouchesEnded(float pointX, float pointY) const; + + /** + * @brief X座標をView座標に変換する。 + * + * @param[in] deviceX デバイスX座標 + */ + float TransformViewX(float deviceX) const; + + /** + * @brief Y座標をView座標に変換する。 + * + * @param[in] deviceY デバイスY座標 + */ + float TransformViewY(float deviceY) const; + + /** + * @brief X座標をScreen座標に変換する。 + * + * @param[in] deviceX デバイスX座標 + */ + float TransformScreenX(float deviceX) const; + + /** + * @brief Y座標をScreen座標に変換する。 + * + * @param[in] deviceY デバイスY座標 + */ + float TransformScreenY(float deviceY) const; + + /** + * @brief モデル1体を描画した直後にコールされる + * + * @param[in] refModel モデルのインスタンス + */ + void PreModelDraw(LAppModel &refModel); + + /** + * @brief モデル1体を描画した直後にコールされる + * + * @param[in] refModel モデルのインスタンス + * @param[in] modelIndex モデルのインデックス + */ + void PostModelDraw(LAppModel &refModel); + + /** + * @brief レンダリング先を切り替える + * @param[in] targetType ターゲットタイプ + */ + void SwitchRenderingTarget(SelectTarget targetType); + + /** + * @brief レンダリング先をデフォルト以外に切り替えた際の背景クリア色設定 + * @param[in] r 赤(0.0~1.0) + * @param[in] g 緑(0.0~1.0) + * @param[in] b 青(0.0~1.0) + */ + void SetRenderTargetClearColor(float r, float g, float b); + /** + * @brief 別レンダリングターゲットにモデルを描画するサンプルで + * 描画時のαを決定する + */ + float GetSpriteAlpha(int assign) const; + + /** + * @brief ウィンドウサイズ変更の際にリソースを破棄する。 + * + * @param[in] device デバイス + */ + void Cleanup(VkDevice device); + + /** + * @brief ウィンドウサイズ変更の際にスプライトを再作成する + * + * @param[in] width 横幅 + * @param[in] height 縦幅 + */ + void ResizeSprite(int width, int height); + + /** + * @brief オフスクリーンの破棄 + */ + void DestroyOffscreenSurface(); + +private: + TouchManager* _touchManager; ///< タッチマネージャー + Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 + Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix + LAppSprite* _back; ///< 背景画像 + LAppSprite* _gear; ///< ギア画像 + LAppSprite* _power; ///< 電源画像 + + // レンダリング先を別ターゲットにする方式の場合に使用 + LAppSprite* _renderSprite; ///< モードによっては_renderBufferのテクスチャを描画 + Csm::Rendering::CubismOffscreenSurface_Vulkan _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング + SelectTarget _renderTarget; ///< レンダリング先の選択肢 + float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + VkShaderModule _vertShaderModule; ///< 頂点シェーダーモジュール + VkShaderModule _fragShaderModule; ///< フラグメントシェーダーモジュール + VkDescriptorSetLayout _descriptorSetLayout; ///< ディスクリプタセットのレイアウト, UBOが1つとテクスチャが1つずつ + VkPipelineLayout _pipelineLayout; ///< スプライト描画に使うパイプラインのレイアウト + VkPipeline _pipeline; ///< スプライト描画に使うパイプライン +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppWavFileHandler.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppWavFileHandler.cpp new file mode 100644 index 00000000..7bb1ff67 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppWavFileHandler.cpp @@ -0,0 +1,232 @@ +/** + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "LAppWavFileHandler.hpp" +#include +#include +#include "LAppPal.hpp" + +LAppWavFileHandler::LAppWavFileHandler() + : _pcmData(NULL) + , _userTimeSeconds(0.0f) + , _lastRms(0.0f) + , _sampleOffset(0) +{ +} + +LAppWavFileHandler::~LAppWavFileHandler() +{ + if (_pcmData != NULL) + { + ReleasePcmData(); + } +} + +Csm::csmBool LAppWavFileHandler::Update(Csm::csmFloat32 deltaTimeSeconds) +{ + Csm::csmUint32 goalOffset; + Csm::csmFloat32 rms; + + // データロード前/ファイル末尾に達した場合は更新しない + if ((_pcmData == NULL) || (_sampleOffset >= _wavFileInfo._samplesPerChannel)) + { + _lastRms = 0.0f; + return false; + } + + // 経過時間後の状態を保持 + _userTimeSeconds += deltaTimeSeconds; + goalOffset = static_cast(_userTimeSeconds * _wavFileInfo._samplingRate); + if (goalOffset > _wavFileInfo._samplesPerChannel) + { + goalOffset = _wavFileInfo._samplesPerChannel; + } + + // RMS計測 + rms = 0.0f; + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + for (Csm::csmUint32 sampleCount = _sampleOffset; sampleCount < goalOffset; sampleCount++) + { + Csm::csmFloat32 pcm = _pcmData[channelCount][sampleCount]; + rms += pcm * pcm; + } + } + rms = sqrt(rms / (_wavFileInfo._numberOfChannels * (goalOffset - _sampleOffset))); + + _lastRms = rms; + _sampleOffset = goalOffset; + return true; +} + +void LAppWavFileHandler::Start(const Csm::csmString& filePath) +{ + // WAVファイルのロード + if (!LoadWavFile(filePath)) + { + return; + } + + // サンプル参照位置を初期化 + _sampleOffset = 0; + _userTimeSeconds = 0.0f; + + // RMS値をリセット + _lastRms = 0.0f; +} + +Csm::csmFloat32 LAppWavFileHandler::GetRms() const +{ + return _lastRms; +} + +Csm::csmBool LAppWavFileHandler::LoadWavFile(const Csm::csmString& filePath) +{ + Csm::csmBool ret; + + // 既にwavファイルロード済みならば領域開放 + if (_pcmData != NULL) + { + ReleasePcmData(); + } + + // ファイルロード + _byteReader._fileByte = LAppPal::LoadFileAsBytes(filePath.GetRawString(), &(_byteReader._fileSize)); + _byteReader._readOffset = 0; + + // ファイルロードに失敗しているか、先頭のシグネチャ"RIFF"を入れるサイズもない場合は失敗 + if ((_byteReader._fileByte == NULL) || (_byteReader._fileSize < 4)) + { + return false; + } + + // ファイル名 + _wavFileInfo._fileName = filePath; + + do { + // シグネチャ "RIFF" + if (!_byteReader.GetCheckSignature("RIFF")) + { + ret = false; + break; + } + // ファイルサイズ-8(読み飛ばし) + _byteReader.Get32LittleEndian(); + // シグネチャ "WAVE" + if (!_byteReader.GetCheckSignature("WAVE")) + { + ret = false; + break; + } + // シグネチャ "fmt " + if (!_byteReader.GetCheckSignature("fmt ")) + { + ret = false; + break; + } + // fmtチャンクサイズ + const Csm::csmUint32 fmtChunkSize = _byteReader.Get32LittleEndian(); + // フォーマットIDは1(リニアPCM)以外受け付けない + if (_byteReader.Get16LittleEndian() != 1) + { + ret = false; + break; + } + // チャンネル数 + _wavFileInfo._numberOfChannels = _byteReader.Get16LittleEndian(); + // サンプリングレート + _wavFileInfo._samplingRate = _byteReader.Get32LittleEndian(); + // データ速度[byte/sec](読み飛ばし) + _byteReader.Get32LittleEndian(); + // ブロックサイズ(読み飛ばし) + _byteReader.Get16LittleEndian(); + // 量子化ビット数 + _wavFileInfo._bitsPerSample = _byteReader.Get16LittleEndian(); + // fmtチャンクの拡張部分の読み飛ばし + if (fmtChunkSize > 16) + { + _byteReader._readOffset += (fmtChunkSize - 16); + } + // "data"チャンクが出現するまで読み飛ばし + while (!(_byteReader.GetCheckSignature("data")) + && (_byteReader._readOffset < _byteReader._fileSize)) + { + _byteReader._readOffset += _byteReader.Get32LittleEndian(); + } + // ファイル内に"data"チャンクが出現しなかった + if (_byteReader._readOffset >= _byteReader._fileSize) + { + ret = false; + break; + } + // サンプル数 + { + const Csm::csmUint32 dataChunkSize = _byteReader.Get32LittleEndian(); + _wavFileInfo._samplesPerChannel = (dataChunkSize * 8) / (_wavFileInfo._bitsPerSample * _wavFileInfo._numberOfChannels); + } + // 領域確保 + _pcmData = static_cast(CSM_MALLOC(sizeof(Csm::csmFloat32*) * _wavFileInfo._numberOfChannels)); + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + _pcmData[channelCount] = static_cast(CSM_MALLOC(sizeof(Csm::csmFloat32) * _wavFileInfo._samplesPerChannel)); + } + // 波形データ取得 + for (Csm::csmUint32 sampleCount = 0; sampleCount < _wavFileInfo._samplesPerChannel; sampleCount++) + { + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + _pcmData[channelCount][sampleCount] = GetPcmSample(); + } + } + + ret = true; + + } while (false); + + // ファイル開放 + LAppPal::ReleaseBytes(_byteReader._fileByte); + _byteReader._fileByte = NULL; + _byteReader._fileSize = 0; + + return ret; +} + +Csm::csmFloat32 LAppWavFileHandler::GetPcmSample() +{ + Csm::csmInt32 pcm32; + + // 32ビット幅に拡張してから-1~1の範囲に丸める + switch (_wavFileInfo._bitsPerSample) + { + case 8: + pcm32 = static_cast(_byteReader.Get8()) - 128; + pcm32 <<= 24; + break; + case 16: + pcm32 = _byteReader.Get16LittleEndian() << 16; + break; + case 24: + pcm32 = _byteReader.Get24LittleEndian() << 8; + break; + default: + // 対応していないビット幅 + pcm32 = 0; + break; + } + + return static_cast(pcm32) / INT32_MAX; +} + +void LAppWavFileHandler::ReleasePcmData() +{ + for (Csm::csmUint32 channelCount = 0; channelCount < _wavFileInfo._numberOfChannels; channelCount++) + { + CSM_FREE(_pcmData[channelCount]); + } + CSM_FREE(_pcmData); + _pcmData = NULL; +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppWavFileHandler.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppWavFileHandler.hpp new file mode 100644 index 00000000..8d5be9a1 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/LAppWavFileHandler.hpp @@ -0,0 +1,182 @@ +/** + * 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. + */ + +#pragma once + +#include +#include + + /** + * @brief wavファイルハンドラ + * @attention 16bit wav ファイル読み込みのみ実装済み + */ +class LAppWavFileHandler +{ +public: + /** + * @brief コンストラクタ + */ + LAppWavFileHandler(); + + /** + * @brief デストラクタ + */ + ~LAppWavFileHandler(); + + /** + * @brief wavファイルハンドラの内部状態更新 + * + * @param[in] deltaTimeSeconds デルタ時間[秒] + * @retval true 更新されている + * @retval false 更新されていない + */ + Csm::csmBool Update(Csm::csmFloat32 deltaTimeSeconds); + + /** + * @brief 引数で指定したwavファイルの読み込みを開始する + * + * @param[in] filePath wavファイルのパス + */ + void Start(const Csm::csmString& filePath); + + /** + * @brief 現在のRMS値取得 + * + * @retval csmFloat32 RMS値 + */ + Csm::csmFloat32 GetRms() const; + +private: + /** + * @brief wavファイルのロード + * + * @param[in] filePath wavファイルのパス + * @retval true 読み込み成功 + * @retval false 読み込み失敗 + */ + Csm::csmBool LoadWavFile(const Csm::csmString& filePath); + + /** + * @brief PCMデータの解放 + */ + void ReleasePcmData(); + + /** + * @brief -1~1の範囲の1サンプル取得 + * @retval csmFloat32 正規化されたサンプル + */ + Csm::csmFloat32 GetPcmSample(); + + /** + * @brief 読み込んだwavfileの情報 + */ + struct WavFileInfo + { + /** + * @brief コンストラクタ + */ + WavFileInfo() : _fileName(""), _numberOfChannels(0), + _bitsPerSample(0), _samplingRate(0), _samplesPerChannel(0) + { } + + Csm::csmString _fileName; ///< ファイル名 + Csm::csmUint32 _numberOfChannels; ///< チャンネル数 + Csm::csmUint32 _bitsPerSample; ///< サンプルあたりビット数 + Csm::csmUint32 _samplingRate; ///< サンプリングレート + Csm::csmUint32 _samplesPerChannel; ///< 1チャンネルあたり総サンプル数 + } _wavFileInfo; + + /** + * @brief バイトリーダ + */ + struct ByteReader { + /** + * @brief コンストラクタ + */ + ByteReader() : _fileByte(NULL), _fileSize(0), _readOffset(0) + { } + + /** + * @brief 8ビット読み込み + * @return Csm::csmUint8 読み取った8ビット値 + */ + Csm::csmUint8 Get8() + { + const Csm::csmUint8 ret = _fileByte[_readOffset]; + _readOffset++; + return ret; + } + + /** + * @brief 16ビット読み込み(リトルエンディアン) + * @return Csm::csmUint16 読み取った16ビット値 + */ + Csm::csmUint16 Get16LittleEndian() + { + const Csm::csmUint16 ret = (_fileByte[_readOffset + 1] << 8) | _fileByte[_readOffset]; + _readOffset += 2; + return ret; + } + + /** + * @brief 24ビット読み込み(リトルエンディアン) + * @return Csm::csmUint32 読み取った24ビット値(下位24ビットに設定) + */ + Csm::csmUint32 Get24LittleEndian() + { + const Csm::csmUint32 ret = + (_fileByte[_readOffset + 2] << 16) | (_fileByte[_readOffset + 1] << 8) + | _fileByte[_readOffset]; + _readOffset += 3; + return ret; + } + + /** + * @brief 32ビット読み込み(リトルエンディアン) + * @return Csm::csmUint32 読み取った32ビット値 + */ + Csm::csmUint32 Get32LittleEndian() + { + const Csm::csmUint32 ret = + (_fileByte[_readOffset + 3] << 24) | (_fileByte[_readOffset + 2] << 16) + | (_fileByte[_readOffset + 1] << 8) | _fileByte[_readOffset]; + _readOffset += 4; + return ret; + } + + /** + * @brief シグネチャの取得と参照文字列との一致チェック + * @param[in] reference 検査対象のシグネチャ文字列 + * @retval true 一致している + * @retval false 一致していない + */ + Csm::csmBool GetCheckSignature(const Csm::csmString& reference) + { + Csm::csmChar getSignature[4] = { 0, 0, 0, 0 }; + const Csm::csmChar* referenceString = reference.GetRawString(); + if (reference.GetLength() != 4) + { + return false; + } + for (Csm::csmUint32 signatureOffset = 0; signatureOffset < 4; signatureOffset++) + { + getSignature[signatureOffset] = static_cast(Get8()); + } + return (getSignature[0] == referenceString[0]) && (getSignature[1] == referenceString[1]) + && (getSignature[2] == referenceString[2]) && (getSignature[3] == referenceString[3]); + } + + Csm::csmByte* _fileByte; ///< ロードしたファイルのバイト列 + Csm::csmSizeInt _fileSize; ///< ファイルサイズ + Csm::csmUint32 _readOffset; ///< ファイル参照位置 + } _byteReader; + + Csm::csmFloat32** _pcmData; ///< -1から1の範囲で表現された音声データ配列 + Csm::csmUint32 _sampleOffset; ///< サンプル参照位置 + Csm::csmFloat32 _lastRms; ///< 最後に計測したRMS値 + Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒] + }; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/MouseActionManager.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/MouseActionManager.cpp new file mode 100644 index 00000000..0caee4c9 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/MouseActionManager.cpp @@ -0,0 +1,141 @@ +/** + * 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. + */ + +#include "MouseActionManager.hpp" + +namespace { + MouseActionManager* instance = NULL; +} + +MouseActionManager* MouseActionManager::GetInstance() +{ + if (!instance) + { + instance = new MouseActionManager(); + } + + return instance; +} + +void MouseActionManager::ReleaseInstance() +{ + if (instance) + { + delete instance; + } + + instance = NULL; +} + +MouseActionManager::MouseActionManager() +{ +} + +MouseActionManager::~MouseActionManager() +{ + // 行列データの解放 + delete _viewMatrix; + delete _deviceToScreen; + delete _touchManager; +} + +void MouseActionManager::Initialize(int windowWidth, int windowHeight) +{ + // 行列の初期化 + ViewInitialize(windowWidth, windowHeight); + + // タッチ関係のイベント管理 + _touchManager = new TouchManager(); + + _captured = false; + _mouseX = 0.0f; + _mouseY = 0.0f; +} + +void MouseActionManager::ViewInitialize(int windowWidth, int windowHeight) +{ + _deviceToScreen = new Csm::CubismMatrix44(); + _viewMatrix = new CubismSampleViewMatrix(_deviceToScreen, windowWidth, windowHeight); +} + +void MouseActionManager::OnDrag(Csm::csmFloat32 x, Csm::csmFloat32 y) +{ + _userModel->SetDragging(x, y); +} + +void MouseActionManager::OnTouchesBegan(float px, float py) +{ + _touchManager->TouchesBegan(px, py); +} + +void MouseActionManager::OnTouchesMoved(float px, float py) +{ + float screenX = _deviceToScreen->TransformX(_touchManager->GetX()); // 論理座標変換した座標を取得。 + float viewX = _viewMatrix->InvertTransformX(screenX); // 拡大、縮小、移動後の値。 + + float screenY = _deviceToScreen->TransformY(_touchManager->GetY()); // 論理座標変換した座標を取得。 + float viewY = _viewMatrix->InvertTransformY(screenY); // 拡大、縮小、移動後の値。 + + _touchManager->TouchesMoved(px, py); + + // ドラッグ情報を設定 + _userModel->SetDragging(viewX, viewY); +} + +void MouseActionManager::OnTouchesEnded(float px, float py) +{ + // タッチ終了 + OnDrag(0.0f, 0.0f); +} + +void MouseActionManager::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) +{ + if (GLFW_MOUSE_BUTTON_LEFT != button) + { + return; + } + + switch (action) + { + case GLFW_PRESS: + _captured = true; + OnTouchesBegan(_mouseX, _mouseY); + break; + case GLFW_RELEASE: + if (_captured) + { + _captured = false; + OnTouchesEnded(_mouseX, _mouseY); + } + break; + default: + break; + } +} + +void MouseActionManager::OnMouseCallBack(GLFWwindow* window, double x, double y) +{ + _mouseX = static_cast(x); + _mouseY = static_cast(y); + + if (!_captured) + { + return; + } + + OnTouchesMoved(_mouseX, _mouseY); +} + +CubismSampleViewMatrix * MouseActionManager::GetViewMatrix() +{ + return _viewMatrix; +} + +void MouseActionManager::SetUserModel(Csm::CubismUserModel * userModel) +{ + _userModel = userModel; +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/MouseActionManager.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/MouseActionManager.hpp new file mode 100644 index 00000000..4bb3f406 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/MouseActionManager.hpp @@ -0,0 +1,149 @@ +/** + * 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. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "LAppDefine.hpp" +#include "TouchManager.hpp" +#include "CubismSampleViewMatrix.hpp" + +/** +* @brief マウスの動作を通知するクラス +* +* マウス操作等を Cubism へ橋渡しする。 +* +*/ +class MouseActionManager +{ +public: + /** + * @brief クラスのインスタンス(シングルトン)を返す + * + * インスタンスが生成されていない場合は内部でインスタンスを生成する + * + * @return クラスのインスタンス + */ + static MouseActionManager* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する + * + */ + static void ReleaseInstance(); + + MouseActionManager(); ///< コンストラクタ + ~MouseActionManager(); ///< デストラクタ + + /** + * @brief 必要なものを初期化する + */ + void Initialize(int windowWidth, int windowHeight); + + /** + * @brief 行列の初期化をする + */ + void ViewInitialize(int windowWidth, int windowHeight); + + /** + * @brief OpenGL用 glfwSetMouseButtonCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] button ボタン種類 + * @param[in] action 実行結果 + * @param[in] modify + */ + void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify); + + /** + * @brief OpenGL用 glfwSetCursorPosCallback用関数。 + * + * @param[in] window コールバックを呼んだWindow情報 + * @param[in] x x座標 + * @param[in] y x座標 + */ + void OnMouseCallBack(GLFWwindow* window, double x, double y); + + /** + * @brief _userModelをセットする + * + */ + void SetUserModel(Csm::CubismUserModel* userModel); + + /** + * @brief _viewMatrixを取得する + * + */ + CubismSampleViewMatrix * GetViewMatrix(); + +private: + /** + * @brief ドラッグ + * + * ドラッグ時にどれだけ移動したかを通知する + */ + void OnDrag(Csm::csmFloat32 x, Csm::csmFloat32 y); + + /** + * @brief クリック入力始め + * + * クリックの入力が始まった時に呼ばれる + */ + void OnTouchesBegan(float px, float py); + + /** + * @brief クリック入力中の移動 + * + * クリック入力中の移動時に呼ばれる + */ + void OnTouchesMoved(float px, float py); + + /** + * @brief クリック入力終了時 + * + * クリックの入力が終了した時に呼ばれる + */ + void OnTouchesEnded(float px, float py); + + Csm::CubismUserModel* _userModel; + + TouchManager* _touchManager; ///< タッチマネージャー + + bool _captured; ///< クリックしているか + float _mouseX; ///< マウスX座標 + float _mouseY; ///< マウスY座標 + + CubismSampleViewMatrix* _viewMatrix; ///< 画面の表示の拡大縮小や移動の変換を行う行列 + Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 +}; + +class EventHandler +{ +public: + /** + * @brief glfwSetMouseButtonCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) + { + MouseActionManager::GetInstance()->OnMouseCallBack(window, button, action, modify); + } + + /** + * @brief glfwSetCursorPosCallback用コールバック関数。 + */ + static void OnMouseCallBack(GLFWwindow* window, double x, double y) + { + MouseActionManager::GetInstance()->OnMouseCallBack(window, x, y); + } +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/SwapchainManager.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/SwapchainManager.cpp new file mode 100644 index 00000000..40dac80f --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/SwapchainManager.cpp @@ -0,0 +1,212 @@ +/** + * 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. + */ + +#include "SwapchainManager.hpp" + +using namespace Csm; + +SwapchainManager::SwapchainManager(GLFWwindow* _window, VkPhysicalDevice physicalDevice, VkDevice device, + VkSurfaceKHR surface, Csm::csmUint32 graphicsFamily, Csm::csmUint32 presentFamily) + : _extent(VkExtent2D{0, 0}) + , _imageCount(0) +{ + CreateSwapchain(_window, physicalDevice, device, surface, graphicsFamily, presentFamily); +} + +SwapchainManager::SwapchainSupportDetails SwapchainManager::QuerySwapchainSupport( + VkPhysicalDevice& physicalDevice, VkSurfaceKHR surface) +{ + SwapchainSupportDetails details; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &details.capabilities); + + csmUint32 formatCount; + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr); + if (formatCount != 0) + { + details.formats.Resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, details.formats.GetPtr()); + } + + csmUint32 presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr); + + if (presentModeCount != 0) + { + details.presentModes.Resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, + details.presentModes.GetPtr()); + } + + return details; +} + +VkSurfaceFormatKHR SwapchainManager::ChooseSwapSurfaceFormat(const csmVector& availableFormats) +{ + for (csmUint32 i = 0; i < availableFormats.GetSize(); i++) + { + if (availableFormats[i].format == _swapchainFormat && availableFormats[i].colorSpace == + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + return availableFormats[i]; + } + } + //他に使えるフォーマットが無かったら最初のフォーマットを使う + return availableFormats[0]; +} + +VkPresentModeKHR SwapchainManager::ChooseSwapPresentMode(const csmVector& availablePresentModes) +{ + for (csmUint32 i = 0; i < availablePresentModes.GetSize(); i++) + { + if (availablePresentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) + { + return availablePresentModes[i]; + } + } + return VK_PRESENT_MODE_FIFO_KHR; +} + +VkExtent2D SwapchainManager::ChooseSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities) +{ + if (capabilities.currentExtent.width != UINT32_MAX) + { + return capabilities.currentExtent; + } + else + { + //for Retina display + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + VkExtent2D actualExtent = { + static_cast(width), + static_cast(height) + }; + + if (actualExtent.width < capabilities.minImageExtent.width) + { + actualExtent.width = capabilities.minImageExtent.width; + } + else if (actualExtent.width > capabilities.maxImageExtent.width) + { + actualExtent.width = capabilities.maxImageExtent.width; + } + + if (actualExtent.height < capabilities.minImageExtent.height) + { + actualExtent.height = capabilities.minImageExtent.height; + } + else if (actualExtent.height > capabilities.maxImageExtent.height) + { + actualExtent.height = capabilities.maxImageExtent.height; + } + + return actualExtent; + } +} + +void SwapchainManager::CreateSwapchain(GLFWwindow* window, VkPhysicalDevice physicalDevice, VkDevice device, + VkSurfaceKHR surface, Csm::csmUint32 graphicsFamily, + Csm::csmUint32 presentFamily) +{ + SwapchainSupportDetails swapChainSupport = QuerySwapchainSupport(physicalDevice, surface); + VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(swapChainSupport.formats); + VkPresentModeKHR presentMode = ChooseSwapPresentMode(swapChainSupport.presentModes); + _extent = ChooseSwapExtent(window, swapChainSupport.capabilities); + + _imageCount = swapChainSupport.capabilities.minImageCount + 1; + if (swapChainSupport.capabilities.maxImageCount > 0 && _imageCount > swapChainSupport.capabilities.maxImageCount) + { + _imageCount = swapChainSupport.capabilities.maxImageCount; + } + + VkSwapchainCreateInfoKHR createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = surface; + createInfo.minImageCount = _imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = _extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT; + if (graphicsFamily != presentFamily) + { + createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + createInfo.queueFamilyIndexCount = 2; + Csm::csmUint32 queueFamilyIndices[2] = {graphicsFamily, presentFamily}; + createInfo.pQueueFamilyIndices = queueFamilyIndices; + } + else + { + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.queueFamilyIndexCount = 0; + createInfo.pQueueFamilyIndices = nullptr; + } + createInfo.preTransform = swapChainSupport.capabilities.currentTransform; + createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = VK_NULL_HANDLE; + if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &_swapchain) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create swap chain"); + } + + // swapchain imageを取得する + vkGetSwapchainImagesKHR(device, _swapchain, &_imageCount, nullptr); + _images.Resize(_imageCount); + vkGetSwapchainImagesKHR(device, _swapchain, &_imageCount, _images.GetPtr()); + + _imageViews.Resize(_imageCount); + for (csmUint32 i = 0; i < _imageCount; i++) + { + VkImageViewCreateInfo viewInfo{}; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.image = _images[i]; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = _swapchainFormat; + viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.subresourceRange.baseMipLevel = 0; + viewInfo.subresourceRange.levelCount = 1; + viewInfo.subresourceRange.baseArrayLayer = 0; + viewInfo.subresourceRange.layerCount = 1; + + if (vkCreateImageView(device, &viewInfo, nullptr, &_imageViews[i]) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create texture image view"); + } + } +} + +VkResult SwapchainManager::QueuePresent(VkQueue& queue, csmUint32 imageIndex) +{ + VkPresentInfoKHR presentInfo{}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + + VkSwapchainKHR swapChains[] = {_swapchain}; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.pImageIndices = &imageIndex; + return vkQueuePresentKHR(queue, &presentInfo); +} + +void SwapchainManager::Cleanup(VkDevice device) +{ + if (_swapchain != VK_NULL_HANDLE) + { + for (csmUint32 i = 0; i < _imageViews.GetSize(); i++) + { + vkDestroyImageView(device, _imageViews[i], nullptr); + } + vkDestroySwapchainKHR(device, _swapchain, nullptr); + } +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/SwapchainManager.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/SwapchainManager.hpp new file mode 100644 index 00000000..ec85ca01 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/SwapchainManager.hpp @@ -0,0 +1,156 @@ +/** + * 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. + */ + +#pragma once +#include +#define GLFW_INCLUDE_VULKAN +#include +#include +#include +#include "LAppPal.hpp" + + +/** + * @brief スワップチェーンを扱うクラス + */ +class SwapchainManager +{ +public: + struct SwapchainSupportDetails + { + VkSurfaceCapabilitiesKHR capabilities; //基本的な機能 + Csm::csmVector formats; //利用可能なフォーマット + Csm::csmVector presentModes; //利用可能な表示モード + }; + + /** + * @brief コンストラクタ + * @param[in] _window -> ウィンドウ + * @param[in] physicalDevice -> 物理デバイス + * @param[in] device -> デバイス + * @param[in] surface -> サーフェス + * @param[in] graphicsFamily -> 描画コマンドに使うキューファミリ + * @param[in] presentFamily -> 表示コマンドに使うキューファミリ + */ + SwapchainManager(GLFWwindow* _window, VkPhysicalDevice physicalDevice, VkDevice device, VkSurfaceKHR surface, Csm::csmUint32 graphicsFamily, Csm::csmUint32 presentFamily); + + /** + * @brief 物理デバイスのサポートを確認する + * + * @param[in] physicalDevice -> 物理デバイス + * @param[in] surface -> スワップチェーンサーフェス + * @return 物理デバイスのサポート情報 + */ + static SwapchainSupportDetails QuerySwapchainSupport(VkPhysicalDevice& physicalDevice, VkSurfaceKHR surface); + + /** + * @brief サーフェスフォーマットを選択する + * @param[in] availableFormats -> 使えるサーフェスフォーマット + * @return 選択するサーフェスフォーマット + */ + VkSurfaceFormatKHR ChooseSwapSurfaceFormat(const Csm::csmVector& availableFormats); + + /** + * @brief 表示モードを選択する + * @param[in] availableFormats -> 使えるフォーマット + */ + VkPresentModeKHR ChooseSwapPresentMode(const Csm::csmVector& availablePresentModes); + + /** + * @brief スワップチェーンイメージの解像度を選択する + * + * @param[in] window -> ウィンドウ + * @param[in] capabilities -> サーフェスの機能を保持する構造体 + * @return スワップチェーンイメージの解像度 + */ + VkExtent2D ChooseSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities); + + /** + * @brief スワップチェーンを作成する + * + * @param[in] _window -> ウィンドウ + * @param[in] physicalDevice -> 物理デバイス + * @param[in] device -> デバイス + * @param[in] surface -> サーフェス + * @param[in] graphicsFamily -> 描画コマンドに使うキューファミリ + * @param[in] presentFamily -> 表示コマンドに使うキューファミリ + */ + void CreateSwapchain(GLFWwindow* window, VkPhysicalDevice physicalDevice, VkDevice device, VkSurfaceKHR surface, Csm::csmUint32 graphicsFamily, Csm::csmUint32 presentFamily); + + /** + * @brief 表示コマンドをキューに積む + * + * @param[in] queue -> キュー + * @param[in] imageIndex -> イメージのインデックス + * @return 成功したか + */ + VkResult QueuePresent(VkQueue& queue, Csm::csmUint32 imageIndex); + + /** + * @brief リソースを破棄&再作成する + * + * @param[in] device -> デバイス + */ + void Cleanup(VkDevice device); + + /** + * @brief extentを取得する + * + * @return extent + */ + VkExtent2D GetExtent() { return _extent; } + + /** + * @brief イメージ数を取得する + * + * @return イメージ数 + */ + Csm::csmInt32 GetImageCount() { return _imageCount; } + + /** + * @brief スワップチェーンイメージビューを取得する + * + * @return スワップチェーンイメージビュー + */ + Csm::csmVector GetViews() { return _imageViews; } + + /** + * @brief スワップチェーンを取得する + * + * @return スワップチェーン + */ + VkSwapchainKHR GetSwapchain() { return _swapchain; } + + /** + * @brief スワップチェーンのフォーマットを取得する + * + * @return フォーマット + */ + VkFormat GetSwapchainImageFormat() { return _swapchainFormat; } + + /** + * @brief スワップチェーンのイメージを取得する + * + * @return イメージ + */ + Csm::csmVector GetImages() { return _images; } + + /** + * @brief スワップチェーンのイメージを取得する + * + * @return イメージ + */ + Csm::csmVector GetImageViews() { return _imageViews; } + +private: + VkExtent2D _extent; ///< イメージの解像度 + Csm::csmUint32 _imageCount; ///< イメージ数 + Csm::csmVector _images; ///< スワップチェーンのイメージ + Csm::csmVector _imageViews; ///< スワップチェーンのイメージビュー + VkSwapchainKHR _swapchain; ///< スワップチェーン + const VkFormat _swapchainFormat = VK_FORMAT_B8G8R8A8_UNORM; ///< スワップチェーンのフォーマット +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/TouchManager.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/TouchManager.cpp new file mode 100644 index 00000000..60003c38 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/TouchManager.cpp @@ -0,0 +1,97 @@ +/** + * 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. + */ + +#include "TouchManager.hpp" +#include + +TouchManager::TouchManager() + : _startY(0.0f) + , _startX(0.0f) + , _lastX(0.0f) + , _lastY(0.0f) + , _lastX1(0.0f) + , _lastY1(0.0f) + , _lastX2(0.0f) + , _lastY2(0.0f) + , _lastTouchDistance(0.0f) + , _deltaX(0.0f) + , _deltaY(0.0f) + , _scale(1.0f) + , _touchSingle(false) + , _flipAvailable(false) +{ } + +void TouchManager::TouchesBegan(float deviceX, float deviceY) +{ + _lastX = deviceX; + _lastY = deviceY; + _startX = deviceX; + _startY = deviceY; + _lastTouchDistance = -1.0f; + _flipAvailable = true; + _touchSingle = true; +} + +void TouchManager::TouchesMoved(float deviceX, float deviceY) +{ + _lastX = deviceX; + _lastY = deviceY; + _lastTouchDistance = -1.0f; + _touchSingle = true; +} + +void TouchManager::TouchesMoved(float deviceX1, float deviceY1, float deviceX2, float deviceY2) +{ + float distance = CalculateDistance(deviceX1, deviceY1, deviceX2, deviceY2); + float centerX = (deviceX1 + deviceX2) * 0.5f; + float centerY = (deviceY1 + deviceY2) * 0.5f; + + if (_lastTouchDistance > 0.0f) + { + _scale = powf(distance / _lastTouchDistance, 0.75f); + _deltaX = CalculateMovingAmount(deviceX1 - _lastX1, deviceX2 - _lastX2); + _deltaY = CalculateMovingAmount(deviceY1 - _lastY1, deviceY2 - _lastY2); + } + else + { + _scale = 1.0f; + _deltaX = 0.0f; + _deltaY = 0.0f; + } + + _lastX = centerX; + _lastY = centerY; + _lastX1 = deviceX1; + _lastY1 = deviceY1; + _lastX2 = deviceX2; + _lastY2 = deviceY2; + _lastTouchDistance = distance; + _touchSingle = false; +} + +float TouchManager::GetFlickDistance() const +{ + return CalculateDistance(_startX, _startY, _lastX, _lastY); +} + +float TouchManager::CalculateDistance(float x1, float y1, float x2, float y2) const +{ + return sqrtf((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); +} + +float TouchManager::CalculateMovingAmount(float v1, float v2) +{ + if ((v1 > 0.0f) != (v2 > 0.0f)) + { + return 0.0f; + } + + float sign = v1 > 0.0f ? 1.0f : -1.0f; + float absoluteValue1 = fabsf(v1); + float absoluteValue2 = fabsf(v2); + return sign * ((absoluteValue1 < absoluteValue2) ? absoluteValue1 : absoluteValue2); +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/TouchManager.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/TouchManager.hpp new file mode 100644 index 00000000..d07072b6 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/TouchManager.hpp @@ -0,0 +1,104 @@ +/** + * 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. + */ + +#pragma once + +class TouchManager +{ +public: + + TouchManager(); + + float GetCenterX() const { return _lastX; } + float GetCenterY() const { return _lastY; } + float GetDeltaX() const { return _deltaX; } + float GetDeltaY() const{ return _deltaY; } + float GetStartX() const{ return _startX; } + float GetStartY() const{ return _startY; } + float GetScale() const { return _scale; } + float GetX() const{ return _lastX; } + float GetY() const{ return _lastY; } + float GetX1() const{ return _lastX1; } + float GetY1() const{ return _lastY1; } + float GetX2() const{ return _lastX2; } + float GetY2() const{ return _lastY2; } + bool IsSingleTouch() const { return _touchSingle; } + bool IsFlickAvailable() const { return _flipAvailable; } + void DisableFlick() { _flipAvailable = false; } + + /* + * @brief タッチ開始時イベント + * + * @param[in] deviceY タッチした画面のyの値 + * @param[in] deviceX タッチした画面のxの値 + */ + void TouchesBegan(float deviceX, float deviceY); + + /* + * @brief ドラッグ時のイベント + * + * @param[in] deviceX タッチした画面のyの値 + * @param[in] deviceY タッチした画面のxの値 + */ + void TouchesMoved(float deviceX, float deviceY); + + /* + * @brief ドラッグ時のイベント + * + * @param[in] deviceX1 1つめのタッチした画面のxの値 + * @param[in] deviceY1 1つめのタッチした画面のyの値 + * @param[in] deviceX2 2つめのタッチした画面のxの値 + * @param[in] deviceY2 2つめのタッチした画面のyの値 + */ + void TouchesMoved(float deviceX1, float deviceY1, float deviceX2, float deviceY2); + + /* + * @brief フリックの距離測定 + * + * @return フリック距離 + */ + float GetFlickDistance() const; + +private: + /* + * @brief 点1から点2への距離を求める + * + * @param[in] x1 1つめのタッチした画面のxの値 + * @param[in] y1 1つめのタッチした画面のyの値 + * @param[in] x2 2つめのタッチした画面のxの値 + * @param[in] y2 2つめのタッチした画面のyの値 + * @return 2点の距離 + */ + float CalculateDistance(float x1, float y1, float x2, float y2) const; + + /* + * 二つの値から、移動量を求める。 + * 違う方向の場合は移動量0。同じ方向の場合は、絶対値が小さい方の値を参照する + * + * @param[in] v1 1つめの移動量 + * @param[in] v2 2つめの移動量 + * + * @return 小さい方の移動量 + */ + float CalculateMovingAmount(float v1, float v2); + + float _startY; // タッチを開始した時のxの値 + float _startX; // タッチを開始した時のyの値 + float _lastX; // シングルタッチ時のxの値 + float _lastY; // シングルタッチ時のyの値 + float _lastX1; // ダブルタッチ時の一つ目のxの値 + float _lastY1; // ダブルタッチ時の一つ目のyの値 + float _lastX2; // ダブルタッチ時の二つ目のxの値 + float _lastY2; // ダブルタッチ時の二つ目のyの値 + float _lastTouchDistance; // 2本以上でタッチしたときの指の距離 + float _deltaX; // 前回の値から今回の値へのxの移動距離。 + float _deltaY; // 前回の値から今回の値へのyの移動距離。 + float _scale; // このフレームで掛け合わせる拡大率。拡大操作中以外は1。 + bool _touchSingle; // シングルタッチ時はtrue + bool _flipAvailable; // フリップが有効かどうか + +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/VulkanManager.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/VulkanManager.cpp new file mode 100644 index 00000000..87e48769 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/VulkanManager.cpp @@ -0,0 +1,576 @@ +/** + * 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. + */ + +#include "VulkanManager.hpp" +#include +#include + +#include "Rendering/Vulkan/CubismRenderer_Vulkan.hpp" +using namespace Csm; + +/** +* @brief デバッグ用コールバック +*/ +static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData) +{ + // LappPal::PrintLogは最大文字数を増やせば使える + // LAppPal::PrintLog("validation layer: %s\n", pCallbackData->pMessage); + std::cout << "validation layer: " << pCallbackData->pMessage << std::endl; + return VK_FALSE; +} + +/** +* @brief デバッグ用拡張関数を使えるようにする +*/ +VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugUtilsMessengerEXT* pDebugMessenger) +{ + PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + if (func != nullptr) + { + return func(instance, pCreateInfo, pAllocator, pDebugMessenger); + } + else + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } +} + +/** +* @brief デバッグメッセンジャーの破棄 +*/ +void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, + const VkAllocationCallbacks* pAllocator) +{ + PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + if (func != nullptr) + { + func(instance, debugMessenger, pAllocator); + } +} + +namespace +{ + VulkanManager* s_vulkanManager = NULL; +} + +VulkanManager* VulkanManager::GetInstance() +{ + if (s_vulkanManager == NULL) + { + s_vulkanManager = new VulkanManager(); + } + + return s_vulkanManager; +} + +void VulkanManager::ReleaseInstance() +{ + if (s_vulkanManager != NULL) + { + delete s_vulkanManager; + } + + s_vulkanManager = NULL; +} + +VulkanManager::VulkanManager() + : _window(NULL) + , _instance(VK_NULL_HANDLE) + , _physicalDevice(VK_NULL_HANDLE) + , _device(VK_NULL_HANDLE) + , _swapchainManager() + , _isSwapchainInvalid(false) + , _surface() + , _graphicQueue(VK_NULL_HANDLE) + , _presentQueue(VK_NULL_HANDLE) + , _commandPool(VK_NULL_HANDLE) + , _debugMessenger() + , _imageIndex(0) + , _framebufferResized(false) +{ +} + +VulkanManager::~VulkanManager() +{ + Destroy(); +} + +bool VulkanManager::CheckValidationLayerSupport() +{ + csmUint32 layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + csmVector availableLayers; + availableLayers.Resize(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.GetPtr()); + + for (const char* layerName : validationLayers) + { + bool layerFound = false; + + for (csmUint32 i = 0; i < availableLayers.GetSize(); i++) + { + if (strcmp(layerName, availableLayers[i].layerName) == 0) + { + layerFound = true; + break; + } + } + + if (!layerFound) + { + return false; + } + } + + return true; +} + +csmVector VulkanManager::GetRequiredExtensions() +{ + csmUint32 glfwExtensionCount = 0; + const char** glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + + csmVector extensions; + for (csmUint32 i = 0; i < glfwExtensionCount; i++) + { + extensions.PushBack(*(glfwExtensions + i)); + } + + if (_enableValidationLayers) + { + extensions.PushBack(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + + return extensions; +} + +void VulkanManager::PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) +{ + createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + createInfo.pfnUserCallback = DebugCallback; +} + +void VulkanManager::CreateInstance() +{ + //検証レイヤーが有効のときに使えるか確認 + if (_enableValidationLayers && !CheckValidationLayerSupport()) + { + LAppPal::PrintLogLn("validation layers requested, but not available!"); + } + + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "SAMPLE"; + appInfo.pEngineName = "SAMPLE"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_3; + + VkInstanceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + + csmVector extensions = GetRequiredExtensions(); + createInfo.enabledExtensionCount = static_cast(extensions.GetSize()); + createInfo.ppEnabledExtensionNames = extensions.GetPtr(); + + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + if (_enableValidationLayers) + { + createInfo.enabledLayerCount = static_cast(sizeof(validationLayers) / sizeof(validationLayers[0])); + createInfo.ppEnabledLayerNames = validationLayers; + // vkDestroyInstanceでデバッグコールが呼ばれるために次の行が必要 + PopulateDebugMessengerCreateInfo(debugCreateInfo); + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo; + } + else + { + createInfo.enabledLayerCount = 0; + } + if (vkCreateInstance(&createInfo, nullptr, &_instance) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create _instance!"); + } +} + +void VulkanManager::SetupDebugMessenger() +{ + if (!_enableValidationLayers) + { + return; + } + + VkDebugUtilsMessengerCreateInfoEXT createInfo; + PopulateDebugMessengerCreateInfo(createInfo); + + if (CreateDebugUtilsMessengerEXT(_instance, &createInfo, nullptr, &_debugMessenger) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to set up debug messenger!"); + } +} + +bool VulkanManager::CheckDeviceExtensionSupport(VkPhysicalDevice physicalDevice) +{ + csmUint32 extensionCount; + vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr); + + csmVector availableExtensions; + availableExtensions.Resize(extensionCount); + vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.GetPtr()); + + for (csmUint32 i = 0; i < sizeof(deviceExtensions) / sizeof(deviceExtensions[0]); i++) + { + bool found = false; + for (csmUint32 j = 0; j < availableExtensions.GetSize(); j++) + { + if (*deviceExtensions[i] == *availableExtensions[j].extensionName) + { + found = true; + } + } + if (found == false) + { + return false; + } + } + return true; +} + +void VulkanManager::CreateSurface() +{ + if (glfwCreateWindowSurface(_instance, _window, nullptr, &_surface) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create _window _surface!"); + } +} + +void VulkanManager::FindQueueFamilies(VkPhysicalDevice device) +{ + csmUint32 queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); + csmVector queueFamilies; + queueFamilies.Resize(queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.GetPtr()); + + for (csmUint32 i = 0; i < queueFamilies.GetSize(); i++) + { + if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + indices.graphicsFamily = i; + } + + VkBool32 presentSupport = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, _surface, &presentSupport); + if (presentSupport) + { + indices.presentFamily = i; + } + + if (indices.IsComplete()) + { + break; + } + } +} + +bool VulkanManager::IsDeviceSuitable(VkPhysicalDevice device) +{ + FindQueueFamilies(device); + bool extensionsSupported = CheckDeviceExtensionSupport(device); + bool swapChainAdequate = false; + //デバイスの拡張機能がサポートされていたら、スワップチェインをサポートしているか確認する + if (extensionsSupported) + { + SwapchainManager::SwapchainSupportDetails swapchainSupport = SwapchainManager::QuerySwapchainSupport( + device, _surface); + swapChainAdequate = swapchainSupport.formats.GetSize() != 0 && swapchainSupport.presentModes.GetSize() != 0; + } + + VkPhysicalDeviceFeatures supportedFeatures; + vkGetPhysicalDeviceFeatures(device, &supportedFeatures); + + return indices.IsComplete() && swapChainAdequate && supportedFeatures.samplerAnisotropy; +} + +void VulkanManager::PickPhysicalDevice() +{ + csmUint32 deviceCount = 0; + vkEnumeratePhysicalDevices(_instance, &deviceCount, nullptr); + + if (deviceCount == 0) + { + LAppPal::PrintLogLn("failed to find GPUs with Vulkan support!"); + } + + csmVector devices; + devices.Resize(deviceCount); + vkEnumeratePhysicalDevices(_instance, &deviceCount, devices.GetPtr()); + + // 一番最初に取得した物理デバイスを使用する + for (csmUint32 i = 0; i < devices.GetSize(); i++) + { + if (IsDeviceSuitable(devices[i])) + { + _physicalDevice = devices[i]; + break; + } + } + + if (_physicalDevice == VK_NULL_HANDLE) + { + LAppPal::PrintLogLn("failed to find a suitable GPU!"); + } +} + +void VulkanManager::CreateLogicalDevice() +{ + FindQueueFamilies(_physicalDevice); + + csmVector uniqueQueueFamilies; + if (indices.graphicsFamily == indices.presentFamily) + { + uniqueQueueFamilies.PushBack(indices.graphicsFamily); + } + else + { + uniqueQueueFamilies.PushBack(indices.graphicsFamily); + uniqueQueueFamilies.PushBack(indices.presentFamily); + } + + float queuePriority = 1.0f; + csmVector queueCreateInfos; + for (csmUint32 i = 0; i < uniqueQueueFamilies.GetSize(); i++) + { + VkDeviceQueueCreateInfo queueCreateInfo{}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = uniqueQueueFamilies[i]; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + queueCreateInfos.PushBack(queueCreateInfo); + } + + VkDeviceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.queueCreateInfoCount = queueCreateInfos.GetSize(); + createInfo.pQueueCreateInfos = queueCreateInfos.GetPtr(); + createInfo.enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0]); + createInfo.ppEnabledExtensionNames = deviceExtensions; + + if (_enableValidationLayers) + { + createInfo.enabledLayerCount = sizeof(validationLayers) / sizeof(validationLayers[0]); + createInfo.ppEnabledLayerNames = validationLayers; + } + else + { + createInfo.enabledLayerCount = 0; + } + + VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingF{}; + dynamicRenderingF.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR; + dynamicRenderingF.dynamicRendering = VK_TRUE; + + VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamicStateF{}; + dynamicStateF.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; + dynamicStateF.extendedDynamicState = VK_TRUE; + dynamicStateF.pNext = &dynamicRenderingF; + + VkPhysicalDeviceFeatures2 deviceFeatures2{}; + deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + deviceFeatures2.pNext = &dynamicStateF; + vkGetPhysicalDeviceFeatures2(_physicalDevice, &deviceFeatures2); + createInfo.pNext = &deviceFeatures2; + + if (vkCreateDevice(_physicalDevice, &createInfo, nullptr, &_device) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create logical _device!"); + } + + // キューハンドルを取得 + vkGetDeviceQueue(_device, indices.graphicsFamily, 0, &_graphicQueue); + vkGetDeviceQueue(_device, indices.presentFamily, 0, &_presentQueue); +} + +void VulkanManager::ChooseSupportedDepthFormat() +{ + VkFormat depthFormats[5] = { + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_D16_UNORM_S8_UINT, + VK_FORMAT_D16_UNORM + }; + + for (csmInt32 i = 0; i < sizeof(depthFormats) / sizeof(depthFormats[0]); i++) + { + VkFormatProperties formatProps; + vkGetPhysicalDeviceFormatProperties(_physicalDevice, depthFormats[i], &formatProps); + + if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) + { + _depthFormat = depthFormats[i]; + return; + } + } + CubismLogError("can't find depth format!"); + _depthFormat = depthFormats[0]; +} + +void VulkanManager::CreateCommandPool() +{ + VkCommandPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + poolInfo.queueFamilyIndex = indices.graphicsFamily; + + if (vkCreateCommandPool(_device, &poolInfo, nullptr, &_commandPool) != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to create graphics command pool!"); + } +} + +void VulkanManager::CreateSyncObjects() +{ + VkSemaphoreCreateInfo semaphoreInfo{}; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + vkCreateSemaphore(_device, &semaphoreInfo, nullptr, &_imageAvailableSemaphore); +} + +void VulkanManager::Initialize(GLFWwindow* wind) +{ + _window = wind; + + CreateInstance(); + SetupDebugMessenger(); + CreateSurface(); + PickPhysicalDevice(); + CreateLogicalDevice(); + ChooseSupportedDepthFormat(); + _swapchainManager = new SwapchainManager(_window, _physicalDevice, _device, _surface, indices.graphicsFamily, + indices.presentFamily); + CreateCommandPool(); + CreateSyncObjects(); +} + +VkCommandBuffer VulkanManager::BeginSingleTimeCommands() +{ + VkCommandBufferAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandPool = _commandPool; + allocInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer; + vkAllocateCommandBuffers(_device, &allocInfo, &commandBuffer); + + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + vkBeginCommandBuffer(commandBuffer, &beginInfo); + + return commandBuffer; +} + +void VulkanManager::SubmitCommand(VkCommandBuffer commandBuffer, bool isFirstDraw) +{ + vkEndCommandBuffer(commandBuffer); + + if(isFirstDraw) + { + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = &_imageAvailableSemaphore; + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + submitInfo.pWaitDstStageMask = waitStages; + vkQueueSubmit(_graphicQueue, 1, &submitInfo, VK_NULL_HANDLE); + } + else + { + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT }; + submitInfo.pWaitDstStageMask = waitStages; + vkQueueSubmit(_graphicQueue, 1, &submitInfo, VK_NULL_HANDLE); + } + + // コマンドの実行終了まで待機 + vkQueueWaitIdle(_graphicQueue); + vkFreeCommandBuffers(_device, _commandPool, 1, &commandBuffer); +} + +void VulkanManager::UpdateDrawFrame() +{ + VkResult result = vkAcquireNextImageKHR(_device, _swapchainManager->GetSwapchain(), UINT64_MAX, + _imageAvailableSemaphore, VK_NULL_HANDLE, + &_imageIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR) + { + _isSwapchainInvalid = true; + } + else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) + { + LAppPal::PrintLogLn("failed to acquire swap chain image!"); + } +} + +void VulkanManager::PostDraw() +{ + VkResult result = _swapchainManager->QueuePresent(_presentQueue, _imageIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || _framebufferResized) + { + _framebufferResized = false; + _isSwapchainInvalid = true; + } + else if (result != VK_SUCCESS) + { + LAppPal::PrintLogLn("failed to present swap chain image!"); + } +} + +void VulkanManager::RecreateSwapchain() +{ + vkDeviceWaitIdle(_device); + _swapchainManager->Cleanup(_device); + _swapchainManager->CreateSwapchain(_window, _physicalDevice, _device, _surface, indices.graphicsFamily, + indices.presentFamily); +} + +void VulkanManager::Destroy() +{ + vkDeviceWaitIdle(_device); + _swapchainManager->Cleanup(_device); + + delete _swapchainManager; + vkDestroySemaphore(_device, _imageAvailableSemaphore, nullptr); + + if (_enableValidationLayers) + { + DestroyDebugUtilsMessengerEXT(_instance, _debugMessenger, nullptr); + } + + vkDestroyCommandPool(_device, _commandPool, nullptr); + vkDestroyDevice(_device, nullptr); + vkDestroySurfaceKHR(_instance, _surface, nullptr); + vkDestroyInstance(_instance, nullptr); +} diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/VulkanManager.hpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/VulkanManager.hpp new file mode 100644 index 00000000..8d3a2d1d --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/VulkanManager.hpp @@ -0,0 +1,288 @@ +/** + * 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. + */ + +#pragma once +#include +#include "Type/csmMap.hpp" +#include "SwapchainManager.hpp" + + /** + * @brief vulkanに必要なリソースを扱うクラス + */ +class VulkanManager +{ +public: + // キューファミリの情報を格納する構造体 + struct QueueFamilyIndices + { + // 描画用と表示用のキューファミリは必ずしも一致するとは限らないので分ける + Csm::csmInt32 graphicsFamily = -1; // 描画コマンドに使用するキューファミリ + Csm::csmInt32 presentFamily = -1; // 表示に使用するキューファミリ + + // 対応するキューファミリがあるか + bool IsComplete() + { + return graphicsFamily != -1 && presentFamily != -1; + } + }indices; + + const char* deviceExtensions[3] = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, + VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME + }; + + const char* validationLayers[1] = { + "VK_LAYER_KHRONOS_validation" + }; + + /** + * @brief クラスのインスタンス(シングルトン)を返す。
+ * インスタンスが生成されていない場合は内部でインスタンを生成する。 + * + * @return クラスのインスタンス + */ + static VulkanManager* GetInstance(); + + /** + * @brief クラスのインスタンス(シングルトン)を解放する。 + * + */ + static void ReleaseInstance(); + + /** + * @brief コンストラクタ + */ + VulkanManager(); + + /** + * @brief デストラクタ + */ + ~VulkanManager(); + + /** + * @brief 検証レイヤーのサポートを確認する + */ + bool CheckValidationLayerSupport(); + + /** + * @brief 必要な拡張機能を取得する + * + * @return 必要な拡張の配列 + */ + Csm::csmVector GetRequiredExtensions(); + + /** + * @brief デバッグメッセージを有効にする + * + * @param[in] createInfo -> デバッグメッセンジャーオブジェクトの情報 + */ + void PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo); + + /** + * @brief インスタンスを生成する + */ + void CreateInstance(); + + /** + * @brief デバッグメッセージを有効にする + */ + void SetupDebugMessenger(); + + /** + * @brief デバイスの拡張をチェックする + * + * @param[in] physicalDevice -> 物理デバイス + */ + bool CheckDeviceExtensionSupport(VkPhysicalDevice physicalDevice); + + /** + * @brief サーフェスを作る + */ + void CreateSurface(); + + /** + * @brief キューファミリを見つける + * + * @param[in] queueFlags -> 物理デバイス + */ + void FindQueueFamilies(VkPhysicalDevice device); + + /** + * @brief デバイスが使えるか確認する + * + * @param[in] device -> 物理デバイス + */ + bool IsDeviceSuitable(VkPhysicalDevice device); + + /** + * @brief 物理デバイスを取得する + */ + void PickPhysicalDevice(); + + /** + * @brief 論理デバイスを作成する + */ + void CreateLogicalDevice(); + + /** + * @brief 深度フォーマットを作成する + */ + void ChooseSupportedDepthFormat(); + + /** + * @brief コマンドプールを作成する + */ + void CreateCommandPool(); + + /** + * @brief 同期オブジェクトを作成する + */ + void CreateSyncObjects(); + + /** + * @brief 初期化する + * @param[in] wind -> ウィンドウ + */ + void Initialize(GLFWwindow* wind); + + /** + * @brief コマンドの記録を開始する + */ + VkCommandBuffer BeginSingleTimeCommands(); + + /** + * @brief コマンドを提出する + * + * @param[in] commandBuffer -> コマンドバッファ + * @param[in] isDraw -> 描画コマンドか + * @param[in] isFirstDraw -> 最初の描画コマンドか + */ + void SubmitCommand(VkCommandBuffer commandBuffer, bool isFirstDraw = false); + + /** + * @brief 描画する + */ + void UpdateDrawFrame(); + + /** + * @brief 描画完了の追加処理 + */ + void PostDraw(); + + /** + * @brief スワップチェーンを再構成する + */ + void RecreateSwapchain(); + + /** + * @brief リソースを破棄する + */ + void Destroy(); + + /** + * @brief デバイスを取得する + * @return デバイス + */ + VkDevice GetDevice() { return _device; } + + /** + * @brief 物理デバイスを取得する + * @return 物理デバイス + */ + VkPhysicalDevice GetPhysicalDevice() { return _physicalDevice; } + + /** + * @brief モデル描画用コマンドバッファを取得する + * @return コマンドバッファの配列 + */ + VkQueue GetGraphicQueue() { return _graphicQueue; } + + /** + * @brief コマンドプールを取得する + * @return コマンドプール + */ + VkCommandPool GetCommandPool() { return _commandPool; } + + /** + * @brief スワップチェーンマネージャーを取得する + * @return スワップチェーンマネージャー + */ + SwapchainManager* GetSwapchainManager() { return _swapchainManager; } + + /** + * @brief ウィンドウサイズが変更されたかのフラグを取得する + * @return ウィンドウサイズの変更フラグ + */ + bool GetIsWindowSizeChanged() { return _isSwapchainInvalid; } + + /** + * @brief ウィンドウサイズが変更されたかのフラグをセットする + * @param[in] flag -> セットするフラグ + */ + void SetIsWindowSizeChanged(bool flag) { _isSwapchainInvalid = flag; } + + /** + * @brief フレームバッファのフラグを更新する + * + */ + void SetFrameBufferResized(bool flag) { _framebufferResized = flag; } + + /** + * @brief 深度フォーマットを取得する + * @return 深度フォーマット + */ + VkFormat GetDepthFormat() const { return _depthFormat; } + + /** + * @brief サーフェスのフォーマットを取得する + * + * @return フォーマット + */ + VkFormat GetImageFormat() { return _surfaceFormat; } + + /** + * @brief モデルテクスチャのフォーマットを取得する + * + * @return フォーマット + */ + VkFormat GetTextureFormat() { return _textureFormat; } + + /** + * @brief スワップチェーンイメージを取得する + * + * @return スワップチェーンイメージ + */ + VkImage GetSwapchainImage() { return GetSwapchainManager()->GetImages()[_imageIndex]; } + + /** + * @brief スワップチェーンイメージを取得する + * + * @return スワップチェーンイメージ + */ + VkImageView GetSwapchainImageView() { return GetSwapchainManager()->GetImageViews()[_imageIndex]; } + +private: + GLFWwindow* _window; // ウィンドウ + VkInstance _instance; // ライブラリを初期化するインスタンス + VkSurfaceKHR _surface; // ウィンドウシステムに描画ために必要なサーフェス + VkPhysicalDevice _physicalDevice; // 物理デバイス + VkDevice _device; // 論理デバイス + VkQueue _graphicQueue; // 描画コマンドを積むキュー + VkQueue _presentQueue; // 表示コマンドに使用するキュー + VkCommandPool _commandPool; // コマンドバッファの作成に必要なコマンドプール + VkSemaphore _imageAvailableSemaphore; // セマフォ + SwapchainManager* _swapchainManager; // スワップチェーンの管理を行うスワップチェーンマネージャー + bool _isSwapchainInvalid; // ウィンドウサイズが変更されたかのフラグ + const bool _enableValidationLayers = true; // 検証レイヤーを有効にするか + VkDebugUtilsMessengerEXT _debugMessenger; // デバッグメッセージを出力するオブジェクト + Csm::csmUint32 _imageIndex; // 現在のイメージインデックス + VkFormat _depthFormat; // 深度フォーマット + const VkFormat _surfaceFormat = VK_FORMAT_B8G8R8A8_UNORM; // サーフェイス用フォーマット + const VkFormat _textureFormat = VK_FORMAT_R8G8B8A8_UNORM; // テクスチャ用フォーマット + bool _framebufferResized; // フレームバッファのサイズが変わったか +}; diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/main.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/main.cpp new file mode 100644 index 00000000..b65c1f09 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/main.cpp @@ -0,0 +1,22 @@ +/** + * 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. + */ + +#include "LAppDelegate.hpp" + +int main(int argc, char* argv[]) +{ + // create the application instance + if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE) + { + return 1; + } + + LAppDelegate::GetInstance()->Run(); + + return 0; +} + diff --git a/Samples/Vulkan/Demo/proj.linux.cmake/src/mainMinimum.cpp b/Samples/Vulkan/Demo/proj.linux.cmake/src/mainMinimum.cpp new file mode 100644 index 00000000..6fc8e934 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.linux.cmake/src/mainMinimum.cpp @@ -0,0 +1,352 @@ +/** + * 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. + */ + +#include + +#include +#include +#include +#include + +#include "LAppDefine.hpp" +#include "LAppAllocator.hpp" +#include "LAppTextureManager.hpp" +#include "LAppPal.hpp" +#include "CubismUserModelExtend.hpp" +#include "MouseActionManager.hpp" +#include "VulkanManager.hpp" + +#include +#include +#include +#include +#include +#include + +/** +*@brief モデルデータのディレクトリ名 +* このディレクトリ名と同名の.model3.jsonを読み込む +*/ +static const Csm::csmChar* _modelDirectoryName = "Hiyori"; + +static Csm::CubismUserModel* _userModel; ///< ユーザーが実際に使用するモデル +static Csm::CubismFramework::Option _cubismOption; ///< CubismFrameworkに関するオプション +static LAppAllocator _cubismAllocator; ///< メモリのアロケーター + +static std::string _executeAbsolutePath; ///< アプリケーションの実行パス +static std::string _currentModelDirectory; ///< 現在のモデルのディレクトリ名 + +static GLFWwindow* _window; ///< ウィンドウオブジェクト +int _windowWidth, _windowHeight; ///< ウィンドウサイズの保存 + +/** +* @brief Cubism SDKの初期化 +* +* Cubism SDKの初期化処理を行う +*/ +static void InitializeCubism() +{ + //Initialize cubism + Csm::CubismFramework::Initialize(); + + LAppPal::UpdateTime(); +} + +/** +* @brief アプリケーションの実行パスの設定 +* +* Linuxのアプリケーションの実行パスを確認し、パスを取得する +*/ +void SetExecuteAbsolutePath() +{ + const int maximumPathBufferSize = 1024; + char path[maximumPathBufferSize]; + ssize_t len = readlink("/proc/self/exe", path, maximumPathBufferSize - 1); + + if (len != -1) + { + path[len] = '\0'; + } + + _executeAbsolutePath = dirname(path); + _executeAbsolutePath += "/"; +} + +/** +* @brief システムの初期化 +* +* 基盤システムの初期化処理を行う +*/ +static bool InitializeSystem() +{ + LAppPal::PrintLogLn("START"); + + // GLFWの初期化 + if (glfwInit() == GL_FALSE) + { + LAppPal::PrintLogLn("Can't initilize GLFW"); + + return GL_FALSE; + } + + // Windowの生成 + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + _window = glfwCreateWindow(LAppDefine::RenderTargetWidth, LAppDefine::RenderTargetHeight, "SIMPLE_SAMPLE", NULL, NULL); + if (_window == NULL) + { + LAppPal::PrintLogLn("Can't create GLFW window."); + + glfwTerminate(); + return GL_FALSE; + } + + glfwSetWindowUserPointer(_window, VulkanManager::GetInstance()); + + // Windowのコンテキストをカレントに設定 + glfwMakeContextCurrent(_window); + glfwSwapInterval(1); + + // コールバック関数の登録 + glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack); + glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack); + + // ウィンドウサイズ記憶 + glfwGetWindowSize(_window, &_windowWidth, &_windowHeight); + + // Cubism SDK の初期化 + _cubismOption.LogFunction = LAppPal::PrintMessage; + _cubismOption.LoggingLevel = Csm::CubismFramework::Option::LogLevel_Verbose; + Csm::CubismFramework::StartUp(&_cubismAllocator, &_cubismOption); + + InitializeCubism(); + + LAppPal::UpdateTime(); + + // vulkanデバイスの作成 + VulkanManager::GetInstance()->Initialize(_window); + SwapchainManager* swapchainManager = VulkanManager::GetInstance()->GetSwapchainManager(); + // レンダラにvulkanManagerの変数を渡す + Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::InitializeConstantSettings( + VulkanManager::GetInstance()->GetDevice(), VulkanManager::GetInstance()->GetPhysicalDevice(), + VulkanManager::GetInstance()->GetCommandPool(), VulkanManager::GetInstance()->GetGraphicQueue(), + swapchainManager->GetImageCount(), swapchainManager->GetExtent(), + VulkanManager::GetInstance()->GetSwapchainImageView(), swapchainManager->GetSwapchainImageFormat(), + VulkanManager::GetInstance()->GetDepthFormat() + ); + + // ドラッグ入力管理クラスの初期化 + MouseActionManager::GetInstance()->Initialize(_windowWidth, _windowHeight); + + SetExecuteAbsolutePath(); + + return GL_TRUE; +} + +/** +* @brief 解放 +* +* 解放の処理を行う +*/ +void Release() +{ + // レンダラの解放 + _userModel->DeleteRenderer(); + + // モデルデータの解放 + delete _userModel; + + // Windowの削除 + glfwDestroyWindow(_window); + + // OpenGLの処理を終了 + glfwTerminate(); + + // MouseActionManagerの解放 + MouseActionManager::ReleaseInstance(); + + // Cubism SDK の解放 + Csm::CubismFramework::Dispose(); +} + +/** +* @brief モデルの読み込み +* +* モデルデータの読み込み処理を行う +* +* @param[in] modelDirectory モデルのディレクトリ名 +*/ +void LoadModel(const std::string modelDirectoryName) +{ + // モデルのディレクトリを指定 + _currentModelDirectory = _executeAbsolutePath + LAppDefine::ResourcesPath + modelDirectoryName + "/"; + + // モデルデータの新規生成 + _userModel = new CubismUserModelExtend(modelDirectoryName, _currentModelDirectory); + + // モデルデータの読み込み及び生成とセットアップを行う + std::string json = ".model3.json"; + std::string fileName = _modelDirectoryName + json; + static_cast(_userModel)->LoadAssets(fileName.c_str()); + + // ユーザーモデルをMouseActionManagerへ渡す + MouseActionManager::GetInstance()->SetUserModel(_userModel); +} + +bool RecreateSwapchain() +{ + int width = 0, height = 0; + if (VulkanManager::GetInstance()->GetIsWindowSizeChanged()) + { + glfwGetFramebufferSize(_window, &width, &height); + while (width == 0 || height == 0) + { + glfwGetFramebufferSize(_window, &width, &height); + glfwWaitEvents(); + } + + VulkanManager::GetInstance()->RecreateSwapchain(); + Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::SetRenderTarget( + VulkanManager::GetInstance()->GetSwapchainImage(), + VulkanManager::GetInstance()->GetSwapchainImageView(), + VulkanManager::GetInstance()->GetSwapchainManager()->GetSwapchainImageFormat(), + VulkanManager::GetInstance()->GetSwapchainManager()->GetExtent() + ); + + // サイズを保存しておく + _windowWidth = width; + _windowHeight = height; + VulkanManager::GetInstance()->SetIsWindowSizeChanged(false); + + return true; + } + return false; +} + +/** +* @brief モデル描画前処理 +* +* スワップチェーンのクリアとメモリーレイアウトの変更を行う +*/ +void PreModelDraw() +{ + VulkanManager* vkManager = VulkanManager::GetInstance(); + VkCommandBuffer commandBuffer = vkManager->BeginSingleTimeCommands(); + + // レイアウト変更 + VkImageMemoryBarrier memoryBarrier{}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + memoryBarrier.srcAccessMask = 0; + memoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + memoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + memoryBarrier.image = vkManager->GetSwapchainImage(); + memoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); + + VkRenderingAttachmentInfoKHR colorAttachment{}; + colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; + colorAttachment.imageView = vkManager->GetSwapchainImageView(); + colorAttachment.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.clearValue = {0.0, 0.0, 0.0, 1.0}; + + VkRenderingInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + renderingInfo.renderArea = {{0, 0}, {vkManager->GetSwapchainManager()->GetExtent()}}; + renderingInfo.layerCount = 1; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &colorAttachment; + + // 画面クリア + vkCmdBeginRendering(commandBuffer, &renderingInfo); + vkCmdEndRendering(commandBuffer); + vkManager->SubmitCommand(commandBuffer, true); + + Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::SetRenderTarget( + VulkanManager::GetInstance()->GetSwapchainImage(), + VulkanManager::GetInstance()->GetSwapchainImageView(), + VulkanManager::GetInstance()->GetSwapchainManager()->GetSwapchainImageFormat(), + VulkanManager::GetInstance()->GetSwapchainManager()->GetExtent() + ); +} + +/** +* @brief モデル描画後処理 +* +* スワップチェーンのレイアウトを描画用へ変更 +*/ +void PostModelDraw() +{ + VulkanManager* vkManager = VulkanManager::GetInstance(); + + VkCommandBuffer commandBuffer = vkManager->BeginSingleTimeCommands(); + + // スワップチェーン描画終了バリア + VkImageMemoryBarrier memoryBarrier{}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + memoryBarrier.dstAccessMask = 0; + memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + memoryBarrier.image = vkManager->GetSwapchainImage(); + memoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); + + vkManager->SubmitCommand(commandBuffer); +} + +void Run() +{ + //メインループ + while (glfwWindowShouldClose(_window) == GL_FALSE) + { + // Poll for and process events + glfwPollEvents(); + + // 時間更新 + LAppPal::UpdateTime(); + VulkanManager::GetInstance()->UpdateDrawFrame(); + + if (RecreateSwapchain()) + { + continue; + } + + // View の PreModelDraw + PreModelDraw(); + + // モデルの更新及び描画 + static_cast(_userModel)->ModelOnUpdate(_window); + + // View の PostModelDraw + PostModelDraw(); + + // バッファの入れ替え + VulkanManager::GetInstance()->PostDraw(); + RecreateSwapchain(); + } +} + +int main() +{ + // 初期化 + InitializeSystem(); + + // モデルの読み込み + LoadModel(_modelDirectoryName); + + // メインループ + Run(); + + // 解放処理 + Release(); + + return 0; +} diff --git a/Samples/Vulkan/Demo/proj.win.cmake/CMakeLists.txt b/Samples/Vulkan/Demo/proj.win.cmake/CMakeLists.txt index d4395186..8fe9329b 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/CMakeLists.txt +++ b/Samples/Vulkan/Demo/proj.win.cmake/CMakeLists.txt @@ -56,19 +56,10 @@ else() message(FATAL_ERROR "[${APP_NAME}] Invalid linker flag ${CMAKE_EXE_LINKER_FLAGS}.") endif() # Detect compiler. -if(MSVC_VERSION MATCHES 1800) - # Visual Studio 2013 - set(COMPILER 120) -elseif(MSVC_VERSION MATCHES 1900) - # Visual Studio 2015 - set(COMPILER 140) -elseif(MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) - # Visual Studio 2017 - set(COMPILER 141) -elseif(MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) +if(MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) # Visual Studio 2019 set(COMPILER 142) -elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) +elseif(MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1950) # Visual Studio 2022 set(COMPILER 143) elseif(MSVC) diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/CMakeLists.txt b/Samples/Vulkan/Demo/proj.win.cmake/src/CMakeLists.txt index 1c58b248..48e0a9b2 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/CMakeLists.txt +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${APP_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/LAppPal.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppSprite.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpritePipeline.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LAppSpritePipeline.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppTextureManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.cpp index 155b9ebe..85bcc284 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.cpp @@ -37,6 +37,13 @@ const csmChar* GearImageName = "icon_gear.png"; // 終了ボタン const csmChar* PowerImageName = "close.png"; +// シェーダー相対パス +const csmChar* ShaderPath = "SampleShaders/"; +// 頂点シェーダー +const csmChar* VertShaderName = "VertSprite.spv"; +// フラグメントシェーダー +const csmChar* FragShaderName = "FragSprite.spv"; + // モデル定義------------------------------------------ // 外部定義ファイル(json)と合わせる const csmChar* MotionGroupIdle = "Idle"; // アイドリング diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.hpp index 50c428fb..04ba5aca 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDefine.hpp @@ -35,6 +35,10 @@ extern const csmChar* BackImageName; ///< 背景画像ファイル extern const csmChar* GearImageName; ///< 歯車画像ファイル extern const csmChar* PowerImageName; ///< 終了ボタン画像ファイル +extern const csmChar* ShaderPath;///< シェーダーパス +extern const csmChar* VertShaderName;///< 頂点シェーダー +extern const csmChar* FragShaderName;///< フラグメントシェーダー + // モデル定義-------------------------------------------- // 外部定義ファイル(json)と合わせる extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.cpp index dc12838f..11adae66 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.cpp @@ -7,8 +7,6 @@ #include "LAppDelegate.hpp" #include -#define GLFW_INCLUDE_VULKAN -#include #include #include "LAppLive2DManager.hpp" #include "LAppView.hpp" @@ -86,7 +84,7 @@ bool LAppDelegate::Initialize() //コールバック関数の登録 glfwSetMouseButtonCallback(window, EventHandler::OnMouseCallBack); glfwSetCursorPosCallback(window, EventHandler::OnMouseCallBack); - glfwSetFramebufferSizeCallback(window, s_vulkanManager->framebufferResizeCallback); + glfwSetFramebufferSizeCallback(window, EventHandler::OnFramebufferResizedCallback); // ウィンドウサイズ記憶 int width, height; @@ -106,9 +104,8 @@ bool LAppDelegate::Initialize() Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::InitializeConstantSettings( s_vulkanManager->GetDevice(), s_vulkanManager->GetPhysicalDevice(), s_vulkanManager->GetCommandPool(), s_vulkanManager->GetGraphicQueue(), - swapchainManager->GetExtent(), swapchainManager->GetSwapchainImageFormat(), - s_vulkanManager->GetImageFormat(), - s_vulkanManager->GetSwapchainImage(), s_vulkanManager->GetSwapchainImageView(), + swapchainManager->GetImageCount() , swapchainManager->GetExtent(), + s_vulkanManager->GetSwapchainImageView(), swapchainManager->GetSwapchainImageFormat(), s_vulkanManager->GetDepthFormat() ); @@ -140,7 +137,8 @@ void LAppDelegate::Release() //Cubism SDK の解放 CubismFramework::Dispose(); - s_vulkanManager->Destroy(); + delete s_vulkanManager; + s_vulkanManager = NULL; } bool LAppDelegate::RecreateSwapchain() @@ -156,10 +154,11 @@ bool LAppDelegate::RecreateSwapchain() } s_vulkanManager->RecreateSwapchain(); - Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::UpdateSwapchainVariable( - s_vulkanManager->GetSwapchainManager()->GetExtent(), + Live2D::Cubism::Framework::Rendering::CubismRenderer_Vulkan::SetRenderTarget( s_vulkanManager->GetSwapchainImage(), - s_vulkanManager->GetSwapchainImageView() + s_vulkanManager->GetSwapchainImageView(), + s_vulkanManager->GetSwapchainManager()->GetSwapchainImageFormat(), + s_vulkanManager->GetSwapchainManager()->GetExtent() ); // AppViewの初期化 diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.hpp index ed7d04e7..66c44feb 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppDelegate.hpp @@ -7,8 +7,6 @@ #pragma once -#define GLFW_INCLUDE_VULKAN -#include #include "LAppAllocator.hpp" #include "VulkanManager.hpp" @@ -148,4 +146,13 @@ class EventHandler { LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y); } + + /** + * @brief glfwSetFramebufferSizeCallback用コールバック関数。 + */ + static void OnFramebufferResizedCallback(GLFWwindow* window, int width, int height) + { + auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); + app->SetFrameBufferResized(true); + } }; diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppLive2DManager.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppLive2DManager.cpp index f139ffd4..86f080e4 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppLive2DManager.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppLive2DManager.cpp @@ -6,11 +6,11 @@ */ #include "LAppLive2DManager.hpp" +#include #include #include #include #include -#include #include "LAppPal.hpp" #include "LAppDefine.hpp" #include "LAppDelegate.hpp" @@ -23,6 +23,11 @@ using namespace LAppDefine; namespace { LAppLive2DManager* s_instance = NULL; +void BeganMotion(ACubismMotion* self) +{ + LAppPal::PrintLogLn("Motion began: %x", self); +} + void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLogLn("Motion Finished: %x", self); @@ -85,30 +90,43 @@ void LAppLive2DManager::SetUpModel() { // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。 // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。 + // 一部文字が受け取れないためワイド文字で受け取ってUTF8に変換し格納する。 + csmString crawlPath(ResourcesPath); crawlPath += "*.*"; - struct _finddata_t fdata; - intptr_t fh = _findfirst(crawlPath.GetRawString(), &fdata); - if (fh == -1) return; + wchar_t wideStr[MAX_PATH]; + csmChar name[MAX_PATH]; + LAppPal::ConvertMultiByteToWide(crawlPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata; + intptr_t fh = _wfindfirst(wideStr, &fdata); + if (fh == -1) + { + return; + } _modelDir.Clear(); - while (_findnext(fh, &fdata) == 0) + while (_wfindnext(fh, &fdata) == 0) { - if ((fdata.attrib & _A_SUBDIR) && strcmp(fdata.name, "..") != 0) + if ((fdata.attrib & _A_SUBDIR) && wcscmp(fdata.name, L"..") != 0) { + LAppPal::ConvertWideToMultiByte(fdata.name, name, MAX_PATH); + // フォルダと同名の.model3.jsonがあるか探索する csmString model3jsonPath(ResourcesPath); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath.Append(1, '/'); - model3jsonPath += fdata.name; + model3jsonPath += name; model3jsonPath += ".model3.json"; - struct _finddata_t fdata2; - if (_findfirst(model3jsonPath.GetRawString(), &fdata2) != -1) + LAppPal::ConvertMultiByteToWide(model3jsonPath.GetRawString(), wideStr, MAX_PATH); + + struct _wfinddata_t fdata2; + if (_wfindfirst(wideStr, &fdata2) != -1) { - _modelDir.PushBack(csmString(fdata.name)); + _modelDir.PushBack(csmString(name)); } } } @@ -168,7 +186,7 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y) { LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody); } - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion); + _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion); } } } @@ -179,7 +197,6 @@ void LAppLive2DManager::OnUpdate() const glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); VulkanManager* vulkanManager = LAppDelegate::GetInstance()->GetVulkanManager(); - Rendering::CubismRenderer_Vulkan::UpdateRendererSettings(vulkanManager->GetSwapchainImage(), vulkanManager->GetSwapchainImageView()); csmUint32 modelCount = _models.GetSize(); for (csmUint32 i = 0; i < modelCount; ++i) @@ -280,7 +297,7 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget); // 別レンダリング先を選択した際の背景クリア色 - float clearColor[3] = {1.0f, 1.0f, 1.0f}; + float clearColor[3] = {0.0f, 0.0f, 0.0f}; LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]); } diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.cpp index 66c8493f..6a339187 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.cpp @@ -281,21 +281,10 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString())); + CubismMotion* tmpMotion = static_cast(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelSetting, group, i)); if (tmpMotion) { - csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, i); - if (fadeTime >= 0.0f) - { - tmpMotion->SetFadeOutTime(fadeTime); - } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); if (_motions[name] != NULL) @@ -449,7 +438,7 @@ void LAppModel::Update() } CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, - ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) + ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (priority == PriorityForce) { @@ -479,21 +468,11 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler, onBeganMotionHandler, _modelSetting, group, no)); csmFloat32 fadeTime = _modelSetting->GetMotionFadeInTimeValue(group, no); if (fadeTime) { - if (fadeTime >= 0.0f) - { - motion->SetFadeInTime(fadeTime); - } - - fadeTime = _modelSetting->GetMotionFadeOutTimeValue(group, no); - if (fadeTime >= 0.0f) - { - motion->SetFadeOutTime(fadeTime); - } motion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); autoDelete = true; // 終了時にメモリから削除 } @@ -502,6 +481,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } else { + motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } @@ -522,7 +502,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt } CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 priority, - ACubismMotion::FinishedMotionCallback onFinishedMotionHandler) + ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { if (_modelSetting->GetMotionCount(group) == 0) { @@ -531,7 +511,7 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group, csmInt32 no = rand() % _modelSetting->GetMotionCount(group); - return StartMotion(group, no, priority, onFinishedMotionHandler); + return StartMotion(group, no, priority, onFinishedMotionHandler, onBeganMotionHandler); } void LAppModel::DoDraw() @@ -586,7 +566,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) if (motion != NULL) { - _expressionManager->StartMotionPriority(motion, false, PriorityForce); + _expressionManager->StartMotion(motion, false); } else { @@ -645,7 +625,7 @@ void LAppModel::SetupTextures(VkDevice device, VkFormat surfaceFormat) CreateTextureFromPngFile( texturePath.GetRawString(), surfaceFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, GetRenderer()->GetAnisotropy()); if (texture) { diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.hpp index e20f52d9..6385b545 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppModel.hpp @@ -70,11 +70,12 @@ class LAppModel : public Csm::CubismUserModel * @param[in] no グループ内の番号 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, - Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = - NULL); + Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, + Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief ランダムに選ばれたモーションの再生を開始する。 @@ -82,11 +83,12 @@ class LAppModel : public Csm::CubismUserModel * @param[in] group モーショングループ名 * @param[in] priority 優先度 * @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 + * @param[in] onBeganMotionHandler モーション再生開始時に呼び出されるコールバック関数。NULLの場合、呼び出されない。 * @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」 */ Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, - Csm::ACubismMotion::FinishedMotionCallback - onFinishedMotionHandler = NULL); + Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL, + Csm::ACubismMotion::BeganMotionCallback onBeganMotionHandler = NULL); /** * @brief 引数で指定した表情モーションをセットする diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.cpp index 48587675..46a885ac 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.cpp @@ -6,11 +6,13 @@ */ #include "LAppPal.hpp" +#include #include #include #include #include #include +#define GLFW_INCLUDE_VULKAN #include #include #include "LAppDefine.hpp" @@ -26,12 +28,12 @@ double LAppPal::s_deltaTime = 0.0; csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { - //filePath;// - const char* path = filePath.c_str(); + wchar_t wideStr[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0U, filePath.c_str(), -1, wideStr, MAX_PATH); int size = 0; - struct stat statBuf; - if (stat(path, &statBuf) == 0) + struct _stat statBuf; + if (_wstat(wideStr, &statBuf) == 0) { size = statBuf.st_size; @@ -39,7 +41,7 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat succeeded but file size is zero. path:%s", path); + PrintLogLn("Stat succeeded but file size is zero. path:%s", filePath.c_str()); } return NULL; } @@ -48,28 +50,33 @@ csmByte* LAppPal::LoadFileAsBytes(const string filePath, csmSizeInt* outSize) { if (DebugLogEnable) { - PrintLogLn("Stat failed. errno:%d path:%s", errno, path); + PrintLogLn("Stat failed. errno:%d path:%s", errno, filePath.c_str()); } return NULL; } - std::fstream file; - - file.open(path, std::ios::in | std::ios::binary); + std::wfstream file; + file.open(wideStr, std::ios::in | std::ios::binary); if (!file.is_open()) { if (DebugLogEnable) { - PrintLogLn("File open failed. path:%s", path); + PrintLogLn("File open failed. path:%s", filePath.c_str()); } return NULL; } - char* buf = new char[size]; - file.read(buf, size); - file.close(); + // ファイル名はワイド文字で探しているがファイルの中身はutf-8なので、1バイトずつ取得する。 *outSize = size; + csmChar* buf = new char[*outSize]; + std::wfilebuf* fileBuf = file.rdbuf(); + for (csmUint32 i = 0; i < *outSize; i++) + { + buf[i] = fileBuf->sbumpc(); + } + file.close(); + return reinterpret_cast(buf); } @@ -129,3 +136,13 @@ void LAppPal::PrintMessageLn(const csmChar* message) { PrintLogLn("%s", message); } + +bool LAppPal::ConvertMultiByteToWide(const csmChar* multiByte, wchar_t* wide, int wideSize) +{ + return MultiByteToWideChar(CP_UTF8, 0U, multiByte, -1, wide, wideSize) != 0; +} + +bool LAppPal::ConvertWideToMultiByte(const wchar_t* wide, csmChar* multiByte, int multiByteSize) +{ + return WideCharToMultiByte(CP_UTF8, 0U, wide, -1, multiByte, multiByteSize, NULL, NULL) != 0; +} diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.hpp index f65e11fb..70c7643e 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppPal.hpp @@ -91,6 +91,24 @@ class LAppPal */ static void PrintMessageLn(const Csm::csmChar* message); + /** + * @brief マルチバイト文字からワイド文字に変換する + * + * @param[in] multiByte 変換元 + * @param[in] wide 格納先 + * @param[in] wideSize 格納先の大きさ + */ + static bool ConvertMultiByteToWide(const Csm::csmChar* multiByte, wchar_t* wide, int wideSize); + + /** + * @brief ワイド文字からマルチバイト文字に変換する + * + * @param[in] wide 変換元 + * @param[in] multiByte 格納先 + * @param[in] multiByteSize 格納先の大きさ + */ + static bool ConvertWideToMultiByte(const wchar_t* wide, Csm::csmChar* multiByte, int multiByteSize); + private: static double s_currentFrame; static double s_lastFrame; diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.cpp index d7233121..ef18cc58 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.cpp @@ -7,14 +7,17 @@ #include "LAppSprite.hpp" #include "LAppTextureManager.hpp" +#include "LAppSpritePipeline.hpp" #include "VulkanManager.hpp" using namespace Csm; LAppSprite::LAppSprite( - VkDevice device, VkPhysicalDevice physicalDevice, VulkanManager* vkManager, float x, float y, float width, float height, - Csm::csmUint32 textureId, VkImageView view, VkSampler sampler, VkDescriptorSetLayout descriptorSetLayout) - : _rect() + VkDevice device, VkPhysicalDevice physicalDevice, VulkanManager* vkManager, + float x, float y, float width, float height, + Csm::csmUint32 textureId, LAppSpritePipeline* pipeline, + VkImageView view, VkSampler sampler) + : _rect(), _pipeline(pipeline) { _rect.left = (x - width * 0.5f); _rect.right = (x + width * 0.5f); @@ -91,8 +94,8 @@ LAppSprite::LAppSprite( LAppPal::PrintLogLn("failed to create descriptor pool!"); } - CreateDescriptorSet(device, descriptorSetLayout); - if (view != NULL && sampler != NULL) + CreateDescriptorSet(device, _pipeline->GetDescriptorSetLayout()); + if (textureId != 0) { SetDescriptorUpdated(false); UpdateDescriptorSet(device, view, sampler); @@ -219,14 +222,14 @@ void LAppSprite::SetDescriptorUpdated(bool frag) isDescriptorUpdated = frag; } -void LAppSprite::Render(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanManager* vkManager, int windowWidth, int windowHeight) +void LAppSprite::Render(VkCommandBuffer commandBuffer, VulkanManager* vkManager, int windowWidth, int windowHeight) { UpdateData(vkManager, windowWidth, windowHeight); VkBuffer vertexBuffers[] = {_vertexBuffer.GetBuffer()}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); vkCmdBindIndexBuffer(commandBuffer, _indexBuffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &_descriptorSet, 0,nullptr); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline->GetPipelineLayout(), 0, 1, &_descriptorSet, 0,nullptr); vkCmdDrawIndexed(commandBuffer, IndexNum, 1, 0, 0, 0); } @@ -257,3 +260,8 @@ void LAppSprite::ResetRect(float x, float y, float width, float height) _rect.up = (y - height * 0.5f); _rect.down = (y + height * 0.5f); } + +void LAppSprite::SetPipeline(LAppSpritePipeline* pipeline) +{ + _pipeline = pipeline; +} diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.hpp index f0ddd7b0..4ac3a8af 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSprite.hpp @@ -10,6 +10,7 @@ // 前方宣言 class VulkanManager; +class LAppSpritePipeline; /** * @brief スプライトを実装するクラス。 @@ -89,13 +90,13 @@ class LAppSprite * @param[in] width 横幅 * @param[in] height 高さ * @param[in] textureId テクスチャID + * @param[in] pipeline パイプライン * @param[in] view テクスチャビュー * @param[in] sampler テクスチャサンプラー - * @param[in] descriptorSetLayout ディスクリプタセット */ LAppSprite( VkDevice device, VkPhysicalDevice physicalDevice, VulkanManager* vkManager, float x, float y, float width, float height, - uint32_t textureId, VkImageView view, VkSampler sampler, VkDescriptorSetLayout descriptorSetLayout + uint32_t textureId, LAppSpritePipeline* pipeline, VkImageView view, VkSampler sampler ); /** @@ -152,7 +153,7 @@ class LAppSprite * @param[in] windowWidth ウィンドウ幅 * @param[in] windowHeight ウィンドウ高さ */ - void Render(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanManager* vkManager, int windowWidth, int windowHeight); + void Render(VkCommandBuffer commandBuffer, VulkanManager* vkManager, int windowWidth, int windowHeight); /** * @brief コンストラクタ @@ -184,6 +185,13 @@ class LAppSprite */ void ResetRect(float x, float y, float width, float height); + /** + * @brief パイプラインのセット + * + * @param[in] pipeline パイプラインクラスへのポインタ + */ + void SetPipeline(LAppSpritePipeline* pipeline); + /** * @brief Getter テクスチャID * @return テクスチャIDを返す @@ -201,6 +209,7 @@ class LAppSprite Live2D::Cubism::Framework::CubismBufferVulkan _stagingBuffer; ///< ステージングバッファ Live2D::Cubism::Framework::CubismBufferVulkan _indexBuffer; ///< インデックスバッファ Live2D::Cubism::Framework::CubismBufferVulkan _uniformBuffer; ///< ユニフォームバッファ + LAppSpritePipeline* _pipeline; ///< パイプライン VkDescriptorPool _descriptorPool; ///< ディスクリプタプール VkDescriptorSet _descriptorSet; ///< ディスクリプタセット モデルの数 bool isDescriptorUpdated; diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSpritePipeline.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSpritePipeline.cpp new file mode 100644 index 00000000..3b8ea1c7 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSpritePipeline.cpp @@ -0,0 +1,241 @@ +/** + * 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. + */ + +#include "LAppSpritePipeline.hpp" +#include + +#include "LAppSprite.hpp" +#include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include "LAppDelegate.hpp" + +LAppSpritePipeline::LAppSpritePipeline(VkDevice device, VkExtent2D extent, VkFormat swapchainFormat) +{ + CreateDescriptorSetLayout(device); + CreatePipelineLayout(device, _descriptorSetLayout); + CreatePipeline(device, extent, swapchainFormat); +} + +LAppSpritePipeline::~LAppSpritePipeline() +{ + VkDevice device = LAppDelegate::GetInstance()->GetVulkanManager()->GetDevice(); + vkDestroyDescriptorSetLayout(device, _descriptorSetLayout, nullptr); + vkDestroyPipelineLayout(device, _pipelineLayout, nullptr); + vkDestroyPipeline(device, _pipeline, nullptr); +} + +VkShaderModule LAppSpritePipeline::CreateShaderModule(VkDevice device, Csm::csmString filename) +{ + // ファイル読み込み + const uint32_t* shaderCode; + Csm::csmSizeInt shaderSize; + shaderCode = reinterpret_cast(LAppPal::LoadFileAsBytes(filename.GetRawString(), &shaderSize)); + + VkShaderModuleCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = shaderSize; + createInfo.pCode = shaderCode; + + VkShaderModule shaderModule; + if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) + { + CubismLogError("failed to create shader module!"); + } + + // 読み込んだコードの開放 + delete[] shaderCode; + + return shaderModule; +} + +void LAppSpritePipeline::CreateDescriptorSetLayout(VkDevice device) +{ + VkDescriptorSetLayoutBinding bindings[2]; + + bindings[0].binding = 0; + bindings[0].descriptorCount = 1; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + bindings[0].pImmutableSamplers = nullptr; + bindings[0].stageFlags = VK_SHADER_STAGE_ALL; + + bindings[1].binding = 1; + bindings[1].descriptorCount = 1; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[1].pImmutableSamplers = nullptr; + bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + + VkDescriptorSetLayoutCreateInfo layoutInfo{}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.bindingCount = sizeof(bindings) / sizeof(bindings[0]); + layoutInfo.pBindings = bindings; + + if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &_descriptorSetLayout) != VK_SUCCESS) + { + LAppPal::PrintLog("failed to create descriptor set layout!"); + } +} + +void LAppSpritePipeline::CreatePipelineLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout) +{ + // パイプラインレイアウト作成 + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; + + if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &_pipelineLayout) != VK_SUCCESS) + { + LAppPal::PrintLog("failed to create pipeline layout!"); + } +} + +void LAppSpritePipeline::CreatePipeline(VkDevice device, VkExtent2D extent, VkFormat swapchainFormat) +{ + // シェーダーのパスの作成 + Csm::csmString vertShaderFile(LAppDefine::ShaderPath); + vertShaderFile += LAppDefine::VertShaderName; + Csm::csmString fragShaderFile(LAppDefine::ShaderPath); + fragShaderFile += LAppDefine::FragShaderName; + + VkShaderModule vertShaderModule = CreateShaderModule(device, vertShaderFile); + VkShaderModule fragShaderModule = CreateShaderModule(device, fragShaderFile); + + // 頂点シェーダー + VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertShaderStageInfo.module = vertShaderModule; + vertShaderStageInfo.pName = "main"; + + // フラグメントシェーダー + VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; + fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragShaderStageInfo.module = fragShaderModule; + fragShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; + + + // 頂点入力バインド + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + + VkVertexInputBindingDescription bindingDescription = LAppSprite::SpriteVertex::GetBindingDescription(); + VkVertexInputAttributeDescription attributeDescriptions[2]{}; + LAppSprite::SpriteVertex::GetAttributeDescriptions(attributeDescriptions); + vertexInputInfo.vertexBindingDescriptionCount = 1; + vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; + vertexInputInfo.vertexAttributeDescriptionCount = sizeof(attributeDescriptions) / sizeof(attributeDescriptions[0]); + vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions; + + // インプットアセンブラ + VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssembly.primitiveRestartEnable = VK_FALSE; + + // ビューポート + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = extent; + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = (float)scissor.extent.width; + viewport.height = (float)scissor.extent.height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkPipelineViewportStateCreateInfo viewportState{}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + // ラスタライザ + VkPipelineRasterizationStateCreateInfo rasterizer{}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + + // サンプラー + VkPipelineMultisampleStateCreateInfo multisampling{}; + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + // ブレンドステート + VkPipelineColorBlendAttachmentState colorBlendAttachment{}; + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT + | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo colorBlending{}; + colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlending.logicOpEnable = VK_FALSE; + colorBlending.logicOp = VK_LOGIC_OP_COPY; + colorBlending.attachmentCount = 1; + colorBlending.pAttachments = &colorBlendAttachment; + + // パイプライン作成 + VkPipelineRenderingCreateInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachmentFormats = &swapchainFormat; + + VkGraphicsPipelineCreateInfo pipelineInfo{}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.stageCount = 2; + pipelineInfo.pStages = shaderStages; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &inputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &rasterizer; + pipelineInfo.pMultisampleState = &multisampling; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.layout = _pipelineLayout; + pipelineInfo.subpass = 0; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + pipelineInfo.pNext = &renderingInfo; + + if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_pipeline) != VK_SUCCESS) + { + LAppPal::PrintLog("failed to create graphics pipeline!"); + } + + vkDestroyShaderModule(device, vertShaderModule, nullptr); + vkDestroyShaderModule(device, fragShaderModule, nullptr); +} + +VkPipelineLayout LAppSpritePipeline::GetPipelineLayout() const +{ + return _pipelineLayout; +} + +VkPipeline LAppSpritePipeline::GetPipeline() const +{ + return _pipeline; +} + +VkDescriptorSetLayout LAppSpritePipeline::GetDescriptorSetLayout() const +{ + return _descriptorSetLayout; +} diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSpritePipeline.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSpritePipeline.hpp new file mode 100644 index 00000000..8806ffd1 --- /dev/null +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppSpritePipeline.hpp @@ -0,0 +1,85 @@ +/** + * 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. + */ + +#pragma once + +#include +#include +#include "CubismFramework.hpp" + +/** +* @brief スプライト用パイプラインクラス +*/ +class LAppSpritePipeline +{ +public: + /** + * @brief コンストラクタ + * + * @param[in] device 論理デバイス + * @param[in] extent フレームバッファのサイズ + * @param[in] swapchainFormat スワップチェーンフォーマット + */ + LAppSpritePipeline(VkDevice device, VkExtent2D extent, VkFormat swapchainFormat); + + /** + * @brief デストラクタ + */ + ~LAppSpritePipeline(); + + /** + * @brief パイプラインレイアウトを取得する + */ + VkPipelineLayout GetPipelineLayout() const; + + /** + * @brief パイプラインを取得する + */ + VkPipeline GetPipeline() const; + + /** + * @brief ディスクリプタセットレイアウトを取得する + */ + VkDescriptorSetLayout GetDescriptorSetLayout() const; + +private: + /** + * @brief スプライト用のディスクリプタセットのレイアウトを作成する。 + * + * @param[in] device 論理デバイス + */ + void CreateDescriptorSetLayout(VkDevice device); + + /** + * @brief パイプラインレイアウトを作成する。 + * + * @param[in] device 論理デバイス + * @param[in] descriptorSetLayout ディスクリプタセットレイアウト + */ + void CreatePipelineLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout); + + /** + * @brief スプライト用のパイプラインを作成する。 + * + * @param[in] device 論理デバイス + * @param[in] extent フレームバッファのサイズ + * @param[in] swapchainFormat スワップチェーンフォーマット + */ + void CreatePipeline(VkDevice device, VkExtent2D extent, VkFormat swapchainFormat); + + /** + * @brief シェーダーモジュ―ルを作成する + * + * @param[in] device 論理デバイス + * @param[in] filename シェーダーのファイル名 + */ + VkShaderModule CreateShaderModule(VkDevice device, Csm::csmString filename); + + VkDescriptorSetLayout _descriptorSetLayout; ///< ディスクリプタセットのレイアウト, UBOが1つとテクスチャが1つずつ + VkPipelineLayout _pipelineLayout; ///< スプライト描画に使うパイプラインのレイアウト + VkPipeline _pipeline; ///< スプライト描画に使うパイプライン +}; diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.cpp index 10bf4639..5a809bf4 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.cpp @@ -130,8 +130,8 @@ void LAppTextureManager::GenerateMipmaps(CubismImageVulkan image, uint32_t texWi } LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile( - std::string fileName, VkFormat format, - VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags imageProperties) + std::string fileName, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, + VkMemoryPropertyFlags imageProperties, Csm::csmFloat32 anisotropy) { VkDevice device = LAppDelegate::GetInstance()->GetVulkanManager()->GetDevice(); VkPhysicalDevice physicalDevice = LAppDelegate::GetInstance()->GetVulkanManager()->GetPhysicalDevice(); @@ -199,9 +199,7 @@ LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile( LAppDelegate::GetInstance()->GetVulkanManager()->SubmitCommand(commandBuffer); GenerateMipmaps(textureImage, width, height, _mipLevels); textureImage.CreateView(device, format, VK_IMAGE_ASPECT_COLOR_BIT, _mipLevels); - VkPhysicalDeviceProperties properties{}; - vkGetPhysicalDeviceProperties(physicalDevice, &properties); - textureImage.CreateSampler(device, properties.limits.maxSamplerAnisotropy, _mipLevels); + textureImage.CreateSampler(device, anisotropy, _mipLevels); _textures.PushBack(textureImage); LAppTextureManager::TextureInfo* textureInfo = new LAppTextureManager::TextureInfo(); diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.hpp index af9eed87..10ae35dc 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppTextureManager.hpp @@ -96,8 +96,8 @@ class LAppTextureManager * @return 作成したイメージのリソース。読み込み失敗時はNULLを返す。 */ TextureInfo* CreateTextureFromPngFile( - std::string fileName, - VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags imageProperties + std::string fileName,VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, + VkMemoryPropertyFlags imageProperties, Csm::csmFloat32 anisotropy ); /** diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.cpp index 95054aeb..deeaf049 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.cpp @@ -15,6 +15,7 @@ #include "LAppDefine.hpp" #include "TouchManager.hpp" #include "LAppSprite.hpp" +#include "LAppSpritePipeline.hpp" #include "LAppModel.hpp" using namespace std; @@ -26,11 +27,7 @@ LAppView::LAppView(): , _power(NULL) , _renderSprite(NULL) , _renderTarget(SelectTarget_None) - , _fragShaderModule(VK_NULL_HANDLE) - , _vertShaderModule(VK_NULL_HANDLE) - , _descriptorSetLayout(VK_NULL_HANDLE) - , _pipeline(VK_NULL_HANDLE) - , _pipelineLayout(VK_NULL_HANDLE) + , _spritePipeline(NULL) { _clearColor[0] = 1.0f; _clearColor[1] = 1.0f; @@ -50,12 +47,7 @@ LAppView::LAppView(): LAppView::~LAppView() { VkDevice device = LAppDelegate::GetInstance()->GetVulkanManager()->GetDevice(); - Cleanup(device); - vkDestroyDescriptorSetLayout(device, _descriptorSetLayout, nullptr); - vkDestroyShaderModule(device, _vertShaderModule, nullptr); - vkDestroyShaderModule(device, _fragShaderModule, nullptr); _renderBuffer.DestroyOffscreenSurface(device); - delete _renderSprite; delete _viewMatrix; delete _deviceToScreen; delete _touchManager; @@ -66,9 +58,12 @@ LAppView::~LAppView() _back->Release(device); _gear->Release(device); _power->Release(device); + _renderSprite->Release(device); delete _back; delete _gear; delete _power; + delete _renderSprite; + delete _spritePipeline; } void LAppView::Initialize() @@ -145,6 +140,21 @@ void LAppView::BeginRendering(VkCommandBuffer commandBuffer, float r, float g, f vkCmdBeginRendering(commandBuffer, &renderingInfo); } +void LAppView::ChangeEndLayout(VkCommandBuffer commandBuffer) +{ + VulkanManager* vkManager = LAppDelegate::GetInstance()->GetVulkanManager(); + VkImageMemoryBarrier memoryBarrier{}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + memoryBarrier.dstAccessMask = 0; + memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + memoryBarrier.image = vkManager->GetSwapchainImage(); + memoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); +} + void LAppView::EndRendering(VkCommandBuffer commandBuffer) { vkCmdEndRendering(commandBuffer); @@ -166,10 +176,10 @@ void LAppView::Render() beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; VkCommandBuffer commandBuffer = vkManager->BeginSingleTimeCommands(); BeginRendering(commandBuffer, 0.0, 0.0, 0.0, 1.0, true); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline); - _back->Render(commandBuffer, _pipelineLayout, vkManager, width, height); - _gear->Render(commandBuffer, _pipelineLayout, vkManager, width, height); - _power->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _spritePipeline->GetPipeline()); + _back->Render(commandBuffer, vkManager, width, height); + _gear->Render(commandBuffer, vkManager, width, height); + _power->Render(commandBuffer, vkManager, width, height); EndRendering(commandBuffer); vkManager->SubmitCommand(commandBuffer, true); @@ -190,196 +200,22 @@ void LAppView::Render() model->GetRenderBuffer().GetTextureView(), model->GetRenderBuffer().GetTextureSampler()); BeginRendering(commandBuffer, 0.f, 0.f, 0.3, 1.f, false); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _spritePipeline->GetPipeline()); float alpha = i < 1 ? 1.0f : model->GetOpacity(); // サンプルとしてαに適当な差をつける _renderSprite->SetColor(1.0f, 1.0f, 1.0f, alpha); if (model) { - _renderSprite->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + _renderSprite->Render(commandBuffer, vkManager, width, height); } EndRendering(commandBuffer); vkManager->SubmitCommand(commandBuffer); } } -} - -VkShaderModule LAppView::CreateShaderModule(VkDevice device, std::string filename) -{ - std::ifstream file(filename, std::ios::ate | std::ios::binary); - - if (!file.is_open()) - { - CubismLogError("failed to open file!"); - } - csmInt32 fileSize = (csmInt32)file.tellg(); - csmVector buffer(fileSize); - - file.seekg(0); - file.read(buffer.GetPtr(), fileSize); - file.close(); - - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = fileSize; - createInfo.pCode = reinterpret_cast(buffer.GetPtr()); - - VkShaderModule shaderModule; - if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) - { - CubismLogError("failed to create shader module!"); - } - - return shaderModule; -} - -void LAppView::CreateDescriptorSetLayout(VkDevice device) -{ - VkDescriptorSetLayoutBinding bindings[2]; - - bindings[0].binding = 0; - bindings[0].descriptorCount = 1; - bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - bindings[0].pImmutableSamplers = nullptr; - bindings[0].stageFlags = VK_SHADER_STAGE_ALL; - - bindings[1].binding = 1; - bindings[1].descriptorCount = 1; - bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - bindings[1].pImmutableSamplers = nullptr; - bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - VkDescriptorSetLayoutCreateInfo layoutInfo{}; - layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - layoutInfo.bindingCount = sizeof(bindings) / sizeof(bindings[0]); - layoutInfo.pBindings = bindings; - - if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &_descriptorSetLayout) != VK_SUCCESS) - { - LAppPal::PrintLogLn("failed to create descriptor set layout!"); - } -} - -void LAppView::CreateSpriteGraphicsPipeline(VkDevice device, VkExtent2D extent, VkShaderModule vertShaderModule, - VkShaderModule fragShaderModule, VkFormat swapchainFormat) -{ - VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; - vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = vertShaderModule; - vertShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; - fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = fragShaderModule; - fragShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; - - VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - VkVertexInputBindingDescription bindingDescription = LAppSprite::SpriteVertex::GetBindingDescription(); - VkVertexInputAttributeDescription attributeDescriptions[2]{}; - LAppSprite::SpriteVertex::GetAttributeDescriptions(attributeDescriptions); - vertexInputInfo.vertexBindingDescriptionCount = 1; - vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; - vertexInputInfo.vertexAttributeDescriptionCount = sizeof(attributeDescriptions) / sizeof(attributeDescriptions[0]); - vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions; - - VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = extent; - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = (float)scissor.extent.width; - viewport.height = (float)scissor.extent.height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkPipelineViewportStateCreateInfo viewportState{}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.pViewports = &viewport; - viewportState.scissorCount = 1; - viewportState.pScissors = &scissor; - - VkPipelineRasterizationStateCreateInfo rasterizer{}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - - VkPipelineMultisampleStateCreateInfo multisampling{}; - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineColorBlendAttachmentState colorBlendAttachment{}; - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT - | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - - VkPipelineColorBlendStateCreateInfo colorBlending{}; - colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlending.logicOpEnable = VK_FALSE; - colorBlending.logicOp = VK_LOGIC_OP_COPY; - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; - - VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 1; - pipelineLayoutInfo.pSetLayouts = &_descriptorSetLayout; - - if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &_pipelineLayout) != VK_SUCCESS) - { - LAppPal::PrintLogLn("failed to create pipeline layout!"); - } - - VkPipelineRenderingCreateInfo renderingInfo{}; - renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; - renderingInfo.colorAttachmentCount = 1; - renderingInfo.pColorAttachmentFormats = &swapchainFormat; - - VkGraphicsPipelineCreateInfo pipelineInfo{}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.stageCount = 2; - pipelineInfo.pStages = shaderStages; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.layout = _pipelineLayout; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - pipelineInfo.pNext = &renderingInfo; - - if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_pipeline) != VK_SUCCESS) - { - LAppPal::PrintLogLn("failed to create graphics pipeline!"); - } + commandBuffer = vkManager->BeginSingleTimeCommands(); + ChangeEndLayout(commandBuffer); + vkManager->SubmitCommand(commandBuffer); } void LAppView::InitializeSprite() @@ -388,11 +224,7 @@ void LAppView::InitializeSprite() VkDevice device = vkManager->GetDevice(); VkPhysicalDevice physicalDevice = vkManager->GetPhysicalDevice(); SwapchainManager* swapchainManager = vkManager->GetSwapchainManager(); - _vertShaderModule = CreateShaderModule(device, "SampleShaders/VertSprite.spv"); - _fragShaderModule = CreateShaderModule(device, "SampleShaders/FragSprite.spv"); - CreateDescriptorSetLayout(device); - CreateSpriteGraphicsPipeline(device, swapchainManager->GetExtent(), _vertShaderModule, _fragShaderModule, - vkManager->GetSwapchainManager()->GetSwapchainImageFormat()); + _spritePipeline = new LAppSpritePipeline(device, swapchainManager->GetExtent(), vkManager->GetSwapchainManager()->GetSwapchainImageFormat()); int width, height; glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); @@ -411,7 +243,7 @@ void LAppView::InitializeSprite() LAppTextureManager::TextureInfo* backgroundTexture = textureManager->CreateTextureFromPngFile( resourcesPath + imageName, vkManager->GetImageFormat(), VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0.0); LAppDelegate::GetInstance()->GetTextureManager()->GetTexture(backgroundTexture->id, textureImage); x = width * 0.5f; @@ -419,13 +251,13 @@ void LAppView::InitializeSprite() fWidth = static_cast(backgroundTexture->width * 2.0f); fHeight = static_cast(height * 0.95f); _back = new LAppSprite(device, physicalDevice, vkManager, x, y, fWidth, fHeight, backgroundTexture->id, - textureImage.GetView(), textureImage.GetSampler(), _descriptorSetLayout); + _spritePipeline, textureImage.GetView(), textureImage.GetSampler()); imageName = GearImageName; LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile( resourcesPath + imageName, vkManager->GetImageFormat(), VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0.0); LAppDelegate::GetInstance()->GetTextureManager()->GetTexture(gearTexture->id, textureImage); //X:右向き正、Y:下向き正 @@ -434,13 +266,13 @@ void LAppView::InitializeSprite() fWidth = static_cast(gearTexture->width); fHeight = static_cast(gearTexture->height); _gear = new LAppSprite(device, physicalDevice, vkManager, x, y, fWidth, fHeight, gearTexture->id, - textureImage.GetView(), textureImage.GetSampler(), _descriptorSetLayout); + _spritePipeline, textureImage.GetView(), textureImage.GetSampler()); imageName = PowerImageName; LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile( resourcesPath + imageName, vkManager->GetImageFormat(), VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0.0); LAppDelegate::GetInstance()->GetTextureManager()->GetTexture(powerTexture->id, textureImage); //X:右向き正、Y:下向き正 @@ -449,13 +281,13 @@ void LAppView::InitializeSprite() fWidth = static_cast(powerTexture->width); fHeight = static_cast(powerTexture->height); _power = new LAppSprite(device, physicalDevice, vkManager, x, y, fWidth, fHeight, powerTexture->id, - textureImage.GetView(), textureImage.GetSampler(), _descriptorSetLayout); + _spritePipeline, textureImage.GetView(), textureImage.GetSampler()); // 画面全体を覆うサイズ x = width * 0.5f; y = height * 0.5f; LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance(); - _renderSprite = new LAppSprite(device, physicalDevice, vkManager, x, y, static_cast(width), static_cast(height),0, NULL, NULL, _descriptorSetLayout); + _renderSprite = new LAppSprite(device, physicalDevice, vkManager, x, y, static_cast(width), static_cast(height),0, _spritePipeline, NULL, NULL); } void LAppView::OnTouchesBegan(float px, float py) const @@ -532,12 +364,22 @@ float LAppView::TransformScreenY(float deviceY) const void LAppView::PreModelDraw(LAppModel& refModel) { - // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ - Csm::Rendering::CubismOffscreenSurface_Vulkan* useTarget = NULL; - useTarget = (_renderTarget == SelectTarget_ViewFrameBuffer) ? &_renderBuffer : &refModel.GetRenderBuffer(); - - if (_renderTarget != SelectTarget_None) + if (_renderTarget == SelectTarget_None) + { + // 通常のスワップチェーンイメージへと描画 + VulkanManager* vkManager = LAppDelegate::GetInstance()->GetVulkanManager(); + Csm::Rendering::CubismRenderer_Vulkan::SetRenderTarget(vkManager->GetSwapchainImage(), + vkManager->GetSwapchainImageView(), + vkManager->GetSwapchainManager()->GetSwapchainImageFormat(), + vkManager->GetSwapchainManager()->GetExtent()); + } + else { + // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ + Csm::Rendering::CubismOffscreenSurface_Vulkan* useTarget = NULL; + useTarget = (_renderTarget == SelectTarget_ViewFrameBuffer) ? &_renderBuffer // LAppView が持つバッファ + : &refModel.GetRenderBuffer(); // Model が持つバッファ + // 別のレンダリングターゲットへ向けて描画する場合 if (!useTarget->IsValid()) { @@ -555,7 +397,10 @@ void LAppView::PreModelDraw(LAppModel& refModel) _renderSprite->SetDescriptorUpdated(false); } } - Csm::Rendering::CubismRenderer_Vulkan::SetRenderTarget(useTarget->GetTextureImage(), useTarget->GetTextureView()); + // 描画先を別のレンダリングターゲットへ指定 + Csm::Rendering::CubismRenderer_Vulkan::SetRenderTarget(useTarget->GetTextureImage(), useTarget->GetTextureView(), + LAppDelegate::GetInstance()->GetVulkanManager()->GetImageFormat(), + VkExtent2D{useTarget->GetBufferWidth(), useTarget->GetBufferHeight()}); } } @@ -581,13 +426,20 @@ void LAppView::PostModelDraw(LAppModel& refModel, csmInt32 modelIndex) _renderSprite->UpdateDescriptorSet(vkManager->GetDevice(), useTarget->GetTextureView(), useTarget->GetTextureSampler()); BeginRendering(commandBuffer, 0.f, 0.f, 0.3, 1.f, false); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _spritePipeline->GetPipeline()); _renderSprite->SetColor(1.0f, 1.0f, 1.0f, GetSpriteAlpha(0)); - _renderSprite->Render(commandBuffer, _pipelineLayout, vkManager, width, height); + _renderSprite->Render(commandBuffer, vkManager, width, height); EndRendering(commandBuffer); vkManager->SubmitCommand(commandBuffer); } } + + // レンダーターゲットをスワップチェーンのものへと戻す + VulkanManager* vkManager = LAppDelegate::GetInstance()->GetVulkanManager(); + Csm::Rendering::CubismRenderer_Vulkan::SetRenderTarget(vkManager->GetSwapchainImage(), + vkManager->GetSwapchainImageView(), + vkManager->GetSwapchainManager()->GetSwapchainImageFormat(), + vkManager->GetSwapchainManager()->GetExtent()); } void LAppView::SwitchRenderingTarget(SelectTarget targetType) @@ -618,20 +470,13 @@ float LAppView::GetSpriteAlpha(int assign) const return alpha; } -void LAppView::Cleanup(VkDevice device) -{ - vkDestroyPipelineLayout(device, _pipelineLayout, nullptr); - vkDestroyPipeline(device, _pipeline, nullptr); -} - void LAppView::ResizeSprite(int width, int height) { VulkanManager* vkManager = LAppDelegate::GetInstance()->GetVulkanManager(); VkDevice device = vkManager->GetDevice(); SwapchainManager* swapchainManager = vkManager->GetSwapchainManager(); - Cleanup(device); - CreateSpriteGraphicsPipeline(device, swapchainManager->GetExtent(), _vertShaderModule, _fragShaderModule, - vkManager->GetSwapchainManager()->GetSwapchainImageFormat()); + delete _spritePipeline; + _spritePipeline = new LAppSpritePipeline(device, swapchainManager->GetExtent(), vkManager->GetSwapchainManager()->GetSwapchainImageFormat()); LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager(); if (!textureManager) @@ -646,6 +491,7 @@ void LAppView::ResizeSprite(int width, int height) if (_back) { + _back->SetPipeline(_spritePipeline); uint32_t id = _back->GetTextureId(); LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id); if (texInfo) @@ -660,6 +506,7 @@ void LAppView::ResizeSprite(int width, int height) if (_power) { + _power->SetPipeline(_spritePipeline); uint32_t id = _power->GetTextureId(); LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id); if (texInfo) @@ -674,6 +521,7 @@ void LAppView::ResizeSprite(int width, int height) if (_gear) { + _gear->SetPipeline(_spritePipeline); uint32_t id = _gear->GetTextureId(); LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id); if (texInfo) @@ -687,6 +535,7 @@ void LAppView::ResizeSprite(int width, int height) } if (_renderSprite) { + _renderSprite->SetPipeline(_spritePipeline); x = width * 0.5f; y = height * 0.5f; _renderSprite->ResetRect(x, y, static_cast(width), static_cast(height)); diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.hpp index a8ed1beb..35cddabd 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/LAppView.hpp @@ -16,6 +16,7 @@ class TouchManager; class LAppSprite; class LAppModel; +class LAppSpritePipeline; /** * @brief 描画クラス @@ -62,6 +63,12 @@ class LAppView */ void BeginRendering(VkCommandBuffer commandBuffer, float r, float g, float b, float a, bool isClear); + /** + * @brief レンダリングを終了する際のレイアウトを変更する。 + * + * @param[in] commandBuffer -> コマンドバッファ + */ + void ChangeEndLayout(VkCommandBuffer commandBuffer); /** * @brief レンダリングを終了する。 @@ -75,32 +82,6 @@ class LAppView */ void Render(); - /** - * @brief シェーダーモジュ―ルを作成する - * - * @param[in] device -> デバイス - * @param[in] filename -> シェーダーのファイル名 - */ - VkShaderModule CreateShaderModule(VkDevice device, std::string filename); - - /** - * @brief スプライト用のディスクリプタセットのレイアウトを作成する。 - * - * @param[in] device 論理デバイス - */ - void CreateDescriptorSetLayout(VkDevice device); - - /** - * @brief スプライト用のパイプラインを作成する。 - * - * @param[in] device デバイス - * @param[in] extent フレームバッファのサイズ - * @param[in] vertShaderModule 頂点シェーダのモジュール - * @param[in] fragShaderModule フラグメントシェーダのモジュール - */ - void CreateSpriteGraphicsPipeline(VkDevice device, VkExtent2D extent, VkShaderModule vertShaderModule, - VkShaderModule fragShaderModule, VkFormat swapchainFormat); - /** * @brief 画像の初期化を行う。 */ @@ -195,13 +176,6 @@ class LAppView */ float GetSpriteAlpha(int assign) const; - /** - * @brief ウィンドウサイズ変更の際にリソースを破棄する。 - * - * @param[in] device デバイス - */ - void Cleanup(VkDevice device); - /** * @brief ウィンドウサイズ変更の際にスプライトを再作成する * @@ -216,19 +190,15 @@ class LAppView void DestroyOffscreenSurface(); private: - TouchManager* _touchManager; ///< タッチマネージャー - Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 - Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix - LAppSprite* _back; ///< 背景画像 - LAppSprite* _gear; ///< ギア画像 - LAppSprite* _power; ///< 電源画像 - LAppSprite* _renderSprite; ///< レンダリング先を別ターゲットにする方式の場合に使用 + TouchManager* _touchManager; ///< タッチマネージャー + Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 + Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix + LAppSprite* _back; ///< 背景画像 + LAppSprite* _gear; ///< ギア画像 + LAppSprite* _power; ///< 電源画像 + LAppSprite* _renderSprite; ///< レンダリング先を別ターゲットにする方式の場合に使用 Csm::Rendering::CubismOffscreenSurface_Vulkan _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング - SelectTarget _renderTarget; ///< レンダリング先の選択肢 - float _clearColor[4]; ///< レンダリングターゲットのクリアカラー - VkShaderModule _vertShaderModule; ///< 頂点シェーダーモジュール - VkShaderModule _fragShaderModule; ///< フラグメントシェーダーモジュール - VkDescriptorSetLayout _descriptorSetLayout; ///< ディスクリプタセットのレイアウト, UBOが1つとテクスチャが1つずつ - VkPipelineLayout _pipelineLayout; ///< スプライト描画に使うパイプラインのレイアウト - VkPipeline _pipeline; ///< スプライト描画に使うパイプライン + SelectTarget _renderTarget; ///< レンダリング先の選択肢 + float _clearColor[4]; ///< レンダリングターゲットのクリアカラー + LAppSpritePipeline* _spritePipeline; ///< スプライト用パイプライン }; diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/SwapchainManager.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/SwapchainManager.hpp index 204bde43..8a87a9a7 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/SwapchainManager.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/SwapchainManager.hpp @@ -7,6 +7,7 @@ #pragma once #include +#define GLFW_INCLUDE_VULKAN #include #include #include @@ -160,5 +161,5 @@ class SwapchainManager Csm::csmVector images; ///< スワップチェーンのイメージ Csm::csmVector imageViews; ///< スワップチェーンのイメージビュー VkSwapchainKHR swapchain; ///< スワップチェーン - const VkFormat swapchainFormat = VK_FORMAT_B8G8R8A8_UNORM; ///< スワップチェーンのフォーマット + const VkFormat swapchainFormat = VK_FORMAT_R8G8B8A8_UNORM; ///< スワップチェーンのフォーマット }; diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.cpp index ca410dd7..434eebb0 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.cpp @@ -50,11 +50,6 @@ void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT } } -void VulkanManager::framebufferResizeCallback(GLFWwindow* window, int width, int height) { - auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); - app->_framebufferResized = true; -} - VulkanManager::VulkanManager(GLFWwindow* wind): _instance(VK_NULL_HANDLE) , _physicalDevice(VK_NULL_HANDLE) @@ -458,17 +453,30 @@ void VulkanManager::SubmitCommand(VkCommandBuffer commandBuffer, bool isFirstDra vkEndCommandBuffer(commandBuffer); VkSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer; + if(isFirstDraw) { + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &_imageAvailableSemaphore; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.pWaitDstStageMask = waitStages; + vkQueueSubmit(_graphicQueue, 1, &submitInfo, VK_NULL_HANDLE); + } + else + { + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT }; + submitInfo.pWaitDstStageMask = waitStages; + vkQueueSubmit(_graphicQueue, 1, &submitInfo, VK_NULL_HANDLE); } - vkQueueSubmit(_graphicQueue, 1, &submitInfo, VK_NULL_HANDLE); + // コマンドの実行終了まで待機 vkQueueWaitIdle(_graphicQueue); vkFreeCommandBuffers(_device, _commandPool, 1, &commandBuffer); @@ -513,6 +521,8 @@ void VulkanManager::RecreateSwapchain() void VulkanManager::Destroy() { _swapchainManager->Cleanup(_device); + delete _swapchainManager; + _swapchainManager = NULL; vkDestroySemaphore(_device, _imageAvailableSemaphore, nullptr); diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.hpp b/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.hpp index 3aba6abd..16358c3b 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.hpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/VulkanManager.hpp @@ -7,7 +7,6 @@ #pragma once #include -#include #include "Type/csmMap.hpp" #include "SwapchainManager.hpp" @@ -40,8 +39,6 @@ class VulkanManager "VK_LAYER_KHRONOS_validation" }; - static void VulkanManager::framebufferResizeCallback(GLFWwindow* window, int width, int height); - /** * @brief コンストラクタ * @param[in] wind -> ウィンドウ @@ -158,7 +155,7 @@ class VulkanManager void UpdateDrawFrame(); /** - * @brief 描画する + * @brief 描画完了の追加処理 */ void PostDraw(); @@ -214,6 +211,12 @@ class VulkanManager */ void SetIsWindowSizeChanged(bool flag) { _isSwapchainInvalid = flag; } + /** + * @brief フレームバッファのフラグを更新する + * + */ + void SetFrameBufferResized(bool flag) { _framebufferResized = flag; } + /** * @brief 深度フォーマットを取得する * @return 深度フォーマット diff --git a/Samples/Vulkan/Demo/proj.win.cmake/src/main.cpp b/Samples/Vulkan/Demo/proj.win.cmake/src/main.cpp index 07b6e814..9430db31 100644 --- a/Samples/Vulkan/Demo/proj.win.cmake/src/main.cpp +++ b/Samples/Vulkan/Demo/proj.win.cmake/src/main.cpp @@ -6,17 +6,24 @@ */ #include "LAppDelegate.hpp" +#include int main() { + // Setting the console character encoding to UTF-8 + UINT preConsoleOutputCP = GetConsoleOutputCP(); + SetConsoleOutputCP(65001); + // create the application instance if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE) { + SetConsoleOutputCP(preConsoleOutputCP); return 1; } LAppDelegate::GetInstance()->Run(); + SetConsoleOutputCP(preConsoleOutputCP); return 0; } diff --git a/Samples/Vulkan/README.ja.md b/Samples/Vulkan/README.ja.md index d8268505..ef439662 100644 --- a/Samples/Vulkan/README.ja.md +++ b/Samples/Vulkan/README.ja.md @@ -8,8 +8,8 @@ Vulkan で実装したアプリケーションのサンプル実装です。 | サードパーティ | バージョン | | --- | --- | | [GLFW] | 3.4 | -| [stb_image.h] | 2.29 | -| [Vulkan SDK] | 1.3 | +| [stb_image.h] | 2.30 | +| [Vulkan SDK] | 1.3.296 | その他の開発環境・動作確認環境はトップディレクトリにある [README.ja.md](/README.ja.md) を参照してください。 @@ -19,7 +19,8 @@ Vulkan で実装したアプリケーションのサンプル実装です。 ``` . ├─ Demo -│ └─ proj.win.cmake # CMake project for Windows +│ ├─ proj.linux.cmake # CMake project for Linux +│ ├─ proj.win.cmake # CMake project for Windows └─ thirdParty # Third party libraries and scripts ``` @@ -34,6 +35,23 @@ Vulkan で実装したアプリケーションのサンプル実装です。 このディレクトリ内に含まれるものは以下の通りです。 +### proj.linux.cmake + +Linux 用の CMake プロジェクトです。 + +`script` ディレクトリのスクリプトを実行すると `build` ディレクトリに CMake 成果物が生成されます + +| スクリプト名 | 生成物 | +| --- | --- | +| `make_gcc` | 実行可能なアプリケーション | + +これらのスクリプトを実行した際にフルバージョンのサンプルを生成するか、ミニマムバージョンのサンプルを生成するかを選択することができます。 + +追加ライブラリとして [GLFW] を使用しています。 +[thirdParty](#thirdParty) の項目を参照して事前にダウンロードを行なってください。 +ビルド時、これ以外に`libpng`やX Windows System依存ライブラリ等必要なパッケージのインストールを求められる場合がございますので、その際は求められたパッケージをインストールしてください。 + + ### proj.win.cmake Windows 用の CMake プロジェクトです。 @@ -58,17 +76,28 @@ Windows 用の CMake プロジェクトです。 | プラットフォーム | スクリプト名 | | --- | --- | -| Windows | `setup_glew_glfw.bat` | +| Linux *1 | `setup_glfw` | +| Windows | `setup_glfw.bat` | スクリプト内の `GLFW_VERSION` を変更することで、ダウンロードするバージョンを変更できます。 -[GLFW]: https://github.com/glfw/glfw -[stb_image.h]: https://github.com/nothings/stb/blob/master/stb_image.h +*1 Linuxでは GLFW が依存するライブラリのインストールが必要になる場合がございますので、公式ページを参考に依存関係にあるライブラリをすべてインストールしてください。 +[GLFW.org Dependencies for X11 on Unix-like systems](https://www.glfw.org/docs/latest/compile_guide.html#compile_deps_x11) +詳しくは [NOTICE.md](/NOTICE.ja.md) をご確認ください。 ### Vulkan SDK のインストール -あらかじめVulkan SDKインストールしておき、環境変数VULKAN_SDKを設定しておく必要があります。 -x86プラットフォームでビルドする場合、Vulkan SDKインストールの際に `SDK 32-bit Core Components` をインストールする必要があります。 +あらかじめVulkan SDKインストールしておき、環境変数VULKAN_SDKを設定しておく必要があります。 +x86プラットフォームでビルドする場合、Vulkan SDKインストールの際に `SDK 32-bit Core Components` をインストールする必要があります。 +[Windowsのインストールの詳細](https://vulkan-tutorial.com/Development_environment#page_Windows) -[Vulkan SDK]: https://www.lunarg.com/vulkan-sdk/ +Linuxでは以下のVulkanパッケージをインストールする必要があります。 +[Linuxのインストールの詳細](https://vulkan-tutorial.com/Development_environment#page_Linux) +| ディストリビューション | パッケージ | +| --- | --- | +| `Ubuntu` | `vulkan-tools` `libvulkan-dev` `vulkan-validationlayers-dev` `spirv-tools` | +| `AlmaLinux` | `vulkan-tools` `vulkan-loader-devel` `vulkan-validation-layers` | +[GLFW]: https://github.com/glfw/glfw +[stb_image.h]: https://github.com/nothings/stb/blob/master/stb_image.h +[Vulkan SDK]: https://www.lunarg.com/vulkan-sdk/ diff --git a/Samples/Vulkan/README.md b/Samples/Vulkan/README.md index a07b60b7..063be9dd 100644 --- a/Samples/Vulkan/README.md +++ b/Samples/Vulkan/README.md @@ -8,8 +8,8 @@ This is a sample implementation of an application implemented with Vulkan. | Third Party | Version | | --- | --- | | [GLFW] | 3.4 | -| [stb_image.h] | 2.29 | -| [Vulkan SDK] | 1.3 | +| [stb_image.h] | 2.30 | +| [Vulkan SDK] | 1.3.296 | For other development environment and operation environment, refer to [README.md](/README.md) in the top directory. @@ -19,6 +19,7 @@ For other development environment and operation environment, refer to [README.md ``` . ├─ Demo +│ ├─ proj.linux.cmake # CMake project for Linux │  └─ proj.win.cmake        # CMake project for Windows └─ thirdParty               # Third party libraries and scripts ``` @@ -34,6 +35,22 @@ You can switch models from the menu button. The items contained in this directory are as follows. +### proj.linux.cmake + +CMake project for Linux. + +Running the script in the `script` directory will generate a CMake deliverable in the `build` directory. + +| Script name | Product | +| --- | --- | +| `make_gcc` | Executable application | + +When you run these scripts, you can choose to generate the full version or the minimum version of the sample. + +[GLFW] are used as additional libraries. +Please refer to the [thirdParty](#thirdParty) section and download in advance. +During the build process, you may be prompted to install additional packages such as `libpng` or X Windows System dependent libraries. If prompted, please install the required packages. + ### proj.win.cmake CMake project for Windows. @@ -58,16 +75,28 @@ Download GLFW by running the script in the 'script' directory. | Platform | Script name | | --- | --- | -| Windows | `setup_glew_glfw.bat` | +| Linux | `setup_glfw` | +| Windows | `set_glfw.bat` | You can change the version to download by changing `GLFW_VERSION` in the script. -[GLFW]: https://github.com/glfw/glfw -[stb_image.h]: https://github.com/nothings/stb/blob/master/stb_image.h +*1 On Linux, it may be necessary to install libraries on which GLFW depends. Please refer to the official page to install all libraries on which GLFW depends. +[GLFW.org Dependencies for X11 on Unix-like systems](https://www.glfw.org/docs/latest/compile_guide.html#compile_deps_x11) +See [NOTICE.md](/NOTICE.md) for details. ### Installing the Vulkan SDK -You need to install the Vulkan SDK in advance and set the environment variable VULKAN_SDK. -When building on an x86 platform, you must install the `SDK 32-bit Core Components` when installing the Vulkan SDK. +You need to install the Vulkan SDK in advance and set the environment variable VULKAN_SDK. +If you are building on an x86 platform, you must install the `SDK 32-bit Core Components` when installing the Vulkan SDK. +[Installation details on windows](https://vulkan-tutorial.com/Development_environment#page_Windows) +On Linux, the following packages must be installed +[Installation details on linux](https://vulkan-tutorial.com/Development_environment#page_Linux) +| Distribution | Package | +| --- | --- | +| `Ubuntu` | `vulkan-tools` `libvulkan-dev` `vulkan-validationlayers-dev` `spirv-tools` | +| `AlmaLinux` | `vulkan-tools` `vulkan-loader-devel` `vulkan-validation-layers` | + +[GLFW]: https://github.com/glfw/glfw +[stb_image.h]: https://github.com/nothings/stb/blob/master/stb_image.h [Vulkan SDK]: https://www.lunarg.com/vulkan-sdk/ diff --git a/Samples/Vulkan/Shaders/CMakeLists.txt b/Samples/Vulkan/Shaders/CMakeLists.txt index 3a8f7297..8a91e3ef 100644 --- a/Samples/Vulkan/Shaders/CMakeLists.txt +++ b/Samples/Vulkan/Shaders/CMakeLists.txt @@ -13,13 +13,23 @@ foreach(shader ${shader_files}) set(compiled_shaders_app ${compiled_shaders_app} ${output_file}) set(compiled_shaders_app ${compiled_shaders_app} PARENT_SCOPE) set_source_files_properties(${shader} PROPERTIES HEADER_FILE_ONLY TRUE) + if(WIN32) + add_custom_command( + OUTPUT ${output_file} + COMMAND ${CMAKE_COMMAND} -E make_directory ${output_dir} + COMMAND $ENV{VK_SDK_PATH}/Bin/glslc.exe ${full_path} -o ${output_file} + DEPENDS ${full_path} + ) + endif() + if(UNIX AND NOT APPLE) + add_custom_command( + OUTPUT ${output_file} + COMMAND ${CMAKE_COMMAND} -E make_directory ${output_dir} + COMMAND glslc ${full_path} -o ${output_file} + DEPENDS ${full_path} + ) + endif() - add_custom_command( - OUTPUT ${output_file} - COMMAND ${CMAKE_COMMAND} -E make_directory ${output_dir} - COMMAND $ENV{VK_SDK_PATH}/Bin/glslc.exe ${full_path} -o ${output_file} - DEPENDS ${full_path} - ) endforeach() source_group("shaders" FILES ${shader_files}) diff --git a/Samples/Vulkan/Shaders/src/FragSprite.frag b/Samples/Vulkan/Shaders/src/FragSprite.frag index 026291f2..144ba7fa 100644 --- a/Samples/Vulkan/Shaders/src/FragSprite.frag +++ b/Samples/Vulkan/Shaders/src/FragSprite.frag @@ -1,3 +1,10 @@ +/** + * 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. + */ + #version 460 #extension GL_GOOGLE_include_directive : enable layout(binding = 0) uniform UBO diff --git a/Samples/Vulkan/Shaders/src/VertSprite.vert b/Samples/Vulkan/Shaders/src/VertSprite.vert index c0504d0e..bd620417 100644 --- a/Samples/Vulkan/Shaders/src/VertSprite.vert +++ b/Samples/Vulkan/Shaders/src/VertSprite.vert @@ -1,3 +1,10 @@ +/** + * 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. + */ + #version 460 #extension GL_GOOGLE_include_directive : enable diff --git a/Samples/Vulkan/Shaders/src/common.glsl b/Samples/Vulkan/Shaders/src/common.glsl index 48066062..7bfc1462 100644 --- a/Samples/Vulkan/Shaders/src/common.glsl +++ b/Samples/Vulkan/Shaders/src/common.glsl @@ -1,3 +1,10 @@ +/** + * 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. + */ + layout(binding = 0) uniform UBO { mat4 u_matrix;