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