Skip to content

Commit 7e2cab2

Browse files
committed
add Android bulid and add javadoc
1 parent b4f1307 commit 7e2cab2

File tree

7 files changed

+311
-37
lines changed

7 files changed

+311
-37
lines changed

.github/workflows/build.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@ jobs:
3030
run: |
3131
sudo apt-get install -y libgles2-mesa-dev
3232
33+
- name: Setup Android NDK
34+
if: contains(matrix.os, 'ubuntu')
35+
uses: nttld/setup-ndk@v1
36+
with:
37+
ndk-version: r26b
38+
3339
- name: Build and Package
3440
run: python3 scripts/build.py
3541

3642
- name: Upload Artifacts
3743
uses: actions/upload-artifact@v4
3844
with:
3945
name: live2d-jars-${{ matrix.os }}
40-
path: out/*.jar
46+
path: out/*.jar

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

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
package dev.eatgrapes.live2d;
22

3+
/**
4+
* Entry point for the Live2D Cubism Framework.
5+
* <p>
6+
* This class manages the lifecycle of the Cubism native framework (startup, initialization, disposal)
7+
* and provides logging capabilities.
8+
*/
39
public class CubismFramework {
410
static {
511
LibraryLoader.load();
612
}
713

14+
/**
15+
* Represents the logging level for the framework.
16+
*/
817
public enum LogLevel {
918
VERBOSE(0),
1019
DEBUG(1),
@@ -17,30 +26,69 @@ public enum LogLevel {
1726
LogLevel(int value) { this.value = value; }
1827
}
1928

29+
/**
30+
* Callback interface for receiving log messages from the native framework.
31+
*/
2032
public interface LogCallback {
33+
/**
34+
* Called when a log message is generated.
35+
* @param message The log message.
36+
*/
2137
void log(String message);
2238
}
2339

2440
private static LogCallback logCallback;
2541

42+
/**
43+
* Starts the Cubism framework with default settings (no logging).
44+
* Must be called before {@link #initialize()}.
45+
*/
2646
public static void startUp() {
2747
startUp(null, LogLevel.OFF);
2848
}
2949

50+
/**
51+
* Starts the Cubism framework with a specific logger and log level.
52+
* Must be called before {@link #initialize()}.
53+
*
54+
* @param callback The callback to handle log messages (can be null).
55+
* @param level The minimum log level to capture.
56+
*/
3057
public static void startUp(LogCallback callback, LogLevel level) {
3158
logCallback = callback;
3259
startUpNative(callback != null, level.value);
3360
}
3461

3562
private static native void startUpNative(boolean hasCallback, int logLevel);
63+
64+
/**
65+
* Initializes the framework resources.
66+
* Must be called after {@link #startUp()} and before using any other framework features.
67+
*/
3668
public static native void initialize();
69+
70+
/**
71+
* Disposes of the framework resources.
72+
* Should be called when Live2D is no longer needed to free native memory.
73+
*/
3774
public static native void dispose();
75+
76+
/**
77+
* Checks if the framework has been started.
78+
* @return true if started, false otherwise.
79+
*/
3880
public static native boolean isStarted();
81+
82+
/**
83+
* Checks if the framework has been initialized.
84+
* @return true if initialized, false otherwise.
85+
*/
3986
public static native boolean isInitialized();
4087

88+
// Called from JNI
4189
private static void onLog(String message) {
4290
if (logCallback != null) {
4391
logCallback.log("[Live2D Native] " + message);
4492
}
4593
}
46-
}
94+
}

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

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@
22

33
import java.util.function.Consumer;
44

