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