Add ImGuiListClipper
Add ImGuiListClipper
This commit is contained in:
1 parent
c024de2b21
commit
7a0e9ec942
8 files changed
+155
-76
No files matched your search
@@ -0,0 +1,65 @@
|
|||||||
|
package imgui;
|
||||||
|
|
||||||
|
import imgui.callbacks.ImListClipperCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper: Manually clip large list of items.
|
||||||
|
* If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all.
|
||||||
|
* The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped.
|
||||||
|
* ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null.
|
||||||
|
* Usage:
|
||||||
|
* <pre>
|
||||||
|
* ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced.
|
||||||
|
* while (clipper.Step())
|
||||||
|
* for (int i = clipper.DisplayStart; i {@code <} clipper.DisplayEnd; i++)
|
||||||
|
* ImGui::Text("line number %d", i);
|
||||||
|
* </pre>
|
||||||
|
* - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor).
|
||||||
|
* - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.
|
||||||
|
* - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.)
|
||||||
|
* - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
|
||||||
|
* <p>
|
||||||
|
* BINDING NOTICE:
|
||||||
|
* It's impossible to implement the same API like in the original. Method {@link #forEach(int, int, ImListClipperCallback)} could be used instead.
|
||||||
|
* <pre>
|
||||||
|
* ImGuiListClipper.forEach(1000, new ImListClipperCallback() {
|
||||||
|
* public void accept(int index) {
|
||||||
|
* ImGui.text(String.format("line number %d", index));
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class ImGuiListClipper {
|
||||||
|
private ImGuiListClipper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*JNI
|
||||||
|
#include <imgui.h>
|
||||||
|
#include "jni_callbacks.h"
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param itemsCount Use -1 to ignore (you can call Begin later).
|
||||||
|
* Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step).
|
||||||
|
* @param callback action to do in iterations
|
||||||
|
*/
|
||||||
|
public static void forEach(final int itemsCount, final ImListClipperCallback callback) {
|
||||||
|
forEach(itemsCount, -1, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param itemsCount Use -1 to ignore (you can call Begin later).
|
||||||
|
* Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step).
|
||||||
|
* @param itemsHeight Use -1.0f to be calculated automatically on first step.
|
||||||
|
* Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
|
||||||
|
* @param callback action to do in iterations
|
||||||
|
*/
|
||||||
|
public static native void forEach(int itemsCount, int itemsHeight, ImListClipperCallback callback); /*
|
||||||
|
ImGuiListClipper clipper(itemsCount);
|
||||||
|
while (clipper.Step()) {
|
||||||
|
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||||
|
Jni::CallImListClipperCallback(env, callback, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package imgui.callbacks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for {@link imgui.ImGuiListClipper} class.
|
||||||
|
*/
|
||||||
|
public abstract class ImListClipperCallback {
|
||||||
|
public abstract void accept(int index);
|
||||||
|
}
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
package imgui.callbacks;
|
package imgui.callbacks;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to supply Java string form native code.
|
* Callback to supply Java string form native code.
|
||||||
*/
|
*/
|
||||||
public abstract class ImStrConsumer implements Consumer<String> {
|
public abstract class ImStrConsumer {
|
||||||
@Override
|
|
||||||
public abstract void accept(String str);
|
public abstract void accept(String str);
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
package imgui.callbacks;
|
package imgui.callbacks;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to get Java string from native code.
|
* Callback to get Java string from native code.
|
||||||
*/
|
*/
|
||||||
public abstract class ImStrSupplier implements Supplier<String> {
|
public abstract class ImStrSupplier {
|
||||||
@Override
|
|
||||||
public abstract String get();
|
public abstract String get();
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,32 @@
|
|||||||
#include "jni_callbacks.h"
|
#include "jni_callbacks.h"
|
||||||
|
|
||||||
|
jmethodID jImListClipperCallbackAcceptMID;
|
||||||
|
|
||||||
jmethodID jImStrConsumerAcceptMID;
|
jmethodID jImStrConsumerAcceptMID;
|
||||||
jmethodID jImStrSupplierGetMID;
|
jmethodID jImStrSupplierGetMID;
|
||||||
|
|
||||||
namespace Jni
|
namespace Jni
|
||||||
{
|
{
|
||||||
void InitCallbacks(JNIEnv* env) {
|
void InitCallbacks(JNIEnv* env) {
|
||||||
jclass jImStrConsumer = env->FindClass("imgui/callbacks/ImStrConsumer");
|
jclass jImListClipperCallback = env->FindClass("imgui/callbacks/ImListClipperCallback");
|
||||||
jImStrConsumerAcceptMID = env->GetMethodID(jImStrConsumer, "accept", "(Ljava/lang/String;)V");
|
jImListClipperCallbackAcceptMID = env->GetMethodID(jImListClipperCallback, "accept", "(I)V");
|
||||||
|
|
||||||
jclass jImStrSupplier = env->FindClass("imgui/callbacks/ImStrSupplier");
|
jclass jImStrConsumer = env->FindClass("imgui/callbacks/ImStrConsumer");
|
||||||
jImStrSupplierGetMID = env->GetMethodID(jImStrSupplier, "get", "()Ljava/lang/String;");
|
jImStrConsumerAcceptMID = env->GetMethodID(jImStrConsumer, "accept", "(Ljava/lang/String;)V");
|
||||||
}
|
|
||||||
|
|
||||||
void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str) {
|
jclass jImStrSupplier = env->FindClass("imgui/callbacks/ImStrSupplier");
|
||||||
env->CallVoidMethod(consumer, jImStrConsumerAcceptMID, env->NewStringUTF(str));
|
jImStrSupplierGetMID = env->GetMethodID(jImStrSupplier, "get", "()Ljava/lang/String;");
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring CallImStrSupplier(JNIEnv* env, jobject supplier) {
|
void CallImListClipperCallback(JNIEnv* env, jobject consumer, int index) {
|
||||||
return (jstring)env->CallObjectMethod(supplier, jImStrSupplierGetMID);
|
env->CallVoidMethod(consumer, jImListClipperCallbackAcceptMID, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str) {
|
||||||
|
env->CallVoidMethod(consumer, jImStrConsumerAcceptMID, env->NewStringUTF(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring CallImStrSupplier(JNIEnv* env, jobject supplier) {
|
||||||
|
return (jstring)env->CallObjectMethod(supplier, jImStrSupplierGetMID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,10 +5,13 @@
|
|||||||
|
|
||||||
namespace Jni
|
namespace Jni
|
||||||
{
|
{
|
||||||
void InitCallbacks(JNIEnv* env);
|
void InitCallbacks(JNIEnv* env);
|
||||||
|
|
||||||
void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str);
|
void CallImListClipperCallback(JNIEnv* env, jobject consumer, int index);
|
||||||
jstring CallImStrSupplier(JNIEnv* env, jobject supplier);
|
|
||||||
|
void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str);
|
||||||
|
|
||||||
|
jstring CallImStrSupplier(JNIEnv* env, jobject supplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -12,58 +12,58 @@ static JavaVM* jvm;
|
|||||||
|
|
||||||
namespace Jni
|
namespace Jni
|
||||||
{
|
{
|
||||||
void InitCommon(JNIEnv* env) {
|
void InitCommon(JNIEnv* env) {
|
||||||
env->GetJavaVM(&jvm);
|
env->GetJavaVM(&jvm);
|
||||||
|
|
||||||
jclass jImVec2Class = env->FindClass("imgui/ImVec2");
|
jclass jImVec2Class = env->FindClass("imgui/ImVec2");
|
||||||
imVec2XID = env->GetFieldID(jImVec2Class, "x", "F");
|
imVec2XID = env->GetFieldID(jImVec2Class, "x", "F");
|
||||||
imVec2YID = env->GetFieldID(jImVec2Class, "y", "F");
|
imVec2YID = env->GetFieldID(jImVec2Class, "y", "F");
|
||||||
|
|
||||||
jclass jImVec4Class = env->FindClass("imgui/ImVec4");
|
jclass jImVec4Class = env->FindClass("imgui/ImVec4");
|
||||||
imVec4XID = env->GetFieldID(jImVec4Class, "x", "F");
|
imVec4XID = env->GetFieldID(jImVec4Class, "x", "F");
|
||||||
imVec4YID = env->GetFieldID(jImVec4Class, "y", "F");
|
imVec4YID = env->GetFieldID(jImVec4Class, "y", "F");
|
||||||
imVec4ZID = env->GetFieldID(jImVec4Class, "z", "F");
|
imVec4ZID = env->GetFieldID(jImVec4Class, "z", "F");
|
||||||
imVec4WID = env->GetFieldID(jImVec4Class, "w", "F");
|
imVec4WID = env->GetFieldID(jImVec4Class, "w", "F");
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEnv* GetEnv() {
|
JNIEnv* GetEnv() {
|
||||||
JNIEnv* env;
|
JNIEnv* env;
|
||||||
jint res = jvm->GetEnv((void**)(&env), JNI_VERSION_1_8);
|
jint res = jvm->GetEnv((void**)(&env), JNI_VERSION_1_8);
|
||||||
assert(res == JNI_OK);
|
assert(res == JNI_OK);
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst) {
|
void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst) {
|
||||||
env->SetFloatField(dst, imVec2XID, src->x);
|
env->SetFloatField(dst, imVec2XID, src->x);
|
||||||
env->SetFloatField(dst, imVec2YID, src->y);
|
env->SetFloatField(dst, imVec2YID, src->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst) {
|
void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst) {
|
||||||
env->SetFloatField(dst, imVec2XID, src.x);
|
env->SetFloatField(dst, imVec2XID, src.x);
|
||||||
env->SetFloatField(dst, imVec2YID, src.y);
|
env->SetFloatField(dst, imVec2YID, src.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst) {
|
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst) {
|
||||||
dst->x = env->GetFloatField(src, imVec2XID);
|
dst->x = env->GetFloatField(src, imVec2XID);
|
||||||
dst->y = env->GetFloatField(src, imVec2YID);
|
dst->y = env->GetFloatField(src, imVec2YID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst) {
|
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst) {
|
||||||
dst.x = env->GetFloatField(src, imVec2XID);
|
dst.x = env->GetFloatField(src, imVec2XID);
|
||||||
dst.y = env->GetFloatField(src, imVec2YID);
|
dst.y = env->GetFloatField(src, imVec2YID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst) {
|
void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst) {
|
||||||
env->SetFloatField(dst, imVec4XID, src->x);
|
env->SetFloatField(dst, imVec4XID, src->x);
|
||||||
env->SetFloatField(dst, imVec4YID, src->y);
|
env->SetFloatField(dst, imVec4YID, src->y);
|
||||||
env->SetFloatField(dst, imVec4ZID, src->z);
|
env->SetFloatField(dst, imVec4ZID, src->z);
|
||||||
env->SetFloatField(dst, imVec4WID, src->w);
|
env->SetFloatField(dst, imVec4WID, src->w);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst) {
|
void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst) {
|
||||||
env->SetFloatField(dst, imVec4XID, src.x);
|
env->SetFloatField(dst, imVec4XID, src.x);
|
||||||
env->SetFloatField(dst, imVec4YID, src.y);
|
env->SetFloatField(dst, imVec4YID, src.y);
|
||||||
env->SetFloatField(dst, imVec4ZID, src.z);
|
env->SetFloatField(dst, imVec4ZID, src.z);
|
||||||
env->SetFloatField(dst, imVec4WID, src.w);
|
env->SetFloatField(dst, imVec4WID, src.w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,18 +6,18 @@
|
|||||||
|
|
||||||
namespace Jni
|
namespace Jni
|
||||||
{
|
{
|
||||||
void InitCommon(JNIEnv* env);
|
void InitCommon(JNIEnv* env);
|
||||||
|
|
||||||
JNIEnv* GetEnv();
|
JNIEnv* GetEnv();
|
||||||
|
|
||||||
void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst);
|
void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst);
|
||||||
void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst);
|
void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst);
|
||||||
|
|
||||||
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst);
|
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst);
|
||||||
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst);
|
void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst);
|
||||||
|
|
||||||
void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst);
|
void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst);
|
||||||
void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst);
|
void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in new issue
Block a user