5+
/**
6+
* Represents a Live2D Cubism user model.
7+
* <p>
8+
* This class provides a high-level API to interact with a Live2D model, including loading assets
9+
* (MOC3, physics, pose, expressions), updating the model state, and rendering it.
10+
*/
511
public class CubismUserModel extends Native {
612
private Consumer<String> motionFinishedCallback;
713

14+
/**
15+
* Creates a new empty user model instance.
16+
*/
817
public CubismUserModel() {
918
super(createNative());
1019
linkNative();
@@ -13,70 +22,155 @@ public CubismUserModel() {
1322
private static native long createNative();
1423
private native void linkNative();
1524

25+
/**
26+
* Loads the model data (MOC3) from a byte buffer.
27+
* @param buffer The byte array containing MOC3 data.
28+
*/
1629
public void loadModel(byte[] buffer) { loadModelNative(_ptr, buffer); }
1730
private static native void loadModelNative(long ptr, byte[] buffer);
1831

32+
/**
33+
* Loads the physics data from a byte buffer.
34+
* @param buffer The byte array containing physics3.json data.
35+
*/
1936
public void loadPhysics(byte[] buffer) { loadPhysicsNative(_ptr, buffer); }
2037
private static native void loadPhysicsNative(long ptr, byte[] buffer);
2138

39+
/**
40+
* Loads the pose data from a byte buffer.
41+
* @param buffer The byte array containing pose3.json data.
42+
*/
2243
public void loadPose(byte[] buffer) { loadPoseNative(_ptr, buffer); }
2344
private static native void loadPoseNative(long ptr, byte[] buffer);
2445

46+
/**
47+
* Loads an expression from a byte buffer and assigns it a name.
48+
* @param buffer The byte array containing exp3.json data.
49+
* @param name The unique name to identify this expression.
50+
*/
2551
public void loadExpression(byte[] buffer, String name) { loadExpressionNative(_ptr, buffer, name); }
2652
private static native void loadExpressionNative(long ptr, byte[] buffer, String name);
2753

54+
/**
55+
* Sets the current active expression by name.
56+
* @param name The name of the expression to activate.
57+
*/
2858
public void setExpression(String name) { setExpressionNative(_ptr, name); }
2959
private static native void setExpressionNative(long ptr, String name);
3060

61+
/**
62+
* Creates the renderer for this model.
63+
* Must be called before drawing.
64+
*/
3165
public void createRenderer() { createRendererNative(_ptr); }
3266
private static native void createRendererNative(long ptr);
3367

68+
/**
69+
* Registers a texture with the model's renderer.
70+
* @param index The texture index (as defined in the model data).
71+
* @param textureId The OpenGL texture ID.
72+
*/
3473
public void registerTexture(int index, int textureId) { registerTextureNative(_ptr, index, textureId); }
3574
private static native void registerTextureNative(long ptr, int index, int textureId);
3675

76+
/**
77+
* Sets the dragging coordinates for interaction (e.g., look-at behavior).
78+
* @param x The x-coordinate in model space.
79+
* @param y The y-coordinate in model space.
80+
*/
3781
public void setDragging(float x, float y) { setDraggingNative(_ptr, x, y); }
3882
private static native void setDraggingNative(long ptr, float x, float y);
3983

84+
/**
85+
* Checks if a point hits a specific drawable part (HitArea).
86+
* @param drawableId The ID of the drawable to check.
87+
* @param x The x-coordinate to test.
88+
* @param y The y-coordinate to test.
89+
* @return true if the point hits the drawable, false otherwise.
90+
*/
4091
public boolean isHit(String drawableId, float x, float y) { return isHitNative(_ptr, drawableId, x, y); }
4192
private static native boolean isHitNative(long ptr, String drawableId, float x, float y);
4293

94+
/**
95+
* Starts playing a motion.
96+
*
97+
* @param buffer The byte array containing motion3.json data.
98+
* @param priority The priority of the motion (1=Low, 2=Normal, 3=Force).
99+
* @param loop Whether the motion should loop.
100+
* @param onFinished Callback to be invoked when the motion finishes.
101+
*/
43102
public void startMotion(byte[] buffer, int priority, boolean loop, Consumer<String> onFinished) {
44103
this.motionFinishedCallback = onFinished;
45104
startMotionNative(_ptr, buffer, priority, loop);
46105
}
47106
private static native void startMotionNative(long ptr, byte[] buffer, int priority, boolean loop);
48107

108+
/**
109+
* Checks if the currently playing motion has finished.
110+
* @return true if finished, false otherwise.
111+
*/
49112
public boolean isMotionFinished() { return isMotionFinishedNative(_ptr); }
50113
private static native boolean isMotionFinishedNative(long ptr);
51114

115+
// Called from JNI
52116
private void onMotionFinished(String name) {
53117
if (motionFinishedCallback != null) {
54118
motionFinishedCallback.accept(name);
55119
}
56120
}
57121

122+
/**
123+
* Updates the model state. Should be called every frame.
124+
* @param deltaTime The time elapsed since the last frame in seconds.
125+
*/
58126
public void update(float deltaTime) { updateNative(_ptr, deltaTime); }
59127
private static native void updateNative(long ptr, float deltaTime);
60128

129+
/**
130+
* Sets a parameter value.
131+
* @param id The parameter ID.
132+
* @param value The value to set.
133+
*/
61134
public void setParameterValue(String id, float value) { setParameterValueNative(_ptr, id, value); }
62135
private static native void setParameterValueNative(long ptr, String id, float value);
63136

137+
/**
138+
* Gets the current value of a parameter.
139+
* @param id The parameter ID.
140+
* @return The current value.
141+
*/
64142
public float getParameterValue(String id) { return getParameterValueNative(_ptr, id); }
65143
private static native float getParameterValueNative(long ptr, String id);
66144

145+
/**
146+
* Gets the width of the model's canvas.
147+
* @return The canvas width.
148+
*/
67149
public float getCanvasWidth() { return getCanvasWidthNative(_ptr); }
68150
private static native float getCanvasWidthNative(long ptr);
69151

152+
/**
153+
* Gets the height of the model's canvas.
154+
* @return The canvas height.
155+
*/
70156
public float getCanvasHeight() { return getCanvasHeightNative(_ptr); }
71157
private static native float getCanvasHeightNative(long ptr);
72158

159+
/**
160+
* Gets the list of drawable IDs in the model.
161+
* @return An array of drawable ID strings.
162+
*/
73163
public String[] getDrawableIds() { return getDrawableIdsNative(_ptr); }
74164
private static native String[] getDrawableIdsNative(long ptr);
75165

166+
/**
167+
* Draws the model using the provided MVP matrix.
168+
* @param mvpMatrix The 4x4 Model-View-Projection matrix.
169+
*/
76170
public void draw(float[] mvpMatrix) { drawNative(_ptr, mvpMatrix); }
77171
private static native void drawNative(long ptr, float[] mvpMatrix);
78172

79173
@Override
80174
public void close() { deleteNative(_ptr); }
81175
private static native void deleteNative(long ptr);
82-
}
176+
}

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,38 @@
44
import java.nio.file.*;
55
import java.util.Locale;
66

7+
/**
8+
* Handles loading of the native Live2D JNI library.
9+
* <p>
10+
* This class automatically detects the current operating system and architecture,
11+
* extracts the appropriate shared library from the JAR, and loads it.
12+
* On Android, it delegates to the system's library loader.
13+
*/
714
public class LibraryLoader {
815
private static boolean loaded = false;
916

17+
/**
18+
* Loads the native library.
19+
* <p>
20+
* This method is idempotent; calling it multiple times has no effect.
21+
* It attempts to load 'live2d_jni'. On desktop platforms, it extracts
22+
* the library to a temporary location first.
23+
*
24+
* @throws RuntimeException if the operating system or architecture is unsupported,
25+
* or if the native library cannot be extracted/loaded.
26+
*/
1027
public static synchronized void load() {
1128
if (loaded) return;
1229

30+
// Check for Android
31+
String vendor = System.getProperty("java.vendor", "").toLowerCase(Locale.ROOT);
32+
String vmName = System.getProperty("java.vm.name", "").toLowerCase(Locale.ROOT);
33+
if (vendor.contains("android") || vmName.contains("dalvik")) {
34+
System.loadLibrary("live2d_jni");
35+
loaded = true;
36+
return;
37+
}
38+
1339
String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
1440
String arch = System.getProperty("os.arch").toLowerCase(Locale.ROOT);
1541

@@ -43,6 +69,12 @@ public static synchronized void load() {
4369
}
4470
}
4571

72+
/**
73+
* Loads a shader resource from the classpath.
74+
*
75+
* @param name The name of the shader file (e.g., "vert_shader.glsl").
76+
* @return The byte content of the shader file, or null if not found.
77+
*/
4678
public static byte[] loadResource(String name) {
4779
String internalPath = "/live2d/shaders/" + name.substring(name.lastIndexOf("/") + 1);
4880
try (InputStream is = LibraryLoader.class.getResourceAsStream(internalPath)) {
@@ -52,4 +84,4 @@ public static byte[] loadResource(String name) {
5284
return null;
5385
}
5486
}
55-
}
87+
}
Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
11
package dev.eatgrapes.live2d;
22

3+
/**
4+
* Base class for objects that wrap a native C++ pointer.
5+
* <p>
6+
* This class implements {@link AutoCloseable} to ensure native resources are properly released.
7+
*/
38
public abstract class Native implements AutoCloseable {
9+
/**
10+
* The raw pointer to the native object.
11+
*/
412
protected final long _ptr;
513

14+
/**
15+
* Constructs a Native wrapper around the given pointer.
16+
* @param ptr The native pointer value.
17+
* @throws RuntimeException if the pointer is null (0).
18+
*/
619
protected Native(long ptr) {
720
if (ptr == 0) throw new RuntimeException("Native pointer is null");
821
this._ptr = ptr;
922
}
1023

24+
/**
25+
* Gets the raw native pointer.
26+
* @return The pointer value.
27+
*/
1128
public long getPtr() {
1229
return _ptr;
1330
}
1431

32+
/**
33+
* Releases the native resources associated with this object.
34+
*/
1535
@Override
1636
public abstract void close();
17-
}
37+
}

0 commit comments

Comments
 (0)