Skip to content

Commit cc0383f

Browse files
committed
fix: resolve Native pointer is null error and fix JNI lifecycle
1 parent 4afe0e3 commit cc0383f

2 files changed

Lines changed: 19 additions & 32 deletions

File tree

binding/src/main/java/dev/eatgrapes/live2d/CubismUserModel.java

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,12 @@ public class CubismUserModel extends Native {
66
private Consumer<String> motionFinishedCallback;
77

88
public CubismUserModel() {
9-
super(0); // Temporary call to super
10-
this.initPtr();
9+
super(createNative());
10+
initNative(_ptr);
1111
}
1212

13-
private void initPtr() {
14-
try {
15-
java.lang.reflect.Field field = Native.class.getDeclaredField("_ptr");
16-
field.setAccessible(true);
17-
field.set(this, createNative());
18-
} catch (Exception e) {
19-
throw new RuntimeException(e);
20-
}
21-
}
22-
23-
private native long createNative();
13+
private static native long createNative();
14+
private native void initNative(long ptr);
2415

2516
public void loadModel(byte[] buffer) { loadModelNative(_ptr, buffer); }
2617
private static native void loadModelNative(long ptr, byte[] buffer);
@@ -40,22 +31,18 @@ private void initPtr() {
4031
public void registerTexture(int index, int textureId) { registerTextureNative(_ptr, index, textureId); }
4132
private static native void registerTextureNative(long ptr, int index, int textureId);
4233

43-
// Eye Tracking / Dragging
4434
public void setDragging(float x, float y) { setDraggingNative(_ptr, x, y); }
4535
private static native void setDraggingNative(long ptr, float x, float y);
4636

47-
// Hit Detection
4837
public boolean isHit(String drawableId, float x, float y) { return isHitNative(_ptr, drawableId, x, y); }
4938
private static native boolean isHitNative(long ptr, String drawableId, float x, float y);
5039

51-
// Motion Playback
5240
public void startMotion(byte[] buffer, int priority, Consumer<String> onFinished) {
5341
this.motionFinishedCallback = onFinished;
5442
startMotionNative(_ptr, buffer, priority);
5543
}
5644
private static native void startMotionNative(long ptr, byte[] buffer, int priority);
5745

58-
// Called from JNI
5946
private void onMotionFinished(String name) {
6047
if (motionFinishedCallback != null) {
6148
motionFinishedCallback.accept(name);
@@ -83,4 +70,4 @@ private void onMotionFinished(String name) {
8370
@Override
8471
public void close() { deleteNative(_ptr); }
8572
private static native void deleteNative(long ptr);
86-
}
73+
}

native/src/CubismUserModel_JNI.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ using namespace Live2D::Cubism::Framework::Rendering;
1212

1313
class JniUserModel : public CubismUserModel {
1414
public:
15-
JniUserModel(JNIEnv* env, jobject javaObj) {
15+
JniUserModel(JNIEnv* env) {
1616
env->GetJavaVM(&_jvm);
17-
_javaObj = env->NewGlobalRef(javaObj);
17+
}
18+
19+
void setJavaObj(JNIEnv* env, jobject obj) {
20+
_javaObj = env->NewGlobalRef(obj);
1821
}
1922

2023
~JniUserModel() {
@@ -42,22 +45,18 @@ class JniUserModel : public CubismUserModel {
4245
std::vector<csmByte> motionBuf(buffer, buffer + size);
4346
auto* motion = CubismMotion::Create(motionBuf.data(), (csmSizeInt)motionBuf.size());
4447
if (!motion) return;
45-
4648
_motionBuffers[motion] = std::move(motionBuf);
47-
4849
motion->SetFinishedMotionHandlerAndMotionCustomData([](ACubismMotion* self) {
4950
auto* m = static_cast<CubismMotion*>(self);
5051
auto* model = static_cast<JniUserModel*>(m->GetFinishedMotionCustomData());
5152
model->onMotionEnd(m);
5253
}, this);
53-
5454
_motionManager->StartMotionPriority(motion, true, priority);
5555
}
5656

5757
void onMotionEnd(CubismMotion* motion) {
5858
_motionBuffers.erase(motion);
5959
CubismMotion::Delete(motion);
60-
6160
JNIEnv* env = getEnv();
6261
if (!env || !_javaObj) return;
6362
jclass cls = env->GetObjectClass(_javaObj);
@@ -69,9 +68,7 @@ class JniUserModel : public CubismUserModel {
6968

7069
bool isHitTransformed(const char* id, float x, float y) {
7170
if (!_model || !_modelMatrix) return false;
72-
float mx = _modelMatrix->InvertTransformX(x);
73-
float my = _modelMatrix->InvertTransformY(y);
74-
return IsHit(CubismFramework::GetIdManager()->GetId(id), mx, my);
71+
return IsHit(CubismFramework::GetIdManager()->GetId(id), _modelMatrix->InvertTransformX(x), _modelMatrix->InvertTransformY(y));
7572
}
7673

7774
void update(float dt) {
@@ -98,17 +95,20 @@ class JniUserModel : public CubismUserModel {
9895
if (_jvm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_EDETACHED) _jvm->AttachCurrentThread((void**)&env, nullptr);
9996
return env;
10097
}
101-
10298
JavaVM* _jvm;
103-
jobject _javaObj;
99+
jobject _javaObj = nullptr;
104100
std::vector<csmByte> _mocBuffer, _physicsBuffer, _poseBuffer;
105101
std::map<CubismMotion*, std::vector<csmByte>> _motionBuffers;
106102
};
107103

108104
extern "C" {
109105

110-
JNIEXPORT jlong JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_createNative(JNIEnv* env, jobject thiz) {
111-
return (jlong) new JniUserModel(env, thiz);
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);
112112
}
113113

114114
JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_deleteNative(JNIEnv*, jclass, jlong ptr) {
@@ -210,4 +210,4 @@ JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_drawNative(JNIE
210210
env->ReleaseFloatArrayElements(matrix, m_ptr, JNI_ABORT);
211211
}
212212

213-
}
213+
}

0 commit comments

Comments
 (0)