Upgrade to Cubism 5 Release R5.
[mouse-tracker-for-cubism.git] / example / demo.patch
CommitLineData
3dc87717
AIL
1diff --git a/CMakeLists.txt b/CMakeLists.txt
2index 45c4b1a..a850115 100644
3--- a/CMakeLists.txt
4+++ b/CMakeLists.txt
830d0ba4
AIL
5@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
6 # Set app name.
7 set(APP_NAME Demo)
8 # Set directory paths.
9-set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
3dc87717 10+set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../CubismSdkForNative-5-r.5)
830d0ba4
AIL
11 set(CORE_PATH ${SDK_ROOT_PATH}/Core)
12 set(FRAMEWORK_PATH ${SDK_ROOT_PATH}/Framework)
13 set(THIRD_PARTY_PATH ${SDK_ROOT_PATH}/Samples/OpenGL/thirdParty)
3dc87717 14@@ -35,7 +35,7 @@ set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
830d0ba4
AIL
15 set(BUILD_UTILS OFF CACHE BOOL "" FORCE)
16
17 # Specify version of compiler.
18-set(CMAKE_CXX_STANDARD 14)
19+set(CMAKE_CXX_STANDARD 17)
20 set(CMAKE_CXX_STANDARD_REQUIRED ON)
21 set(CMAKE_CXX_EXTENSIONS OFF)
22
3dc87717 23@@ -67,6 +67,11 @@ target_link_libraries(Framework Live2DCubismCore glew_s)
830d0ba4
AIL
24 # Find opengl libraries.
25 find_package(OpenGL REQUIRED)
26
126d8fa4 27+# Add MouseTrackerForCubism
33ad240c
AIL
28+find_package(PkgConfig)
29+pkg_check_modules(GTKMM gtkmm-3.0)
126d8fa4 30+add_subdirectory(../.. MouseTrackerForCubism_build)
830d0ba4
AIL
31+
32 # Make executable app.
33 add_executable(${APP_NAME})
ee3fcae5
AIL
34 # Add common source files.
35@@ -79,9 +84,20 @@ target_link_libraries(${APP_NAME}
830d0ba4
AIL
36 Framework
37 glfw
38 ${OPENGL_LIBRARIES}
126d8fa4 39+ MouseTrackerForCubism
830d0ba4
AIL
40+ stdc++fs
41 )
42 # Specify include directories.
43-target_include_directories(${APP_NAME} PRIVATE ${STB_PATH})
33ad240c
AIL
44+target_include_directories(${APP_NAME} PRIVATE ${STB_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../../include ${GTKMM_INCLUDE_DIRS})
45+
46+# Copy GUI to build directory
47+add_custom_command(
48+ TARGET ${APP_NAME}
49+ POST_BUILD
50+ COMMAND
51+ ${CMAKE_COMMAND} -E
52+ copy ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gui.glade $<TARGET_FILE_DIR:${APP_NAME}>/gui.glade
53+)
830d0ba4
AIL
54
55 # Copy resource directory to build directory.
56 add_custom_command(
3dc87717
AIL
57diff --git a/scripts/make_gcc b/scripts/make_gcc
58index 4441a91..71adb1a 100755
59--- a/scripts/make_gcc
60+++ b/scripts/make_gcc
1ed58df4 61@@ -5,42 +5,9 @@ set -ue
cd5de0f5
AIL
62 SCRIPT_PATH=$(cd $(dirname $0) && pwd)
63 CMAKE_PATH=$SCRIPT_PATH/..
64 BUILD_PATH=$SCRIPT_PATH/../build/make_gcc
65-MINIMUM_DEMO="OFF"
66-DATA=""
67-
68-if [ "$#" -ne 0 ]; then
69- DATA="$1"
70-fi
71-
72-while :
73-do
74-
75- if [ -z "$DATA" ]; then
76- echo "Choose which format you would like to create the demo."
77- echo "Full version : 1"
78- echo "Minimum version : 2"
79- read -p "Your Choice : " DATA
80- fi
81-
82- case "$DATA" in
83- "1" )
84- echo "Making Full Demo"
85- MINIMUM_DEMO="OFF"
86- break ;;
87- "2" )
88- echo "Making Minimum Demo"
89- MINIMUM_DEMO="ON"
90- break ;;
91- * )
92- echo "You need to enter a valid number."
93- DATA="" ;;
94- esac
95-done
96
97 # Run CMake.
830d0ba4
AIL
98 cmake -S "$CMAKE_PATH" \
99 -B "$BUILD_PATH" \
cd5de0f5 100- -D CMAKE_BUILD_TYPE=Release \
1ed58df4
AIL
101- -D CSM_MINIMUM_DEMO=$MINIMUM_DEMO \
102- -D GLFW_BUILD_WAYLAND=OFF
830d0ba4 103-cd "$BUILD_PATH" && make
cd5de0f5 104+ -D CMAKE_BUILD_TYPE=Release
830d0ba4 105+cd "$BUILD_PATH" && make -j4
3dc87717
AIL
106diff --git a/src/LAppDefine.cpp b/src/LAppDefine.cpp
107index d7226d2..b534fb7 100644
108--- a/src/LAppDefine.cpp
109+++ b/src/LAppDefine.cpp
ee3fcae5 110@@ -60,11 +60,11 @@ namespace LAppDefine {
eba2eb3a
AIL
111 const csmInt32 PriorityForce = 3;
112
113 // デバッグ用ログの表示オプション
114- const csmBool DebugLogEnable = true;
115+ const csmBool DebugLogEnable = false;
116 const csmBool DebugTouchLogEnable = false;
117
118 // Frameworkから出力するログのレベル設定
119- const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Verbose;
120+ const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Warning;
121
122 // デフォルトのレンダーターゲットサイズ
123 const csmInt32 RenderTargetWidth = 1900;
3dc87717
AIL
124diff --git a/src/LAppDelegate.cpp b/src/LAppDelegate.cpp
125index 242e3ca..2da992d 100644
126--- a/src/LAppDelegate.cpp
127+++ b/src/LAppDelegate.cpp
ee3fcae5 128@@ -46,7 +46,8 @@ void LAppDelegate::ReleaseInstance()
830d0ba4
AIL
129 s_instance = NULL;
130 }
131
132-bool LAppDelegate::Initialize()
133+bool LAppDelegate::Initialize(int initWindowWidth, int initWindowHeight,
134+ const char *windowTitle)
135 {
136 if (DebugLogEnable)
137 {
ee3fcae5 138@@ -64,7 +65,13 @@ bool LAppDelegate::Initialize()
830d0ba4
AIL
139 }
140
141 // Windowの生成_
142- _window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL);
143+ _window = glfwCreateWindow(
144+ initWindowWidth ? initWindowWidth : RenderTargetWidth,
145+ initWindowHeight ? initWindowHeight : RenderTargetHeight,
146+ windowTitle ? windowTitle : "SAMPLE",
147+ NULL,
148+ NULL);
149+
150 if (_window == NULL)
151 {
152 if (DebugLogEnable)
ee3fcae5 153@@ -96,10 +103,6 @@ bool LAppDelegate::Initialize()
830d0ba4 154 glEnable(GL_BLEND);
ee3fcae5 155 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
830d0ba4
AIL
156
157- //コールバック関数の登録
158- glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack);
159- glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack);
160-
161 // ウィンドウサイズ記憶
162 int width, height;
163 glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
3dc87717
AIL
164diff --git a/src/LAppDelegate.hpp b/src/LAppDelegate.hpp
165index 89ea99b..50279fd 100644
166--- a/src/LAppDelegate.hpp
167+++ b/src/LAppDelegate.hpp
830d0ba4
AIL
168@@ -40,7 +40,8 @@ public:
169 /**
170 * @brief APPに必要なものを初期化する。
171 */
172- bool Initialize();
173+ bool Initialize(int initWindowWidth = 0, int initWindowHeight = 0,
174+ const char *windowTitle = "SAMPLE");
175
176 /**
177 * @brief 解放する。
3dc87717
AIL
178diff --git a/src/LAppLive2DManager.cpp b/src/LAppLive2DManager.cpp
179index ac3d356..4a5fed6 100644
180--- a/src/LAppLive2DManager.cpp
181+++ b/src/LAppLive2DManager.cpp
1ed58df4
AIL
182@@ -6,13 +6,7 @@
183 */
184
185 #include "LAppLive2DManager.hpp"
186-#include <stdio.h>
187-#include <stdlib.h>
188-#include <string.h>
189-#include <dirent.h>
190-#include <unistd.h>
191-#include <libgen.h>
192-#include <limits.h>
193+#include <string>
194 #include <GL/glew.h>
195 #include <GLFW/glfw3.h>
196 #include <Rendering/CubismRenderer.hpp>
3dc87717 197@@ -69,12 +63,11 @@ void LAppLive2DManager::ReleaseInstance()
830d0ba4
AIL
198
199 LAppLive2DManager::LAppLive2DManager()
200 : _viewMatrix(NULL)
201- , _sceneIndex(0)
202+ , _projScaleFactor(1.0f)
203+ , _translateX(0.0f)
204+ , _translateY(0.0f)
205 {
76316970 206 _viewMatrix = new CubismMatrix44();
1ed58df4 207- SetUpModel();
76316970 208-
830d0ba4
AIL
209- ChangeScene(_sceneIndex);
210 }
211
212 LAppLive2DManager::~LAppLive2DManager()
3dc87717 213@@ -94,60 +87,6 @@ void LAppLive2DManager::ReleaseAllModel()
1ed58df4
AIL
214 _models.Clear();
215 }
216
217-void LAppLive2DManager::SetUpModel()
218-{
219- // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。
220- // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。
221- struct dirent *dirent;
222- csmString crawlPath(LAppDelegate::GetInstance()->GetExecuteAbsolutePath().c_str());
223- crawlPath += ResourcesPath;
224-
225- DIR *pDir = opendir(crawlPath.GetRawString());
226- if (pDir == NULL) return;
227-
228- _modelDir.Clear();
229-
230- while ((dirent = readdir(pDir)) != NULL)
231- {
232- if ((dirent->d_type & DT_DIR) && strcmp(dirent->d_name, "..") != 0)
233- {
234- // フォルダと同名の.model3.jsonがあるか探索する
235- struct dirent *dirent2;
236-
237- csmString modelName(dirent->d_name);
238-
239- csmString modelPath(crawlPath);
240- modelPath += modelName;
241- modelPath.Append(1, '/');
242-
243- csmString model3jsonName(modelName);
244- model3jsonName += ".model3.json";
245-
246- DIR *pDir2 = opendir(modelPath.GetRawString());
247- while ((dirent2 = readdir(pDir2)) != NULL)
248- {
249- if (strcmp(dirent2->d_name, model3jsonName.GetRawString()) == 0)
250- {
251- _modelDir.PushBack(csmString(dirent->d_name));
252- }
253- }
254- closedir(pDir2);
255- }
256- }
257- closedir(pDir);
258- qsort(_modelDir.GetPtr(), _modelDir.GetSize(), sizeof(csmString), CompareCsmString);
259-}
260-
261-csmVector<csmString> LAppLive2DManager::GetModelDir() const
262-{
263- return _modelDir;
264-}
265-
266-csmInt32 LAppLive2DManager::GetModelDirSize() const
267-{
268- return _modelDir.GetSize();
269-}
270-
271 LAppModel* LAppLive2DManager::GetModel(csmUint32 no) const
272 {
273 if (no < _models.GetSize())
3dc87717 274@@ -184,26 +123,6 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y)
830d0ba4 275 {
ee3fcae5
AIL
276 LAppPal::PrintLogLn("[APP]tap point: {x:%.2f y:%.2f}", x, y);
277 }
830d0ba4
AIL
278-
279- for (csmUint32 i = 0; i < _models.GetSize(); i++)
280- {
281- if (_models[i]->HitTest(HitAreaNameHead, x, y))
282- {
283- if (DebugLogEnable)
284- {
1ed58df4 285- LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameHead);
830d0ba4
AIL
286- }
287- _models[i]->SetRandomExpression();
288- }
289- else if (_models[i]->HitTest(HitAreaNameBody, x, y))
290- {
291- if (DebugLogEnable)
292- {
1ed58df4 293- LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody);
830d0ba4 294- }
a30911c5 295- _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion);
830d0ba4 296- }
ee3fcae5 297- }
830d0ba4
AIL
298 }
299
ee3fcae5 300 void LAppLive2DManager::OnUpdate() const
3dc87717 301@@ -230,12 +149,15 @@ void LAppLive2DManager::OnUpdate() const
76316970
AIL
302 {
303 // 横に長いモデルを縦長ウィンドウに表示する際モデルの横サイズでscaleを算出する
304 model->GetModelMatrix()->SetWidth(2.0f);
305- projection.Scale(1.0f, static_cast<float>(width) / static_cast<float>(height));
306+ projection.Scale(_projScaleFactor,
307+ _projScaleFactor * static_cast<float>(width) / static_cast<float>(height));
308 }
309 else
310 {
311- projection.Scale(static_cast<float>(height) / static_cast<float>(width), 1.0f);
312+ projection.Scale(_projScaleFactor * static_cast<float>(height) / static_cast<float>(width),
313+ _projScaleFactor);
314 }
315+ projection.Translate(_translateX, _translateY);
830d0ba4 316
76316970
AIL
317 // 必要があればここで乗算
318 if (_viewMatrix != NULL)
3dc87717
AIL
319@@ -257,37 +179,15 @@ void LAppLive2DManager::OnUpdate() const
320 Csm::Rendering::CubismOffscreenManager_OpenGLES2::GetInstance()->ReleaseStaleRenderTextures();
830d0ba4
AIL
321 }
322
323-void LAppLive2DManager::NextScene()
ee3fcae5
AIL
324+void LAppLive2DManager::SetModel(std::string modelName, bool useOldParamId)
325 {
1ed58df4 326- csmInt32 no = (_sceneIndex + 1) % GetModelDirSize();
830d0ba4
AIL
327- ChangeScene(no);
328-}
329-
330-void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
ee3fcae5 331-{
830d0ba4
AIL
332- _sceneIndex = index;
333- if (DebugLogEnable)
334- {
1ed58df4 335- LAppPal::PrintLogLn("[APP]model index: %d", _sceneIndex);
830d0ba4
AIL
336- }
337-
338- // ModelDir[]に保持したディレクトリ名から
339- // model3.jsonのパスを決定する.
340- // ディレクトリ名とmodel3.jsonの名前を一致させておくこと.
1ed58df4
AIL
341- const csmString& model = _modelDir[index];
342- LAppPal::PrintLogLn("[APP]_modelDir: %s", model.GetRawString());
343-
344- csmString modelPath(LAppDelegate::GetInstance()->GetExecuteAbsolutePath().c_str());
345- modelPath += ResourcesPath;
346- modelPath += model;
347- modelPath.Append(1, '/');
348-
349- csmString modelJsonName(model);
ee3fcae5 350+ std::string modelPath = LAppDelegate::GetInstance()->GetExecuteAbsolutePath() + ResourcesPath + modelName + "/";
830d0ba4
AIL
351+ std::string modelJsonName = modelName;
352 modelJsonName += ".model3.json";
353
354 ReleaseAllModel();
2c3e79c6 355- _models.PushBack(new LAppModel());
1ed58df4 356- _models[0]->LoadAssets(modelPath.GetRawString(), modelJsonName.GetRawString());
2c3e79c6 357+ _models.PushBack(new LAppModel(useOldParamId));
1ed58df4 358+ _models[0]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
2c3e79c6
AIL
359
360 /*
1ed58df4 361 * モデル半透明表示を行うサンプルを提示する。
3dc87717 362@@ -308,8 +208,8 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
2c3e79c6
AIL
363
364 #if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET)
365 // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす
366- _models.PushBack(new LAppModel());
1ed58df4 367- _models[1]->LoadAssets(modelPath.GetRawString(), modelJsonName.GetRawString());
2c3e79c6 368+ _models.PushBack(new LAppModel(useOldParamId));
1ed58df4 369+ _models[1]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
2c3e79c6
AIL
370 _models[1]->GetModelMatrix()->TranslateX(0.2f);
371 #endif
1ed58df4 372
3dc87717 373@@ -337,3 +237,20 @@ void LAppLive2DManager::SetViewMatrix(CubismMatrix44* m)
76316970
AIL
374 _viewMatrix->GetArray()[i] = m->GetArray()[i];
375 }
830d0ba4
AIL
376 }
377+
126d8fa4 378+void LAppLive2DManager::SetTracker(MouseCursorTracker *tracker)
830d0ba4
AIL
379+{
380+ for (auto it = _models.Begin(); it != _models.End(); ++it)
381+ {
126d8fa4 382+ (*it)->SetTracker(tracker);
830d0ba4
AIL
383+ }
384+}
385+
386+void LAppLive2DManager::SetProjectionScaleTranslate(float scaleFactor,
387+ float translateX,
388+ float translateY)
389+{
390+ _projScaleFactor = scaleFactor;
391+ _translateX = translateX;
392+ _translateY = translateY;
393+}
3dc87717
AIL
394diff --git a/src/LAppLive2DManager.hpp b/src/LAppLive2DManager.hpp
395index 2c9939c..5907a82 100644
396--- a/src/LAppLive2DManager.hpp
397+++ b/src/LAppLive2DManager.hpp
830d0ba4
AIL
398@@ -6,12 +6,15 @@
399 */
400 #pragma once
401
402+#include <string>
403 #include <CubismFramework.hpp>
404 #include <Math/CubismMatrix44.hpp>
405 #include <Type/csmVector.hpp>
406
407 class LAppModel;
408
126d8fa4 409+class MouseCursorTracker;
830d0ba4
AIL
410+
411 /**
412 * @brief サンプルアプリケーションにおいてCubismModelを管理するクラス<br>
413 * モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。
3dc87717
AIL
414@@ -35,24 +38,6 @@ public:
415 */
1ed58df4
AIL
416 static void ReleaseInstance();
417
3dc87717 418- /**
1ed58df4
AIL
419- * @brief Resources フォルダにあるモデルフォルダ名をセットする
420- *
421- */
422- void SetUpModel();
423-
424- /**
425- * @brief Resources フォルダにあるモデルフォルダ名を取得する
426- *
427- */
428- Csm::csmVector<Csm::csmString> GetModelDir() const;
429-
430- /**
431- * @brief Resources フォルダにあるモデルフォルダのサイズを取得する
432- *
433- */
434- Csm::csmInt32 GetModelDirSize() const;
435-
3dc87717 436 /**
1ed58df4
AIL
437 * @brief 現在のシーンで保持しているモデルを返す
438 *
3dc87717 439@@ -98,16 +83,14 @@ public:
830d0ba4
AIL
440 void OnUpdate() const;
441
442 /**
443- * @brief 次のシーンに切り替える<br>
444- * サンプルアプリケーションではモデルセットの切り替えを行う。
445- */
446- void NextScene();
447-
448- /**
449- * @brief シーンを切り替える<br>
450- * サンプルアプリケーションではモデルセットの切り替えを行う。
451- */
452- void ChangeScene(Csm::csmInt32 index);
453+ * @brief Set model data
454+ *
455+ * @param[in] modelName : Name of model, should be the same for both
456+ * the directory and the model3.json file
2c3e79c6
AIL
457+ * @param[in] useOldParamId : If true, translate new (Cubism 3+)
458+ * parameter IDs to old (Cubism 2.1) ones
830d0ba4 459+ */
2c3e79c6 460+ void SetModel(std::string modelName, bool useOldParamId);
830d0ba4
AIL
461
462 /**
463 * @brief モデル個数を得る
3dc87717 464@@ -120,6 +103,24 @@ public:
830d0ba4 465 */
76316970 466 void SetViewMatrix(Live2D::Cubism::Framework::CubismMatrix44* m);
830d0ba4
AIL
467
468+ /**
126d8fa4 469+ * @brief Set the pointer to the MouseCursorTracker instance
830d0ba4 470+ *
126d8fa4 471+ * @param[in] tracker : Pointer to MouseCursorTracker instance
830d0ba4 472+ */
126d8fa4 473+ void SetTracker(MouseCursorTracker *tracker);
830d0ba4
AIL
474+
475+ /**
476+ * @brief Set projection scale factor and translation parameters
477+ *
478+ * @param[in] scaleFactor : Scale factor applied in both X and Y directions
479+ * @param[in] translateX : Translation in X direction
480+ * @param[in] translateY : Translation in Y direction
481+ */
482+ void SetProjectionScaleTranslate(float scaleFactor,
483+ float translateX,
484+ float translateY);
485+
486 private:
487 /**
488 * @brief コンストラクタ
3dc87717 489@@ -133,7 +134,8 @@ private:
830d0ba4 490
ee3fcae5
AIL
491 Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列
492 Csm::csmVector<LAppModel*> _models; ///< モデルインスタンスのコンテナ
1ed58df4 493- Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値
1ed58df4
AIL
494
495- Csm::csmVector<Csm::csmString> _modelDir; ///< モデルディレクトリ名のコンテナ
830d0ba4
AIL
496+ float _projScaleFactor;
497+ float _translateX;
498+ float _translateY;
499 };
3dc87717
AIL
500diff --git a/src/LAppModel.cpp b/src/LAppModel.cpp
501index 7b8e0ea..14b9754 100644
502--- a/src/LAppModel.cpp
503+++ b/src/LAppModel.cpp
504@@ -28,27 +28,33 @@
505 #include "Motion/CubismPhysicsUpdater.hpp"
506 #include "Motion/CubismPoseUpdater.hpp"
830d0ba4 507
126d8fa4 508+#include "mouse_cursor_tracker.h"
830d0ba4 509+
eba2eb3a
AIL
510+#include <iostream>
511+
830d0ba4
AIL
512 using namespace Live2D::Cubism::Framework;
513 using namespace Live2D::Cubism::Framework::DefaultParameterId;
514 using namespace LAppDefine;
2c3e79c6
AIL
515
516-LAppModel::LAppModel()
517+LAppModel::LAppModel(bool useOldParamId)
ee3fcae5 518 : LAppModel_Common()
126d8fa4
AIL
519 , _modelSetting(NULL)
520 , _userTimeSeconds(0.0f)
3dc87717 521 , _motionUpdated(false)
126d8fa4 522+ , _tracker(nullptr)
2c3e79c6 523+ , _useOldParamId(useOldParamId)
126d8fa4
AIL
524 {
525 if (DebugLogEnable)
526 {
2c3e79c6
AIL
527 _debugMode = true;
528 }
529
530- _idParamAngleX = CubismFramework::GetIdManager()->GetId(ParamAngleX);
531- _idParamAngleY = CubismFramework::GetIdManager()->GetId(ParamAngleY);
532- _idParamAngleZ = CubismFramework::GetIdManager()->GetId(ParamAngleZ);
533- _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(ParamBodyAngleX);
534- _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(ParamEyeBallX);
535- _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(ParamEyeBallY);
536+ _idParamAngleX = CubismFramework::GetIdManager()->GetId(_(ParamAngleX));
537+ _idParamAngleY = CubismFramework::GetIdManager()->GetId(_(ParamAngleY));
538+ _idParamAngleZ = CubismFramework::GetIdManager()->GetId(_(ParamAngleZ));
539+ _idParamBodyAngleX = CubismFramework::GetIdManager()->GetId(_(ParamBodyAngleX));
540+ _idParamEyeBallX = CubismFramework::GetIdManager()->GetId(_(ParamEyeBallX));
541+ _idParamEyeBallY = CubismFramework::GetIdManager()->GetId(_(ParamEyeBallY));
542 }
543
544 LAppModel::~LAppModel()
3dc87717 545@@ -207,7 +213,7 @@ void LAppModel::SetupModel(ICubismModelSetting* setting)
2c3e79c6
AIL
546 breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleY, 0.0f, 8.0f, 3.5345f, 0.5f));
547 breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamAngleZ, 0.0f, 10.0f, 5.5345f, 0.5f));
548 breathParameters.PushBack(CubismBreath::BreathParameterData(_idParamBodyAngleX, 0.0f, 4.0f, 15.5345f, 0.5f));
549- breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(ParamBreath), 0.5f, 0.5f, 3.2345f, 0.5f));
550+ breathParameters.PushBack(CubismBreath::BreathParameterData(CubismFramework::GetIdManager()->GetId(_(ParamBreath)), 0.5f, 0.5f, 3.2345f, 0.5f));
551
552 _breath->SetParameters(breathParameters);
3dc87717
AIL
553
554@@ -241,9 +247,6 @@ void LAppModel::SetupModel(ICubismModelSetting* setting)
555 {
556 _lipSyncIds.PushBack(_modelSetting->GetLipSyncParameterId(i));
557 }
558-
559- CubismLipSyncUpdater* lipSync = CSM_NEW CubismLipSyncUpdater(_lipSyncIds, _wavFileHandler);
560- _updateScheduler.AddUpdatableList(lipSync);
2c3e79c6 561 }
3dc87717
AIL
562
563 // Look
564@@ -377,27 +380,122 @@ void LAppModel::Update()
830d0ba4
AIL
565 const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime();
566 _userTimeSeconds += deltaTimeSeconds;
567
830d0ba4 568- // モーションによるパラメータ更新の有無
3dc87717 569- _motionUpdated = false;
830d0ba4
AIL
570-
571- //-----------------------------------------------------------------
572- _model->LoadParameters(); // 前回セーブされた状態をロード
573- if (_motionManager->IsFinished())
1ed58df4
AIL
574+ if (_tracker)
575 {
3dc87717
AIL
576- // モーションの再生がない場合、待機モーションの中からランダムで再生する
577- StartRandomMotion(MotionGroupIdle, PriorityIdle);
2b1f0c7c 578+ auto idMan = CubismFramework::GetIdManager();
126d8fa4 579+ auto params = _tracker->getParams();
3dc87717 580+
2772c864 581+ _model->LoadParameters(); // 前回セーブされた状態をロード
3dc87717 582+
eba2eb3a
AIL
583+ int paramsMotionPriority = static_cast<int>(params.motionPriority);
584+
585+ if (paramsMotionPriority != PriorityNone)
3dc87717 586+ {
eba2eb3a
AIL
587+ StartMotion(params.motionGroup.c_str(), params.motionNumber,
588+ paramsMotionPriority);
3dc87717 589+ }
eba2eb3a
AIL
590+ else if (params.randomIdleMotion && _motionManager->IsFinished())
591+ {
2b1f0c7c
AIL
592+ // モーションの再生がない場合、待機モーションの中からランダムで再生する
593+ StartRandomMotion(MotionGroupIdle, PriorityIdle);
2772c864 594+ }
eba2eb3a
AIL
595+ // FIXME pose does not return to normal after motion
596+ // if we don't have randomIdleMotion set
597+ else
598+ {
599+ _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
600+ }
601+ _model->SaveParameters(); // 状態を保存
3dc87717 602+
eba2eb3a 603+ if (params.expression != "")
126d8fa4 604+ {
eba2eb3a 605+ SetExpression(params.expression.c_str());
126d8fa4 606+ }
eba2eb3a 607+ if (_expressionManager != NULL)
2b1f0c7c 608+ {
eba2eb3a 609+ _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化)
2b1f0c7c 610+ }
3dc87717 611+
eba2eb3a
AIL
612+ bool autoBlink = params.autoBlink && _eyeBlink;
613+ auto eyeLOpenIt = params.live2d.find("ParamEyeLOpen");
614+ auto eyeROpenIt = params.live2d.find("ParamEyeROpen");
3dc87717 615+
eba2eb3a 616+ if (autoBlink)
126d8fa4 617+ {
eba2eb3a
AIL
618+ // Handle blink first
619+ _eyeBlink->UpdateParameters(_model, deltaTimeSeconds);
620+ }
3dc87717 621+
eba2eb3a
AIL
622+ if (eyeLOpenIt != params.live2d.end())
623+ {
624+ // If value specified, override blinking
2c3e79c6 625+ _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")),
eba2eb3a
AIL
626+ eyeLOpenIt->second);
627+ }
628+ else if (!autoBlink)
629+ {
630+ // If no value specified and no auto blink, set to 1
2c3e79c6 631+ _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")), 1);
3dc87717 632+
eba2eb3a 633+ }
3dc87717 634+
eba2eb3a
AIL
635+ if (eyeROpenIt != params.live2d.end())
636+ {
2c3e79c6 637+ _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")),
eba2eb3a
AIL
638+ eyeROpenIt->second);
639+ }
640+ else if (!autoBlink)
641+ {
2c3e79c6 642+ _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")), 1);
eba2eb3a 643+ }
3dc87717
AIL
644+
645+
646+ if (params.useLipSync)
5c2628e8 647+ {
eba2eb3a 648+ csmFloat32 value = params.lipSyncParam; // 0 to 1
3dc87717 649+
126d8fa4
AIL
650+ for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i)
651+ {
652+ _model->AddParameterValue(_lipSyncIds[i], value, 0.8f);
653+ }
2b1f0c7c
AIL
654+ }
655+ else
ee3fcae5 656+ {
2c3e79c6 657+ _model->SetParameterValue(idMan->GetId(_("ParamMouthOpenY")),
eba2eb3a 658+ params.live2d["ParamMouthOpenY"]);
ee3fcae5 659+ }
a30911c5 660+
eba2eb3a 661+ for (auto const &entry : params.live2d)
a30911c5 662+ {
eba2eb3a
AIL
663+ std::string key = entry.first;
664+ double val = entry.second;
2772c864 665+
eba2eb3a
AIL
666+ if (key != "ParamEyeLOpen" && key != "ParamEyeROpen" &&
667+ key != "ParamMouthOpenY")
668+ {
2c3e79c6 669+ _model->SetParameterValue(idMan->GetId(_(key)), val);
eba2eb3a 670+ }
2b1f0c7c 671+ }
1ed58df4 672+
2b1f0c7c 673+ if (params.autoBreath && _breath)
3dc87717 674+ {
2b1f0c7c
AIL
675+ // Note: _model->LoadParameters and SaveParameters is needed
676+ // before - see above.
677+ _breath->UpdateParameters(_model, deltaTimeSeconds);
3dc87717 678+ }
ee3fcae5 679 }
3dc87717
AIL
680- else
681+
76316970
AIL
682+ // 物理演算の設定
683+ if (_physics != NULL)
3dc87717
AIL
684 {
685- _motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
76316970 686+ _physics->Evaluate(_model, deltaTimeSeconds);
3dc87717
AIL
687 }
688- _model->SaveParameters(); // 状態を保存
689- //-----------------------------------------------------------------
690
691- // 不透明度
692- _opacity = _model->GetModelOpacity();
693-
694- _updateScheduler.OnLateUpdate(_model, deltaTimeSeconds);
695+ // ポーズの設定
696+ if (_pose != NULL)
697+ {
698+ _pose->UpdateParameters(_model, deltaTimeSeconds);
ee3fcae5 699+ }
3dc87717
AIL
700
701 _model->Update();
702
703@@ -455,7 +553,6 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt
76316970
AIL
704 {
705 csmString path = voice;
706 path = _modelHomeDir + path;
707- _wavFileHandler.Start(path);
708 }
709
710 if (_debugMode)
3dc87717 711@@ -607,3 +704,42 @@ Csm::Rendering::CubismRenderTarget_OpenGLES2& LAppModel::GetRenderBuffer()
830d0ba4
AIL
712 {
713 return _renderBuffer;
714 }
715+
126d8fa4 716+void LAppModel::SetTracker(MouseCursorTracker *tracker)
830d0ba4 717+{
126d8fa4 718+ _tracker = tracker;
830d0ba4
AIL
719+}
720+
eba2eb3a
AIL
721+Csm::ICubismModelSetting* LAppModel::GetModelSetting(void) const
722+{
723+ return _modelSetting;
724+}
725+
2c3e79c6
AIL
726+Csm::csmString LAppModel::_(std::string s)
727+{
728+ std::string ans;
729+ if (_useOldParamId)
730+ {
731+ if (s == "ParamTere")
732+ {
733+ ans = "PARAM_CHEEK";
734+ }
735+ else
736+ {
737+ for (size_t i = 0; i < s.size(); i++)
738+ {
739+ if (std::isupper(s[i]) && i != 0)
740+ {
741+ ans += '_';
742+ }
743+ ans += std::toupper(s[i]);
744+ }
745+ }
746+ }
747+ else
748+ {
749+ ans = s;
750+ }
751+ return csmString(ans.c_str());
752+}
753+
3dc87717
AIL
754diff --git a/src/LAppModel.hpp b/src/LAppModel.hpp
755index 2637a54..1cddb56 100644
756--- a/src/LAppModel.hpp
757+++ b/src/LAppModel.hpp
ee3fcae5 758@@ -12,8 +12,8 @@
830d0ba4 759 #include <Type/csmRectF.hpp>
3dc87717 760 #include <Rendering/OpenGL/CubismRenderTarget_OpenGLES2.hpp>
830d0ba4 761
ee3fcae5
AIL
762-#include "LAppWavFileHandler_Common.hpp"
763 #include "LAppModel_Common.hpp"
126d8fa4 764+#include "mouse_cursor_tracker.h"
830d0ba4
AIL
765
766 /**
767 * @brief ユーザーが実際に使用するモデルの実装クラス<br>
3dc87717 768@@ -25,8 +25,11 @@ class LAppModel : public LAppModel_Common
2c3e79c6
AIL
769 public:
770 /**
771 * @brief コンストラクタ
772+ *
773+ * @param[in] useOldParamId : If true, translate new (Cubism 3+)
774+ * parameter IDs to old (Cubism 2.1) ones
775 */
776- LAppModel();
777+ LAppModel(bool useOldParamId);
778
779 /**
780 * @brief デストラクタ
ee3fcae5 781@@ -116,6 +119,15 @@ public:
830d0ba4 782 */
3dc87717 783 Csm::Rendering::CubismRenderTarget_OpenGLES2& GetRenderBuffer();
830d0ba4
AIL
784
785+ /**
126d8fa4 786+ * @brief Set the pointer to the MouseCursorTracker instance
830d0ba4 787+ *
126d8fa4 788+ * @param[in] tracker : Pointer to MouseCursorTracker instance
830d0ba4 789+ */
126d8fa4 790+ void SetTracker(MouseCursorTracker *tracker);
830d0ba4 791+
eba2eb3a
AIL
792+ Csm::ICubismModelSetting* GetModelSetting(void) const;
793+
830d0ba4
AIL
794 protected:
795 /**
796 * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。
ee3fcae5 797@@ -169,6 +181,17 @@ private:
2c3e79c6
AIL
798 */
799 void ReleaseExpressions();
800
801+ /**
802+ * @brief Translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) ones
803+ *
804+ * @param[in] s : New parameter ID
805+ *
806+ * @return Old parameter ID
807+ */
808+ Csm::csmString _(std::string s);
809+
810+ bool _useOldParamId;
811+
812 Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報
813 Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ
814 Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒]
3dc87717
AIL
815@@ -187,7 +210,7 @@ private:
816
817 Csm::csmBool _motionUpdated; ///< モーション更新フラグ
830d0ba4 818
ee3fcae5 819- LAppWavFileHandler_Common _wavFileHandler; ///< wavファイルハンドラ
3dc87717
AIL
820+ Csm::Rendering::CubismRenderTarget_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先 Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
821
822- Csm::Rendering::CubismRenderTarget_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
126d8fa4 823+ MouseCursorTracker *_tracker;
830d0ba4 824 };
3dc87717
AIL
825diff --git a/src/LAppTextureManager.cpp b/src/LAppTextureManager.cpp
826index 97cec74..191bdc0 100644
827--- a/src/LAppTextureManager.cpp
828+++ b/src/LAppTextureManager.cpp
829@@ -96,6 +96,46 @@ LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile(st
830d0ba4
AIL
830
831 }
832
833+LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromColor(
834+ uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha
835+)
836+{
837+ int width = 8, height = 8;
838+
839+ uint8_t pixels[height][width][4];
840+ for (std::size_t h = 0; h < height; h++)
841+ {
842+ for (std::size_t w = 0; w < width; w++)
843+ {
844+ pixels[h][w][0] = red;
845+ pixels[h][w][1] = green;
846+ pixels[h][w][2] = blue;
847+ pixels[h][w][3] = alpha;
848+ }
849+ }
850+
851+ GLuint textureId;
852+ glGenTextures(1, &textureId);
853+ glBindTexture(GL_TEXTURE_2D, textureId);
854+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
855+
856+ glGenerateMipmap(GL_TEXTURE_2D);
857+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
858+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
859+ glBindTexture(GL_TEXTURE_2D, 0);
860+
861+
862+ LAppTextureManager::TextureInfo* textureInfo = new LAppTextureManager::TextureInfo();
863+ textureInfo->fileName = "";
864+ textureInfo->width = width;
865+ textureInfo->height = height;
866+ textureInfo->id = textureId;
867+
ee3fcae5 868+ _texturesInfo.PushBack(textureInfo);
830d0ba4
AIL
869+
870+ return textureInfo;
871+}
872+
873 void LAppTextureManager::ReleaseTextures()
874 {
ee3fcae5 875 for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++)
3dc87717
AIL
876diff --git a/src/LAppTextureManager.hpp b/src/LAppTextureManager.hpp
877index a6713df..a42a112 100644
878--- a/src/LAppTextureManager.hpp
879+++ b/src/LAppTextureManager.hpp
ee3fcae5 880@@ -41,6 +41,8 @@ public:
830d0ba4
AIL
881 */
882 TextureInfo* CreateTextureFromPngFile(std::string fileName);
883
884+ TextureInfo *CreateTextureFromColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255);
885+
886 /**
887 * @brief 画像の解放
888 *
3dc87717
AIL
889diff --git a/src/LAppView.cpp b/src/LAppView.cpp
890index 4e42040..2ee08db 100644
891--- a/src/LAppView.cpp
892+++ b/src/LAppView.cpp
893@@ -84,9 +84,6 @@ void LAppView::Initialize(int width, int height)
830d0ba4
AIL
894 void LAppView::Render()
895 {
896 _back->Render();
897- _gear->Render();
898- _power->Render();
899-
900
901 LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance();
902
3dc87717 903@@ -128,36 +125,17 @@ void LAppView::InitializeSprite()
830d0ba4
AIL
904 glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
905
906 LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager();
1ed58df4 907- const string resourcesPath = LAppDelegate::GetInstance()->GetExecuteAbsolutePath() + ResourcesPath;
830d0ba4
AIL
908
909- string imageName = BackImageName;
910- LAppTextureManager::TextureInfo* backgroundTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
911+
912+ LAppTextureManager::TextureInfo* backgroundTexture =
913+ textureManager->CreateTextureFromColor(0, 255, 0);
914
915 float x = width * 0.5f;
916 float y = height * 0.5f;
830d0ba4 917- float fHeight = static_cast<float>(height) * 0.95f;
3dc87717
AIL
918- float ratio = fHeight / static_cast<float>(backgroundTexture->height);
919- float fWidth = static_cast<float>(backgroundTexture->width) * ratio;
ee3fcae5
AIL
920+ float fWidth = static_cast<float>(width);
921+ float fHeight = static_cast<float>(height);
922 _back = new LAppSprite(x, y, fWidth, fHeight, backgroundTexture->id, programId);
923
830d0ba4
AIL
924- imageName = GearImageName;
925- LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
926-
927- x = static_cast<float>(width - gearTexture->width * 0.5f);
928- y = static_cast<float>(height - gearTexture->height * 0.5f);
929- fWidth = static_cast<float>(gearTexture->width);
930- fHeight = static_cast<float>(gearTexture->height);
a30911c5 931- _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId);
830d0ba4
AIL
932-
933- imageName = PowerImageName;
934- LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
935-
936- x = static_cast<float>(width - powerTexture->width * 0.5f);
937- y = static_cast<float>(powerTexture->height * 0.5f);
938- fWidth = static_cast<float>(powerTexture->width);
939- fHeight = static_cast<float>(powerTexture->height);
a30911c5 940- _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId);
ee3fcae5 941-
830d0ba4
AIL
942 // 画面全体を覆うサイズ
943 x = width * 0.5f;
944 y = height * 0.5f;
3dc87717 945@@ -196,18 +174,6 @@ void LAppView::OnTouchesEnded(float px, float py) const
ee3fcae5
AIL
946 LAppPal::PrintLogLn("[APP]touchesEnded x:%.2f y:%.2f", x, y);
947 }
948 live2DManager->OnTap(x, y);
830d0ba4 949-
830d0ba4
AIL
950- // 歯車にタップしたか
951- if (_gear->IsHit(px, py))
952- {
953- live2DManager->NextScene();
954- }
955-
956- // 電源ボタンにタップしたか
957- if (_power->IsHit(px, py))
958- {
959- LAppDelegate::GetInstance()->AppEnd();
960- }
ee3fcae5 961 }
a30911c5
AIL
962 }
963
3dc87717 964@@ -334,41 +300,6 @@ void LAppView::ResizeSprite()
830d0ba4
AIL
965 _back->ResetRect(x, y, fWidth, fHeight);
966 }
967 }
968-
969- if (_power)
970- {
971- GLuint id = _power->GetTextureId();
972- LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
973- if (texInfo)
974- {
975- x = static_cast<float>(width - texInfo->width * 0.5f);
976- y = static_cast<float>(texInfo->height * 0.5f);
977- fWidth = static_cast<float>(texInfo->width);
978- fHeight = static_cast<float>(texInfo->height);
979- _power->ResetRect(x, y, fWidth, fHeight);
980- }
981- }
982-
983- if (_gear)
984- {
985- GLuint id = _gear->GetTextureId();
986- LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
987- if (texInfo)
988- {
989- x = static_cast<float>(width - texInfo->width * 0.5f);
990- y = static_cast<float>(height - texInfo->height * 0.5f);
991- fWidth = static_cast<float>(texInfo->width);
992- fHeight = static_cast<float>(texInfo->height);
993- _gear->ResetRect(x, y, fWidth, fHeight);
994- }
995- }
3dc87717
AIL
996-
997- if (_renderSprite)
998- {
999- x = width * 0.5f;
1000- y = height * 0.5f;
1001- _renderSprite->ResetRect(x, y, static_cast<float>(width), static_cast<float>(height));
1002- }
830d0ba4 1003 }
3dc87717
AIL
1004
1005 void LAppView::DestroySpriteRenderTarget()
1006diff --git a/src/main.cpp b/src/main.cpp
1007index b65c1f0..7da9d0a 100644
1008--- a/src/main.cpp
1009+++ b/src/main.cpp
ee3fcae5 1010@@ -5,18 +5,186 @@
830d0ba4
AIL
1011 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
1012 */
1013
1014+#include <thread>
1015+#include <stdexcept>
1016+#include <sstream>
eba2eb3a
AIL
1017+#include <vector>
1018+#include <utility>
1019+#include <string>
830d0ba4
AIL
1020+
1021+#ifdef __cpp_lib_filesystem
1022+#include <filesystem>
1023+namespace fs = std::filesystem;
1024+#else
1025+#include <experimental/filesystem>
1026+namespace fs = std::experimental::filesystem;
1027+#endif
1028+
eba2eb3a 1029+#include "ICubismModelSetting.hpp"
830d0ba4
AIL
1030 #include "LAppDelegate.hpp"
1031+#include "LAppLive2DManager.hpp"
eba2eb3a 1032+#include "LAppModel.hpp"
126d8fa4 1033+#include "mouse_cursor_tracker.h"
830d0ba4
AIL
1034+
1035+struct CmdArgs
1036+{
1037+ int windowWidth;
1038+ int windowHeight;
1039+ std::string windowTitle;
1040+ std::string rootDir;
1041+ float scaleFactor;
1042+ float translateX;
1043+ float translateY;
1044+ std::string modelName;
2c3e79c6 1045+ bool oldId; // If true, translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) IDs
126d8fa4 1046+ std::string cfgPath; // Path to config file for MouseCursorTracker
830d0ba4
AIL
1047+};
1048+
1049+CmdArgs parseArgv(int argc, char *argv[])
1050+{
1051+ // I think the command-line args are simple enough to not justify using a library...
1052+ CmdArgs cmdArgs;
1053+ // Set default values
1054+ cmdArgs.windowWidth = 600;
1055+ cmdArgs.windowHeight = 600;
126d8fa4 1056+ cmdArgs.windowTitle = "MouseTrackerForCubism example";
830d0ba4 1057+ cmdArgs.rootDir = fs::current_path();
76316970 1058+ cmdArgs.scaleFactor = 4.5f;
830d0ba4 1059+ cmdArgs.translateX = 0.0f;
76316970 1060+ cmdArgs.translateY = -3.1f;
830d0ba4 1061+ cmdArgs.modelName = "Haru";
2c3e79c6 1062+ cmdArgs.oldId = false;
830d0ba4
AIL
1063+ cmdArgs.cfgPath = "";
1064+
1065+ int i = 1;
1066+ while (i < argc)
1067+ {
1068+ std::string arg = argv[i];
1069+ std::stringstream ss;
1070+
1071+ if (arg == "--window-width" || arg == "-W") // capital W for consistency with height
1072+ {
1073+ ss << argv[i + 1];
1074+ if (!(ss >> cmdArgs.windowWidth))
1075+ {
1076+ throw std::runtime_error("Invalid argument for window width");
1077+ }
1078+ }
1079+ else if (arg == "--window-height" || arg == "-H") // avoiding "-h", typically for help
1080+ {
1081+ ss << argv[i + 1];
1082+ if (!(ss >> cmdArgs.windowHeight))
1083+ {
1084+ throw std::runtime_error("Invalid argument for window height");
1085+ }
1086+ }
1087+ else if (arg == "--window-title" || arg == "-t")
1088+ {
1089+ cmdArgs.windowTitle = argv[i + 1];
1090+ }
1091+ else if (arg == "--root-dir" || arg == "-d")
1092+ {
1093+ cmdArgs.rootDir = argv[i + 1];
1094+ }
1095+ else if (arg == "--scale-factor" || arg == "-f")
1096+ {
1097+ ss << argv[i + 1];
1098+ if (!(ss >> cmdArgs.scaleFactor))
1099+ {
1100+ throw std::runtime_error("Invalid argument for scale factor");
1101+ }
1102+ }
1103+ else if (arg == "--translate-x" || arg == "-x")
1104+ {
1105+ ss << argv[i + 1];
1106+ if (!(ss >> cmdArgs.translateX))
1107+ {
1108+ throw std::runtime_error("Invalid argument for translate X");
1109+ }
1110+ }
1111+ else if (arg == "--translate-y" || arg == "-y")
1112+ {
1113+ ss << argv[i + 1];
1114+ if (!(ss >> cmdArgs.translateY))
1115+ {
1116+ throw std::runtime_error("Invalid argument for translate Y");
1117+ }
1118+ }
1119+ else if (arg == "--model" || arg == "-m")
1120+ {
1121+ cmdArgs.modelName = argv[i + 1];
1122+ }
1123+ else if (arg == "--config" || arg == "-c")
1124+ {
1125+ cmdArgs.cfgPath = argv[i + 1];
1126+ }
2c3e79c6
AIL
1127+ else if (arg == "--old-param-id" || arg == "-o")
1128+ {
1129+ cmdArgs.oldId = (argv[i + 1][0] == '1');
1130+ }
830d0ba4
AIL
1131+ else
1132+ {
1133+ throw std::runtime_error("Unrecognized argument: " + arg);
1134+ }
1135+
1136+ i += 2;
1137+ }
1138+
1139+ return cmdArgs;
1140+}
1141
1142 int main(int argc, char* argv[])
1143 {
1144- // create the application instance
1145- if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE)
1146+ auto cmdArgs = parseArgv(argc, argv);
1147+
1148+ LAppDelegate *delegate = LAppDelegate::GetInstance();
1149+
1150+ if (!delegate->Initialize(cmdArgs.windowWidth,
1151+ cmdArgs.windowHeight,
1152+ cmdArgs.windowTitle.c_str()))
1153 {
1154- return 1;
1155+ throw std::runtime_error("Unable to initialize LAppDelegate");
1156 }
1157
1158- LAppDelegate::GetInstance()->Run();
830d0ba4 1159+ LAppLive2DManager *manager = LAppLive2DManager::GetInstance();
2c3e79c6 1160+ manager->SetModel(cmdArgs.modelName, cmdArgs.oldId);
830d0ba4
AIL
1161+
1162+ manager->SetProjectionScaleTranslate(cmdArgs.scaleFactor,
1163+ cmdArgs.translateX,
1164+ cmdArgs.translateY);
eba2eb3a
AIL
1165+
1166+ LAppModel *model = manager->GetModel(0);
1167+ if (!model) throw std::runtime_error("model is null");
1168+
1169+ Live2D::Cubism::Framework::ICubismModelSetting *modelSetting = model->GetModelSetting();
1170+ if (!modelSetting) throw std::runtime_error("modelSetting is null");
1171+
1172+ std::vector<std::pair<std::string, int> > motions;
1173+ int motionGroupCount = modelSetting->GetMotionGroupCount();
1174+ for (int i = 0; i < motionGroupCount; i++)
1175+ {
1176+ const char *motionGroup = modelSetting->GetMotionGroupName(i);
1177+ int motionCount = modelSetting->GetMotionCount(motionGroup);
1178+ motions.push_back(std::make_pair(std::string(motionGroup), motionCount));
1179+ }
1180+
1181+ std::vector<std::string> expressions;
1182+ int expCount = modelSetting->GetExpressionCount();
1183+ for (int i = 0; i < expCount; i++)
1184+ {
1185+ const char *expName = modelSetting->GetExpressionName(i);
1186+ expressions.push_back(std::string(expName));
1187+ }
1188+
1189+ MouseCursorTracker tracker(cmdArgs.cfgPath, motions, expressions);
1190+
1191+ std::thread trackerThread(&MouseCursorTracker::mainLoop, &tracker);
126d8fa4 1192+ manager->SetTracker(&tracker);
830d0ba4
AIL
1193+
1194+ delegate->Run();
1195+
126d8fa4
AIL
1196+ tracker.stop();
1197+ trackerThread.join();
830d0ba4
AIL
1198
1199 return 0;
1200 }
1201-