Skip to content

Commit dbb8a35

Browse files
committed
fix: restore automatic idle motion resume by implementing state-based transition
1 parent eedc019 commit dbb8a35

3 files changed

Lines changed: 25 additions & 5 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ private void onMotionFinished(String name) {
4949
}
5050
}
5151

52+
public boolean isMotionFinished() { return isMotionFinishedNative(_ptr); }
53+
private static native boolean isMotionFinishedNative(long ptr);
54+
5255
public void update(float deltaTime) { updateNative(_ptr, deltaTime); }
5356
private static native void updateNative(long ptr, float deltaTime);
5457

example/src/main/java/dev/eatgrapes/live2d/example/Main.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@ private void setup() throws Exception {
8989

9090
motions.put("idle", load("/model/Hiyori/motions/Hiyori_m01.motion3.json"));
9191
motions.put("m04", load("/model/Hiyori/motions/Hiyori_m04.motion3.json"));
92-
93-
// Start background idle loop once at priority 1
94-
model.startMotion(motions.get("idle"), 1, true, null);
9592
}
9693

9794
private void loop() {
@@ -107,6 +104,11 @@ private void loop() {
107104
mvp[0] = 1.0f / aspect; mvp[5] = 1.0f; mvp[10] = 1.0f; mvp[15] = 1.0f;
108105
}
109106

107+
// Standard state machine: if nothing is playing, play idle
108+
if (model.isMotionFinished()) {
109+
model.startMotion(motions.get("idle"), 1, false, null);
110+
}
111+
110112
model.update(0.016f);
111113
model.draw(mvp);
112114
glfwSwapBuffers(window);

native/src/CubismUserModel_JNI.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class JniUserModel : public CubismUserModel {
7070
void update(float dt) {
7171
if (!_model) return;
7272

73+
// Cleanup finished motions safely
7374
{
7475
std::lock_guard<std::mutex> lock(_pendingMutex);
7576
for (auto* m : _pendingDeletion) {
@@ -83,7 +84,13 @@ class JniUserModel : public CubismUserModel {
8384
}
8485

8586
_model->LoadParameters();
86-
_motionManager->UpdateMotion(_model, dt);
87+
88+
// Update motion and check if we are idle
89+
bool isMotionPlaying = !_motionManager->IsFinished();
90+
if (isMotionPlaying) {
91+
_motionManager->UpdateMotion(_model, dt);
92+
}
93+
8794
_model->SaveParameters();
8895

8996
if (_pose) _pose->UpdateParameters(_model, dt);
@@ -101,6 +108,10 @@ class JniUserModel : public CubismUserModel {
101108
_model->Update();
102109
}
103110

111+
bool isMotionFinished() {
112+
return _motionManager->IsFinished();
113+
}
114+
104115
void notifyFinished() {
105116
JNIEnv* env = getEnv();
106117
if (!env || !_javaObj) return;
@@ -205,6 +216,10 @@ JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_startMotionNati
205216
env->ReleaseByteArrayElements(buffer, data, JNI_ABORT);
206217
}
207218

219+
JNIEXPORT jboolean JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_isMotionFinishedNative(JNIEnv*, jclass, jlong ptr) {
220+
return ((JniUserModel*)ptr)->isMotionFinished();
221+
}
222+
208223
JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_updateNative(JNIEnv*, jclass, jlong ptr, jfloat dt) {
209224
((JniUserModel*)ptr)->update(dt);
210225
}
@@ -243,4 +258,4 @@ JNIEXPORT void JNICALL Java_dev_eatgrapes_live2d_CubismUserModel_drawNative(JNIE
243258
env->ReleaseFloatArrayElements(matrix, m_ptr, JNI_ABORT);
244259
}
245260

246-
}
261+
}

0 commit comments

Comments
 (0)