-diff -pruN --exclude build ./demo_clean/src/CMakeLists.txt ./demo_dev/src/CMakeLists.txt
---- ./demo_clean/src/CMakeLists.txt 2025-02-14 07:18:07.000000000 +0000
-+++ ./demo_dev/src/CMakeLists.txt 2024-03-28 18:01:22.284448149 +0000
-@@ -1,51 +1,22 @@
--if (CSM_MINIMUM_DEMO)
-- target_sources(${APP_NAME}
-+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}/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}/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}/MouseActionManager.cpp
-- ${CMAKE_CURRENT_SOURCE_DIR}/MouseActionManager.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}/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}/main.cpp
-- ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.cpp
-- ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp
-- )
--endif ()
-+ ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp
-+ ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.hpp
-+ ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
-+)
-diff -pruN --exclude build ./demo_clean/src/CubismUserModelExtend.cpp ./demo_dev/src/CubismUserModelExtend.cpp
---- ./demo_clean/src/CubismUserModelExtend.cpp 2025-02-14 07:18:07.000000000 +0000
-+++ ./demo_dev/src/CubismUserModelExtend.cpp 2024-03-28 18:01:22.292448274 +0000
-@@ -119,15 +119,12 @@ void CubismUserModelExtend::SetupModel()
- buffer = CreateBuffer(path.GetRawString(), &size);
- ACubismMotion* motion = LoadExpression(buffer, size, name.GetRawString());
-
-- if (motion)
-+ if (_expressions[name])
- {
-- if (_expressions[name])
-- {
-- ACubismMotion::Delete(_expressions[name]);
-- _expressions[name] = nullptr;
-- }
-- _expressions[name] = motion;
-+ ACubismMotion::Delete(_expressions[name]);
-+ _expressions[name] = nullptr;
- }
-+ _expressions[name] = motion;
-
- DeleteBuffer(buffer, path.GetRawString());
- }
-@@ -211,17 +208,28 @@ void CubismUserModelExtend::PreloadMotio
- csmSizeInt size;
- buffer = CreateBuffer(path.GetRawString(), &size);
- // モーションデータの読み込み
-- CubismMotion* tmpMotion = static_cast<CubismMotion*>(LoadMotion(buffer, size, name.GetRawString(), NULL, NULL, _modelJson, group, i));
-+ CubismMotion* tmpMotion = static_cast<CubismMotion*>(LoadMotion(buffer, size, name.GetRawString()));
-
-- if (tmpMotion)
-+ // フェードインの時間を取得
-+ csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, i);
-+ if (fadeTime >= 0.0f)
- {
-- if (_motions[name])
-- {
-- // インスタンスを破棄
-- ACubismMotion::Delete(_motions[name]);
-- }
-- _motions[name] = tmpMotion;
-+ 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());
- }
-@@ -254,9 +262,10 @@ void CubismUserModelExtend::ReleaseModel
- * @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::CubismMotionQueueEntryHandle CubismUserModelExtend::StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler)
- {
- // モーション数が取得出来なかった、もしくは0の時
- if (!(_modelJson->GetMotionCount(group)))
-@@ -292,16 +301,30 @@ Csm::CubismMotionQueueEntryHandle Cubism
- csmSizeInt size;
- buffer = CreateBuffer(path.GetRawString(), &size);
- // 一番先頭のモーションを読み込む
-- motion = static_cast<CubismMotion*>(LoadMotion(buffer, size, NULL, NULL, NULL, _modelJson, group, no));
-+ motion = static_cast<CubismMotion*>(LoadMotion(buffer, size, NULL, onFinishedMotionHandler));
-+
-+ csmFloat32 fadeTime = _modelJson->GetMotionFadeInTimeValue(group, no);
-+ if (fadeTime >= 0.0f)
-+ {
-+ motion->SetFadeInTime(fadeTime);
-+ }
-
-- if (motion)
-+ fadeTime = _modelJson->GetMotionFadeOutTimeValue(group, no);
-+ if (fadeTime >= 0.0f)
- {
-- // 終了時にメモリから削除
-- autoDelete = true;
-+ motion->SetFadeOutTime(fadeTime);
- }
-
-+ // 終了時にメモリから削除
-+ autoDelete = true;
-+
- DeleteBuffer(buffer, path.GetRawString());
- }
-+ else
-+ {
-+ // モーションの再生終了コールバックを登録
-+ motion->SetFinishedMotionHandler(onFinishedMotionHandler);
-+ }
-
- // 優先度を設定してモーションを始める
- return _motionManager->StartMotionPriority(motion, autoDelete, priority);
-diff -pruN --exclude build ./demo_clean/src/CubismUserModelExtend.hpp ./demo_dev/src/CubismUserModelExtend.hpp
---- ./demo_clean/src/CubismUserModelExtend.hpp 2025-02-14 07:18:07.000000000 +0000
-+++ ./demo_dev/src/CubismUserModelExtend.hpp 2024-03-28 18:01:22.292448274 +0000
-@@ -59,9 +59,10 @@ private:
- * @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::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL);
-
- /**
- * @brief 解放
-diff -pruN --exclude build ./demo_clean/src/LAppDefine.cpp ./demo_dev/src/LAppDefine.cpp
---- ./demo_clean/src/LAppDefine.cpp 2025-02-14 07:18:07.000000000 +0000
-+++ ./demo_dev/src/LAppDefine.cpp 2024-03-28 18:01:22.292448274 +0000
-@@ -37,14 +37,19 @@ namespace LAppDefine {
- // 終了ボタン
- const csmChar* PowerImageName = "close.png";
-
-- // シェーダー相対パス
-- const csmChar* ShaderPath = "SampleShaders/";
-- // 頂点シェーダー
-- const csmChar* VertShaderName = "VertSprite.vert";
-- // フラグメントシェーダー
-- const csmChar* FragShaderName = "FragSprite.frag";
--
- // モデル定義------------------------------------------
-+ // モデルを配置したディレクトリ名の配列
-+ // ディレクトリ名とmodel3.jsonの名前を一致させておくこと
-+ const csmChar* ModelDir[] = {
-+ "Haru",
-+ "Hiyori",
-+ "Mark",
-+ "Natori",
-+ "Rice",
-+ "Mao"
-+ };
-+ const csmInt32 ModelDirSize = sizeof(ModelDir) / sizeof(const csmChar*);
-+
- // 外部定義ファイル(json)と合わせる
- const csmChar* MotionGroupIdle = "Idle"; // アイドリング
- const csmChar* MotionGroupTapBody = "TapBody"; // 体をタップしたとき
-diff -pruN --exclude build ./demo_clean/src/LAppDefine.hpp ./demo_dev/src/LAppDefine.hpp
---- ./demo_clean/src/LAppDefine.hpp 2025-02-14 07:18:07.000000000 +0000
-+++ ./demo_dev/src/LAppDefine.hpp 2024-03-28 18:01:22.292448274 +0000
-@@ -36,11 +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; ///< モデルディレクトリ配列のサイズ
-+
- // 外部定義ファイル(json)と合わせる
- extern const csmChar* MotionGroupIdle; ///< アイドリング時に再生するモーションのリスト
- extern const csmChar* MotionGroupTapBody; ///< 体をタップした時に再生するモーションのリスト