Merge branch 'master' into rpi
[mouse-tracker-for-cubism.git] / example / demo.patch
1 diff -pruN --exclude build ./demo_clean/CMakeLists.txt ./demo_dev/CMakeLists.txt
2 --- ./demo_clean/CMakeLists.txt 2021-02-17 01:23:17.000000000 +0000
3 +++ ./demo_dev/CMakeLists.txt   2021-04-28 12:32:48.468744883 +0100
4 @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
5  # Set app name.
6  set(APP_NAME Demo)
7  # Set directory paths.
8 -set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
9 +set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../CubismSdkForNative-4-r.2)
10  set(CORE_PATH ${SDK_ROOT_PATH}/Core)
11  set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework)
12  set(THIRD_PARTY_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/thirdParty)
13 @@ -32,7 +32,7 @@ set(GLFW_INSTALL OFF CACHE BOOL "" FORCE
14  set(BUILD_UTILS OFF CACHE BOOL "" FORCE)
15  
16  # Specify version of compiler.
17 -set(CMAKE_CXX_STANDARD 14)
18 +set(CMAKE_CXX_STANDARD 17)
19  set(CMAKE_CXX_STANDARD_REQUIRED ON)
20  set(CMAKE_CXX_EXTENSIONS OFF)
21  
22 @@ -42,7 +42,7 @@ add_library(Live2DCubismCore STATIC IMPO
23  # Find library path.
24  set_target_properties(Live2DCubismCore
25    PROPERTIES
26 -    IMPORTED_LOCATION ${CORE_PATH}/lib/linux/x86_64/libLive2DCubismCore.a
27 +    IMPORTED_LOCATION ${CORE_PATH}/lib/experimental/rpi/libLive2DCubismCore.a
28      INTERFACE_INCLUDE_DIRECTORIES ${CORE_PATH}/include
29  )
30  
31 @@ -64,6 +64,11 @@ target_link_libraries(Framework Live2DCu
32  # Find opengl libraries.
33  find_package(OpenGL REQUIRED)
34  
35 +# Add MouseTrackerForCubism
36 +find_package(PkgConfig)
37 +pkg_check_modules(GTKMM gtkmm-3.0)
38 +add_subdirectory(../.. MouseTrackerForCubism_build)
39 +
40  # Make executable app.
41  add_executable(${APP_NAME})
42  # Add source files.
43 @@ -73,9 +78,20 @@ target_link_libraries(${APP_NAME}
44    Framework
45    glfw
46    ${OPENGL_LIBRARIES}
47 +  MouseTrackerForCubism
48 +  stdc++fs
49  )
50  # Specify include directories.
51 -target_include_directories(${APP_NAME} PRIVATE ${STB_PATH})
52 +target_include_directories(${APP_NAME} PRIVATE ${STB_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../../include ${GTKMM_INCLUDE_DIRS})
53 +
54 +# Copy GUI to build directory
55 +add_custom_command(
56 +  TARGET ${APP_NAME}
57 +  POST_BUILD
58 +  COMMAND
59 +    ${CMAKE_COMMAND} -E
60 +      copy ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gui.glade $<TARGET_FILE_DIR:${APP_NAME}>/gui.glade
61 +)
62  
63  # Copy resource directory to build directory.
64  add_custom_command(
65 diff -pruN --exclude build ./demo_clean/scripts/make_gcc ./demo_dev/scripts/make_gcc
66 --- ./demo_clean/scripts/make_gcc       2021-02-17 01:23:17.000000000 +0000
67 +++ ./demo_dev/scripts/make_gcc 2021-04-28 12:18:50.948333190 +0100
68 @@ -10,4 +10,4 @@ BUILD_PATH=$SCRIPT_PATH/../build/make_gc
69  cmake -S "$CMAKE_PATH" \
70    -B "$BUILD_PATH" \
71    -D CMAKE_BUILD_TYPE=Release
72 -cd "$BUILD_PATH" && make
73 +cd "$BUILD_PATH" && make -j4
74 diff -pruN --exclude build ./demo_clean/src/CMakeLists.txt ./demo_dev/src/CMakeLists.txt
75 --- ./demo_clean/src/CMakeLists.txt     2021-02-17 01:23:17.000000000 +0000
76 +++ ./demo_dev/src/CMakeLists.txt       2021-04-28 12:21:56.795134807 +0100
77 @@ -6,8 +6,6 @@ target_sources(${APP_NAME}
78      ${CMAKE_CURRENT_SOURCE_DIR}/LAppDefine.hpp
79      ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.cpp
80      ${CMAKE_CURRENT_SOURCE_DIR}/LAppDelegate.hpp
81 -    ${CMAKE_CURRENT_SOURCE_DIR}/LAppWavFileHandler.cpp
82 -    ${CMAKE_CURRENT_SOURCE_DIR}/LAppWavFileHandler.hpp
83      ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.cpp
84      ${CMAKE_CURRENT_SOURCE_DIR}/LAppLive2DManager.hpp
85      ${CMAKE_CURRENT_SOURCE_DIR}/LAppModel.cpp
86 @@ -21,6 +19,4 @@ target_sources(${APP_NAME}
87      ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.cpp
88      ${CMAKE_CURRENT_SOURCE_DIR}/LAppView.hpp
89      ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
90 -    ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.cpp
91 -    ${CMAKE_CURRENT_SOURCE_DIR}/TouchManager.hpp
92  )
93 diff -pruN --exclude build ./demo_clean/src/LAppDefine.cpp ./demo_dev/src/LAppDefine.cpp
94 --- ./demo_clean/src/LAppDefine.cpp     2021-02-17 01:23:17.000000000 +0000
95 +++ ./demo_dev/src/LAppDefine.cpp       2021-04-28 12:18:50.948333190 +0100
96 @@ -64,11 +64,11 @@ namespace LAppDefine {
97      const csmInt32 PriorityForce = 3;
98  
99      // デバッグ用ログの表示オプション
100 -    const csmBool DebugLogEnable = true;
101 +    const csmBool DebugLogEnable = false;
102      const csmBool DebugTouchLogEnable = false;
103  
104      // Frameworkから出力するログのレベル設定
105 -    const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Verbose;
106 +    const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Warning;
107  
108      // デフォルトのレンダーターゲットサイズ
109      const csmInt32 RenderTargetWidth = 1900;
110 diff -pruN --exclude build ./demo_clean/src/LAppDelegate.cpp ./demo_dev/src/LAppDelegate.cpp
111 --- ./demo_clean/src/LAppDelegate.cpp   2021-02-17 01:23:17.000000000 +0000
112 +++ ./demo_dev/src/LAppDelegate.cpp     2021-04-28 12:18:50.948333190 +0100
113 @@ -45,7 +45,8 @@ void LAppDelegate::ReleaseInstance()
114      s_instance = NULL;
115  }
116  
117 -bool LAppDelegate::Initialize()
118 +bool LAppDelegate::Initialize(int initWindowWidth, int initWindowHeight,
119 +                              const char *windowTitle)
120  {
121      if (DebugLogEnable)
122      {
123 @@ -63,7 +64,13 @@ bool LAppDelegate::Initialize()
124      }
125  
126      // Windowの生成_
127 -    _window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL);
128 +    _window = glfwCreateWindow(
129 +        initWindowWidth ? initWindowWidth : RenderTargetWidth,
130 +        initWindowHeight ? initWindowHeight : RenderTargetHeight,
131 +        windowTitle ? windowTitle : "SAMPLE",
132 +        NULL,
133 +        NULL);
134 +
135      if (_window == NULL)
136      {
137          if (DebugLogEnable)
138 @@ -95,10 +102,6 @@ bool LAppDelegate::Initialize()
139      glEnable(GL_BLEND);
140      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
141  
142 -    //コールバック関数の登録
143 -    glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack);
144 -    glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack);
145 -
146      // ウィンドウサイズ記憶
147      int width, height;
148      glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
149 @@ -111,8 +114,6 @@ bool LAppDelegate::Initialize()
150      // Cubism3の初期化
151      InitializeCubism();
152  
153 -    SetRootDirectory();
154 -
155      //load model
156      LAppLive2DManager::GetInstance();
157  
158 @@ -214,49 +215,6 @@ void LAppDelegate::InitializeCubism()
159      LAppPal::UpdateTime();
160  }
161  
162 -void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify)
163 -{
164 -    if (_view == NULL)
165 -    {
166 -        return;
167 -    }
168 -    if (GLFW_MOUSE_BUTTON_LEFT != button)
169 -    {
170 -        return;
171 -    }
172 -
173 -    if (GLFW_PRESS == action)
174 -    {
175 -        _captured = true;
176 -        _view->OnTouchesBegan(_mouseX, _mouseY);
177 -    }
178 -    else if (GLFW_RELEASE == action)
179 -    {
180 -        if (_captured)
181 -        {
182 -            _captured = false;
183 -            _view->OnTouchesEnded(_mouseX, _mouseY);
184 -        }
185 -    }
186 -}
187 -
188 -void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y)
189 -{
190 -    _mouseX = static_cast<float>(x);
191 -    _mouseY = static_cast<float>(y);
192 -
193 -    if (!_captured)
194 -    {
195 -        return;
196 -    }
197 -    if (_view == NULL)
198 -    {
199 -        return;
200 -    }
201 -
202 -    _view->OnTouchesMoved(_mouseX, _mouseY);
203 -}
204 -
205  GLuint LAppDelegate::CreateShader()
206  {
207      //バーテックスシェーダのコンパイル
208 @@ -299,29 +257,9 @@ GLuint LAppDelegate::CreateShader()
209      return programId;
210  }
211  
212 -void LAppDelegate::SetRootDirectory()
213 +void LAppDelegate::SetRootDirectory(std::string rootDir)
214  {
215 -    char path[1024];
216 -    ssize_t len = readlink("/proc/self/exe", path, 1024 - 1);
217 -
218 -    if (len != -1)
219 -    {
220 -        path[len] = '\0';
221 -    }
222 -
223 -    std::string pathString(path);
224 -
225 -    pathString = pathString.substr(0, pathString.rfind("Demo"));
226 -    Csm::csmVector<string> splitStrings = this->Split(pathString, '/');
227 -
228 -    this->_rootDirectory = "";
229 -
230 -    for(int i = 0; i < splitStrings.GetSize(); i++)
231 -    {
232 -        this->_rootDirectory = this->_rootDirectory + "/" +splitStrings[i];
233 -    }
234 -
235 -    this->_rootDirectory += "/";
236 +    this->_rootDirectory = rootDir + "/";
237  }
238  
239  Csm::csmVector<string> LAppDelegate::Split(const std::string& baseString, char delimiter)
240 diff -pruN --exclude build ./demo_clean/src/LAppDelegate.hpp ./demo_dev/src/LAppDelegate.hpp
241 --- ./demo_clean/src/LAppDelegate.hpp   2021-02-17 01:23:17.000000000 +0000
242 +++ ./demo_dev/src/LAppDelegate.hpp     2021-04-28 12:18:50.948333190 +0100
243 @@ -40,7 +40,8 @@ public:
244      /**
245      * @brief   APPに必要なものを初期化する。
246      */
247 -    bool Initialize();
248 +    bool Initialize(int initWindowWidth = 0, int initWindowHeight = 0,
249 +                    const char *windowTitle = "SAMPLE");
250  
251      /**
252      * @brief   解放する。
253 @@ -53,25 +54,6 @@ public:
254      void Run();
255  
256      /**
257 -    * @brief   OpenGL用 glfwSetMouseButtonCallback用関数。
258 -    *
259 -    * @param[in]       window            コールバックを呼んだWindow情報
260 -    * @param[in]       button            ボタン種類
261 -    * @param[in]       action            実行結果
262 -    * @param[in]       modify
263 -    */
264 -    void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify);
265 -
266 -    /**
267 -    * @brief   OpenGL用 glfwSetCursorPosCallback用関数。
268 -    *
269 -    * @param[in]       window            コールバックを呼んだWindow情報
270 -    * @param[in]       x                 x座標
271 -    * @param[in]       y                 x座標
272 -    */
273 -    void OnMouseCallBack(GLFWwindow* window, double x, double y);
274 -
275 -    /**
276      * @brief シェーダーを登録する。
277      */
278      GLuint CreateShader();
279 @@ -98,8 +80,10 @@ public:
280  
281      /**
282       * @brief   ルートディレクトリを設定する。
283 +     *
284 +     * @param[in] rootDir : The root directory to set to.
285       */
286 -    void SetRootDirectory();
287 +    void SetRootDirectory(std::string rootDir);
288  
289      /**
290       * @brief   ルートディレクトリを取得する。
291 @@ -146,24 +130,3 @@ private:
292      int _windowWidth;                            ///< Initialize関数で設定したウィンドウ幅
293      int _windowHeight;                           ///< Initialize関数で設定したウィンドウ高さ
294  };
295 -
296 -class EventHandler
297 -{
298 -public:
299 -    /**
300 -    * @brief   glfwSetMouseButtonCallback用コールバック関数。
301 -    */
302 -    static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify)
303 -    {
304 -        LAppDelegate::GetInstance()->OnMouseCallBack(window, button, action, modify);
305 -    }
306 -
307 -    /**
308 -    * @brief   glfwSetCursorPosCallback用コールバック関数。
309 -    */
310 -    static void OnMouseCallBack(GLFWwindow* window, double x, double y)
311 -    {
312 -         LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y);
313 -    }
314 -
315 -};
316 diff -pruN --exclude build ./demo_clean/src/LAppLive2DManager.cpp ./demo_dev/src/LAppLive2DManager.cpp
317 --- ./demo_clean/src/LAppLive2DManager.cpp      2021-02-17 01:23:17.000000000 +0000
318 +++ ./demo_dev/src/LAppLive2DManager.cpp        2021-04-28 12:24:45.405646016 +0100
319 @@ -52,11 +52,11 @@ void LAppLive2DManager::ReleaseInstance(
320  
321  LAppLive2DManager::LAppLive2DManager()
322      : _viewMatrix(NULL)
323 -    , _sceneIndex(0)
324 +    , _projScaleFactor(1.0f)
325 +    , _translateX(0.0f)
326 +    , _translateY(0.0f)
327  {
328      _viewMatrix = new CubismMatrix44();
329 -
330 -    ChangeScene(_sceneIndex);
331  }
332  
333  LAppLive2DManager::~LAppLive2DManager()
334 @@ -100,26 +100,6 @@ void LAppLive2DManager::OnTap(csmFloat32
335      {
336          LAppPal::PrintLog("[APP]tap point: {x:%.2f y:%.2f}", x, y);
337      }
338 -
339 -    for (csmUint32 i = 0; i < _models.GetSize(); i++)
340 -    {
341 -        if (_models[i]->HitTest(HitAreaNameHead, x, y))
342 -        {
343 -            if (DebugLogEnable)
344 -            {
345 -                LAppPal::PrintLog("[APP]hit area: [%s]", HitAreaNameHead);
346 -            }
347 -            _models[i]->SetRandomExpression();
348 -        }
349 -        else if (_models[i]->HitTest(HitAreaNameBody, x, y))
350 -        {
351 -            if (DebugLogEnable)
352 -            {
353 -                LAppPal::PrintLog("[APP]hit area: [%s]", HitAreaNameBody);
354 -            }
355 -            _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion);
356 -        }
357 -    }
358  }
359  
360  void LAppLive2DManager::OnUpdate() const
361 @@ -136,12 +116,15 @@ void LAppLive2DManager::OnUpdate() const
362          {
363              // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する
364              model->GetModelMatrix()->SetWidth(2.0f);
365 -            projection.Scale(1.0f, static_cast<float>(width) / static_cast<float>(height));
366 +            projection.Scale(_projScaleFactor,
367 +                             _projScaleFactor * static_cast<float>(width) / static_cast<float>(height));
368          }
369          else
370          {
371 -            projection.Scale(static_cast<float>(height) / static_cast<float>(width), 1.0f);
372 +            projection.Scale(_projScaleFactor * static_cast<float>(height) / static_cast<float>(width),
373 +                             _projScaleFactor);
374          }
375 +        projection.Translate(_translateX, _translateY);
376  
377          // 必要があればここで乗算
378          if (_viewMatrix != NULL)
379 @@ -158,30 +141,14 @@ void LAppLive2DManager::OnUpdate() const
380      }
381  }
382  
383 -void LAppLive2DManager::NextScene()
384 -{
385 -    csmInt32 no = (_sceneIndex + 1) % ModelDirSize;
386 -    ChangeScene(no);
387 -}
388 -
389 -void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
390 +void LAppLive2DManager::SetModel(std::string modelName, bool useOldParamId)
391  {
392 -    _sceneIndex = index;
393 -    if (DebugLogEnable)
394 -    {
395 -        LAppPal::PrintLog("[APP]model index: %d", _sceneIndex);
396 -    }
397 -
398 -    // ModelDir[]に保持したディレクトリ名から
399 -    // model3.jsonのパスを決定する.
400 -    // ディレクトリ名とmodel3.jsonの名前を一致させておくこと.
401 -    std::string model = ModelDir[index];
402 -    std::string modelPath = LAppDelegate::GetInstance()->GetRootDirectory() + ResourcesPath + model + "/";
403 -    std::string modelJsonName = ModelDir[index];
404 +    std::string modelPath = LAppDelegate::GetInstance()->GetRootDirectory() + ResourcesPath + modelName + "/";
405 +    std::string modelJsonName = modelName;
406      modelJsonName += ".model3.json";
407  
408      ReleaseAllModel();
409 -    _models.PushBack(new LAppModel());
410 +    _models.PushBack(new LAppModel(useOldParamId));
411      _models[0]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
412  
413      /*
414 @@ -203,7 +170,7 @@ void LAppLive2DManager::ChangeScene(Csm:
415  
416  #if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET)
417          // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす
418 -        _models.PushBack(new LAppModel());
419 +        _models.PushBack(new LAppModel(useOldParamId));
420          _models[1]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
421          _models[1]->GetModelMatrix()->TranslateX(0.2f);
422  #endif
423 @@ -232,3 +199,20 @@ void LAppLive2DManager::SetViewMatrix(Cu
424          _viewMatrix->GetArray()[i] = m->GetArray()[i];
425      }
426  }
427 +
428 +void LAppLive2DManager::SetTracker(MouseCursorTracker *tracker)
429 +{
430 +    for (auto it = _models.Begin(); it != _models.End(); ++it)
431 +    {
432 +        (*it)->SetTracker(tracker);
433 +    }
434 +}
435 +
436 +void LAppLive2DManager::SetProjectionScaleTranslate(float scaleFactor,
437 +                                                    float translateX,
438 +                                                    float translateY)
439 +{
440 +    _projScaleFactor = scaleFactor;
441 +    _translateX = translateX;
442 +    _translateY = translateY;
443 +}
444 diff -pruN --exclude build ./demo_clean/src/LAppLive2DManager.hpp ./demo_dev/src/LAppLive2DManager.hpp
445 --- ./demo_clean/src/LAppLive2DManager.hpp      2021-02-17 01:23:17.000000000 +0000
446 +++ ./demo_dev/src/LAppLive2DManager.hpp        2021-04-28 12:18:50.948333190 +0100
447 @@ -6,12 +6,15 @@
448   */
449  #pragma once
450  
451 +#include <string>
452  #include <CubismFramework.hpp>
453  #include <Math/CubismMatrix44.hpp>
454  #include <Type/csmVector.hpp>
455  
456  class LAppModel;
457  
458 +class MouseCursorTracker;
459 +
460  /**
461  * @brief サンプルアプリケーションにおいてCubismModelを管理するクラス<br>
462  *         モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。
463 @@ -72,16 +75,14 @@ public:
464      void OnUpdate() const;
465  
466      /**
467 -    * @brief   次のシーンに切り替える<br>
468 -    *           サンプルアプリケーションではモデルセットの切り替えを行う。
469 -    */
470 -    void NextScene();
471 -
472 -    /**
473 -    * @brief   シーンを切り替える<br>
474 -    *           サンプルアプリケーションではモデルセットの切り替えを行う。
475 -    */
476 -    void ChangeScene(Csm::csmInt32 index);
477 +     * @brief Set model data
478 +     *
479 +     * @param[in] modelName : Name of model, should be the same for both
480 +     *                        the directory and the model3.json file
481 +     * @param[in] useOldParamId : If true, translate new (Cubism 3+)
482 +     *                            parameter IDs to old (Cubism 2.1) ones
483 +     */
484 +    void SetModel(std::string modelName, bool useOldParamId);
485  
486      /**
487       * @brief   モデル個数を得る
488 @@ -94,6 +95,24 @@ public:
489       */
490      void SetViewMatrix(Live2D::Cubism::Framework::CubismMatrix44* m);
491  
492 +    /**
493 +     * @brief Set the pointer to the MouseCursorTracker instance
494 +     *
495 +     * @param[in] tracker : Pointer to MouseCursorTracker instance
496 +     */
497 +    void SetTracker(MouseCursorTracker *tracker);
498 +
499 +    /**
500 +     * @brief Set projection scale factor and translation parameters
501 +     *
502 +     * @param[in] scaleFactor : Scale factor applied in both X and Y directions
503 +     * @param[in] translateX : Translation in X direction
504 +     * @param[in] translateY : Translation in Y direction
505 +     */
506 +    void SetProjectionScaleTranslate(float scaleFactor,
507 +                                     float translateX,
508 +                                     float translateY);
509 +
510  private:
511      /**
512      * @brief  コンストラクタ
513 @@ -107,5 +126,8 @@ private:
514  
515      Csm::CubismMatrix44*        _viewMatrix; ///< モデル描画に用いるView行列
516      Csm::csmVector<LAppModel*>  _models; ///< モデルインスタンスのコンテナ
517 -    Csm::csmInt32               _sceneIndex; ///< 表示するシーンのインデックス値
518 +
519 +    float _projScaleFactor;
520 +    float _translateX;
521 +    float _translateY;
522  };
523 diff -pruN --exclude build ./demo_clean/src/LAppModel.cpp ./demo_dev/src/LAppModel.cpp
524 --- ./demo_clean/src/LAppModel.cpp      2021-02-17 01:23:17.000000000 +0000
525 +++ ./demo_dev/src/LAppModel.cpp        2021-04-28 12:26:56.699586813 +0100
526 @@ -21,6 +21,10 @@
527  #include "LAppTextureManager.hpp"
528  #include "LAppDelegate.hpp"
529  
530 +#include "mouse_cursor_tracker.h"
531 +
532 +#include <iostream>
533 +
534  using namespace Live2D::Cubism::Framework;
535  using namespace Live2D::Cubism::Framework::DefaultParameterId;
536  using namespace LAppDefine;
537 @@ -45,22 +49,24 @@ namespace {
538      }
539  }
540  
541 -LAppModel::LAppModel()
542 +LAppModel::LAppModel(bool useOldParamId)
543      : CubismUserModel()
544      , _modelSetting(NULL)
545      , _userTimeSeconds(0.0f)
546 +    , _tracker(nullptr)
547 +    , _useOldParamId(useOldParamId)
548  {
549      if (DebugLogEnable)
550      {
551          _debugMode = true;
552      }
553  
554 -    _idParamAngleX = CubismFramework::GetIdManager()->GetId(ParamAngleX);
555 -    _idParamAngleY = CubismFramework::GetIdManager()->GetId(ParamAngleY);
556 -    _idParamAngleZ = CubismFramework::GetIdManager()->GetId(ParamAngleZ);
557 -    _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(ParamBodyAngleX);
558 -    _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(ParamEyeBallX);
559 -    _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(ParamEyeBallY);
560 +    _idParamAngleX = CubismFramework::GetIdManager()->GetId(_(ParamAngleX));
561 +    _idParamAngleY = CubismFramework::GetIdManager()->GetId(_(ParamAngleY));
562 +    _idParamAngleZ = CubismFramework::GetIdManager()->GetId(_(ParamAngleZ));
563 +    _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(_(ParamBodyAngleX));
564 +    _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(_(ParamEyeBallX));
565 +    _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(_(ParamEyeBallY));
566  }
567  
568  LAppModel::~LAppModel()
569 @@ -190,7 +196,7 @@ void LAppModel::SetupModel(ICubismModelS
570          breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleY, 0.0f, 8.0f, 3.5345f, 0.5f));
571          breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleZ, 0.0f, 10.0f, 5.5345f, 0.5f));
572          breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamBodyAngleX, 0.0f, 4.0f, 15.5345f, 0.5f));
573 -        breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(ParamBreath), 0.5f, 0.5f, 3.2345f, 0.5f));
574 +        breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(_(ParamBreath)), 0.5f, 0.5f, 3.2345f, 0.5f));
575  
576          _breath->SetParameters(breathParameters);
577      }
578 @@ -335,83 +341,118 @@ void LAppModel::Update()
579      const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime();
580      _userTimeSeconds += deltaTimeSeconds;
581  
582 -    _dragManager->Update(deltaTimeSeconds);
583 -    _dragX = _dragManager->GetX();
584 -    _dragY = _dragManager->GetY();
585 -
586 -    // モーションによるパラメータ更新の有無
587 -    csmBool motionUpdated = false;
588 -
589 -    //-----------------------------------------------------------------
590 -    _model->LoadParameters(); // 前回セーブされた状態をロード
591 -    if (_motionManager->IsFinished())
592 -    {
593 -        // モーションの再生がない場合、待機モーションの中からランダムで再生する
594 -        StartRandomMotion(MotionGroupIdle, PriorityIdle);
595 -    }
596 -    else
597 +    if (_tracker)
598      {
599 -        motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
600 -    }
601 -    _model->SaveParameters(); // 状態を保存
602 -    //-----------------------------------------------------------------
603 +        auto idMan = CubismFramework::GetIdManager();
604 +        auto params = _tracker->getParams();
605  
606 -    // まばたき
607 -    if (!motionUpdated)
608 -    {
609 -        if (_eyeBlink != NULL)
610 +        _model->LoadParameters(); // 前回セーブされた状態をロード
611 +
612 +        int paramsMotionPriority = static_cast<int>(params.motionPriority);
613 +
614 +        if (paramsMotionPriority != PriorityNone)
615          {
616 -            // メインモーションの更新がないとき
617 -            _eyeBlink->UpdateParameters(_model, deltaTimeSeconds); // 目パチ
618 +            StartMotion(params.motionGroup.c_str(), params.motionNumber,
619 +                        paramsMotionPriority);
620 +        }
621 +        else if (params.randomIdleMotion && _motionManager->IsFinished())
622 +        {
623 +            // モーションの再生がない場合、待機モーションの中からランダムで再生する
624 +            StartRandomMotion(MotionGroupIdle, PriorityIdle);
625          }
626 -    }
627  
628 -    if (_expressionManager != NULL)
629 -    {
630 -        _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化)
631 -    }
632 +        // FIXME pose does not return to normal after motion
633 +        // if we don't have randomIdleMotion set
634 +        else
635 +        {
636 +            _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
637 +        }
638 +        _model->SaveParameters(); // 状態を保存
639  
640 -    //ドラッグによる変化
641 -    //ドラッグによる顔の向きの調整
642 -    _model->AddParameterValue(_idParamAngleX, _dragX * 30); // -30から30の値を加える
643 -    _model->AddParameterValue(_idParamAngleY, _dragY * 30);
644 -    _model->AddParameterValue(_idParamAngleZ, _dragX * _dragY * -30);
645 +        if (params.expression != "")
646 +        {
647 +            SetExpression(params.expression.c_str());
648 +        }
649 +        if (_expressionManager != NULL)
650 +        {
651 +            _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化)
652 +        }
653  
654 -    //ドラッグによる体の向きの調整
655 -    _model->AddParameterValue(_idParamBodyAngleX, _dragX * 10); // -10から10の値を加える
656 +        bool autoBlink = params.autoBlink && _eyeBlink;
657 +        auto eyeLOpenIt = params.live2d.find("ParamEyeLOpen");
658 +        auto eyeROpenIt = params.live2d.find("ParamEyeROpen");
659  
660 -    //ドラッグによる目の向きの調整
661 -    _model->AddParameterValue(_idParamEyeBallX, _dragX); // -1から1の値を加える
662 -    _model->AddParameterValue(_idParamEyeBallY, _dragY);
663 +        if (autoBlink)
664 +        {
665 +            // Handle blink first
666 +            _eyeBlink->UpdateParameters(_model, deltaTimeSeconds);
667 +        }
668  
669 -    // 呼吸など
670 -    if (_breath != NULL)
671 -    {
672 -        _breath->UpdateParameters(_model, deltaTimeSeconds);
673 -    }
674 +        if (eyeLOpenIt != params.live2d.end())
675 +        {
676 +            // If value specified, override blinking
677 +            _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")),
678 +                                      eyeLOpenIt->second);
679 +        }
680 +        else if (!autoBlink)
681 +        {
682 +            // If no value specified and no auto blink, set to 1
683 +            _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")), 1);
684  
685 -    // 物理演算の設定
686 -    if (_physics != NULL)
687 -    {
688 -        _physics->Evaluate(_model, deltaTimeSeconds);
689 -    }
690 +        }
691  
692 -    // リップシンクの設定
693 -    if (_lipSync)
694 -    {
695 -        // リアルタイムでリップシンクを行う場合、システムから音量を取得して0〜1の範囲で値を入力します。
696 -        csmFloat32 value = 0.0f;
697 +        if (eyeROpenIt != params.live2d.end())
698 +        {
699 +            _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")),
700 +                                      eyeROpenIt->second);
701 +        }
702 +        else if (!autoBlink)
703 +        {
704 +            _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")), 1);
705 +        }
706  
707 -        // 状態更新/RMS値取得
708 -        _wavFileHandler.Update(deltaTimeSeconds);
709 -        value = _wavFileHandler.GetRms();
710  
711 -        for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i)
712 +        if (params.useLipSync && _lipSync)
713          {
714 -            _model->AddParameterValue(_lipSyncIds[i], value, 0.8f);
715 +            csmFloat32 value = params.lipSyncParam; // 0 to 1
716 +
717 +            for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i)
718 +            {
719 +                _model->AddParameterValue(_lipSyncIds[i], value, 0.8f);
720 +            }
721 +        }
722 +        else
723 +        {
724 +            _model->SetParameterValue(idMan->GetId(_("ParamMouthOpenY")),
725 +                                      params.live2d["ParamMouthOpenY"]);
726 +        }
727 +
728 +        for (auto const &entry : params.live2d)
729 +        {
730 +            std::string key = entry.first;
731 +            double val = entry.second;
732 +
733 +            if (key != "ParamEyeLOpen" && key != "ParamEyeROpen" &&
734 +                key != "ParamMouthOpenY")
735 +            {
736 +                _model->SetParameterValue(idMan->GetId(_(key)), val);
737 +            }
738 +        }
739 +
740 +        if (params.autoBreath && _breath)
741 +        {
742 +            // Note: _model->LoadParameters and SaveParameters is needed
743 +            // before - see above.
744 +            _breath->UpdateParameters(_model, deltaTimeSeconds);
745          }
746      }
747  
748 +    // 物理演算の設定
749 +    if (_physics != NULL)
750 +    {
751 +        _physics->Evaluate(_model, deltaTimeSeconds);
752 +    }
753 +
754      // ポーズの設定
755      if (_pose != NULL)
756      {
757 @@ -480,7 +521,6 @@ CubismMotionQueueEntryHandle LAppModel::
758      {
759          csmString path = voice;
760          path = _modelHomeDir + path;
761 -        _wavFileHandler.Start(path);
762      }
763  
764      if (_debugMode)
765 @@ -632,3 +672,42 @@ Csm::Rendering::CubismOffscreenFrame_Ope
766  {
767      return _renderBuffer;
768  }
769 +
770 +void LAppModel::SetTracker(MouseCursorTracker *tracker)
771 +{
772 +    _tracker = tracker;
773 +}
774 +
775 +Csm::ICubismModelSetting* LAppModel::GetModelSetting(void) const
776 +{
777 +    return _modelSetting;
778 +}
779 +
780 +Csm::csmString LAppModel::_(std::string s)
781 +{
782 +    std::string ans;
783 +    if (_useOldParamId)
784 +    {
785 +        if (s == "ParamTere")
786 +        {
787 +            ans = "PARAM_CHEEK";
788 +        }
789 +        else
790 +        {
791 +            for (size_t i = 0; i < s.size(); i++)
792 +            {
793 +                if (std::isupper(s[i]) && i != 0)
794 +                {
795 +                    ans += '_';
796 +                }
797 +                ans += std::toupper(s[i]);
798 +            }
799 +        }
800 +    }
801 +    else
802 +    {
803 +        ans = s;
804 +    }
805 +    return csmString(ans.c_str());
806 +}
807 +
808 diff -pruN --exclude build ./demo_clean/src/LAppModel.hpp ./demo_dev/src/LAppModel.hpp
809 --- ./demo_clean/src/LAppModel.hpp      2021-02-17 01:23:17.000000000 +0000
810 +++ ./demo_dev/src/LAppModel.hpp        2021-04-28 12:27:55.836457680 +0100
811 @@ -13,7 +13,7 @@
812  #include <Type/csmRectF.hpp>
813  #include <Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.hpp>
814  
815 -#include "LAppWavFileHandler.hpp"
816 +#include "mouse_cursor_tracker.h"
817  
818  /**
819   * @brief ユーザーが実際に使用するモデルの実装クラス<br>
820 @@ -25,8 +25,11 @@ class LAppModel : public Csm::CubismUser
821  public:
822      /**
823       * @brief コンストラクタ
824 +     *
825 +     * @param[in] useOldParamId : If true, translate new (Cubism 3+)
826 +     *                            parameter IDs to old (Cubism 2.1)  ones
827       */
828 -    LAppModel();
829 +    LAppModel(bool useOldParamId);
830  
831      /**
832       * @brief デストラクタ
833 @@ -114,6 +117,15 @@ public:
834       */
835      Csm::Rendering::CubismOffscreenFrame_OpenGLES2& GetRenderBuffer();
836  
837 +    /**
838 +     * @brief Set the pointer to the MouseCursorTracker instance
839 +     *
840 +     * @param[in] tracker : Pointer to MouseCursorTracker instance
841 +     */
842 +    void SetTracker(MouseCursorTracker *tracker);
843 +
844 +    Csm::ICubismModelSetting* GetModelSetting(void) const;
845 +
846  protected:
847      /**
848       *  @brief  モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。
849 @@ -167,6 +179,17 @@ private:
850      */
851      void ReleaseExpressions();
852  
853 +    /**
854 +     * @brief Translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) ones
855 +     *
856 +     * @param[in] s : New parameter ID
857 +     *
858 +     * @return Old parameter ID
859 +     */
860 +    Csm::csmString _(std::string s);
861 +
862 +    bool _useOldParamId;
863 +
864      Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報
865      Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ
866      Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒]
867 @@ -183,9 +206,9 @@ private:
868      const Csm::CubismId* _idParamEyeBallX; ///< パラメータID: ParamEyeBallX
869      const Csm::CubismId* _idParamEyeBallY; ///< パラメータID: ParamEyeBallXY
870  
871 -    LAppWavFileHandler _wavFileHandler; ///< wavファイルハンドラ
872 -
873      Csm::Rendering::CubismOffscreenFrame_OpenGLES2 _renderBuffer;   ///< フレームバッファ以外の描画先
874 +
875 +    MouseCursorTracker *_tracker;
876  };
877  
878  
879 diff -pruN --exclude build ./demo_clean/src/LAppPal.cpp ./demo_dev/src/LAppPal.cpp
880 --- ./demo_clean/src/LAppPal.cpp        2021-02-17 01:23:17.000000000 +0000
881 +++ ./demo_dev/src/LAppPal.cpp  2021-04-28 12:18:50.952333251 +0100
882 @@ -6,6 +6,7 @@
883   */
884  
885  #include "LAppPal.hpp"
886 +#include <stdexcept>
887  #include <stdio.h>
888  #include <stdlib.h>
889  #include <stdarg.h>
890 @@ -36,7 +37,6 @@ csmByte* LAppPal::LoadFileAsBytes(const
891      if (stat(path, &statBuf) == 0)
892      {
893          size = statBuf.st_size;
894 -        PrintLog(path);
895      }
896  
897      std::fstream file;
898 @@ -45,10 +45,7 @@ csmByte* LAppPal::LoadFileAsBytes(const
899      file.open(path, std::ios::in | std::ios::binary);
900      if (!file.is_open())
901      {
902 -        if (DebugLogEnable)
903 -        {
904 -            PrintLog("file open error");
905 -        }
906 +        throw std::runtime_error("Failed to open file " + filePath);
907          return NULL;
908      }
909      file.read(buf, size);
910 diff -pruN --exclude build ./demo_clean/src/LAppTextureManager.cpp ./demo_dev/src/LAppTextureManager.cpp
911 --- ./demo_clean/src/LAppTextureManager.cpp     2021-02-17 01:23:17.000000000 +0000
912 +++ ./demo_dev/src/LAppTextureManager.cpp       2021-04-28 12:18:50.952333251 +0100
913 @@ -96,6 +96,46 @@ LAppTextureManager::TextureInfo* LAppTex
914  
915  }
916  
917 +LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromColor(
918 +    uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha
919 +)
920 +{
921 +    int width = 8, height = 8;
922 +
923 +    uint8_t pixels[height][width][4];
924 +    for (std::size_t h = 0; h < height; h++)
925 +    {
926 +        for (std::size_t w = 0; w < width; w++)
927 +        {
928 +            pixels[h][w][0] = red;
929 +            pixels[h][w][1] = green;
930 +            pixels[h][w][2] = blue;
931 +            pixels[h][w][3] = alpha;
932 +        }
933 +    }
934 +
935 +    GLuint textureId;
936 +    glGenTextures(1, &textureId);
937 +    glBindTexture(GL_TEXTURE_2D, textureId);
938 +    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
939 +
940 +    glGenerateMipmap(GL_TEXTURE_2D);
941 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
942 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
943 +    glBindTexture(GL_TEXTURE_2D, 0);
944 +
945 +
946 +    LAppTextureManager::TextureInfo* textureInfo = new LAppTextureManager::TextureInfo();
947 +    textureInfo->fileName = "";
948 +    textureInfo->width = width;
949 +    textureInfo->height = height;
950 +    textureInfo->id = textureId;
951 +
952 +    _textures.PushBack(textureInfo);
953 +
954 +    return textureInfo;
955 +}
956 +
957  void LAppTextureManager::ReleaseTextures()
958  {
959      for (Csm::csmUint32 i = 0; i < _textures.GetSize(); i++)
960 diff -pruN --exclude build ./demo_clean/src/LAppTextureManager.hpp ./demo_dev/src/LAppTextureManager.hpp
961 --- ./demo_clean/src/LAppTextureManager.hpp     2021-02-17 01:23:17.000000000 +0000
962 +++ ./demo_dev/src/LAppTextureManager.hpp       2021-04-28 12:18:50.952333251 +0100
963 @@ -72,6 +72,8 @@ public:
964      */
965      TextureInfo* CreateTextureFromPngFile(std::string fileName);
966  
967 +    TextureInfo *CreateTextureFromColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255);
968 +
969      /**
970      * @brief 画像の解放
971      *
972 diff -pruN --exclude build ./demo_clean/src/LAppView.cpp ./demo_dev/src/LAppView.cpp
973 --- ./demo_clean/src/LAppView.cpp       2021-02-17 01:23:17.000000000 +0000
974 +++ ./demo_dev/src/LAppView.cpp 2021-04-28 12:18:50.952333251 +0100
975 @@ -13,7 +13,6 @@
976  #include "LAppLive2DManager.hpp"
977  #include "LAppTextureManager.hpp"
978  #include "LAppDefine.hpp"
979 -#include "TouchManager.hpp"
980  #include "LAppSprite.hpp"
981  #include "LAppModel.hpp"
982  
983 @@ -26,8 +25,6 @@ using namespace LAppDefine;
984  LAppView::LAppView():
985      _programId(0),
986      _back(NULL),
987 -    _gear(NULL),
988 -    _power(NULL),
989      _renderSprite(NULL),
990      _renderTarget(SelectTarget_None)
991  {
992 @@ -35,8 +32,6 @@ LAppView::LAppView():
993      _clearColor[1] = 1.0f;
994      _clearColor[2] = 1.0f;
995      _clearColor[3] = 0.0f;
996 -    // タッチ関係のイベント管理
997 -    _touchManager = new TouchManager();
998  
999      // デバイス座標からスクリーン座標に変換するための
1000      _deviceToScreen = new CubismMatrix44();
1001 @@ -52,10 +47,7 @@ LAppView::~LAppView()
1002  
1003      delete _viewMatrix;
1004      delete _deviceToScreen;
1005 -    delete _touchManager;
1006      delete _back;
1007 -    delete _gear;
1008 -    delete _power;
1009  }
1010  
1011  void LAppView::Initialize()
1012 @@ -107,9 +99,6 @@ void LAppView::Initialize()
1013  void LAppView::Render()
1014  {
1015      _back->Render();
1016 -    _gear->Render();
1017 -    _power->Render();
1018 -
1019  
1020      LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance();
1021  
1022 @@ -151,35 +140,17 @@ void LAppView::InitializeSprite()
1023      glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
1024  
1025      LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager();
1026 -    const string resourcesPath = LAppDelegate::GetInstance()->GetRootDirectory() + ResourcesPath;
1027  
1028 -    string imageName = BackImageName;
1029 -    LAppTextureManager::TextureInfo* backgroundTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
1030 +
1031 +    LAppTextureManager::TextureInfo* backgroundTexture =
1032 +        textureManager->CreateTextureFromColor(0, 255, 0);
1033  
1034      float x = width * 0.5f;
1035      float y = height * 0.5f;
1036 -    float fWidth = static_cast<float>(backgroundTexture->width * 2.0f);
1037 -    float fHeight = static_cast<float>(height) * 0.95f;
1038 +    float fWidth = static_cast<float>(width);
1039 +    float fHeight = static_cast<float>(height);
1040      _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, _programId);
1041  
1042 -    imageName = GearImageName;
1043 -    LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
1044 -
1045 -    x = static_cast<float>(width - gearTexture->width * 0.5f);
1046 -    y = static_cast<float>(height - gearTexture->height * 0.5f);
1047 -    fWidth = static_cast<float>(gearTexture->width);
1048 -    fHeight = static_cast<float>(gearTexture->height);
1049 -    _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, _programId);
1050 -
1051 -    imageName = PowerImageName;
1052 -    LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
1053 -
1054 -    x = static_cast<float>(width - powerTexture->width * 0.5f);
1055 -    y = static_cast<float>(powerTexture->height * 0.5f);
1056 -    fWidth = static_cast<float>(powerTexture->width);
1057 -    fHeight = static_cast<float>(powerTexture->height);
1058 -    _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, _programId);
1059 -
1060      // 画面全体を覆うサイズ
1061      x = width * 0.5f;
1062      y = height * 0.5f;
1063 @@ -187,52 +158,6 @@ void LAppView::InitializeSprite()
1064  
1065  }
1066  
1067 -void LAppView::OnTouchesBegan(float px, float py) const
1068 -{
1069 -    _touchManager->TouchesBegan(px, py);
1070 -}
1071 -
1072 -void LAppView::OnTouchesMoved(float px, float py) const
1073 -{
1074 -    float viewX = this->TransformViewX(_touchManager->GetX());
1075 -    float viewY = this->TransformViewY(_touchManager->GetY());
1076 -
1077 -    _touchManager->TouchesMoved(px, py);
1078 -
1079 -    LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance();
1080 -    Live2DManager->OnDrag(viewX, viewY);
1081 -}
1082 -
1083 -void LAppView::OnTouchesEnded(float px, float py) const
1084 -{
1085 -    // タッチ終了
1086 -    LAppLive2DManager* live2DManager = LAppLive2DManager::GetInstance();
1087 -    live2DManager->OnDrag(0.0f, 0.0f);
1088 -    {
1089 -
1090 -        // シングルタップ
1091 -        float x = _deviceToScreen->TransformX(_touchManager->GetX()); // 論理座標変換した座標を取得。
1092 -        float y = _deviceToScreen->TransformY(_touchManager->GetY()); // 論理座標変換した座標を取得。
1093 -        if (DebugTouchLogEnable)
1094 -        {
1095 -            LAppPal::PrintLog("[APP]touchesEnded x:%.2f y:%.2f", x, y);
1096 -        }
1097 -        live2DManager->OnTap(x, y);
1098 -
1099 -        // 歯車にタップしたか
1100 -        if (_gear->IsHit(px, py))
1101 -        {
1102 -            live2DManager->NextScene();
1103 -        }
1104 -
1105 -        // 電源ボタンにタップしたか
1106 -        if (_power->IsHit(px, py))
1107 -        {
1108 -            LAppDelegate::GetInstance()->AppEnd();
1109 -        }
1110 -    }
1111 -}
1112 -
1113  float LAppView::TransformViewX(float deviceX) const
1114  {
1115      float screenX = _deviceToScreen->TransformX(deviceX); // 論理座標変換した座標を取得。
1116 @@ -374,32 +299,4 @@ void LAppView::ResizeSprite()
1117              _back->ResetRect(x, y, fWidth, fHeight);
1118          }
1119      }
1120 -
1121 -    if (_power)
1122 -    {
1123 -        GLuint id = _power->GetTextureId();
1124 -        LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
1125 -        if (texInfo)
1126 -        {
1127 -            x = static_cast<float>(width - texInfo->width * 0.5f);
1128 -            y = static_cast<float>(texInfo->height * 0.5f);
1129 -            fWidth = static_cast<float>(texInfo->width);
1130 -            fHeight = static_cast<float>(texInfo->height);
1131 -            _power->ResetRect(x, y, fWidth, fHeight);
1132 -        }
1133 -    }
1134 -
1135 -    if (_gear)
1136 -    {
1137 -        GLuint id = _gear->GetTextureId();
1138 -        LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
1139 -        if (texInfo)
1140 -        {
1141 -            x = static_cast<float>(width - texInfo->width * 0.5f);
1142 -            y = static_cast<float>(height - texInfo->height * 0.5f);
1143 -            fWidth = static_cast<float>(texInfo->width);
1144 -            fHeight = static_cast<float>(texInfo->height);
1145 -            _gear->ResetRect(x, y, fWidth, fHeight);
1146 -        }
1147 -    }
1148  }
1149 diff -pruN --exclude build ./demo_clean/src/LAppView.hpp ./demo_dev/src/LAppView.hpp
1150 --- ./demo_clean/src/LAppView.hpp       2021-02-17 01:23:17.000000000 +0000
1151 +++ ./demo_dev/src/LAppView.hpp 2021-04-28 12:18:50.952333251 +0100
1152 @@ -14,7 +14,6 @@
1153  #include "CubismFramework.hpp"
1154  #include <Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.hpp>
1155  
1156 -class TouchManager;
1157  class LAppSprite;
1158  class LAppModel;
1159  
1160 @@ -66,30 +65,6 @@ public:
1161      void ResizeSprite();
1162  
1163      /**
1164 -    * @brief タッチされたときに呼ばれる。
1165 -    *
1166 -    * @param[in]       pointX            スクリーンX座標
1167 -    * @param[in]       pointY            スクリーンY座標
1168 -    */
1169 -    void OnTouchesBegan(float pointX, float pointY) const;
1170 -
1171 -    /**
1172 -    * @brief タッチしているときにポインタが動いたら呼ばれる。
1173 -    *
1174 -    * @param[in]       pointX            スクリーンX座標
1175 -    * @param[in]       pointY            スクリーンY座標
1176 -    */
1177 -    void OnTouchesMoved(float pointX, float pointY) const;
1178 -
1179 -    /**
1180 -    * @brief タッチが終了したら呼ばれる。
1181 -    *
1182 -    * @param[in]       pointX            スクリーンX座標
1183 -    * @param[in]       pointY            スクリーンY座標
1184 -    */
1185 -    void OnTouchesEnded(float pointX, float pointY) const;
1186 -
1187 -    /**
1188      * @brief X座標をView座標に変換する。
1189      *
1190      * @param[in]       deviceX            デバイスX座標
1191 @@ -147,13 +122,10 @@ public:
1192      void SetRenderTargetClearColor(float r, float g, float b);
1193  
1194  private:
1195 -    TouchManager* _touchManager;                 ///< タッチマネージャー
1196      Csm::CubismMatrix44* _deviceToScreen;    ///< デバイスからスクリーンへの行列
1197      Csm::CubismViewMatrix* _viewMatrix;      ///< viewMatrix
1198      GLuint _programId;                       ///< シェーダID
1199      LAppSprite* _back;                       ///< 背景画像
1200 -    LAppSprite* _gear;                       ///< ギア画像
1201 -    LAppSprite* _power;                      ///< 電源画像
1202  
1203      // レンダリング先を別ターゲットにする方式の場合に使用
1204      LAppSprite* _renderSprite;                                  ///< モードによっては_renderBufferのテクスチャを描画
1205 diff -pruN --exclude build ./demo_clean/src/main.cpp ./demo_dev/src/main.cpp
1206 --- ./demo_clean/src/main.cpp   2021-02-17 01:23:17.000000000 +0000
1207 +++ ./demo_dev/src/main.cpp     2021-04-28 12:28:55.845339613 +0100
1208 @@ -5,18 +5,188 @@
1209   * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
1210   */
1211  
1212 +#include <thread>
1213 +#include <stdexcept>
1214 +#include <sstream>
1215 +#include <vector>
1216 +#include <utility>
1217 +#include <string>
1218 +
1219 +#ifdef __cpp_lib_filesystem
1220 +#include <filesystem>
1221 +namespace fs = std::filesystem;
1222 +#else
1223 +#include <experimental/filesystem>
1224 +namespace fs = std::experimental::filesystem;
1225 +#endif
1226 +
1227 +#include "ICubismModelSetting.hpp"
1228  #include "LAppDelegate.hpp"
1229 +#include "LAppLive2DManager.hpp"
1230 +#include "LAppModel.hpp"
1231 +#include "mouse_cursor_tracker.h"
1232 +
1233 +struct CmdArgs
1234 +{
1235 +    int windowWidth;
1236 +    int windowHeight;
1237 +    std::string windowTitle;
1238 +    std::string rootDir;
1239 +    float scaleFactor;
1240 +    float translateX;
1241 +    float translateY;
1242 +    std::string modelName;
1243 +    bool oldId; // If true, translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) IDs
1244 +    std::string cfgPath; // Path to config file for MouseCursorTracker
1245 +};
1246 +
1247 +CmdArgs parseArgv(int argc, char *argv[])
1248 +{
1249 +    // I think the command-line args are simple enough to not justify using a library...
1250 +    CmdArgs cmdArgs;
1251 +    // Set default values
1252 +    cmdArgs.windowWidth = 600;
1253 +    cmdArgs.windowHeight = 600;
1254 +    cmdArgs.windowTitle = "MouseTrackerForCubism example";
1255 +    cmdArgs.rootDir = fs::current_path();
1256 +    cmdArgs.scaleFactor = 4.5f;
1257 +    cmdArgs.translateX = 0.0f;
1258 +    cmdArgs.translateY = -3.1f;
1259 +    cmdArgs.modelName = "Haru";
1260 +    cmdArgs.oldId = false;
1261 +    cmdArgs.cfgPath = "";
1262 +
1263 +    int i = 1;
1264 +    while (i < argc)
1265 +    {
1266 +        std::string arg = argv[i];
1267 +        std::stringstream ss;
1268 +
1269 +        if (arg == "--window-width" || arg == "-W") // capital W for consistency with height
1270 +        {
1271 +            ss << argv[i + 1];
1272 +            if (!(ss >> cmdArgs.windowWidth))
1273 +            {
1274 +                throw std::runtime_error("Invalid argument for window width");
1275 +            }
1276 +        }
1277 +        else if (arg == "--window-height" || arg == "-H") // avoiding "-h", typically for help
1278 +        {
1279 +            ss << argv[i + 1];
1280 +            if (!(ss >> cmdArgs.windowHeight))
1281 +            {
1282 +                throw std::runtime_error("Invalid argument for window height");
1283 +            }
1284 +        }
1285 +        else if (arg == "--window-title" || arg == "-t")
1286 +        {
1287 +            cmdArgs.windowTitle = argv[i + 1];
1288 +        }
1289 +        else if (arg == "--root-dir" || arg == "-d")
1290 +        {
1291 +            cmdArgs.rootDir = argv[i + 1];
1292 +        }
1293 +        else if (arg == "--scale-factor" || arg == "-f")
1294 +        {
1295 +            ss << argv[i + 1];
1296 +            if (!(ss >> cmdArgs.scaleFactor))
1297 +            {
1298 +                throw std::runtime_error("Invalid argument for scale factor");
1299 +            }
1300 +        }
1301 +        else if (arg == "--translate-x" || arg == "-x")
1302 +        {
1303 +            ss << argv[i + 1];
1304 +            if (!(ss >> cmdArgs.translateX))
1305 +            {
1306 +                throw std::runtime_error("Invalid argument for translate X");
1307 +            }
1308 +        }
1309 +        else if (arg == "--translate-y" || arg == "-y")
1310 +        {
1311 +            ss << argv[i + 1];
1312 +            if (!(ss >> cmdArgs.translateY))
1313 +            {
1314 +                throw std::runtime_error("Invalid argument for translate Y");
1315 +            }
1316 +        }
1317 +        else if (arg == "--model" || arg == "-m")
1318 +        {
1319 +            cmdArgs.modelName = argv[i + 1];
1320 +        }
1321 +        else if (arg == "--config" || arg == "-c")
1322 +        {
1323 +            cmdArgs.cfgPath = argv[i + 1];
1324 +        }
1325 +        else if (arg == "--old-param-id" || arg == "-o")
1326 +        {
1327 +            cmdArgs.oldId = (argv[i + 1][0] == '1');
1328 +        }
1329 +        else
1330 +        {
1331 +            throw std::runtime_error("Unrecognized argument: " + arg);
1332 +        }
1333 +
1334 +        i += 2;
1335 +    }
1336 +
1337 +    return cmdArgs;
1338 +}
1339  
1340  int main(int argc, char* argv[])
1341  {
1342 -    // create the application instance
1343 -    if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE)
1344 +    auto cmdArgs = parseArgv(argc, argv);
1345 +
1346 +    LAppDelegate *delegate = LAppDelegate::GetInstance();
1347 +
1348 +    if (!delegate->Initialize(cmdArgs.windowWidth,
1349 +                              cmdArgs.windowHeight,
1350 +                              cmdArgs.windowTitle.c_str()))
1351      {
1352 -        return 1;
1353 +        throw std::runtime_error("Unable to initialize LAppDelegate");
1354      }
1355  
1356 -    LAppDelegate::GetInstance()->Run();
1357 +    delegate->SetRootDirectory(cmdArgs.rootDir);
1358 +
1359 +    LAppLive2DManager *manager = LAppLive2DManager::GetInstance();
1360 +    manager->SetModel(cmdArgs.modelName, cmdArgs.oldId);
1361 +
1362 +    manager->SetProjectionScaleTranslate(cmdArgs.scaleFactor,
1363 +                                         cmdArgs.translateX,
1364 +                                         cmdArgs.translateY);
1365 +
1366 +    LAppModel *model = manager->GetModel(0);
1367 +    if (!model) throw std::runtime_error("model is null");
1368 +
1369 +    Live2D::Cubism::Framework::ICubismModelSetting *modelSetting = model->GetModelSetting();
1370 +    if (!modelSetting) throw std::runtime_error("modelSetting is null");
1371 +
1372 +    std::vector<std::pair<std::string, int> > motions;
1373 +    int motionGroupCount = modelSetting->GetMotionGroupCount();
1374 +    for (int i = 0; i < motionGroupCount; i++)
1375 +    {
1376 +        const char *motionGroup = modelSetting->GetMotionGroupName(i);
1377 +        int motionCount = modelSetting->GetMotionCount(motionGroup);
1378 +        motions.push_back(std::make_pair(std::string(motionGroup), motionCount));
1379 +    }
1380 +
1381 +    std::vector<std::string> expressions;
1382 +    int expCount = modelSetting->GetExpressionCount();
1383 +    for (int i = 0; i < expCount; i++)
1384 +    {
1385 +        const char *expName = modelSetting->GetExpressionName(i);
1386 +        expressions.push_back(std::string(expName));
1387 +    }
1388 +
1389 +    MouseCursorTracker tracker(cmdArgs.cfgPath, motions, expressions);
1390 +
1391 +    std::thread trackerThread(&MouseCursorTracker::mainLoop, &tracker);
1392 +    manager->SetTracker(&tracker);
1393 +
1394 +    delegate->Run();
1395 +
1396 +    tracker.stop();
1397 +    trackerThread.join();
1398  
1399      return 0;
1400  }
1401 -