66#include < vector>
77#include < string>
88#include < map>
9+ #include < mutex>
910
1011using namespace Live2D ::Cubism::Framework;
1112using namespace Live2D ::Cubism::Framework::Rendering;
1213
1314class JniUserModel : public CubismUserModel {
1415public:
15- JniUserModel (JNIEnv* env) {
16+ JniUserModel (JNIEnv* env, jobject javaObj ) {
1617 env->GetJavaVM (&_jvm);
17- }
18-
19- void setJavaObj (JNIEnv* env, jobject obj) {
20- _javaObj = env->NewGlobalRef (obj);
18+ _javaObj = env->NewGlobalRef (javaObj);
2119 }
2220
2321 ~JniUserModel () {
@@ -45,38 +43,41 @@ class JniUserModel : public CubismUserModel {
4543 std::vector<csmByte> motionBuf (buffer, buffer + size);
4644 auto * motion = CubismMotion::Create (motionBuf.data (), (csmSizeInt)motionBuf.size ());
4745 if (!motion) return ;
46+
4847 _motionBuffers[motion] = std::move (motionBuf);
48+
4949 motion->SetFinishedMotionHandlerAndMotionCustomData ([](ACubismMotion* self) {
5050 auto * m = static_cast <CubismMotion*>(self);
5151 auto * model = static_cast <JniUserModel*>(m->GetFinishedMotionCustomData ());
52- model->onMotionEnd (m);
52+ model->queueFinishedMotion (m);
5353 }, this );
54- _motionManager->StartMotionPriority (motion, true , priority);
55- }
5654
57- void onMotionEnd (CubismMotion* motion) {
58- _motionBuffers.erase (motion);
59- CubismMotion::Delete (motion);
60- JNIEnv* env = getEnv ();
61- if (!env || !_javaObj) return ;
62- jclass cls = env->GetObjectClass (_javaObj);
63- jmethodID mid = env->GetMethodID (cls, " onMotionFinished" , " (Ljava/lang/String;)V" );
64- jstring name = env->NewStringUTF (" motion" );
65- env->CallVoidMethod (_javaObj, mid, name);
66- env->DeleteLocalRef (name);
55+ _motionManager->StartMotionPriority (motion, true , priority);
6756 }
6857
69- bool isHitTransformed ( const char * id, float x, float y ) {
70- if (!_model || !_modelMatrix) return false ;
71- return IsHit ( CubismFramework::GetIdManager ()-> GetId (id), _modelMatrix-> InvertTransformX (x), _modelMatrix-> InvertTransformY (y) );
58+ void queueFinishedMotion (CubismMotion* motion ) {
59+ std::lock_guard<std::mutex> lock (_pendingMutex) ;
60+ _pendingDeletion. push_back (motion );
7261 }
7362
7463 void update (float dt) {
7564 if (!_model) return ;
65+
66+ {
67+ std::lock_guard<std::mutex> lock (_pendingMutex);
68+ for (auto * m : _pendingDeletion) {
69+ _motionBuffers.erase (m);
70+ CubismMotion::Delete (m);
71+ notifyFinished ();
72+ }
73+ _pendingDeletion.clear ();
74+ }
75+
7676 _model->LoadParameters ();
7777 _motionManager->UpdateMotion (_model, dt);
7878 _model->SaveParameters ();
7979 if (_pose) _pose->UpdateParameters (_model, dt);
80+
8081 if (_dragManager) {
8182 _dragManager->Update (dt);
8283 auto * idm = CubismFramework::GetIdManager ();
@@ -85,30 +86,45 @@ class JniUserModel : public CubismUserModel {
8586 _model->AddParameterValue (idm->GetId (" ParamEyeBallX" ), _dragManager->GetX ());
8687 _model->AddParameterValue (idm->GetId (" ParamEyeBallY" ), _dragManager->GetY ());
8788 }
89+
8890 if (_physics) _physics->Evaluate (_model, dt);
8991 _model->Update ();
9092 }
9193
94+ void notifyFinished () {
95+ JNIEnv* env = getEnv ();
96+ if (!env || !_javaObj) return ;
97+ jclass cls = env->GetObjectClass (_javaObj);
98+ jmethodID mid = env->GetMethodID (cls, " onMotionFinished" , " (Ljava/lang/String;)V" );
99+ jstring name = env->NewStringUTF (" motion" );
100+ env->CallVoidMethod (_javaObj, mid, name);
101+ env->DeleteLocalRef (name);
102+ }
103+
104+ bool isHitTransformed (const char * id, float x, float y) {
105+ if (!_model || !_modelMatrix) return false ;
106+ return IsHit (CubismFramework::GetIdManager ()->GetId (id), _modelMatrix->InvertTransformX (x), _modelMatrix->InvertTransformY (y));
107+ }
108+
92109private:
93110 JNIEnv* getEnv () {
94111 JNIEnv* env;
95112 if (_jvm->GetEnv ((void **)&env, JNI_VERSION_1_6) == JNI_EDETACHED) _jvm->AttachCurrentThread ((void **)&env, nullptr );
96113 return env;
97114 }
115+
98116 JavaVM* _jvm;
99- jobject _javaObj = nullptr ;
117+ jobject _javaObj;
100118 std::vector<csmByte> _mocBuffer, _physicsBuffer, _poseBuffer;
101119 std::map<CubismMotion*, std::vector<csmByte>> _motionBuffers;
120+ std::vector<CubismMotion*> _pendingDeletion;
121+ std::mutex _pendingMutex;
102122};
103123
104124extern " C" {
105125
106- JNIEXPORT jlong JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_createNative (JNIEnv* env, jclass) {
107- return (jlong) new JniUserModel (env);
108- }
109-
110- JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_initNative (JNIEnv* env, jobject thiz, jlong ptr) {
111- ((JniUserModel*)ptr)->setJavaObj (env, thiz);
126+ JNIEXPORT jlong JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_createNative (JNIEnv* env, jobject thiz) {
127+ return (jlong) new JniUserModel (env, thiz);
112128}
113129
114130JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_deleteNative (JNIEnv*, jclass, jlong ptr) {
@@ -210,4 +226,4 @@ JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_drawNative(JNIE
210226 env->ReleaseFloatArrayElements (matrix, m_ptr, JNI_ABORT);
211227}
212228
213- }
229+ }
0 commit comments