Upgrade to Cubism 5 Release R5.
[mouse-tracker-for-cubism.git] / example / demo.patch
... / ...
CommitLineData
1diff --git a/CMakeLists.txt b/CMakeLists.txt
2index 45c4b1a..a850115 100644
3--- a/CMakeLists.txt
4+++ b/CMakeLists.txt
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}/../../../..)
10+set(SDK_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../CubismSdkForNative-5-r.5)
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)
14@@ -35,7 +35,7 @@ set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
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
23@@ -67,6 +67,11 @@ target_link_libraries(Framework Live2DCubismCore glew_s)
24 # Find opengl libraries.
25 find_package(OpenGL REQUIRED)
26
27+# Add MouseTrackerForCubism
28+find_package(PkgConfig)
29+pkg_check_modules(GTKMM gtkmm-3.0)
30+add_subdirectory(../.. MouseTrackerForCubism_build)
31+
32 # Make executable app.
33 add_executable(${APP_NAME})
34 # Add common source files.
35@@ -79,9 +84,20 @@ target_link_libraries(${APP_NAME}
36 Framework
37 glfw
38 ${OPENGL_LIBRARIES}
39+ MouseTrackerForCubism
40+ stdc++fs
41 )
42 # Specify include directories.
43-target_include_directories(${APP_NAME} PRIVATE ${STB_PATH})
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+)
54
55 # Copy resource directory to build directory.
56 add_custom_command(
57diff --git a/scripts/make_gcc b/scripts/make_gcc
58index 4441a91..71adb1a 100755
59--- a/scripts/make_gcc
60+++ b/scripts/make_gcc
61@@ -5,42 +5,9 @@ set -ue
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.
98 cmake -S "$CMAKE_PATH" \
99 -B "$BUILD_PATH" \
100- -D CMAKE_BUILD_TYPE=Release \
101- -D CSM_MINIMUM_DEMO=$MINIMUM_DEMO \
102- -D GLFW_BUILD_WAYLAND=OFF
103-cd "$BUILD_PATH" && make
104+ -D CMAKE_BUILD_TYPE=Release
105+cd "$BUILD_PATH" && make -j4
106diff --git a/src/LAppDefine.cpp b/src/LAppDefine.cpp
107index d7226d2..b534fb7 100644
108--- a/src/LAppDefine.cpp
109+++ b/src/LAppDefine.cpp
110@@ -60,11 +60,11 @@ namespace LAppDefine {
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;
124diff --git a/src/LAppDelegate.cpp b/src/LAppDelegate.cpp
125index 242e3ca..2da992d 100644
126--- a/src/LAppDelegate.cpp
127+++ b/src/LAppDelegate.cpp
128@@ -46,7 +46,8 @@ void LAppDelegate::ReleaseInstance()
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 {
138@@ -64,7 +65,13 @@ bool LAppDelegate::Initialize()
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)
153@@ -96,10 +103,6 @@ bool LAppDelegate::Initialize()
154 glEnable(GL_BLEND);
155 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
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);
164diff --git a/src/LAppDelegate.hpp b/src/LAppDelegate.hpp
165index 89ea99b..50279fd 100644
166--- a/src/LAppDelegate.hpp
167+++ b/src/LAppDelegate.hpp
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 解放する。
178diff --git a/src/LAppLive2DManager.cpp b/src/LAppLive2DManager.cpp
179index ac3d356..4a5fed6 100644
180--- a/src/LAppLive2DManager.cpp
181+++ b/src/LAppLive2DManager.cpp
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>
197@@ -69,12 +63,11 @@ void LAppLive2DManager::ReleaseInstance()
198
199 LAppLive2DManager::LAppLive2DManager()
200 : _viewMatrix(NULL)
201- , _sceneIndex(0)
202+ , _projScaleFactor(1.0f)
203+ , _translateX(0.0f)
204+ , _translateY(0.0f)
205 {
206 _viewMatrix = new CubismMatrix44();
207- SetUpModel();
208-
209- ChangeScene(_sceneIndex);
210 }
211
212 LAppLive2DManager::~LAppLive2DManager()
213@@ -94,60 +87,6 @@ void LAppLive2DManager::ReleaseAllModel()
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())
274@@ -184,26 +123,6 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y)
275 {
276 LAppPal::PrintLogLn("[APP]tap point: {x:%.2f y:%.2f}", x, y);
277 }
278-
279- for (csmUint32 i = 0; i < _models.GetSize(); i++)
280- {
281- if (_models[i]->HitTest(HitAreaNameHead, x, y))
282- {
283- if (DebugLogEnable)
284- {
285- LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameHead);
286- }
287- _models[i]->SetRandomExpression();
288- }
289- else if (_models[i]->HitTest(HitAreaNameBody, x, y))
290- {
291- if (DebugLogEnable)
292- {
293- LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody);
294- }
295- _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion);
296- }
297- }
298 }
299
300 void LAppLive2DManager::OnUpdate() const
301@@ -230,12 +149,15 @@ void LAppLive2DManager::OnUpdate() const
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);
316
317 // 必要があればここで乗算
318 if (_viewMatrix != NULL)
319@@ -257,37 +179,15 @@ void LAppLive2DManager::OnUpdate() const
320 Csm::Rendering::CubismOffscreenManager_OpenGLES2::GetInstance()->ReleaseStaleRenderTextures();
321 }
322
323-void LAppLive2DManager::NextScene()
324+void LAppLive2DManager::SetModel(std::string modelName, bool useOldParamId)
325 {
326- csmInt32 no = (_sceneIndex + 1) % GetModelDirSize();
327- ChangeScene(no);
328-}
329-
330-void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
331-{
332- _sceneIndex = index;
333- if (DebugLogEnable)
334- {
335- LAppPal::PrintLogLn("[APP]model index: %d", _sceneIndex);
336- }
337-
338- // ModelDir[]に保持したディレクトリ名から
339- // model3.jsonのパスを決定する.
340- // ディレクトリ名とmodel3.jsonの名前を一致させておくこと.
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);
350+ std::string modelPath = LAppDelegate::GetInstance()->GetExecuteAbsolutePath() + ResourcesPath + modelName + "/";
351+ std::string modelJsonName = modelName;
352 modelJsonName += ".model3.json";
353
354 ReleaseAllModel();
355- _models.PushBack(new LAppModel());
356- _models[0]->LoadAssets(modelPath.GetRawString(), modelJsonName.GetRawString());
357+ _models.PushBack(new LAppModel(useOldParamId));
358+ _models[0]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
359
360 /*
361 * モデル半透明表示を行うサンプルを提示する。
362@@ -308,8 +208,8 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
363
364 #if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET)
365 // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす
366- _models.PushBack(new LAppModel());
367- _models[1]->LoadAssets(modelPath.GetRawString(), modelJsonName.GetRawString());
368+ _models.PushBack(new LAppModel(useOldParamId));
369+ _models[1]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
370 _models[1]->GetModelMatrix()->TranslateX(0.2f);
371 #endif
372
373@@ -337,3 +237,20 @@ void LAppLive2DManager::SetViewMatrix(CubismMatrix44* m)
374 _viewMatrix->GetArray()[i] = m->GetArray()[i];
375 }
376 }
377+
378+void LAppLive2DManager::SetTracker(MouseCursorTracker *tracker)
379+{
380+ for (auto it = _models.Begin(); it != _models.End(); ++it)
381+ {
382+ (*it)->SetTracker(tracker);
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+}
394diff --git a/src/LAppLive2DManager.hpp b/src/LAppLive2DManager.hpp
395index 2c9939c..5907a82 100644
396--- a/src/LAppLive2DManager.hpp
397+++ b/src/LAppLive2DManager.hpp
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
409+class MouseCursorTracker;
410+
411 /**
412 * @brief サンプルアプリケーションにおいてCubismModelを管理するクラス<br>
413 * モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。
414@@ -35,24 +38,6 @@ public:
415 */
416 static void ReleaseInstance();
417
418- /**
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-
436 /**
437 * @brief 現在のシーンで保持しているモデルを返す
438 *
439@@ -98,16 +83,14 @@ public:
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
457+ * @param[in] useOldParamId : If true, translate new (Cubism 3+)
458+ * parameter IDs to old (Cubism 2.1) ones
459+ */
460+ void SetModel(std::string modelName, bool useOldParamId);
461
462 /**
463 * @brief モデル個数を得る
464@@ -120,6 +103,24 @@ public:
465 */
466 void SetViewMatrix(Live2D::Cubism::Framework::CubismMatrix44* m);
467
468+ /**
469+ * @brief Set the pointer to the MouseCursorTracker instance
470+ *
471+ * @param[in] tracker : Pointer to MouseCursorTracker instance
472+ */
473+ void SetTracker(MouseCursorTracker *tracker);
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 コンストラクタ
489@@ -133,7 +134,8 @@ private:
490
491 Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列
492 Csm::csmVector<LAppModel*> _models; ///< モデルインスタンスのコンテナ
493- Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値
494
495- Csm::csmVector<Csm::csmString> _modelDir; ///< モデルディレクトリ名のコンテナ
496+ float _projScaleFactor;
497+ float _translateX;
498+ float _translateY;
499 };
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"
507
508+#include "mouse_cursor_tracker.h"
509+
510+#include <iostream>
511+
512 using namespace Live2D::Cubism::Framework;
513 using namespace Live2D::Cubism::Framework::DefaultParameterId;
514 using namespace LAppDefine;
515
516-LAppModel::LAppModel()
517+LAppModel::LAppModel(bool useOldParamId)
518 : LAppModel_Common()
519 , _modelSetting(NULL)
520 , _userTimeSeconds(0.0f)
521 , _motionUpdated(false)
522+ , _tracker(nullptr)
523+ , _useOldParamId(useOldParamId)
524 {
525 if (DebugLogEnable)
526 {
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()
545@@ -207,7 +213,7 @@ void LAppModel::SetupModel(ICubismModelSetting* setting)
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);
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);
561 }
562
563 // Look
564@@ -377,27 +380,122 @@ void LAppModel::Update()
565 const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime();
566 _userTimeSeconds += deltaTimeSeconds;
567
568- // モーションによるパラメータ更新の有無
569- _motionUpdated = false;
570-
571- //-----------------------------------------------------------------
572- _model->LoadParameters(); // 前回セーブされた状態をロード
573- if (_motionManager->IsFinished())
574+ if (_tracker)
575 {
576- // モーションの再生がない場合、待機モーションの中からランダムで再生する
577- StartRandomMotion(MotionGroupIdle, PriorityIdle);
578+ auto idMan = CubismFramework::GetIdManager();
579+ auto params = _tracker->getParams();
580+
581+ _model->LoadParameters(); // 前回セーブされた状態をロード
582+
583+ int paramsMotionPriority = static_cast<int>(params.motionPriority);
584+
585+ if (paramsMotionPriority != PriorityNone)
586+ {
587+ StartMotion(params.motionGroup.c_str(), params.motionNumber,
588+ paramsMotionPriority);
589+ }
590+ else if (params.randomIdleMotion && _motionManager->IsFinished())
591+ {
592+ // モーションの再生がない場合、待機モーションの中からランダムで再生する
593+ StartRandomMotion(MotionGroupIdle, PriorityIdle);
594+ }
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(); // 状態を保存
602+
603+ if (params.expression != "")
604+ {
605+ SetExpression(params.expression.c_str());
606+ }
607+ if (_expressionManager != NULL)
608+ {
609+ _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化)
610+ }
611+
612+ bool autoBlink = params.autoBlink && _eyeBlink;
613+ auto eyeLOpenIt = params.live2d.find("ParamEyeLOpen");
614+ auto eyeROpenIt = params.live2d.find("ParamEyeROpen");
615+
616+ if (autoBlink)
617+ {
618+ // Handle blink first
619+ _eyeBlink->UpdateParameters(_model, deltaTimeSeconds);
620+ }
621+
622+ if (eyeLOpenIt != params.live2d.end())
623+ {
624+ // If value specified, override blinking
625+ _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")),
626+ eyeLOpenIt->second);
627+ }
628+ else if (!autoBlink)
629+ {
630+ // If no value specified and no auto blink, set to 1
631+ _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")), 1);
632+
633+ }
634+
635+ if (eyeROpenIt != params.live2d.end())
636+ {
637+ _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")),
638+ eyeROpenIt->second);
639+ }
640+ else if (!autoBlink)
641+ {
642+ _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")), 1);
643+ }
644+
645+
646+ if (params.useLipSync)
647+ {
648+ csmFloat32 value = params.lipSyncParam; // 0 to 1
649+
650+ for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i)
651+ {
652+ _model->AddParameterValue(_lipSyncIds[i], value, 0.8f);
653+ }
654+ }
655+ else
656+ {
657+ _model->SetParameterValue(idMan->GetId(_("ParamMouthOpenY")),
658+ params.live2d["ParamMouthOpenY"]);
659+ }
660+
661+ for (auto const &entry : params.live2d)
662+ {
663+ std::string key = entry.first;
664+ double val = entry.second;
665+
666+ if (key != "ParamEyeLOpen" && key != "ParamEyeROpen" &&
667+ key != "ParamMouthOpenY")
668+ {
669+ _model->SetParameterValue(idMan->GetId(_(key)), val);
670+ }
671+ }
672+
673+ if (params.autoBreath && _breath)
674+ {
675+ // Note: _model->LoadParameters and SaveParameters is needed
676+ // before - see above.
677+ _breath->UpdateParameters(_model, deltaTimeSeconds);
678+ }
679 }
680- else
681+
682+ // 物理演算の設定
683+ if (_physics != NULL)
684 {
685- _motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
686+ _physics->Evaluate(_model, deltaTimeSeconds);
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);
699+ }
700
701 _model->Update();
702
703@@ -455,7 +553,6 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt
704 {
705 csmString path = voice;
706 path = _modelHomeDir + path;
707- _wavFileHandler.Start(path);
708 }
709
710 if (_debugMode)
711@@ -607,3 +704,42 @@ Csm::Rendering::CubismRenderTarget_OpenGLES2& LAppModel::GetRenderBuffer()
712 {
713 return _renderBuffer;
714 }
715+
716+void LAppModel::SetTracker(MouseCursorTracker *tracker)
717+{
718+ _tracker = tracker;
719+}
720+
721+Csm::ICubismModelSetting* LAppModel::GetModelSetting(void) const
722+{
723+ return _modelSetting;
724+}
725+
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+
754diff --git a/src/LAppModel.hpp b/src/LAppModel.hpp
755index 2637a54..1cddb56 100644
756--- a/src/LAppModel.hpp
757+++ b/src/LAppModel.hpp
758@@ -12,8 +12,8 @@
759 #include <Type/csmRectF.hpp>
760 #include <Rendering/OpenGL/CubismRenderTarget_OpenGLES2.hpp>
761
762-#include "LAppWavFileHandler_Common.hpp"
763 #include "LAppModel_Common.hpp"
764+#include "mouse_cursor_tracker.h"
765
766 /**
767 * @brief ユーザーが実際に使用するモデルの実装クラス<br>
768@@ -25,8 +25,11 @@ class LAppModel : public LAppModel_Common
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 デストラクタ
781@@ -116,6 +119,15 @@ public:
782 */
783 Csm::Rendering::CubismRenderTarget_OpenGLES2& GetRenderBuffer();
784
785+ /**
786+ * @brief Set the pointer to the MouseCursorTracker instance
787+ *
788+ * @param[in] tracker : Pointer to MouseCursorTracker instance
789+ */
790+ void SetTracker(MouseCursorTracker *tracker);
791+
792+ Csm::ICubismModelSetting* GetModelSetting(void) const;
793+
794 protected:
795 /**
796 * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。
797@@ -169,6 +181,17 @@ private:
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; ///< デルタ時間の積算値[秒]
815@@ -187,7 +210,7 @@ private:
816
817 Csm::csmBool _motionUpdated; ///< モーション更新フラグ
818
819- LAppWavFileHandler_Common _wavFileHandler; ///< wavファイルハンドラ
820+ Csm::Rendering::CubismRenderTarget_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先 Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
821
822- Csm::Rendering::CubismRenderTarget_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
823+ MouseCursorTracker *_tracker;
824 };
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
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+
868+ _texturesInfo.PushBack(textureInfo);
869+
870+ return textureInfo;
871+}
872+
873 void LAppTextureManager::ReleaseTextures()
874 {
875 for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++)
876diff --git a/src/LAppTextureManager.hpp b/src/LAppTextureManager.hpp
877index a6713df..a42a112 100644
878--- a/src/LAppTextureManager.hpp
879+++ b/src/LAppTextureManager.hpp
880@@ -41,6 +41,8 @@ public:
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 *
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)
894 void LAppView::Render()
895 {
896 _back->Render();
897- _gear->Render();
898- _power->Render();
899-
900
901 LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance();
902
903@@ -128,36 +125,17 @@ void LAppView::InitializeSprite()
904 glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
905
906 LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager();
907- const string resourcesPath = LAppDelegate::GetInstance()->GetExecuteAbsolutePath() + ResourcesPath;
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;
917- float fHeight = static_cast<float>(height) * 0.95f;
918- float ratio = fHeight / static_cast<float>(backgroundTexture->height);
919- float fWidth = static_cast<float>(backgroundTexture->width) * ratio;
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
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);
931- _gear = new LAppSprite(x, y, fWidth, fHeight, gearTexture->id, programId);
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);
940- _power = new LAppSprite(x, y, fWidth, fHeight, powerTexture->id, programId);
941-
942 // 画面全体を覆うサイズ
943 x = width * 0.5f;
944 y = height * 0.5f;
945@@ -196,18 +174,6 @@ void LAppView::OnTouchesEnded(float px, float py) const
946 LAppPal::PrintLogLn("[APP]touchesEnded x:%.2f y:%.2f", x, y);
947 }
948 live2DManager->OnTap(x, y);
949-
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- }
961 }
962 }
963
964@@ -334,41 +300,6 @@ void LAppView::ResizeSprite()
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- }
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- }
1003 }
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
1010@@ -5,18 +5,186 @@
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>
1017+#include <vector>
1018+#include <utility>
1019+#include <string>
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+
1029+#include "ICubismModelSetting.hpp"
1030 #include "LAppDelegate.hpp"
1031+#include "LAppLive2DManager.hpp"
1032+#include "LAppModel.hpp"
1033+#include "mouse_cursor_tracker.h"
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;
1045+ bool oldId; // If true, translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) IDs
1046+ std::string cfgPath; // Path to config file for MouseCursorTracker
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;
1056+ cmdArgs.windowTitle = "MouseTrackerForCubism example";
1057+ cmdArgs.rootDir = fs::current_path();
1058+ cmdArgs.scaleFactor = 4.5f;
1059+ cmdArgs.translateX = 0.0f;
1060+ cmdArgs.translateY = -3.1f;
1061+ cmdArgs.modelName = "Haru";
1062+ cmdArgs.oldId = false;
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+ }
1127+ else if (arg == "--old-param-id" || arg == "-o")
1128+ {
1129+ cmdArgs.oldId = (argv[i + 1][0] == '1');
1130+ }
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();
1159+ LAppLive2DManager *manager = LAppLive2DManager::GetInstance();
1160+ manager->SetModel(cmdArgs.modelName, cmdArgs.oldId);
1161+
1162+ manager->SetProjectionScaleTranslate(cmdArgs.scaleFactor,
1163+ cmdArgs.translateX,
1164+ cmdArgs.translateY);
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);
1192+ manager->SetTracker(&tracker);
1193+
1194+ delegate->Run();
1195+
1196+ tracker.stop();
1197+ trackerThread.join();
1198
1199 return 0;
1200 }
1201-