1 diff --git a/CMakeLists.txt b/CMakeLists.txt
2 index 45c4b1a..a850115 100644
5 @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
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)
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)
23 @@ -67,6 +67,11 @@ target_link_libraries(Framework Live2DCubismCore glew_s)
24 # Find opengl libraries.
25 find_package(OpenGL REQUIRED)
27 +# Add MouseTrackerForCubism
28 +find_package(PkgConfig)
29 +pkg_check_modules(GTKMM gtkmm-3.0)
30 +add_subdirectory(../.. MouseTrackerForCubism_build)
32 # Make executable app.
33 add_executable(${APP_NAME})
34 # Add common source files.
35 @@ -79,9 +84,20 @@ target_link_libraries(${APP_NAME}
39 + MouseTrackerForCubism
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})
46 +# Copy GUI to build directory
52 + copy ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gui.glade $<TARGET_FILE_DIR:${APP_NAME}>/gui.glade
55 # Copy resource directory to build directory.
57 diff --git a/scripts/make_gcc b/scripts/make_gcc
58 index 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
68 -if [ "$#" -ne 0 ]; then
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
84 - echo "Making Full Demo"
88 - echo "Making Minimum Demo"
92 - echo "You need to enter a valid number."
98 cmake -S "$CMAKE_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
106 diff --git a/src/LAppDefine.cpp b/src/LAppDefine.cpp
107 index 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;
114 - const csmBool DebugLogEnable = true;
115 + const csmBool DebugLogEnable = false;
116 const csmBool DebugTouchLogEnable = false;
118 // Frameworkから出力するログのレベル設定
119 - const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Verbose;
120 + const CubismFramework::Option::LogLevel CubismLoggingLevel = CubismFramework::Option::LogLevel_Warning;
122 // デフォルトのレンダーターゲットサイズ
123 const csmInt32 RenderTargetWidth = 1900;
124 diff --git a/src/LAppDelegate.cpp b/src/LAppDelegate.cpp
125 index 242e3ca..2da992d 100644
126 --- a/src/LAppDelegate.cpp
127 +++ b/src/LAppDelegate.cpp
128 @@ -46,7 +46,8 @@ void LAppDelegate::ReleaseInstance()
132 -bool LAppDelegate::Initialize()
133 +bool LAppDelegate::Initialize(int initWindowWidth, int initWindowHeight,
134 + const char *windowTitle)
138 @@ -64,7 +65,13 @@ bool LAppDelegate::Initialize()
142 - _window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL);
143 + _window = glfwCreateWindow(
144 + initWindowWidth ? initWindowWidth : RenderTargetWidth,
145 + initWindowHeight ? initWindowHeight : RenderTargetHeight,
146 + windowTitle ? windowTitle : "SAMPLE",
153 @@ -96,10 +103,6 @@ bool LAppDelegate::Initialize()
155 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
158 - glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack);
159 - glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack);
163 glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
164 diff --git a/src/LAppDelegate.hpp b/src/LAppDelegate.hpp
165 index 89ea99b..50279fd 100644
166 --- a/src/LAppDelegate.hpp
167 +++ b/src/LAppDelegate.hpp
168 @@ -40,7 +40,8 @@ public:
170 * @brief APPに必要なものを初期化する。
173 + bool Initialize(int initWindowWidth = 0, int initWindowHeight = 0,
174 + const char *windowTitle = "SAMPLE");
178 diff --git a/src/LAppLive2DManager.cpp b/src/LAppLive2DManager.cpp
179 index ac3d356..4a5fed6 100644
180 --- a/src/LAppLive2DManager.cpp
181 +++ b/src/LAppLive2DManager.cpp
185 #include "LAppLive2DManager.hpp"
195 #include <GLFW/glfw3.h>
196 #include <Rendering/CubismRenderer.hpp>
197 @@ -69,12 +63,11 @@ void LAppLive2DManager::ReleaseInstance()
199 LAppLive2DManager::LAppLive2DManager()
202 + , _projScaleFactor(1.0f)
203 + , _translateX(0.0f)
204 + , _translateY(0.0f)
206 _viewMatrix = new CubismMatrix44();
209 - ChangeScene(_sceneIndex);
212 LAppLive2DManager::~LAppLive2DManager()
213 @@ -94,60 +87,6 @@ void LAppLive2DManager::ReleaseAllModel()
217 -void LAppLive2DManager::SetUpModel()
219 - // ResourcesPathの中にあるフォルダ名を全てクロールし、モデルが存在するフォルダを定義する。
220 - // フォルダはあるが同名の.model3.jsonが見つからなかった場合はリストに含めない。
221 - struct dirent *dirent;
222 - csmString crawlPath(LAppDelegate::GetInstance()->GetExecuteAbsolutePath().c_str());
223 - crawlPath += ResourcesPath;
225 - DIR *pDir = opendir(crawlPath.GetRawString());
226 - if (pDir == NULL) return;
230 - while ((dirent = readdir(pDir)) != NULL)
232 - if ((dirent->d_type & DT_DIR) && strcmp(dirent->d_name, "..") != 0)
234 - // フォルダと同名の.model3.jsonがあるか探索する
235 - struct dirent *dirent2;
237 - csmString modelName(dirent->d_name);
239 - csmString modelPath(crawlPath);
240 - modelPath += modelName;
241 - modelPath.Append(1, '/');
243 - csmString model3jsonName(modelName);
244 - model3jsonName += ".model3.json";
246 - DIR *pDir2 = opendir(modelPath.GetRawString());
247 - while ((dirent2 = readdir(pDir2)) != NULL)
249 - if (strcmp(dirent2->d_name, model3jsonName.GetRawString()) == 0)
251 - _modelDir.PushBack(csmString(dirent->d_name));
258 - qsort(_modelDir.GetPtr(), _modelDir.GetSize(), sizeof(csmString), CompareCsmString);
261 -csmVector<csmString> LAppLive2DManager::GetModelDir() const
266 -csmInt32 LAppLive2DManager::GetModelDirSize() const
268 - return _modelDir.GetSize();
271 LAppModel* LAppLive2DManager::GetModel(csmUint32 no) const
273 if (no < _models.GetSize())
274 @@ -184,26 +123,6 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y)
276 LAppPal::PrintLogLn("[APP]tap point: {x:%.2f y:%.2f}", x, y);
279 - for (csmUint32 i = 0; i < _models.GetSize(); i++)
281 - if (_models[i]->HitTest(HitAreaNameHead, x, y))
283 - if (DebugLogEnable)
285 - LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameHead);
287 - _models[i]->SetRandomExpression();
289 - else if (_models[i]->HitTest(HitAreaNameBody, x, y))
291 - if (DebugLogEnable)
293 - LAppPal::PrintLogLn("[APP]hit area: [%s]", HitAreaNameBody);
295 - _models[i]->StartRandomMotion(MotionGroupTapBody, PriorityNormal, FinishedMotion, BeganMotion);
300 void LAppLive2DManager::OnUpdate() const
301 @@ -230,12 +149,15 @@ void LAppLive2DManager::OnUpdate() const
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));
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),
315 + projection.Translate(_translateX, _translateY);
318 if (_viewMatrix != NULL)
319 @@ -257,37 +179,15 @@ void LAppLive2DManager::OnUpdate() const
320 Csm::Rendering::CubismOffscreenManager_OpenGLES2::GetInstance()->ReleaseStaleRenderTextures();
323 -void LAppLive2DManager::NextScene()
324 +void LAppLive2DManager::SetModel(std::string modelName, bool useOldParamId)
326 - csmInt32 no = (_sceneIndex + 1) % GetModelDirSize();
330 -void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
332 - _sceneIndex = index;
333 - if (DebugLogEnable)
335 - LAppPal::PrintLogLn("[APP]model index: %d", _sceneIndex);
338 - // ModelDir[]に保持したディレクトリ名から
339 - // model3.jsonのパスを決定する.
340 - // ディレクトリ名とmodel3.jsonの名前を一致させておくこと.
341 - const csmString& model = _modelDir[index];
342 - LAppPal::PrintLogLn("[APP]_modelDir: %s", model.GetRawString());
344 - csmString modelPath(LAppDelegate::GetInstance()->GetExecuteAbsolutePath().c_str());
345 - modelPath += ResourcesPath;
346 - modelPath += model;
347 - modelPath.Append(1, '/');
349 - csmString modelJsonName(model);
350 + std::string modelPath = LAppDelegate::GetInstance()->GetExecuteAbsolutePath() + ResourcesPath + modelName + "/";
351 + std::string modelJsonName = modelName;
352 modelJsonName += ".model3.json";
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());
361 * モデル半透明表示を行うサンプルを提示する。
362 @@ -308,8 +208,8 @@ void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
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);
373 @@ -337,3 +237,20 @@ void LAppLive2DManager::SetViewMatrix(CubismMatrix44* m)
374 _viewMatrix->GetArray()[i] = m->GetArray()[i];
378 +void LAppLive2DManager::SetTracker(MouseCursorTracker *tracker)
380 + for (auto it = _models.Begin(); it != _models.End(); ++it)
382 + (*it)->SetTracker(tracker);
386 +void LAppLive2DManager::SetProjectionScaleTranslate(float scaleFactor,
390 + _projScaleFactor = scaleFactor;
391 + _translateX = translateX;
392 + _translateY = translateY;
394 diff --git a/src/LAppLive2DManager.hpp b/src/LAppLive2DManager.hpp
395 index 2c9939c..5907a82 100644
396 --- a/src/LAppLive2DManager.hpp
397 +++ b/src/LAppLive2DManager.hpp
403 #include <CubismFramework.hpp>
404 #include <Math/CubismMatrix44.hpp>
405 #include <Type/csmVector.hpp>
409 +class MouseCursorTracker;
412 * @brief サンプルアプリケーションにおいてCubismModelを管理するクラス<br>
413 * モデル生成と破棄、タップイベントの処理、モデル切り替えを行う。
414 @@ -35,24 +38,6 @@ public:
416 static void ReleaseInstance();
419 - * @brief Resources フォルダにあるモデルフォルダ名をセットする
425 - * @brief Resources フォルダにあるモデルフォルダ名を取得する
428 - Csm::csmVector<Csm::csmString> GetModelDir() const;
431 - * @brief Resources フォルダにあるモデルフォルダのサイズを取得する
434 - Csm::csmInt32 GetModelDirSize() const;
437 * @brief 現在のシーンで保持しているモデルを返す
439 @@ -98,16 +83,14 @@ public:
440 void OnUpdate() const;
443 - * @brief 次のシーンに切り替える<br>
444 - * サンプルアプリケーションではモデルセットの切り替えを行う。
449 - * @brief シーンを切り替える<br>
450 - * サンプルアプリケーションではモデルセットの切り替えを行う。
452 - void ChangeScene(Csm::csmInt32 index);
453 + * @brief Set model data
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
460 + void SetModel(std::string modelName, bool useOldParamId);
464 @@ -120,6 +103,24 @@ public:
466 void SetViewMatrix(Live2D::Cubism::Framework::CubismMatrix44* m);
469 + * @brief Set the pointer to the MouseCursorTracker instance
471 + * @param[in] tracker : Pointer to MouseCursorTracker instance
473 + void SetTracker(MouseCursorTracker *tracker);
476 + * @brief Set projection scale factor and translation parameters
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
482 + void SetProjectionScaleTranslate(float scaleFactor,
489 @@ -133,7 +134,8 @@ private:
491 Csm::CubismMatrix44* _viewMatrix; ///< モデル描画に用いるView行列
492 Csm::csmVector<LAppModel*> _models; ///< モデルインスタンスのコンテナ
493 - Csm::csmInt32 _sceneIndex; ///< 表示するシーンのインデックス値
495 - Csm::csmVector<Csm::csmString> _modelDir; ///< モデルディレクトリ名のコンテナ
496 + float _projScaleFactor;
500 diff --git a/src/LAppModel.cpp b/src/LAppModel.cpp
501 index 7b8e0ea..14b9754 100644
502 --- a/src/LAppModel.cpp
503 +++ b/src/LAppModel.cpp
505 #include "Motion/CubismPhysicsUpdater.hpp"
506 #include "Motion/CubismPoseUpdater.hpp"
508 +#include "mouse_cursor_tracker.h"
512 using namespace Live2D::Cubism::Framework;
513 using namespace Live2D::Cubism::Framework::DefaultParameterId;
514 using namespace LAppDefine;
516 -LAppModel::LAppModel()
517 +LAppModel::LAppModel(bool useOldParamId)
519 , _modelSetting(NULL)
520 , _userTimeSeconds(0.0f)
521 , _motionUpdated(false)
522 + , _tracker(nullptr)
523 + , _useOldParamId(useOldParamId)
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));
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));
552 _breath->SetParameters(breathParameters);
554 @@ -241,9 +247,6 @@ void LAppModel::SetupModel(ICubismModelSetting* setting)
556 _lipSyncIds.PushBack(_modelSetting->GetLipSyncParameterId(i));
559 - CubismLipSyncUpdater* lipSync = CSM_NEW CubismLipSyncUpdater(_lipSyncIds, _wavFileHandler);
560 - _updateScheduler.AddUpdatableList(lipSync);
564 @@ -377,27 +380,122 @@ void LAppModel::Update()
565 const csmFloat32 deltaTimeSeconds = LAppPal::GetDeltaTime();
566 _userTimeSeconds += deltaTimeSeconds;
568 - // モーションによるパラメータ更新の有無
569 - _motionUpdated = false;
571 - //-----------------------------------------------------------------
572 - _model->LoadParameters(); // 前回セーブされた状態をロード
573 - if (_motionManager->IsFinished())
576 - // モーションの再生がない場合、待機モーションの中からランダムで再生する
577 - StartRandomMotion(MotionGroupIdle, PriorityIdle);
578 + auto idMan = CubismFramework::GetIdManager();
579 + auto params = _tracker->getParams();
581 + _model->LoadParameters(); // 前回セーブされた状態をロード
583 + int paramsMotionPriority = static_cast<int>(params.motionPriority);
585 + if (paramsMotionPriority != PriorityNone)
587 + StartMotion(params.motionGroup.c_str(), params.motionNumber,
588 + paramsMotionPriority);
590 + else if (params.randomIdleMotion && _motionManager->IsFinished())
592 + // モーションの再生がない場合、待機モーションの中からランダムで再生する
593 + StartRandomMotion(MotionGroupIdle, PriorityIdle);
595 + // FIXME pose does not return to normal after motion
596 + // if we don't have randomIdleMotion set
599 + _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
601 + _model->SaveParameters(); // 状態を保存
603 + if (params.expression != "")
605 + SetExpression(params.expression.c_str());
607 + if (_expressionManager != NULL)
609 + _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化)
612 + bool autoBlink = params.autoBlink && _eyeBlink;
613 + auto eyeLOpenIt = params.live2d.find("ParamEyeLOpen");
614 + auto eyeROpenIt = params.live2d.find("ParamEyeROpen");
618 + // Handle blink first
619 + _eyeBlink->UpdateParameters(_model, deltaTimeSeconds);
622 + if (eyeLOpenIt != params.live2d.end())
624 + // If value specified, override blinking
625 + _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")),
626 + eyeLOpenIt->second);
628 + else if (!autoBlink)
630 + // If no value specified and no auto blink, set to 1
631 + _model->SetParameterValue(idMan->GetId(_("ParamEyeLOpen")), 1);
635 + if (eyeROpenIt != params.live2d.end())
637 + _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")),
638 + eyeROpenIt->second);
640 + else if (!autoBlink)
642 + _model->SetParameterValue(idMan->GetId(_("ParamEyeROpen")), 1);
646 + if (params.useLipSync)
648 + csmFloat32 value = params.lipSyncParam; // 0 to 1
650 + for (csmUint32 i = 0; i < _lipSyncIds.GetSize(); ++i)
652 + _model->AddParameterValue(_lipSyncIds[i], value, 0.8f);
657 + _model->SetParameterValue(idMan->GetId(_("ParamMouthOpenY")),
658 + params.live2d["ParamMouthOpenY"]);
661 + for (auto const &entry : params.live2d)
663 + std::string key = entry.first;
664 + double val = entry.second;
666 + if (key != "ParamEyeLOpen" && key != "ParamEyeROpen" &&
667 + key != "ParamMouthOpenY")
669 + _model->SetParameterValue(idMan->GetId(_(key)), val);
673 + if (params.autoBreath && _breath)
675 + // Note: _model->LoadParameters and SaveParameters is needed
676 + // before - see above.
677 + _breath->UpdateParameters(_model, deltaTimeSeconds);
683 + if (_physics != NULL)
685 - _motionUpdated = _motionManager->UpdateMotion(_model, deltaTimeSeconds); // モーションを更新
686 + _physics->Evaluate(_model, deltaTimeSeconds);
688 - _model->SaveParameters(); // 状態を保存
689 - //-----------------------------------------------------------------
692 - _opacity = _model->GetModelOpacity();
694 - _updateScheduler.OnLateUpdate(_model, deltaTimeSeconds);
698 + _pose->UpdateParameters(_model, deltaTimeSeconds);
703 @@ -455,7 +553,6 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt
705 csmString path = voice;
706 path = _modelHomeDir + path;
707 - _wavFileHandler.Start(path);
711 @@ -607,3 +704,42 @@ Csm::Rendering::CubismRenderTarget_OpenGLES2& LAppModel::GetRenderBuffer()
713 return _renderBuffer;
716 +void LAppModel::SetTracker(MouseCursorTracker *tracker)
718 + _tracker = tracker;
721 +Csm::ICubismModelSetting* LAppModel::GetModelSetting(void) const
723 + return _modelSetting;
726 +Csm::csmString LAppModel::_(std::string s)
729 + if (_useOldParamId)
731 + if (s == "ParamTere")
733 + ans = "PARAM_CHEEK";
737 + for (size_t i = 0; i < s.size(); i++)
739 + if (std::isupper(s[i]) && i != 0)
743 + ans += std::toupper(s[i]);
751 + return csmString(ans.c_str());
754 diff --git a/src/LAppModel.hpp b/src/LAppModel.hpp
755 index 2637a54..1cddb56 100644
756 --- a/src/LAppModel.hpp
757 +++ b/src/LAppModel.hpp
759 #include <Type/csmRectF.hpp>
760 #include <Rendering/OpenGL/CubismRenderTarget_OpenGLES2.hpp>
762 -#include "LAppWavFileHandler_Common.hpp"
763 #include "LAppModel_Common.hpp"
764 +#include "mouse_cursor_tracker.h"
767 * @brief ユーザーが実際に使用するモデルの実装クラス<br>
768 @@ -25,8 +25,11 @@ class LAppModel : public LAppModel_Common
773 + * @param[in] useOldParamId : If true, translate new (Cubism 3+)
774 + * parameter IDs to old (Cubism 2.1) ones
777 + LAppModel(bool useOldParamId);
781 @@ -116,6 +119,15 @@ public:
783 Csm::Rendering::CubismRenderTarget_OpenGLES2& GetRenderBuffer();
786 + * @brief Set the pointer to the MouseCursorTracker instance
788 + * @param[in] tracker : Pointer to MouseCursorTracker instance
790 + void SetTracker(MouseCursorTracker *tracker);
792 + Csm::ICubismModelSetting* GetModelSetting(void) const;
796 * @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。
797 @@ -169,6 +181,17 @@ private:
799 void ReleaseExpressions();
802 + * @brief Translate new (Cubism 3+) parameter IDs to old (Cubism 2.1) ones
804 + * @param[in] s : New parameter ID
806 + * @return Old parameter ID
808 + Csm::csmString _(std::string s);
810 + bool _useOldParamId;
812 Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報
813 Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ
814 Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒]
815 @@ -187,7 +210,7 @@ private:
817 Csm::csmBool _motionUpdated; ///< モーション更新フラグ
819 - LAppWavFileHandler_Common _wavFileHandler; ///< wavファイルハンドラ
820 + Csm::Rendering::CubismRenderTarget_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先 Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
822 - Csm::Rendering::CubismRenderTarget_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
823 + MouseCursorTracker *_tracker;
825 diff --git a/src/LAppTextureManager.cpp b/src/LAppTextureManager.cpp
826 index 97cec74..191bdc0 100644
827 --- a/src/LAppTextureManager.cpp
828 +++ b/src/LAppTextureManager.cpp
829 @@ -96,6 +96,46 @@ LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromPngFile(st
833 +LAppTextureManager::TextureInfo* LAppTextureManager::CreateTextureFromColor(
834 + uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha
837 + int width = 8, height = 8;
839 + uint8_t pixels[height][width][4];
840 + for (std::size_t h = 0; h < height; h++)
842 + for (std::size_t w = 0; w < width; w++)
844 + pixels[h][w][0] = red;
845 + pixels[h][w][1] = green;
846 + pixels[h][w][2] = blue;
847 + pixels[h][w][3] = alpha;
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);
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);
862 + LAppTextureManager::TextureInfo* textureInfo = new LAppTextureManager::TextureInfo();
863 + textureInfo->fileName = "";
864 + textureInfo->width = width;
865 + textureInfo->height = height;
866 + textureInfo->id = textureId;
868 + _texturesInfo.PushBack(textureInfo);
870 + return textureInfo;
873 void LAppTextureManager::ReleaseTextures()
875 for (Csm::csmUint32 i = 0; i < _texturesInfo.GetSize(); i++)
876 diff --git a/src/LAppTextureManager.hpp b/src/LAppTextureManager.hpp
877 index a6713df..a42a112 100644
878 --- a/src/LAppTextureManager.hpp
879 +++ b/src/LAppTextureManager.hpp
880 @@ -41,6 +41,8 @@ public:
882 TextureInfo* CreateTextureFromPngFile(std::string fileName);
884 + TextureInfo *CreateTextureFromColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255);
889 diff --git a/src/LAppView.cpp b/src/LAppView.cpp
890 index 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()
901 LAppLive2DManager* Live2DManager = LAppLive2DManager::GetInstance();
903 @@ -128,36 +125,17 @@ void LAppView::InitializeSprite()
904 glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
906 LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager();
907 - const string resourcesPath = LAppDelegate::GetInstance()->GetExecuteAbsolutePath() + ResourcesPath;
909 - string imageName = BackImageName;
910 - LAppTextureManager::TextureInfo* backgroundTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
912 + LAppTextureManager::TextureInfo* backgroundTexture =
913 + textureManager->CreateTextureFromColor(0, 255, 0);
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);
924 - imageName = GearImageName;
925 - LAppTextureManager::TextureInfo* gearTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
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);
933 - imageName = PowerImageName;
934 - LAppTextureManager::TextureInfo* powerTexture = textureManager->CreateTextureFromPngFile(resourcesPath + imageName);
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);
945 @@ -196,18 +174,6 @@ void LAppView::OnTouchesEnded(float px, float py) const
946 LAppPal::PrintLogLn("[APP]touchesEnded x:%.2f y:%.2f", x, y);
948 live2DManager->OnTap(x, y);
951 - if (_gear->IsHit(px, py))
953 - live2DManager->NextScene();
957 - if (_power->IsHit(px, py))
959 - LAppDelegate::GetInstance()->AppEnd();
964 @@ -334,41 +300,6 @@ void LAppView::ResizeSprite()
965 _back->ResetRect(x, y, fWidth, fHeight);
971 - GLuint id = _power->GetTextureId();
972 - LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
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);
985 - GLuint id = _gear->GetTextureId();
986 - LAppTextureManager::TextureInfo* texInfo = textureManager->GetTextureInfoById(id);
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);
1000 - y = height * 0.5f;
1001 - _renderSprite->ResetRect(x, y, static_cast<float>(width), static_cast<float>(height));
1005 void LAppView::DestroySpriteRenderTarget()
1006 diff --git a/src/main.cpp b/src/main.cpp
1007 index b65c1f0..7da9d0a 100644
1011 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
1015 +#include <stdexcept>
1021 +#ifdef __cpp_lib_filesystem
1022 +#include <filesystem>
1023 +namespace fs = std::filesystem;
1025 +#include <experimental/filesystem>
1026 +namespace fs = std::experimental::filesystem;
1029 +#include "ICubismModelSetting.hpp"
1030 #include "LAppDelegate.hpp"
1031 +#include "LAppLive2DManager.hpp"
1032 +#include "LAppModel.hpp"
1033 +#include "mouse_cursor_tracker.h"
1039 + std::string windowTitle;
1040 + std::string rootDir;
1041 + float scaleFactor;
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
1049 +CmdArgs parseArgv(int argc, char *argv[])
1051 + // I think the command-line args are simple enough to not justify using a library...
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 = "";
1068 + std::string arg = argv[i];
1069 + std::stringstream ss;
1071 + if (arg == "--window-width" || arg == "-W") // capital W for consistency with height
1073 + ss << argv[i + 1];
1074 + if (!(ss >> cmdArgs.windowWidth))
1076 + throw std::runtime_error("Invalid argument for window width");
1079 + else if (arg == "--window-height" || arg == "-H") // avoiding "-h", typically for help
1081 + ss << argv[i + 1];
1082 + if (!(ss >> cmdArgs.windowHeight))
1084 + throw std::runtime_error("Invalid argument for window height");
1087 + else if (arg == "--window-title" || arg == "-t")
1089 + cmdArgs.windowTitle = argv[i + 1];
1091 + else if (arg == "--root-dir" || arg == "-d")
1093 + cmdArgs.rootDir = argv[i + 1];
1095 + else if (arg == "--scale-factor" || arg == "-f")
1097 + ss << argv[i + 1];
1098 + if (!(ss >> cmdArgs.scaleFactor))
1100 + throw std::runtime_error("Invalid argument for scale factor");
1103 + else if (arg == "--translate-x" || arg == "-x")
1105 + ss << argv[i + 1];
1106 + if (!(ss >> cmdArgs.translateX))
1108 + throw std::runtime_error("Invalid argument for translate X");
1111 + else if (arg == "--translate-y" || arg == "-y")
1113 + ss << argv[i + 1];
1114 + if (!(ss >> cmdArgs.translateY))
1116 + throw std::runtime_error("Invalid argument for translate Y");
1119 + else if (arg == "--model" || arg == "-m")
1121 + cmdArgs.modelName = argv[i + 1];
1123 + else if (arg == "--config" || arg == "-c")
1125 + cmdArgs.cfgPath = argv[i + 1];
1127 + else if (arg == "--old-param-id" || arg == "-o")
1129 + cmdArgs.oldId = (argv[i + 1][0] == '1');
1133 + throw std::runtime_error("Unrecognized argument: " + arg);
1142 int main(int argc, char* argv[])
1144 - // create the application instance
1145 - if (LAppDelegate::GetInstance()->Initialize() == GL_FALSE)
1146 + auto cmdArgs = parseArgv(argc, argv);
1148 + LAppDelegate *delegate = LAppDelegate::GetInstance();
1150 + if (!delegate->Initialize(cmdArgs.windowWidth,
1151 + cmdArgs.windowHeight,
1152 + cmdArgs.windowTitle.c_str()))
1155 + throw std::runtime_error("Unable to initialize LAppDelegate");
1158 - LAppDelegate::GetInstance()->Run();
1159 + LAppLive2DManager *manager = LAppLive2DManager::GetInstance();
1160 + manager->SetModel(cmdArgs.modelName, cmdArgs.oldId);
1162 + manager->SetProjectionScaleTranslate(cmdArgs.scaleFactor,
1163 + cmdArgs.translateX,
1164 + cmdArgs.translateY);
1166 + LAppModel *model = manager->GetModel(0);
1167 + if (!model) throw std::runtime_error("model is null");
1169 + Live2D::Cubism::Framework::ICubismModelSetting *modelSetting = model->GetModelSetting();
1170 + if (!modelSetting) throw std::runtime_error("modelSetting is null");
1172 + std::vector<std::pair<std::string, int> > motions;
1173 + int motionGroupCount = modelSetting->GetMotionGroupCount();
1174 + for (int i = 0; i < motionGroupCount; i++)
1176 + const char *motionGroup = modelSetting->GetMotionGroupName(i);
1177 + int motionCount = modelSetting->GetMotionCount(motionGroup);
1178 + motions.push_back(std::make_pair(std::string(motionGroup), motionCount));
1181 + std::vector<std::string> expressions;
1182 + int expCount = modelSetting->GetExpressionCount();
1183 + for (int i = 0; i < expCount; i++)
1185 + const char *expName = modelSetting->GetExpressionName(i);
1186 + expressions.push_back(std::string(expName));
1189 + MouseCursorTracker tracker(cmdArgs.cfgPath, motions, expressions);
1191 + std::thread trackerThread(&MouseCursorTracker::mainLoop, &tracker);
1192 + manager->SetTracker(&tracker);
1197 + trackerThread.join();