77#include < string>
88#include < map>
99#include < mutex>
10+ #include < algorithm>
1011
1112using namespace Live2D ::Cubism::Framework;
1213using namespace Live2D ::Cubism::Framework::Rendering;
@@ -42,39 +43,51 @@ class JniUserModel : public CubismUserModel {
4243 LoadPose (_poseBuffer.data (), (csmSizeInt)_poseBuffer.size ());
4344 }
4445
45- void startMotionCopy (const csmByte* buffer, csmSizeInt size, int priority) {
46+ void startMotionCopy (const csmByte* buffer, csmSizeInt size, int priority, bool loop ) {
4647 std::vector<csmByte> motionBuf (buffer, buffer + size);
4748 auto * motion = CubismMotion::Create (motionBuf.data (), (csmSizeInt)motionBuf.size ());
4849 if (!motion) return ;
50+
51+ motion->SetLoop (loop);
4952 _motionBuffers[motion] = std::move (motionBuf);
53+
5054 motion->SetFinishedMotionHandlerAndMotionCustomData ([](ACubismMotion* self) {
5155 auto * m = static_cast <CubismMotion*>(self);
5256 auto * model = static_cast <JniUserModel*>(m->GetFinishedMotionCustomData ());
5357 model->queueFinishedMotion (m);
5458 }, this );
55- _motionManager->StartMotionPriority (motion, true , priority);
59+
60+ _motionManager->StartMotionPriority (motion, false , priority);
5661 }
5762
5863 void queueFinishedMotion (CubismMotion* motion) {
5964 std::lock_guard<std::mutex> lock (_pendingMutex);
60- _pendingDeletion.push_back (motion);
65+ if (std::find (_pendingDeletion.begin (), _pendingDeletion.end (), motion) == _pendingDeletion.end ()) {
66+ _pendingDeletion.push_back (motion);
67+ }
6168 }
6269
6370 void update (float dt) {
6471 if (!_model) return ;
72+
6573 {
6674 std::lock_guard<std::mutex> lock (_pendingMutex);
6775 for (auto * m : _pendingDeletion) {
68- _motionBuffers.erase (m);
69- CubismMotion::Delete (m);
70- notifyFinished ();
76+ if (_motionBuffers.count (m)) {
77+ _motionBuffers.erase (m);
78+ CubismMotion::Delete (m);
79+ notifyFinished ();
80+ }
7181 }
7282 _pendingDeletion.clear ();
7383 }
84+
7485 _model->LoadParameters ();
7586 _motionManager->UpdateMotion (_model, dt);
7687 _model->SaveParameters ();
88+
7789 if (_pose) _pose->UpdateParameters (_model, dt);
90+
7891 if (_dragManager) {
7992 _dragManager->Update (dt);
8093 auto * idm = CubismFramework::GetIdManager ();
@@ -83,6 +96,7 @@ class JniUserModel : public CubismUserModel {
8396 _model->AddParameterValue (idm->GetId (" ParamEyeBallX" ), _dragManager->GetX ());
8497 _model->AddParameterValue (idm->GetId (" ParamEyeBallY" ), _dragManager->GetY ());
8598 }
99+
86100 if (_physics) _physics->Evaluate (_model, dt);
87101 _model->Update ();
88102 }
@@ -108,6 +122,7 @@ class JniUserModel : public CubismUserModel {
108122 if (_jvm->GetEnv ((void **)&env, JNI_VERSION_1_6) == JNI_EDETACHED) _jvm->AttachCurrentThread ((void **)&env, nullptr );
109123 return env;
110124 }
125+
111126 JavaVM* _jvm;
112127 jobject _javaObj = nullptr ;
113128 std::vector<csmByte> _mocBuffer, _physicsBuffer, _poseBuffer;
@@ -183,10 +198,10 @@ JNIEXPORT jboolean JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_isHitNative
183198 return hit;
184199}
185200
186- JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_startMotionNative (JNIEnv* env, jclass, jlong ptr, jbyteArray buffer, jint priority) {
201+ JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_startMotionNative (JNIEnv* env, jclass, jlong ptr, jbyteArray buffer, jint priority, jboolean loop ) {
187202 jsize len = env->GetArrayLength (buffer);
188203 jbyte* data = env->GetByteArrayElements (buffer, nullptr );
189- ((JniUserModel*)ptr)->startMotionCopy ((const csmByte*)data, len, priority);
204+ ((JniUserModel*)ptr)->startMotionCopy ((const csmByte*)data, len, priority, loop );
190205 env->ReleaseByteArrayElements (buffer, data, JNI_ABORT);
191206}
192207
@@ -228,4 +243,4 @@ JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_drawNative(JNIE
228243 env->ReleaseFloatArrayElements (matrix, m_ptr, JNI_ABORT);
229244}
230245
231- }
246+ }
0 commit comments